Skip to content

Commit 7cebcdf

Browse files
authored
Refactor JvmOptionsParser for testability (#52102)
This commit prepares the JvmOptionsParser to be more unit testable by refactoring the class to have some input that it pulls from external sources passed in as arguments. We do not change any functionality in this commit, nor add any unit tests, we are only preparing the way.
1 parent 4dd50f5 commit 7cebcdf

File tree

1 file changed

+75
-41
lines changed

1 file changed

+75
-41
lines changed

distribution/tools/launchers/src/main/java/org/elasticsearch/tools/launchers/JvmOptionsParser.java

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,27 @@
5252
*/
5353
final class JvmOptionsParser {
5454

55+
private static class JvmOptionsFileParserException extends Exception {
56+
57+
private final Path jvmOptionsFile;
58+
59+
Path jvmOptionsFile() {
60+
return jvmOptionsFile;
61+
}
62+
63+
private final SortedMap<Integer, String> invalidLines;
64+
65+
SortedMap<Integer, String> invalidLines() {
66+
return invalidLines;
67+
}
68+
69+
JvmOptionsFileParserException(final Path jvmOptionsFile, final SortedMap<Integer, String> invalidLines) {
70+
this.jvmOptionsFile = jvmOptionsFile;
71+
this.invalidLines = invalidLines;
72+
}
73+
74+
}
75+
5576
/**
5677
* The main entry point. The exit code is 0 if the JVM options were successfully parsed, otherwise the exit code is 1. If an improperly
5778
* formatted line is discovered, the line is output to standard error.
@@ -63,15 +84,58 @@ public static void main(final String[] args) throws InterruptedException, IOExce
6384
throw new IllegalArgumentException("expected one argument specifying path to ES_PATH_CONF but was " + Arrays.toString(args));
6485
}
6586

87+
final JvmOptionsParser parser = new JvmOptionsParser();
88+
89+
final Map<String, String> substitutions = new HashMap<>();
90+
substitutions.put("ES_TMPDIR", System.getenv("ES_TMPDIR"));
91+
final String environmentPathConf = System.getenv("ES_PATH_CONF");
92+
if (environmentPathConf != null) {
93+
substitutions.put("ES_PATH_CONF", environmentPathConf);
94+
}
95+
96+
try {
97+
final List<String> jvmOptions = parser.jvmOptions(Paths.get(args[0]), System.getenv("ES_JAVA_OPTS"), substitutions);
98+
final String spaceDelimitedJvmOptions = spaceDelimitJvmOptions(jvmOptions);
99+
Launchers.outPrintln(spaceDelimitedJvmOptions);
100+
} catch (final JvmOptionsFileParserException e) {
101+
final String errorMessage = String.format(
102+
Locale.ROOT,
103+
"encountered [%d] error%s parsing [%s]",
104+
e.invalidLines().size(),
105+
e.invalidLines().size() == 1 ? "" : "s",
106+
e.jvmOptionsFile()
107+
);
108+
Launchers.errPrintln(errorMessage);
109+
int count = 0;
110+
for (final Map.Entry<Integer, String> entry : e.invalidLines().entrySet()) {
111+
count++;
112+
final String message = String.format(
113+
Locale.ROOT,
114+
"[%d]: encountered improperly formatted JVM option in [%s] on line number [%d]: [%s]",
115+
count,
116+
e.jvmOptionsFile(),
117+
entry.getKey(),
118+
entry.getValue()
119+
);
120+
Launchers.errPrintln(message);
121+
}
122+
Launchers.exit(1);
123+
}
124+
125+
Launchers.exit(0);
126+
}
127+
128+
private List<String> jvmOptions(final Path config, final String esJavaOpts, final Map<String, String> substitutions)
129+
throws InterruptedException,
130+
IOException,
131+
JvmOptionsFileParserException {
66132
final ArrayList<Path> jvmOptionsFiles = new ArrayList<>();
67-
jvmOptionsFiles.add(Paths.get(args[0], "jvm.options"));
133+
jvmOptionsFiles.add(config.resolve("jvm.options"));
68134

69-
final Path jvmOptionsDirectory = Paths.get(args[0], "jvm.options.d");
135+
final Path jvmOptionsDirectory = config.resolve("jvm.options.d");
70136

71137
if (Files.isDirectory(jvmOptionsDirectory)) {
72-
try (
73-
DirectoryStream<Path> jvmOptionsDirectoryStream = Files.newDirectoryStream(Paths.get(args[0], "jvm.options.d"), "*.options")
74-
) {
138+
try (DirectoryStream<Path> jvmOptionsDirectoryStream = Files.newDirectoryStream(config.resolve("jvm.options.d"), "*.options")) {
75139
// collect the matching JVM options files after sorting them by Path::compareTo
76140
StreamSupport.stream(jvmOptionsDirectoryStream.spliterator(), false).sorted().forEach(jvmOptionsFiles::add);
77141
}
@@ -89,45 +153,16 @@ public static void main(final String[] args) throws InterruptedException, IOExce
89153
parse(JavaVersion.majorVersion(JavaVersion.CURRENT), br, jvmOptions::add, invalidLines::put);
90154
}
91155
if (invalidLines.isEmpty() == false) {
92-
final String errorMessage = String.format(
93-
Locale.ROOT,
94-
"encountered [%d] error%s parsing [%s]",
95-
invalidLines.size(),
96-
invalidLines.size() == 1 ? "" : "s",
97-
jvmOptionsFile
98-
);
99-
Launchers.errPrintln(errorMessage);
100-
int count = 0;
101-
for (final Map.Entry<Integer, String> entry : invalidLines.entrySet()) {
102-
count++;
103-
final String message = String.format(
104-
Locale.ROOT,
105-
"[%d]: encountered improperly formatted JVM option in [%s] on line number [%d]: [%s]",
106-
count,
107-
jvmOptionsFile,
108-
entry.getKey(),
109-
entry.getValue()
110-
);
111-
Launchers.errPrintln(message);
112-
}
113-
Launchers.exit(1);
156+
throw new JvmOptionsFileParserException(jvmOptionsFile, invalidLines);
114157
}
115158
}
116159

117-
// now append the JVM options from ES_JAVA_OPTS
118-
final String environmentJvmOptions = System.getenv("ES_JAVA_OPTS");
119-
if (environmentJvmOptions != null) {
160+
if (esJavaOpts != null) {
120161
jvmOptions.addAll(
121-
Arrays.stream(environmentJvmOptions.split("\\s+"))
122-
.filter(Predicate.not(String::isBlank))
123-
.collect(Collectors.toUnmodifiableList())
162+
Arrays.stream(esJavaOpts.split("\\s+")).filter(Predicate.not(String::isBlank)).collect(Collectors.toUnmodifiableList())
124163
);
125164
}
126-
final Map<String, String> substitutions = new HashMap<>();
127-
substitutions.put("ES_TMPDIR", System.getenv("ES_TMPDIR"));
128-
if (null != System.getenv("ES_PATH_CONF")) {
129-
substitutions.put("ES_PATH_CONF", System.getenv("ES_PATH_CONF"));
130-
}
165+
131166
final List<String> substitutedJvmOptions = substitutePlaceholders(jvmOptions, Collections.unmodifiableMap(substitutions));
132167
final List<String> ergonomicJvmOptions = JvmErgonomics.choose(substitutedJvmOptions);
133168
final List<String> systemJvmOptions = SystemJvmOptions.systemJvmOptions();
@@ -137,9 +172,8 @@ public static void main(final String[] args) throws InterruptedException, IOExce
137172
finalJvmOptions.addAll(systemJvmOptions); // add the system JVM options first so that they can be overridden
138173
finalJvmOptions.addAll(substitutedJvmOptions);
139174
finalJvmOptions.addAll(ergonomicJvmOptions);
140-
final String spaceDelimitedJvmOptions = spaceDelimitJvmOptions(finalJvmOptions);
141-
Launchers.outPrintln(spaceDelimitedJvmOptions);
142-
Launchers.exit(0);
175+
176+
return finalJvmOptions;
143177
}
144178

145179
static List<String> substitutePlaceholders(final List<String> jvmOptions, final Map<String, String> substitutions) {

0 commit comments

Comments
 (0)