Skip to content

Commit bbf0117

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

4 files changed

Lines changed: 145 additions & 59 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) Mirth Corporation. All rights reserved.
3+
*
4+
* http://www.mirthcorp.com
5+
*
6+
* The software in this package is published under the terms of the MPL license a copy of which has
7+
* been included with this distribution in the LICENSE.txt file.
8+
*/
9+
10+
package com.mirth.connect.server.launcher;
11+
12+
import java.io.File;
13+
import java.io.IOException;
14+
import java.nio.charset.StandardCharsets;
15+
import java.util.List;
16+
17+
import org.apache.commons.io.FileUtils;
18+
19+
public class Log4jMigrations {
20+
private static final String INVALID_LOG4J_PROPERTY = "dir.logs";
21+
22+
private Log4jMigrations() {}
23+
24+
public static void migrateConfiguration(File propertiesFile) {
25+
if (!propertiesFile.exists() || !propertiesFile.isFile()) {
26+
return;
27+
}
28+
29+
try {
30+
List<String> lines = FileUtils.readLines(propertiesFile, StandardCharsets.UTF_8);
31+
if (stripDirLogs(lines)) {
32+
FileUtils.writeLines(propertiesFile, StandardCharsets.UTF_8.name(), lines, System.lineSeparator(), false);
33+
}
34+
} catch (IOException e) {
35+
System.err.println("Failed to migrate Log4j configuration: " + propertiesFile.getAbsolutePath());
36+
e.printStackTrace();
37+
}
38+
}
39+
40+
private static boolean stripDirLogs(List<String> lines) {
41+
return lines.removeIf(line -> isPropertyLine(line, INVALID_LOG4J_PROPERTY));
42+
}
43+
44+
private static boolean isPropertyLine(String line, String propertyName) {
45+
String trimmedLine = line.trim();
46+
int equalsIndex = trimmedLine.indexOf('=');
47+
return equalsIndex >= 0 && trimmedLine.substring(0, equalsIndex).trim().equals(propertyName);
48+
}
49+
}

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
import java.io.IOException;
1616
import java.net.URL;
1717
import java.net.URLClassLoader;
18-
import java.nio.charset.StandardCharsets;
1918
import java.util.ArrayList;
2019
import java.util.Collection;
2120
import java.util.List;
@@ -47,7 +46,6 @@ public class MirthLauncher {
4746
private static final String[] 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-
private static final String INVALID_LOG4J_PROPERTY = "dir.logs";
5149

5250
private static String appDataDir = null;
5351

@@ -56,7 +54,7 @@ public class MirthLauncher {
5654
public static void main(String[] args) {
5755
JarFile mirthClientCoreJarFile = null;
5856
try {
59-
sanitizeLog4jConfiguration(new File(LOG4J_PROPERTIES_FILE));
57+
Log4jMigrations.migrateConfiguration(new File(LOG4J_PROPERTIES_FILE));
6058

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

136-
private static void sanitizeLog4jConfiguration(File propertiesFile) {
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 (IOException e) {
147-
System.err.println("Failed to sanitize Log4j configuration: " + propertiesFile.getAbsolutePath());
148-
e.printStackTrace();
149-
}
150-
}
151-
152-
private static boolean isInvalidLog4jPropertyLine(String line) {
153-
String trimmedLine = line.trim();
154-
int equalsIndex = trimmedLine.indexOf('=');
155-
return equalsIndex >= 0 && trimmedLine.substring(0, equalsIndex).trim().equals(INVALID_LOG4J_PROPERTY);
156-
}
157-
158134
// if we have an uninstall file, uninstall the listed extensions
159135
private static void uninstallPendingExtensions() throws Exception {
160136
File extensionsDir = new File(EXTENSIONS_DIR);
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.mirth.connect.server.launcher;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
import static org.junit.Assert.assertTrue;
6+
7+
import java.io.ByteArrayOutputStream;
8+
import java.io.File;
9+
import java.io.PrintStream;
10+
import java.nio.charset.StandardCharsets;
11+
import java.nio.file.Files;
12+
import java.nio.file.attribute.FileTime;
13+
14+
import org.junit.Test;
15+
16+
public class Log4jMigrationsTest {
17+
18+
@Test
19+
public void testMigrateLog4jRemovesDirLogs() throws Exception {
20+
File file = File.createTempFile("log4j2", ".properties");
21+
file.deleteOnExit();
22+
Files.writeString(file.toPath(), String.join(System.lineSeparator(),
23+
"rootLogger = ERROR,stdout,fout",
24+
"dir.logs = logs",
25+
"property.log.dir = logs",
26+
"appender.rolling.fileName = ${log.dir}/mirth.log"), StandardCharsets.UTF_8);
27+
28+
Log4jMigrations.migrateConfiguration(file);
29+
30+
String fileContents = Files.readString(file.toPath(), StandardCharsets.UTF_8);
31+
assertFalse(fileContents.contains("dir.logs"));
32+
assertTrue(fileContents.contains("property.log.dir = logs"));
33+
assertTrue(fileContents.contains("appender.rolling.fileName = ${log.dir}/mirth.log"));
34+
}
35+
36+
@Test
37+
public void testMigrateLog4jDoesNotRewriteCleanFile() throws Exception {
38+
File file = File.createTempFile("log4j2-clean", ".properties");
39+
file.deleteOnExit();
40+
String contents = String.join(System.lineSeparator(),
41+
"rootLogger = ERROR,stdout,fout",
42+
"property.log.dir = logs",
43+
"appender.rolling.fileName = ${log.dir}/mirth.log");
44+
Files.writeString(file.toPath(), contents, StandardCharsets.UTF_8);
45+
46+
FileTime expectedModifiedTime = FileTime.fromMillis(1_700_000_000_000L);
47+
Files.setLastModifiedTime(file.toPath(), expectedModifiedTime);
48+
49+
Log4jMigrations.migrateConfiguration(file);
50+
51+
assertEquals(expectedModifiedTime, Files.getLastModifiedTime(file.toPath()));
52+
assertEquals(contents, Files.readString(file.toPath(), StandardCharsets.UTF_8));
53+
}
54+
55+
@Test
56+
public void testMigrateLog4jFailsGracefullyWithReadOnlyFile() throws Exception {
57+
File file = File.createTempFile("log4j2-readonly", ".properties");
58+
file.deleteOnExit();
59+
String contents = String.join(System.lineSeparator(),
60+
"rootLogger = ERROR,stdout,fout",
61+
"dir.logs = logs",
62+
"property.log.dir = logs");
63+
Files.writeString(file.toPath(), contents, StandardCharsets.UTF_8);
64+
65+
ByteArrayOutputStream errBytes = new ByteArrayOutputStream();
66+
PrintStream originalErr = System.err;
67+
68+
try {
69+
assertTrue(file.setWritable(false, false));
70+
System.setErr(new PrintStream(errBytes, true, StandardCharsets.UTF_8.name()));
71+
72+
Log4jMigrations.migrateConfiguration(file);
73+
} finally {
74+
file.setWritable(true, false);
75+
System.setErr(originalErr);
76+
}
77+
78+
String errOutput = errBytes.toString(StandardCharsets.UTF_8.name());
79+
assertTrue(errOutput.contains("Failed to Migrate Log4j configuration"));
80+
assertEquals(contents, Files.readString(file.toPath(), StandardCharsets.UTF_8));
81+
}
82+
83+
@Test
84+
public void testMigrateLog4jIgnoresMissingFile() throws Exception {
85+
File parentDir = Files.createTempDirectory("log4j2-missing").toFile();
86+
parentDir.deleteOnExit();
87+
File file = new File(parentDir, "missing-log4j2.properties");
88+
89+
assertFalse(file.exists());
90+
91+
Log4jMigrations.migrateConfiguration(file);
92+
93+
assertFalse(file.exists());
94+
}
95+
}

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

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

0 commit comments

Comments
 (0)