1+ // SPDX-License-Identifier: MPL-2.0
2+ // SPDX-FileCopyrightText: 2026 Mitch Gaffigan <mitch@gaffigan.net>
3+
4+ package com .mirth .connect .server .launcher ;
5+
6+ import static org .junit .Assert .assertEquals ;
7+ import static org .junit .Assert .assertFalse ;
8+ import static org .junit .Assert .assertTrue ;
9+
10+ import java .io .ByteArrayOutputStream ;
11+ import java .io .File ;
12+ import java .io .PrintStream ;
13+ import java .nio .charset .StandardCharsets ;
14+ import java .nio .file .Files ;
15+ import java .nio .file .Path ;
16+ import java .nio .file .attribute .FileTime ;
17+ import java .nio .file .attribute .PosixFilePermission ;
18+ import java .util .EnumSet ;
19+ import java .util .Set ;
20+
21+ import org .junit .Assume ;
22+ import org .junit .Test ;
23+
24+ public class Log4jMigrationsTest {
25+
26+ @ Test
27+ public void testMigrateLog4jRemovesDirLogs () throws Exception {
28+ File file = 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+ String fileContents = 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+ public void testMigrateLog4jDoesNotRewriteCleanFile () throws Exception {
46+ File file = File .createTempFile ("log4j2-clean" , ".properties" );
47+ file .deleteOnExit ();
48+ String contents = 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+ FileTime expectedModifiedTime = 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+ public void testMigrateLog4jFailsGracefullyWithReadOnlyFile () throws Exception {
65+ File file = File .createTempFile ("log4j2-readonly" , ".properties" );
66+ file .deleteOnExit ();
67+ String contents = String .join (System .lineSeparator (),
68+ "rootLogger = ERROR,stdout,fout" ,
69+ "dir.logs = logs" ,
70+ "property.log.dir = logs" );
71+ Path path = file .toPath ();
72+ Files .writeString (path , contents , StandardCharsets .UTF_8 );
73+
74+ Assume .assumeTrue (Files .getFileStore (path ).supportsFileAttributeView ("posix" ));
75+
76+ ByteArrayOutputStream errBytes = new ByteArrayOutputStream ();
77+ PrintStream originalErr = 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 (new PrintStream (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+ String errOutput = 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+ public void testMigrateLog4jIgnoresMissingFile () throws Exception {
98+ File parentDir = Files .createTempDirectory ("log4j2-missing" ).toFile ();
99+ parentDir .deleteOnExit ();
100+ File file = new File (parentDir , "missing-log4j2.properties" );
101+
102+ assertFalse (file .exists ());
103+
104+ Log4jMigrations .migrateConfiguration (file );
105+
106+ assertFalse (file .exists ());
107+ }
108+ }
0 commit comments