Skip to content

Commit a6ae879

Browse files
committed
Clean up log4j migration code, add more tests
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
1 parent cf36b70 commit a6ae879

4 files changed

Lines changed: 152 additions & 59 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// SPDX-FileCopyrightText: 2026 Mitch Gaffigan <mitch@gaffigan.net>
3+
4+
packagecom.mirth.connect.server.launcher;
5+
6+
importjava.io.File;
7+
importjava.io.IOException;
8+
importjava.nio.charset.StandardCharsets;
9+
importjava.util.List;
10+
11+
importorg.apache.commons.io.FileUtils;
12+
13+
publicclassLog4jMigrations {
14+
privatestaticfinalStringINVALID_LOG4J_PROPERTY = "dir.logs";
15+
16+
privateLog4jMigrations() {}
17+
18+
publicstaticvoidmigrateConfiguration(FilepropertiesFile) {
19+
if (!propertiesFile.exists() || !propertiesFile.isFile()) {
20+
return;
21+
}
22+
23+
try {
24+
List<String> lines = FileUtils.readLines(propertiesFile, StandardCharsets.UTF_8);
25+
if (stripDirLogs(lines)) {
26+
FileUtils.writeLines(propertiesFile, StandardCharsets.UTF_8.name(), lines, System.lineSeparator(), false);
27+
}
28+
} catch (IOExceptione) {
29+
System.err.println("Failed to migrate Log4j configuration: " + propertiesFile.getAbsolutePath());
30+
e.printStackTrace();
31+
}
32+
}
33+
34+
privatestaticbooleanstripDirLogs(List<String> lines) {
35+
returnlines.removeIf(line -> isPropertyLine(line, INVALID_LOG4J_PROPERTY));
36+
}
37+
38+
privatestaticbooleanisPropertyLine(Stringline, StringpropertyName) {
39+
StringtrimmedLine = line.trim();
40+
intequalsIndex = trimmedLine.indexOf('=');
41+
returnequalsIndex >= 0 && trimmedLine.substring(0, equalsIndex).trim().equals(propertyName);
42+
}
43+
}

