This is an automated email from the ASF dual-hosted git repository.
ddekany pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/freemarker-docgen.git
The following commit(s) were added to refs/heads/master by this push:
new b21e4dd - Feature to execute a Java main method and insert its output
into the documentation now works - Improved castSetting API
b21e4dd is described below
commit b21e4dde5e3c7b0652f06700b6b9b12f891bd9a7
Author: ddekany <[email protected]>
AuthorDate: Mon Feb 8 08:59:48 2021 +0100
- Feature to execute a Java main method and insert its output into the
documentation now works
- Improved castSetting API
---
.../org/freemarker/docgen/core/DefaultValue.java | 34 +++
.../PrintTextWithDocgenSubstitutionsDirective.java | 234 +++++++++++++++++----
.../org/freemarker/docgen/core/SettingUtils.java | 14 +-
.../java/org/freemarker/docgen/core/Transform.java | 125 ++++++++---
.../freemarker/docgen/core/SettingUtilsTest.java | 4 +-
5 files changed, 329 insertions(+), 82 deletions(-)
diff --git
a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/DefaultValue.java
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/DefaultValue.java
new file mode 100644
index 0000000..9026834
--- /dev/null
+++
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/DefaultValue.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.freemarker.docgen.core;
+
+final class DefaultValue<T> {
+ private final T value;
+
+ static final DefaultValue NULL = new DefaultValue(null);
+
+ public DefaultValue(T value) {
+ this.value = value;
+ }
+
+ public T get() {
+ return value;
+ }
+}
diff --git
a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/PrintTextWithDocgenSubstitutionsDirective.java
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/PrintTextWithDocgenSubstitutionsDirective.java
index 55adcbf..624f66c 100644
---
a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/PrintTextWithDocgenSubstitutionsDirective.java
+++
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/PrintTextWithDocgenSubstitutionsDirective.java
@@ -19,14 +19,23 @@
package org.freemarker.docgen.core;
+import static
org.freemarker.docgen.core.PrintTextWithDocgenSubstitutionsDirective.InsertDirectiveType.*;
+
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -35,11 +44,15 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import java.util.stream.Collectors;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.WriterOutputStream;
import org.apache.commons.text.StringEscapeUtils;
+import com.google.common.collect.ImmutableList;
+
import freemarker.core.Environment;
import freemarker.core.HTMLOutputFormat;
import freemarker.core.NonStringException;
@@ -63,8 +76,17 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
private static final String DOCGEN_TAG_START = "[docgen";
private static final String DOCGEN_TAG_END = "]";
private static final String DOCGEN_END_TAG_START = "[/docgen";
- private static final String INSERT_FILE = "insertFile";
- private static final String INSERT_OUTPUT = "insertOutput";
+
+ enum InsertDirectiveType {
+ INSERT_FILE("insertFile"),
+ INSERT_OUTPUT("insertOutput");
+
+ private final String directiveName;
+
+ InsertDirectiveType(String directiveName) {
+ this.directiveName = directiveName;
+ }
+ }
private final Transform transform;
@@ -105,6 +127,9 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
new DocgenSubstitutionInterpreter(text, env).execute();
}
+ private static final String DOCGEN_WD_TAG = "[docgen:wd]";
+ private static final Pattern DOCGEN_WD_TAG_AND_SLASH_PATTERN =
Pattern.compile(Pattern.quote(DOCGEN_WD_TAG) + "/?");
+
private class DocgenSubstitutionInterpreter {
private final String text;
private final Environment env;
@@ -142,12 +167,12 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
lastUnprintedIdx = cursor;
insertCustomVariable(customVarName);
- } else if (INSERT_FILE.equals(subvarName)) {
- InsertDirectiveArgs args =
fetchInsertDirectiveArgs(subvarName, true, true, false);
+ } else if (INSERT_FILE.directiveName.equals(subvarName)) {
+ InsertDirectiveArgs args =
fetchInsertDirectiveArgs(subvarName, INSERT_FILE);
lastUnprintedIdx = cursor;
insertFile(args);
- } else if (INSERT_OUTPUT.equals(subvarName)) {
- InsertDirectiveArgs args =
fetchInsertDirectiveArgs(subvarName, false, false, true);
+ } else if (INSERT_OUTPUT.directiveName.equals(subvarName)) {
+ InsertDirectiveArgs args =
fetchInsertDirectiveArgs(subvarName, INSERT_OUTPUT);
lastUnprintedIdx = cursor;
insertOutput(args);
} else {
@@ -257,43 +282,22 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
fileContent = removeFTLCopyrightComment(fileContent);
}
- if (args.from != null) {
- Matcher matcher = args.from.matcher(fileContent);
- if (matcher.find()) {
- String remaining =
fileContent.substring(matcher.start());
- fileContent = "[\u2026]"
- + (remaining.startsWith("\n") ||
remaining.startsWith("\r") ? "" : "\n")
- + remaining;
- } else if (!args.fromOptional) {
- throw newErrorInDocgenTag(
- "\"from\" regular expression has no match in
the file content: " + args.from);
- }
- }
-
- if (args.to != null) {
- Matcher matcher = args.to.matcher(fileContent);
- if (matcher.find()) {
- String remaining = fileContent.substring(0,
matcher.start());
- fileContent = remaining
- + (remaining.endsWith("\n") ||
remaining.endsWith("\r") ? "" : "\n")
- + "[\u2026]";
- } else if (!args.toOptional) {
- throw newErrorInDocgenTag(
- "\"to\" regular expression has no match in the
file content: " + args.to);
- }
- }
-
- HTMLOutputFormat.INSTANCE.output(fileContent, out);
+ cutAndInsertContent(args, fileContent);
}
}
private void insertOutput(InsertDirectiveArgs args) throws
TemplateException, IOException {
+ if (args.printCommand) {
+ 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);
- List<String> cmdArgs = splitCmdLine.subList(1,
splitCmdLine.size());
Map<String, Transform.InsertableOutputCommandProperties>
cmdPropsMap =
transform.getInsertableOutputCommands();
Transform.InsertableOutputCommandProperties cmdProps =
cmdPropsMap.get(cmdKey);
@@ -306,14 +310,134 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
? "That setting is empty."
: "It has these keys: " +
String.join(", ", cmdPropsMap.keySet())));
}
- HTMLOutputFormat.INSTANCE.output("!!T\n" + cmdProps + "\n" +
cmdArgs, out);
+
+ Method mainMethod = getMainMethod(cmdKey, cmdProps);
+
+ StringWriter stdOutCapturer;
+ PrintStream prevOut = System.out;
+ Map<String, String> prevSystemProperties = new HashMap<>();
+ try {
+ stdOutCapturer = new StringWriter();
+ PrintStream stdOutCapturerPrintStream = new PrintStream(
+ new WriterOutputStream(stdOutCapturer,
Charset.defaultCharset()));
+ System.setOut(stdOutCapturerPrintStream);
+
+ 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.toAbsolutePath().toString());
+ })
+ .collect(Collectors.toList());
+
+ Object returnValue;
+ try {
+ returnValue = mainMethod.invoke(null, (Object)
cmdArgs.toArray(new String[0]));
+ } catch (Exception e) {
+ throw newErrorInDocgenTag("Error when executing command
with "
+ + cmdProps.getMainClassName() + "." +
cmdProps.getMainMethodName()
+ + ", and arguments " + cmdArgs + ".",
+ e);
+ }
+ if (returnValue instanceof Integer && ((Integer) returnValue)
!= 0) {
+ throw newErrorInDocgenTag(
+ "Command execution has returned with non-0 exit
code " + returnValue
+ + ", from " + cmdProps.getMainClassName()
+ "." + cmdProps.getMainMethodName()
+ + ", called with arguments " + cmdArgs +
".");
+ }
+
+ stdOutCapturerPrintStream.flush();
+ } finally {
+
prevSystemProperties.forEach(PrintTextWithDocgenSubstitutionsDirective::setOrClearSystemProperty);
+ System.setOut(prevOut);
+ }
+ cutAndInsertContent(args, stdOutCapturer.toString());
+ }
+
+ private void cutAndInsertContent(InsertDirectiveArgs args, String
content)
+ throws TemplateException, IOException {
+ if (args.from != null) {
+ Matcher matcher = args.from.matcher(content);
+ if (matcher.find()) {
+ String remaining = content.substring(matcher.start());
+ content = "[\u2026]"
+ + (remaining.startsWith("\n") ||
remaining.startsWith("\r") ? "" : "\n")
+ + remaining;
+ } else if (!args.fromOptional) {
+ throw newErrorInDocgenTag(
+ "\"from\" regular expression has no match in the
file content: " + args.from);
+ }
+ }
+
+ if (args.to != null) {
+ Matcher matcher = args.to.matcher(content);
+ if (matcher.find()) {
+ String remaining = content.substring(0, matcher.start());
+ content = remaining
+ + (remaining.endsWith("\n") ||
remaining.endsWith("\r") ? "" : "\n")
+ + "[\u2026]";
+ } else if (!args.toOptional) {
+ throw newErrorInDocgenTag(
+ "\"to\" regular expression has no match in the
file content: " + args.to);
+ }
+ }
+
+ HTMLOutputFormat.INSTANCE.output(content, out);
}
- private TemplateException newFormattingFailedException(String
customVarName, TemplateValueFormatException e) {
- return new TemplateException(
- "Formatting failed for Docgen custom variable "
- + StringUtil.jQuote(customVarName),
- e, env);
+ private Method getMainMethod(String cmdKey,
Transform.InsertableOutputCommandProperties cmdProps) throws
+ TemplateException {
+ String mainClassName = cmdProps.getMainClassName();
+ Class<?> mainClass;
+ try {
+ mainClass =
Transform.class.getClassLoader().loadClass(mainClassName);
+ } catch (Exception e) {
+ throw newErrorInDocgenTag(
+ "The main class referred by "
+ + Transform.SETTING_INSERTABLE_OUTPUT_COMMANDS
+ "[" + StringUtil.jQuote(cmdKey) + "], "
+ + StringUtil.jQuote(mainClassName) + ",
couldn't be loaded",
+ e);
+ }
+
+ String mainMethodName = cmdProps.getMainMethodName();
+ Method mainMethod;
+ try {
+ mainMethod = mainClass.getMethod(mainMethodName,
String[].class);
+ } catch (Exception e) {
+ throw newErrorInDocgenTag(
+ "Couldn't get " + mainMethodName + "(String[]) method
from class "
+ + mainClassName + ".",
+ e);
+ }
+ if ((mainMethod.getModifiers() & Modifier.STATIC) == 0) {
+ throw newErrorInDocgenTag(
+ mainMethodName + "(String[]) method from class "
+ + mainClassName + " must be static.");
+ }
+ if ((mainMethod.getModifiers() & Modifier.PUBLIC) == 0) {
+ throw newErrorInDocgenTag(
+ mainMethodName + "(String[]) method from class "
+ + mainClassName + " must be public.");
+ }
+ Class<?> returnType = mainMethod.getReturnType();
+ if (returnType != void.class && returnType != int.class) {
+ throw newErrorInDocgenTag(
+ mainMethodName + "(String[]) method from class "
+ + mainClassName + " must return void or int,
but return type was " + returnType);
+ }
+ return mainMethod;
}
private int findNextDocgenTagStart(int fromIndex) {
@@ -460,7 +584,6 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
}
}
-
private char charAt(int index) {
return index < text.length() ? text.charAt(index) : 0;
}
@@ -472,19 +595,30 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
}
private TemplateException newErrorInDocgenTag(String errorDetail) {
+ return newErrorInDocgenTag(errorDetail, null);
+ }
+
+ private TemplateException newErrorInDocgenTag(String errorDetail,
Throwable cause) {
return new DocgenTagException(
- "\nError in docgen tag: " +
text.substring(lastDocgenTagStart, cursor) + "\n" + errorDetail,
+ "\nError in docgen tag: " +
text.substring(lastDocgenTagStart, cursor) + "\n" + errorDetail
+ + (cause != null ? "\nSee cause exception for
more!" : ""),
+ cause,
env);
+ }
+ private TemplateException newFormattingFailedException(String
customVarName, TemplateValueFormatException e) {
+ return new TemplateException(
+ "Formatting failed for Docgen custom variable " +
StringUtil.jQuote(customVarName),
+ e, env);
}
private InsertDirectiveArgs fetchInsertDirectiveArgs(
- String subvarName, boolean hasPath, boolean allowCharsetArg,
boolean hasBodyArg) throws
+ String subvarName, InsertDirectiveType insertDirectiveType)
throws
TemplateException {
InsertDirectiveArgs args = new InsertDirectiveArgs();
args.toOptional = true;
- if (hasPath) {
+ if (insertDirectiveType == INSERT_FILE) {
skipWS();
args.path = fetchRequiredString();
}
@@ -498,7 +632,7 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
"Duplicate docgen." + subvarName + " parameter "
+ StringUtil.jQuote(paramName) + ".",
env);
}
- if (allowCharsetArg && paramName.equals("charset")) {
+ if (insertDirectiveType == INSERT_FILE &&
paramName.equals("charset")) {
args.charset =
StringEscapeUtils.unescapeXml(fetchRequiredString());
} else if (paramName.equals("from")) {
args.from = parseRegularExpressionParam(paramName,
StringEscapeUtils.unescapeXml(fetchRequiredString()));
@@ -508,6 +642,9 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
args.fromOptional = fetchRequiredBoolean();
} else if (paramName.equals("toOptional")) {
args.toOptional = fetchRequiredBoolean();
+ } else if (insertDirectiveType == INSERT_OUTPUT
+ && paramName.equals("printCommand")) {
+ args.printCommand = fetchRequiredBoolean();
} else {
throw new DocgenTagException(
"Unsupported docgen." + subvarName + " parameter
" + StringUtil.jQuote(paramName) + ".",
@@ -518,7 +655,7 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
skipRequiredToken(DOCGEN_TAG_END);
int indexAfterStartTag = cursor;
- if (hasBodyArg) {
+ if (insertDirectiveType == INSERT_OUTPUT) {
int endTagIndex = findNextDocgenEndTag(cursor);
if (endTagIndex == -1) {
throw new DocgenTagException(
@@ -559,6 +696,10 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
}
+ private static String setOrClearSystemProperty(String k, String v) {
+ return v != null ? System.setProperty(k, v) : System.clearProperty(k);
+ }
+
public static String removeFTLCopyrightComment(String ftl) {
int copyrightPartIdx = ftl.indexOf("Licensed to the Apache Software
Foundation");
if (copyrightPartIdx == -1) {
@@ -616,6 +757,7 @@ public class PrintTextWithDocgenSubstitutionsDirective
implements TemplateDirect
private boolean toOptional;
private String body;
private int indexAfterDirective;
+ private boolean printCommand;
}
}
diff --git
a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/SettingUtils.java
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/SettingUtils.java
index c53d905..39c1f59 100644
---
a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/SettingUtils.java
+++
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/SettingUtils.java
@@ -76,13 +76,13 @@ final class SettingUtils {
Object settingValue, Class<T> elementClass) {
return castSetting(
settingName, settingValue,
- false,
+ null,
List.class, new ListItemType(elementClass)
);
}
static <T> T castSetting(SettingName settingName, Object settingValue,
Class<T> valueType) {
- return castSetting(settingName, settingValue, false, valueType);
+ return castSetting(settingName, settingValue, null, valueType);
}
/**
@@ -91,23 +91,25 @@ final class SettingUtils {
static <T> T castSetting(
SettingName settingName, Object settingValue, Class<T> valueType,
ContainedValueType... containedValueTypes) {
- return castSetting(settingName, settingValue, false, valueType,
containedValueTypes);
+ return castSetting(settingName, settingValue, null, valueType,
containedValueTypes);
}
/**
* @param valueType
* The expected type of the value (on the top-level, if it's a
container)
+ * @param defaultValue
+ * {@code null} if the setting is required or can't have {@code null}
value. Non-null otherwise.
* @param containedValueTypes
* The expected type of the contained values, and of the values
contained inside them, and so on. (This is
* separate from {@code valueType} because Java can't match s generic
return type with the type of the first
*/
static <T> T castSetting(
SettingName settingName, Object settingValue,
- boolean optional,
+ DefaultValue<T> defaultValue,
Class<T> valueType, ContainedValueType... containedValueTypes) {
if (settingValue == null) {
- if (optional) {
- return null;
+ if (defaultValue != null) {
+ return defaultValue.get();
}
throw newNullSettingValueException(settingName);
}
diff --git
a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java
index 5808fac..3d46668 100644
---
a/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java
+++
b/freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/Transform.java
@@ -45,6 +45,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Optional;
import java.util.Set;
import java.util.SortedMap;
import java.util.TimeZone;
@@ -155,17 +156,24 @@ public final class Transform {
static final String SETTING_CUSTOM_VARIABLES = "customVariables";
static final String SETTING_INSERTABLE_FILES = "insertableFiles";
static final String SETTING_INSERTABLE_OUTPUT_COMMANDS =
"insertableOutputCommands";
- static final String SETTING_INSERTABLE_OUTPUT_COMMADS_CLASS_KEY = "class";
- static final String
SETTING_INSERTABLE_OUTPUT_COMMADS_PREPENDED_ARGUMENTS_KEY =
"prependedArguments";
- static final String SETTING_INSERTABLE_OUTPUT_COMMADS_WORK_DIRECTORY_KEY =
"workDirectory";
- static final Set<String> SETTING_INSERTABLE_OUTPUT_COMMADS_OPTIONAL_KEYS;
- static final Set<String> SETTING_INSERTABLE_OUTPUT_COMMADS_REQUIRED_KEYS;
+ static final String SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_CLASS_KEY =
"mainClass";
+ static final String SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_METHOD_KEY =
"mainMethod";
+ static final String
SETTING_INSERTABLE_OUTPUT_COMMANDS_SYSTEM_PROPERTIES_KEY = "systemProperties";
+ static final String
SETTING_INSERTABLE_OUTPUT_COMMANDS_PREPENDED_ARGUMENTS_KEY =
"prependedArguments";
+ static final String
SETTING_INSERTABLE_OUTPUT_COMMANDS_APPENDED_ARGUMENTS_KEY = "appendedArguments";
+ static final String
SETTING_INSERTABLE_OUTPUT_COMMANDS_DOCGEN_WD_REPLACED_WITH_KEY =
"docgenWdReplacedWith";
+ static final Set<String> SETTING_INSERTABLE_OUTPUT_COMMANDS_OPTIONAL_KEYS;
+ static final Set<String> SETTING_INSERTABLE_OUTPUT_COMMANDS_REQUIRED_KEYS;
static {
- SETTING_INSERTABLE_OUTPUT_COMMADS_REQUIRED_KEYS = new
LinkedHashSet<>();
-
SETTING_INSERTABLE_OUTPUT_COMMADS_REQUIRED_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMADS_CLASS_KEY);
- SETTING_INSERTABLE_OUTPUT_COMMADS_OPTIONAL_KEYS = new
LinkedHashSet<>();
-
SETTING_INSERTABLE_OUTPUT_COMMADS_OPTIONAL_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMADS_PREPENDED_ARGUMENTS_KEY);
-
SETTING_INSERTABLE_OUTPUT_COMMADS_OPTIONAL_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMADS_WORK_DIRECTORY_KEY);
+ SETTING_INSERTABLE_OUTPUT_COMMANDS_REQUIRED_KEYS = new
LinkedHashSet<>();
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_REQUIRED_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_CLASS_KEY);
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_REQUIRED_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_METHOD_KEY);
+ SETTING_INSERTABLE_OUTPUT_COMMANDS_OPTIONAL_KEYS = new
LinkedHashSet<>();
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_OPTIONAL_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMANDS_SYSTEM_PROPERTIES_KEY);
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_OPTIONAL_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMANDS_PREPENDED_ARGUMENTS_KEY);
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_OPTIONAL_KEYS.add(SETTING_INSERTABLE_OUTPUT_COMMANDS_APPENDED_ARGUMENTS_KEY);
+ SETTING_INSERTABLE_OUTPUT_COMMANDS_OPTIONAL_KEYS.add(
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_DOCGEN_WD_REPLACED_WITH_KEY);
}
static final String SETTING_VALIDATION_PROGRAMLISTINGS_REQ_ROLE
@@ -623,27 +631,51 @@ public final class Transform {
Map.class,
new MapEntryType(String.class, Map.class),
new MapEntryType(
- String.class,
SETTING_INSERTABLE_OUTPUT_COMMADS_REQUIRED_KEYS,
SETTING_INSERTABLE_OUTPUT_COMMADS_OPTIONAL_KEYS,
+ String.class,
SETTING_INSERTABLE_OUTPUT_COMMANDS_REQUIRED_KEYS,
SETTING_INSERTABLE_OUTPUT_COMMANDS_OPTIONAL_KEYS,
Object.class, false));
for (Entry<String, Map<String, Object>> ent :
m.entrySet()) {
String commandKey = ent.getKey();
Map<String, Object> outputCmdProps = ent.getValue();
InsertableOutputCommandProperties commandProps = new
InsertableOutputCommandProperties(
castSetting(
- settingName.subKey(commandKey,
SETTING_INSERTABLE_OUTPUT_COMMADS_CLASS_KEY),
-
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMADS_CLASS_KEY),
+ settingName.subKey(commandKey,
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_CLASS_KEY),
+
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_CLASS_KEY),
String.class
),
castSetting(
- settingName.subKey(commandKey,
SETTING_INSERTABLE_OUTPUT_COMMADS_PREPENDED_ARGUMENTS_KEY),
-
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMADS_PREPENDED_ARGUMENTS_KEY),
+ settingName.subKey(commandKey,
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_METHOD_KEY),
+
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMANDS_MAIN_METHOD_KEY),
+ String.class
+ ),
+ castSetting(
+ settingName.subKey(commandKey,
SETTING_INSERTABLE_OUTPUT_COMMANDS_SYSTEM_PROPERTIES_KEY),
+
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMANDS_SYSTEM_PROPERTIES_KEY),
+ new
DefaultValue<>(Collections.emptyMap()),
+ Map.class, new
MapEntryType(String.class, String.class)
+ ),
+ castSetting(
+ settingName.subKey(commandKey,
SETTING_INSERTABLE_OUTPUT_COMMANDS_PREPENDED_ARGUMENTS_KEY),
+
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMANDS_PREPENDED_ARGUMENTS_KEY),
+ new
DefaultValue<>(Collections.emptyList()),
List.class
),
- Paths.get(castSetting(
- settingName.subKey(commandKey,
SETTING_INSERTABLE_OUTPUT_COMMADS_WORK_DIRECTORY_KEY),
-
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMADS_WORK_DIRECTORY_KEY),
- String.class
- ))
+ castSetting(
+ settingName.subKey(commandKey,
SETTING_INSERTABLE_OUTPUT_COMMANDS_APPENDED_ARGUMENTS_KEY),
+
outputCmdProps.get(SETTING_INSERTABLE_OUTPUT_COMMANDS_APPENDED_ARGUMENTS_KEY),
+ new
DefaultValue<>(Collections.emptyList()),
+ List.class
+ ),
+ Optional.ofNullable(
+ castSetting(
+ settingName.subKey(commandKey,
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_DOCGEN_WD_REPLACED_WITH_KEY),
+ outputCmdProps.get(
+
SETTING_INSERTABLE_OUTPUT_COMMANDS_DOCGEN_WD_REPLACED_WITH_KEY),
DefaultValue.NULL,
+ String.class
+ )
+ ).map(Paths::get).orElse(null)
);
insertableOutputCommands.put(commandKey, commandProps);
}
@@ -1304,7 +1336,7 @@ public final class Transform {
private static Logo castMapToLogo(SettingName settingName, Object
settingValue) {
Map<String, String> logoMap = castSetting(
settingName,
- settingValue, false,
+ settingValue, null,
Map.class,
new MapEntryType(String.class, SETTING_LOGO_MAP_KEYS,
String.class));
return new Logo(
@@ -2780,21 +2812,58 @@ public final class Transform {
static class InsertableOutputCommandProperties {
private final String mainClassName;
+ private final String mainMethodName;
+ private final Map<String, String> systemProperties;
private final List<String> prependedArguments;
- private final Path workDirectory;
+ private final List<String> appendedArguments;
+ private final Path wdSubstitution;
- public InsertableOutputCommandProperties(String mainClassName,
List<String> prependedArguments, Path workDirectory) {
+ public InsertableOutputCommandProperties(
+ String mainClassName, String mainMethodName,
+ Map<String, String> systemProperties,
+ List<String> prependedArguments, List<String>
appendedArguments, Path wdSubstitution) {
this.mainClassName = mainClassName;
+ this.mainMethodName = mainMethodName;
+ this.systemProperties = systemProperties;
this.prependedArguments = prependedArguments;
- this.workDirectory = workDirectory;
+ this.appendedArguments = appendedArguments;
+ this.wdSubstitution = wdSubstitution;
+ }
+
+ public String getMainClassName() {
+ return mainClassName;
+ }
+
+ public String getMainMethodName() {
+ return mainMethodName;
+ }
+
+ public Map<String, String> getSystemProperties() {
+ return systemProperties;
+ }
+
+ public List<String> getPrependedArguments() {
+ return prependedArguments;
+ }
+
+ public List<String> getAppendedArguments() {
+ return appendedArguments;
+ }
+
+ public Path getWdSubstitution() {
+ return wdSubstitution;
}
@Override
public String toString() {
- return "InsertableOutputCommandProperties{"
- + "mainClassName='" + mainClassName + '\''
- + ", prependedArguments=" + prependedArguments
- + ", workDirectory=" + workDirectory + '}';
+ return "InsertableOutputCommandProperties{" +
+ "mainClassName='" + mainClassName + '\'' +
+ ", mainMethodName='" + mainMethodName + '\'' +
+ ", systemProperties=" + systemProperties +
+ ", prependedArguments=" + prependedArguments +
+ ", appendedArguments=" + appendedArguments +
+ ", wdSubstitution=" + wdSubstitution +
+ '}';
}
}
diff --git
a/freemarker-docgen-core/src/test/java/org/freemarker/docgen/core/SettingUtilsTest.java
b/freemarker-docgen-core/src/test/java/org/freemarker/docgen/core/SettingUtilsTest.java
index b615f3b..ae1b86c 100644
---
a/freemarker-docgen-core/src/test/java/org/freemarker/docgen/core/SettingUtilsTest.java
+++
b/freemarker-docgen-core/src/test/java/org/freemarker/docgen/core/SettingUtilsTest.java
@@ -49,7 +49,7 @@ public class SettingUtilsTest {
ImmutableList<ImmutableList<?>> originalValue =
ImmutableList.of(ImmutableList.of(), ImmutableList.of(1));
Object value = castSetting(
SETTING_NAME,
- originalValue, true,
+ originalValue, DefaultValue.NULL,
List.class,
new ListItemType(List.class),
new ListItemType(Integer.class)
@@ -73,7 +73,7 @@ public class SettingUtilsTest {
@Test
public void testOptional() {
- assertNull(castSetting(SETTING_NAME, null, true, Integer.class));
+ assertNull(castSetting(SETTING_NAME, null, DefaultValue.NULL,
Integer.class));
try {
castSetting(SETTING_NAME, null, Integer.class);
fail();