in freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/PrintTextWithDocgenSubstitutionsDirective.java [303:411]
private void insertCommandAndOutput(InsertDirectiveType insertDirectiveType, InsertDirectiveArgs args)
throws TemplateException, IOException {
if (args.printCommand || insertDirectiveType == CHECK_COMMAND) {
out.write("> ");
out.write(DOCGEN_WD_TAG_AND_SLASH_PATTERN.matcher(StringUtil.chomp(args.body)).replaceAll(""));
out.write("\n");
}
List<String> splitCmdLine = BashCommandLineArgsParser.parse(args.body);
if (splitCmdLine.isEmpty()) {
throw newErrorInDocgenTag("Command to execute was empty");
}
String cmdKey = splitCmdLine.get(0);
Map<String, Transform.InsertableOutputCommandProperties> cmdPropsMap =
transform.getInsertableOutputCommands();
Transform.InsertableOutputCommandProperties cmdProps = cmdPropsMap.get(cmdKey);
if (cmdProps == null) {
throw newErrorInDocgenTag(
"The " + Transform.SETTING_INSERTABLE_OUTPUT_COMMANDS
+ " configuration setting doesn't have entry with key " + StringUtil.jQuote(cmdKey)
+ ". "
+ (cmdPropsMap.isEmpty()
? "That setting is empty."
: "It has these keys: " + String.join(", ", cmdPropsMap.keySet())));
}
Method mainMethod = getMainMethod(cmdKey, cmdProps);
String cmdRunExceptionShortMessage;
TemplateException cmdRunException;
Writer outCapturer;
PrintStream prevOut = System.out;
PrintStream prevErr = System.err;
InputStream prevIn = System.in;
Map<String, String> prevSystemProperties = new HashMap<>();
try {
outCapturer = insertDirectiveType != CHECK_COMMAND ? new StringWriter() : NullWriter.INSTANCE;
PrintStream outCapturerPrintStream = new PrintStream(
new WriterOutputStream(outCapturer, Charset.defaultCharset()));
System.setOut(outCapturerPrintStream);
System.setErr(outCapturerPrintStream);
System.setIn(ClosedInputStream.CLOSED_INPUT_STREAM);
cmdProps.getSystemProperties().forEach((k, v) -> {
String prevValue = setOrClearSystemProperty(k, v);
prevSystemProperties.put(k, prevValue);
});
List<String> rawCmdArgs = splitCmdLine.subList(1, splitCmdLine.size());
List<String> cmdArgs = ImmutableList.<String>builder()
.addAll(cmdProps.getPrependedArguments())
.addAll(rawCmdArgs)
.addAll(cmdProps.getAppendedArguments())
.build().stream()
.map(cmdArg -> {
Path wdSubst = cmdProps.getWdSubstitution();
if (wdSubst == null) {
return cmdArg;
}
return cmdArg.replace(DOCGEN_WD_TAG, wdSubst.toString());
})
.collect(Collectors.toList());
Map<String, String> systemPropertiesToRestore = new HashMap<>();
try {
Object cmdExitCode = withSystemPropertiesOverridden(
Optional.ofNullable(args.systemProperties).orElse(Collections.emptyMap()),
() -> mainMethod.invoke(null, (Object) cmdArgs.toArray(new String[0])));
if (cmdExitCode instanceof Integer && ((Integer) cmdExitCode) != 0) {
cmdRunExceptionShortMessage = "Command execution has returned with non-0 exit code " + cmdExitCode + ".";
cmdRunException = newErrorInInsertOutputCommandException(
cmdRunExceptionShortMessage,
cmdProps, cmdArgs,
null);
} else {
cmdRunExceptionShortMessage = null;
cmdRunException = null;
}
} catch (Exception e) {
cmdRunExceptionShortMessage = "The main method has thrown this exception:\n" + e;
cmdRunException = newErrorInInsertOutputCommandException(
cmdRunExceptionShortMessage,
cmdProps, cmdArgs,
e);
}
outCapturerPrintStream.flush();
} finally {
prevSystemProperties.forEach(PrintTextWithDocgenSubstitutionsDirective::setOrClearSystemProperty);
System.setIn(prevIn);
System.setErr(prevErr);
System.setOut(prevOut);
}
if (cmdRunException == null) {
if (insertDirectiveType != CHECK_COMMAND) {
cutAndInsertContent(args, outCapturer.toString());
}
} else {
out.write(
"--------------------\n" +
"Docgen " + INSERT_WITH_OUTPUT.directiveName + " directive failed: "
+ cmdRunExceptionShortMessage + "\n"
+ "The command was:\n"
+ StringUtil.chomp(args.body) + "\n\n"
+ "The output of the command (if any) until it failed:\n\n");
HTMLOutputFormat.INSTANCE.output(outCapturer.toString(), out);
throw cmdRunException;
}
}