‎server/src/com/mirth/connect/server/launcher/MirthLauncher.java‎

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
importjava.io.IOException;
1616
importjava.net.URL;
1717
importjava.net.URLClassLoader;
18-
importjava.nio.charset.StandardCharsets;
1918
importjava.util.ArrayList;
2019
importjava.util.Collection;
2120
importjava.util.List;
@@ -47,7 +46,6 @@ public class MirthLauncher {
4746
privatestaticfinalString[] LOG4J_JAR_FILES = { "./server-lib/log4j/log4j-core-2.25.3.jar",
4847
"./server-lib/log4j/log4j-api-2.25.3.jar",
4948
"./server-lib/log4j/log4j-1.2-api-2.25.3.jar" };
50-
privatestaticfinalStringINVALID_LOG4J_PROPERTY = "dir.logs";
5149

5250
privatestaticStringappDataDir = null;
5351

@@ -56,7 +54,7 @@ public class MirthLauncher {
5654
publicstaticvoidmain(String[] args) {
5755
JarFilemirthClientCoreJarFile = null;
5856
try {
59-
sanitizeLog4jConfiguration(newFile(LOG4J_PROPERTIES_FILE));
57+
Log4jMigrations.migrateConfiguration(newFile(LOG4J_PROPERTIES_FILE));
6058

6159
List<URL> classpathUrls = newArrayList<>();
6260
// Always add log4j
@@ -133,28 +131,6 @@ public static void main(String[] args) {
133131
}
134132
}
135133

136-
privatestaticvoidsanitizeLog4jConfiguration(FilepropertiesFile) {
137-
if (!propertiesFile.exists() || !propertiesFile.isFile()) {
138-
return;
139-
}
140-
141-
try {
142-
List<String> lines = FileUtils.readLines(propertiesFile, StandardCharsets.UTF_8);
143-
if (lines.removeIf(MirthLauncher::isInvalidLog4jPropertyLine)) {
144-
FileUtils.writeLines(propertiesFile, StandardCharsets.UTF_8.name(), lines, System.lineSeparator(), false);
145-
}
146-
} catch (IOExceptione) {
147-
System.err.println("Failed to sanitize Log4j configuration: " + propertiesFile.getAbsolutePath());
148-
e.printStackTrace();
149-
}
150-
}
151-
152-
privatestaticbooleanisInvalidLog4jPropertyLine(Stringline) {
153-
StringtrimmedLine = line.trim();
154-
intequalsIndex = trimmedLine.indexOf('=');
155-
returnequalsIndex >= 0 && trimmedLine.substring(0, equalsIndex).trim().equals(INVALID_LOG4J_PROPERTY);
156-
}
157-
158134
// if we have an uninstall file, uninstall the listed extensions
159135
privatestaticvoiduninstallPendingExtensions() throwsException {
160136
FileextensionsDir = newFile(EXTENSIONS_DIR);
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// SPDX-FileCopyrightText: 2026 Mitch Gaffigan <mitch@gaffigan.net>
3+
4+
packagecom.mirth.connect.server.launcher;
5+
6+
importstaticorg.junit.Assert.assertEquals;
7+
importstaticorg.junit.Assert.assertFalse;
8+
importstaticorg.junit.Assert.assertTrue;
9+
10+
importjava.io.ByteArrayOutputStream;
11+
importjava.io.File;
12+
importjava.io.PrintStream;
13+
importjava.nio.charset.StandardCharsets;
14+
importjava.nio.file.Files;
15+
importjava.nio.file.Path;
16+
importjava.nio.file.attribute.FileTime;
17+
importjava.nio.file.attribute.PosixFilePermission;
18+
importjava.util.EnumSet;
19+
importjava.util.Set;
20+
21+
importorg.junit.Assume;
22+
importorg.junit.Test;
23+
24+
publicclassLog4jMigrationsTest {
25+
26+
@Test
27+
publicvoidtestMigrateLog4jRemovesDirLogs() throwsException {
28+
Filefile = File.createTempFile("log4j2", ".properties");
29+
file.deleteOnExit();
30+
Files.writeString(file.toPath(), String.join(System.lineSeparator(),
31+
"rootLogger = ERROR,stdout,fout",
32+
"dir.logs = logs",
33+
"property.log.dir = logs",
34+
"appender.rolling.fileName = ${log.dir}/mirth.log"), StandardCharsets.UTF_8);
35+
36+
Log4jMigrations.migrateConfiguration(file);
37+
38+
StringfileContents = Files.readString(file.toPath(), StandardCharsets.UTF_8);
39+
assertFalse(fileContents.contains("dir.logs"));
40+
assertTrue(fileContents.contains("property.log.dir = logs"));
41+
assertTrue(fileContents.contains("appender.rolling.fileName = ${log.dir}/mirth.log"));
42+
}
43+
44+
@Test
45+
publicvoidtestMigrateLog4jDoesNotRewriteCleanFile() throwsException {
46+
Filefile = File.createTempFile("log4j2-clean", ".properties");
47+
file.deleteOnExit();
48+
Stringcontents = String.join(System.lineSeparator(),
49+
"rootLogger = ERROR,stdout,fout",
50+
"property.log.dir = logs",
51+
"appender.rolling.fileName = ${log.dir}/mirth.log");
52+
Files.writeString(file.toPath(), contents, StandardCharsets.UTF_8);
53+
54+
FileTimeexpectedModifiedTime = FileTime.fromMillis(1_700_000_000_000L);
55+
Files.setLastModifiedTime(file.toPath(), expectedModifiedTime);
56+
57+
Log4jMigrations.migrateConfiguration(file);
58+
59+
assertEquals(expectedModifiedTime, Files.getLastModifiedTime(file.toPath()));
60+
assertEquals(contents, Files.readString(file.toPath(), StandardCharsets.UTF_8));
61+
}
62+
63+
@Test
64+
publicvoidtestMigrateLog4jFailsGracefullyWithReadOnlyFile() throwsException {
65+
Filefile = File.createTempFile("log4j2-readonly", ".properties");
66+
file.deleteOnExit();
67+
Stringcontents = String.join(System.lineSeparator(),
68+
"rootLogger = ERROR,stdout,fout",
69+
"dir.logs = logs",
70+
"property.log.dir = logs");
71+
Pathpath = file.toPath();
72+
Files.writeString(path, contents, StandardCharsets.UTF_8);
73+
74+
Assume.assumeTrue(Files.getFileStore(path).supportsFileAttributeView("posix"));
75+
76+
ByteArrayOutputStreamerrBytes = newByteArrayOutputStream();
77+
PrintStreamoriginalErr = System.err;
78+
Set<PosixFilePermission> originalPermissions = Files.getPosixFilePermissions(path);
79+
80+
try {
81+
Files.setPosixFilePermissions(path, EnumSet.of(PosixFilePermission.OWNER_READ));
82+
assertFalse(Files.isWritable(path));
83+
System.setErr(newPrintStream(errBytes, true, StandardCharsets.UTF_8.name()));
84+
85+
Log4jMigrations.migrateConfiguration(file);
86+
} finally {
87+
Files.setPosixFilePermissions(path, originalPermissions);
88+
System.setErr(originalErr);
89+
}
90+
91+
StringerrOutput = errBytes.toString(StandardCharsets.UTF_8.name());
92+
assertTrue(errOutput.contains("Failed to migrate Log4j configuration"));
93+
assertEquals(contents, Files.readString(path, StandardCharsets.UTF_8));
94+
}
95+
96+
@Test
97+
publicvoidtestMigrateLog4jIgnoresMissingFile() throwsException {
98+
FileparentDir = Files.createTempDirectory("log4j2-missing").toFile();
99+
parentDir.deleteOnExit();
100+
Filefile = newFile(parentDir, "missing-log4j2.properties");
101+
102+
assertFalse(file.exists());
103+
104+
Log4jMigrations.migrateConfiguration(file);
105+
106+
assertFalse(file.exists());
107+
}
108+
}

‎server/test/com/mirth/connect/server/launcher/MirthLauncherTest.java‎

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)