Preserve Log4j 1 lookups when converting a properties configuration - #4353
kalayciburak wants to merge 3 commits into
Conversation
The converter shared the runtime parser, so ${...} was resolved against
the current JVM and the output captured host system properties. Rewrite
file-defined names to configuration properties and other names to
${sys:name}. The runtime factory still resolves variables.
Fixes apache#4348
Signed-off-by: Burak KALAYCI <kalayciburak1996@gmail.com>
Signed-off-by: Burak KALAYCI <kalayciburak1996@gmail.com>
ramanathan1504
left a comment
There was a problem hiding this comment.
The converter now writes ${sys:user.home} instead of the home directory of the machine that ran it, and the new test fails on 2.x without the change.
Can translateLookups in Log4j1ConfigurationParser turn every ${name} into ${sys:name}? Log4j 1 reads system properties before the file, and ${sys:app.dir} falls back to the <Property> when -Dapp.dir is not set, so isDefinedProperty can go. The log4j.threshold branch for a value with ${ also needs a test in Log4j1ConfigurationConverterLookupTest.
| if (isDefinedProperty(key)) { | ||
| translated.append("${").append(key).append('}'); | ||
| } else { | ||
| translated.append("${sys:").append(key).append('}'); | ||
| } |
There was a problem hiding this comment.
Log4j 1 checks system properties before the file. ${sys:app.dir} does the same and falls back to the <Property>, while ${app.dir} ignores -Dapp.dir.
| if (isDefinedProperty(key)) { | |
| translated.append("${").append(key).append('}'); | |
| } else { | |
| translated.append("${sys:").append(key).append('}'); | |
| } | |
| translated.append("${sys:").append(key).append('}'); |
|
|
||
| private boolean isDefinedProperty(final String key) { | ||
| return !key.startsWith("log4j.") | ||
| && !key.equals(ROOTCATEGORY) | ||
| && !key.equals(ROOTLOGGER) | ||
| && properties.getProperty(key) != null; | ||
| } |
There was a problem hiding this comment.
With every name mapped to ${sys:...}, this method has no caller.
| private boolean isDefinedProperty(final String key) { | |
| return !key.startsWith("log4j.") | |
| && !key.equals(ROOTCATEGORY) | |
| && !key.equals(ROOTLOGGER) | |
| && properties.getProperty(key) != null; | |
| } |
| + "log4j.appender.FILE.File=${app.dir}/app.log\n"); | ||
|
|
||
| assertFalse(xml.contains(home), xml); | ||
| assertTrue(xml.contains("${app.dir}/app.log"), xml); |
There was a problem hiding this comment.
This assert fails after the two changes above. The file property now reads through ${sys:app.dir}.
| assertTrue(xml.contains("${app.dir}/app.log"), xml); | |
| assertTrue(xml.contains("${sys:app.dir}/app.log"), xml); |
|
|
||
| assertTrue(xml.contains(home + "/logs/app.log"), xml); | ||
| assertFalse(xml.contains("${sys:user.home}"), xml); | ||
| } |
There was a problem hiding this comment.
Nothing covers the threshold branch for a value with ${. This test fails if that branch is removed.
| } | |
| } | |
| @Test | |
| public void thresholdLookupIsKept() throws Exception { | |
| final String xml = convert("log4j.rootLogger=INFO, FILE\n" | |
| + "log4j.threshold=${lvl}\n" | |
| + "log4j.appender.FILE=org.apache.log4j.FileAppender\n" | |
| + "log4j.appender.FILE.File=app.log\n"); | |
| assertTrue(xml.contains("level=\"${sys:lvl}\""), xml); | |
| } |
Log4j 1 reads system properties before the file, and ${sys:name} falls
back to a configuration property when the system property is unset.
Drop isDefinedProperty and cover the threshold lookup.
Signed-off-by: Burak KALAYCI <kalayciburak1996@gmail.com>
|
yes, every name is ${sys:name} now. dropped isDefinedProperty and added the threshold test. |
Log4j1ConfigurationConvertersharesLog4j1ConfigurationParserwith the runtime factory.getPropertycallsOptionConverter.substVars, which resolves each${...}against the current JVM before the value is written. A converted file therefore captures host system properties (user.home, paths, anything set with-D) and loses the indirection.The converter now rewrites every
${name}to${sys:name}instead of resolving it. Log4j 1 reads system properties before the file, and${sys:name}falls back to a configuration<Property>when-Dnameis not set.<Property>${sys:name}Log4j1ConfigurationFactorystill uses the default parser and resolves variables.Fixes #4348
Checklist
2.xbranch if you are targeting Log4j 2; usemainotherwisesrc/changelog/.2.x.xdirectory./mvnw verifywas not run.Tests
Executed with
JAVA_HOMEset to Java 17:./mvnw -pl log4j-1.2-api -am -Dtest=Log4j1ConfigurationConverterLookupTest -Dsurefire.failIfNoSpecifiedTests=false test- 4 tests, 0 failures (includes the threshold lookup)./mvnw -pl log4j-1.2-api spotless:check- clean