Returns the result of a command. @param qc query context @param fork fork process @return result, or null if process is forked @throws QueryException query exception
(final QueryContext qc, final boolean fork)
| 38 | * @throws QueryException query exception |
| 39 | */ |
| 40 | final ProcResult exec(final QueryContext qc, final boolean fork) throws QueryException { |
| 41 | // arguments |
| 42 | final String command = toString(arg(0), qc); |
| 43 | final StringList args = new StringList().add(command); |
| 44 | for(final Item item : arg(1).atomValue(qc, info)) args.add(toString(item)); |
| 45 | |
| 46 | // options |
| 47 | final ProcOptions options = toOptions(arg(2), new ProcOptions(), qc); |
| 48 | final Charset cs = Prop.CHARSET; |
| 49 | final String encoding = options.get(ProcOptions.ENCODING); |
| 50 | if(encoding != null) { |
| 51 | final String error = Strings.checkEncoding(encoding); |
| 52 | if(error != null) throw PROC_ENCODING_X.get(info, error); |
| 53 | } |
| 54 | final long seconds = options.get(ProcOptions.TIMEOUT); |
| 55 | final String dir = options.get(ProcOptions.DIR); |
| 56 | final Map<String, String> env = options.get(ProcOptions.ENVIRONMENT).free(); |
| 57 | final String input = options.get(ProcOptions.INPUT); |
| 58 | |
| 59 | final ProcResult result = new ProcResult(); |
| 60 | final Process proc; |
| 61 | final ProcessBuilder pb = new ProcessBuilder(args.finish()); |
| 62 | if(dir != null) pb.directory(toPath(dir, qc).toFile()); |
| 63 | if(!env.isEmpty()) { |
| 64 | pb.environment().clear(); |
| 65 | pb.environment().putAll(env); |
| 66 | } |
| 67 | |
| 68 | try { |
| 69 | proc = pb.start(); |
| 70 | } catch(final IOException ex) { |
| 71 | result.exception(ex); |
| 72 | return result; |
| 73 | } |
| 74 | if(fork) return null; |
| 75 | |
| 76 | final Thread outt = reader(proc.getInputStream(), result.output, cs, result); |
| 77 | final Thread errt = reader(proc.getErrorStream(), result.error, cs, result); |
| 78 | outt.start(); |
| 79 | errt.start(); |
| 80 | |
| 81 | final Thread thread = new Thread(() -> { |
| 82 | try { |
| 83 | if(input != null) { |
| 84 | try(OutputStream os = proc.getOutputStream()) { |
| 85 | os.write(token(input)); |
| 86 | } |
| 87 | } |
| 88 | proc.waitFor(); |
| 89 | outt.join(); |
| 90 | errt.join(); |
| 91 | } catch(final IOException ex) { |
| 92 | result.exception(ex); |
| 93 | } catch(final InterruptedException ex) { |
| 94 | result.error.add(Util.message(ex)); |
| 95 | } |
| 96 | }); |
| 97 | thread.start(); |
no test coverage detected