Codebase list apache-log4j2 / 7507091
Merge branch 'bullseye' into buster Markus Koschany 2 years ago
101 changed file(s) with 1178 addition(s) and 682 deletion(s). Raw diff Collapse all Expand all
3030 uses: actions/checkout@v2
3131
3232 # JDK 11 is needed for the build.
33 # Search `maven-toolchains-plugin` usages for details.
3334 - name: Set up JDK 11
3435 uses: actions/setup-java@v2.4.0
3536 with:
4950 java-package: jdk
5051 architecture: x64
5152 cache: maven
52
53 - name: Set up Maven caching
54 uses: actions/cache@v2
55 with:
56 path: ~/.m2/repository
57 key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
58 restore-keys: ${{ runner.os }}-maven-
5953
6054 - name: Build with Maven
6155 shell: bash
0 # Licensed to the Apache Software Foundation (ASF) under one or more
1 # contributor license agreements. See the NOTICE file distributed with
2 # this work for additional information regarding copyright ownership.
3 # The ASF licenses this file to You under the Apache license, Version 2.0
4 # (the "License"); you may not use this file except in compliance with
5 # the License. You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the license for the specific language governing permissions and
13 # limitations under the license.
14
15 name: build
16
17 on: [ push, pull_request ]
18
19 jobs:
20 build:
21
22 runs-on: ${{ matrix.os }}
23
24 strategy:
25 matrix:
26 os: [ ubuntu-latest, windows-latest, macos-latest ]
27
28 steps:
29
30 - name: Checkout repository
31 uses: actions/checkout@v2
32
33 # JDK 11 is needed for the build.
34 # Search `maven-toolchains-plugin` usages for details.
35 - name: Setup JDK 11
36 uses: actions/setup-java@v2.4.0
37 with:
38 distribution: temurin
39 java-version: 11
40 java-package: jdk
41 architecture: x64
42 cache: maven
43
44 # JDK 8 is needed for the build, and it is the primary bytecode target.
45 # Hence, JDK 8 is set up after 11, so that JAVA_HOME used by Maven during build will point to 8.
46 - name: Setup JDK 8
47 uses: actions/setup-java@v2.3.0
48 with:
49 distribution: temurin
50 java-version: 8
51 java-package: jdk
52 architecture: x64
53 cache: maven
54
55 - name: Inspect environment (Linux)
56 if: runner.os == 'Linux'
57 run: env | grep '^JAVA'
58
59 - name: Inspect environment (Windows)
60 if: runner.os == 'Windows'
61 run: set java
62
63 - name: Inspect environment (MacOS)
64 if: runner.os == 'macOS'
65 run: env | grep '^JAVA'
66
67 - name: Build with Maven
68 timeout-minutes: 60
69 shell: bash
70 run: |
71 ./mvnw \
72 --show-version --batch-mode --errors --no-transfer-progress \
73 -DtrimStackTrace=false \
74 -Dsurefire.rerunFailingTestsCount=2 \
75 -Dlog4j2.junit.fileCleanerSleepPeriodMillis=1000 \
76 --global-toolchains ".github/workflows/maven-toolchains.xml" \
77 verify
+0
-106
.github/workflows/main.yml less more
0 # Licensed to the Apache Software Foundation (ASF) under one or more
1 # contributor license agreements. See the NOTICE file distributed with
2 # this work for additional information regarding copyright ownership.
3 # The ASF licenses this file to You under the Apache license, Version 2.0
4 # (the "License"); you may not use this file except in compliance with
5 # the License. You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the license for the specific language governing permissions and
13 # limitations under the license.
14
15 name: CI
16
17 on: [push, pull_request]
18
19 jobs:
20 build:
21
22 runs-on: ${{ matrix.os }}
23
24 strategy:
25 matrix:
26 os: [ubuntu-latest, windows-latest, macos-latest]
27
28 steps:
29
30 - name: Checkout repository
31 uses: actions/checkout@v2
32
33 - name: Setup Maven caching
34 uses: actions/cache@v2
35 with:
36 path: ~/.m2/repository
37 key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
38 restore-keys: |
39 ${{ runner.os }}-maven-
40
41 - name: Setup JDK 11
42 uses: actions/setup-java@v2.4.0
43 with:
44 distribution: 'temurin'
45 java-version: 11
46 java-package: jdk
47 architecture: x64
48
49 - name: Setup JDK 8
50 uses: actions/setup-java@v2.3.0
51 with:
52 distribution: 'temurin'
53 java-version: 8
54 java-package: jdk
55 architecture: x64
56 cache: 'maven'
57
58 - name: Inspect environment (Linux)
59 if: runner.os == 'Linux'
60 run: env | grep '^JAVA'
61
62 - name: Build with Maven (Linux)
63 timeout-minutes: 60
64 if: runner.os == 'Linux'
65 continue-on-error: true
66 run: ./mvnw -V -B --no-transfer-progress -e -DtrimStackTrace=false -Dmaven.test.failure.ignore=true -Dsurefire.rerunFailingTestsCount=1 --global-toolchains .github/workflows/maven-toolchains.xml verify
67
68 - name: Inspect environment (Windows)
69 if: runner.os == 'Windows'
70 run: set java
71
72 - name: Build with Maven (Windows)
73 timeout-minutes: 60
74 if: runner.os == 'Windows'
75 continue-on-error: true
76 run: ./mvnw -V -B --no-transfer-progress -e "-DtrimStackTrace=false" "-Dmaven.test.failure.ignore=true" "-Dsurefire.rerunFailingTestsCount=1" "-Dlog4j2.junit.fileCleanerSleepPeriodMillis=1000" --global-toolchains ".github\workflows\maven-toolchains.xml" verify
77
78 - name: Inspect environment (MacOS)
79 if: runner.os == 'macOS'
80 run: env | grep '^JAVA'
81
82 - name: Build with Maven (MacOS)
83 timeout-minutes: 60
84 if: runner.os == 'macOS'
85 continue-on-error: true
86 run: ./mvnw -V -B --no-transfer-progress -e -DtrimStackTrace=false -Dmaven.test.failure.ignore=true -Dsurefire.rerunFailingTestsCount=1 --global-toolchains .github/workflows/maven-toolchains.xml verify
87
88 - name: Publish Test Results
89 # If the CI run is not initiated from the primary repository, it is highly likely that this is a PR from a user who doesn't have commit rights.
90 # Hence, skip this step to avoid permission failures.
91 if: github.repository == 'apache/logging-log4j2'
92 uses: scacap/action-surefire-report@v1
93 with:
94 github_token: ${{ secrets.GITHUB_TOKEN }}
95 check_name: Test Report (${{ matrix.os }})
96 report_paths: '**/*-reports/TEST-*.xml'
97
98 - name: Upload Test Reports
99 # If the CI run is not initiated from the primary repository, it is highly likely that this is a PR from a user who doesn't have commit rights.
100 # Hence, skip this step to avoid permission failures.
101 if: github.repository == 'apache/logging-log4j2'
102 uses: actions/upload-artifact@v2
103 with:
104 name: test-reports-${{ matrix.os }}
105 path: '**/*-reports'
0 <!---
1 Licensed to the Apache Software Foundation (ASF) under one or more
2 contributor license agreements. See the NOTICE file distributed with
3 this work for additional information regarding copyright ownership.
4 The ASF licenses this file to You under the Apache License, Version 2.0
5 (the "License"); you may not use this file except in compliance with
6 the License. You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 -->
16 The Apache code of conduct page is [https://www.apache.org/foundation/policies/conduct.html](https://www.apache.org/foundation/policies/conduct.html).
99
1010 ## Pull Requests on Github
1111
12 By sending a pull request you grant the Apache Software Foundation sufficient rights to use and release the submitted
13 work under the Apache license. You grant the same rights (copyright license, patent license, etc.) to the
14 Apache Software Foundation as if you have signed a Contributor License Agreement. For contributions that are
12 By sending a pull request you grant the Apache Software Foundation sufficient rights to use and release the submitted
13 work under the Apache license. You grant the same rights (copyright license, patent license, etc.) to the
14 Apache Software Foundation as if you have signed a Contributor License Agreement. For contributions that are
1515 judged to be non-trivial, you will be asked to actually signing a Contributor License Agreement.
1616
1717 ## Usage
6868
6969 ## Requirements
7070
71 Log4j 2.4 and greater requires Java 7, versions 2.0-alpha1 to 2.3 required Java 6.
72 Some features require optional dependencies; the documentation for these features specifies the dependencies.
71 * Java 8 users should use 2.17.0 or greater.
72 * Java 7 users should use 2.12.2.
73 * Java 6 users should use 2.3.
74 * Some features require optional dependencies; the documentation for these features specifies the dependencies.
7375
7476 ## License
7577
7981
8082 [How to download Log4j](http://logging.apache.org/log4j/2.x/download.html),
8183 and [how to use it from Maven, Ivy and Gradle](http://logging.apache.org/log4j/2.x/maven-artifacts.html).
82 You can access the latest development snapshot by using the Maven repository `https://repository.apache.org/snapshots`,
84 You can access the latest development snapshot by using the Maven repository `https://repository.apache.org/snapshots`,
8385 see [Snapshot builds](https://logging.apache.org/log4j/2.x/maven-artifacts.html#Snapshot_builds).
8486
8587 ## Issue Tracking
8688
87 Issues, bugs, and feature requests should be submitted to the
89 Issues, bugs, and feature requests should be submitted to the
8890 [JIRA issue tracking system for this project](https://issues.apache.org/jira/browse/LOG4J2).
8991
90 Pull request on GitHub are welcome, but please open a ticket in the JIRA issue tracker first, and mention the
92 Pull request on GitHub are welcome, but please open a ticket in the JIRA issue tracker first, and mention the
9193 JIRA issue in the Pull Request.
9294
9395 ## Building From Source
1313 See the License for the specific language governing permissions and
1414 limitations under the License.
1515 -->
16 # Apache Log4j 2.17.0 Release Notes
16 # Apache Log4j 2.17.1 Release Notes
1717
18 The Apache Log4j 2 team is pleased to announce the Log4j 2.17.0 release!
18 The Apache Log4j 2 team is pleased to announce the Log4j 2.17.1 release!
1919
2020 Apache Log4j is a well known framework for logging application behavior. Log4j 2 is an upgrade
2121 to Log4j that provides significant improvements over its predecessor, Log4j 1.x, and provides
3737 later. SLF4J-2.0.0 alpha releases are not fully supported. See https://issues.apache.org/jira/browse/LOG4J2-2975 and
3838 https://jira.qos.ch/browse/SLF4J-511.
3939
40 Some of the changes in Log4j 2.17.0 include:
40 Some of the changes in Log4j 2.17.1 include:
4141
4242 * Disable recursive evaluation of Lookups during log event processing. Recursive evaluation is still allwoed while
4343 generating the configuration.
4444 * The JndiLookup, JndiContextSelector, and JMSAppender now require individual system properties to be enabled.
4545 * Removed support for the LDAP and LDAPS protocols via JNDI.
4646
47 The Log4j 2.17.0 API, as well as many core components, maintains binary compatibility with previous releases.
47 The Log4j 2.17.1 API, as well as many core components, maintains binary compatibility with previous releases.
4848
49 ## GA Release 2.17.0
49 ## GA Release 2.17.1
5050
5151 Changes in this version include:
5252
5353
5454 ### Fixed Bugs
55 * [LOG4J2-3230](https://issues.apache.org/jira/browse/LOG4J2-3230):
56 Fix string substitution recursion.
57 * [LOG4J2-3242](https://issues.apache.org/jira/browse/LOG4J2-3242):
58 Limit JNDI to the java protocol only. JNDI will remain disabled by default. Rename JNDI enablement property from
59 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
60 * [LOG4J2-3242](https://issues.apache.org/jira/browse/LOG4J2-3242):
61 Limit JNDI to the java protocol only. JNDI will remain disabled by default. The enablement
62 property has been renamed to 'log4j2.enableJndiJava'
63 * [LOG4J2-3241](https://issues.apache.org/jira/browse/LOG4J2-3241):
64 Do not declare log4j-api-java9 and log4j-core-java9 as dependencies as it causes problems with the
65 Maven enforcer plugin.
66 * [LOG4J2-3247](https://issues.apache.org/jira/browse/LOG4J2-3247):
67 PropertiesConfiguration.parseAppenderFilters NPE when parsing properties file filters.
68 * [LOG4J2-3249](https://issues.apache.org/jira/browse/LOG4J2-3249):
69 Log4j 1.2 bridge for Syslog Appender defaults to port 512 instead of 514.
70 * [LOG4J2-3237](https://issues.apache.org/jira/browse/LOG4J2-3237):
71 Log4j 1.2 bridge API hard codes the Syslog protocol to TCP.
55 * [LOG4J2-3290](https://issues.apache.org/jira/browse/LOG4J2-3290):
56 Remove unused method.
57 * [LOG4J2-3292](https://issues.apache.org/jira/browse/LOG4J2-3292):
58 ExtendedLoggerWrapper.logMessage no longer double-logs when location is requested.
59 * [LOG4J2-3289](https://issues.apache.org/jira/browse/LOG4J2-3289):
60 log4j-to-slf4j no longer re-interpolates formatted message contents.
61 * [LOG4J2-3204](https://issues.apache.org/jira/browse/LOG4J2-3204):
62 Correct SpringLookup package name in Interpolator. Thanks to Francis-FY.
63 * [LOG4J2-3284](https://issues.apache.org/jira/browse/LOG4J2-3284):
64 log4j-to-slf4j takes the provided MessageFactory into account Thanks to Michael Vorburger.
65 * [LOG4J2-3264](https://issues.apache.org/jira/browse/LOG4J2-3264):
66 Fix MapLookup to lookup MapMessage before DefaultMap Thanks to Yanming Zhou.
67 * [LOG4J2-3274](https://issues.apache.org/jira/browse/LOG4J2-3274):
68 Buffered I/O checked had inverted logic in RollingFileAppenderBuidler. Thanks to Faisal Khan Thayub Khan.
69 * [](https://issues.apache.org/jira/browse/LOG4J2-3274):
70 Fix NPE when input is null in StrSubstitutor.replace(String, Properties).
71 * [LOG4J2-3270](https://issues.apache.org/jira/browse/LOG4J2-3270):
72 Lookups with no prefix only read values from the configuration properties as expected.
73 * [LOG4J2-3256](https://issues.apache.org/jira/browse/LOG4J2-3256):
74 Reduce ignored package scope of KafkaAppender. Thanks to Lee Dongjin.
7275
7376
7477 ---
7578
76 Apache Log4j 2.17.0 requires a minimum of Java 8 to build and run. Log4j 2.12.1 is the last release to support
79 Apache Log4j 2.17.1 requires a minimum of Java 8 to build and run. Log4j 2.12.1 is the last release to support
7780 Java 7. Java 7 is not longer supported by the Log4j team.
7881
7982 For complete information on Apache Log4j 2, including instructions on how to submit bug
8184
8285 https://logging.apache.org/log4j/2.x/
8386
87 ---
88
89 Earlier release notes are accessible in [Release History](https://logging.apache.org/log4j/2.x/changes-report.html).
0 apache-log4j2 (2.17.0-1~deb10u1) buster-security; urgency=high
1
2 * Team upload.
3 * Backport 2.17.0-1 to Buster and fix CVE-2021-45105. (Closes: #1001891)
4
5 -- Markus Koschany <apo@debian.org> Sat, 18 Dec 2021 18:56:50 +0100
0 apache-log4j2 (2.17.1-1~deb10u1) buster; urgency=medium
1
2 * Team upload.
3 * Backport 2.17.1 to Buster and fix CVE-2021-44832: remote code execution
4 vulnerability but requires permission to modify the logging configuration.
5
6 -- Markus Koschany <apo@debian.org> Fri, 11 Feb 2022 20:55:04 +0100
7
8 apache-log4j2 (2.17.1-1) unstable; urgency=high
9
10 * Team upload.
11 * New upstream version 2.17.1.
12 - Fix CVE-2021-44832:
13 Apache Log4j2 is vulnerable to a remote code execution
14 (RCE) attack where an attacker with permission to modify the logging
15 configuration file can construct a malicious configuration using a JDBC
16 Appender with a data source referencing a JNDI URI which can execute
17 remote code. This issue is fixed by limiting JNDI data source names to
18 the java protocol.
19 Thanks to Salvatore Bonaccorso for the report. (Closes: #1002813)
20
21 -- Markus Koschany <apo@debian.org> Wed, 29 Dec 2021 11:44:21 +0100
622
723 apache-log4j2 (2.17.0-1) unstable; urgency=high
824
0 I'd like to go into detail on some of the changes in 2.17.0, why they're so important, and how they relate to both [CVE-2021-45046](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-45046) and [CVE-2021-45105](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-45105).
1
2 The substitution of untrusted log data allowed access to code that was never meant to be exposed. Lookups should be triggered only by configuration and the logging framework (including custom layout/appender/etc plugins). Not by user-provided inputs.
3
4 ## 1. PatternLayout rendered message substitution
5
6 Substitution within the contents of a rendered log message provided the largest opportunity for untrusted inputs to be evaluated by the string replacement system. This was [removed (by default) in 2.15.0](https://github.com/apache/logging-log4j2/commit/001aaada7dab82c3c09cde5f8e14245dc9d8b454), and [removed entirely in 2.16.0](https://github.com/apache/logging-log4j2/commit/27972043b76c9645476f561c5adc483dec6d3f5d) after public disclosure.
7
8 ## 2. Recursive Substitution Within Lookups
9
10 Despite message replacements being removed in 2.15.0, other pathways still exist (based on the configuration) which can evaluate untrusted user-provided values. For example, a `PatternLayout` using the pattern `%p %t %c $${ctx:userAgent} %m%n`[1][2] would re-evaluate `config.getStrSubstitutor().replace(event, " ${ctx:userAgent} ")` for each log-event due to the [LiteralPatternConverter](https://github.com/apache/logging-log4j2/blob/cffe58f6a433ea1ab60ceb129d4c9b3377acda1d/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LiteralPatternConverter.java#L62-L65). The substitutor would evaluate recursively, and invoke unexpected lookups. At worst triggering something like jndi or an exception preventing logging, but even resulting in logging that doesn't match the literal data input is a very serious bug. For example if `MDC.put("userAgent", "${lower:FOO}")` then `${ctx:userAgent}` would evaluate to literal `foo` instead of literal `${lower:FOO}`
11
12 This is not isolated to the PatternLayout, rather anywhere lookups in which the result contained user-provided data. e.g. `${ctx:USER_PROVIDED}`, `${event:Message}`. For example `<Routes pattern="$${ctx:userAgent}">` would be impacted as well.
13
14 In 2.17.0 we resolved this class of issues with a simple idea:
15 Recursive evaluation is allowed while parsing the configuration (no user-input/LogEvent data is present, and configuration breaks are to be avoided) however when log-events themselves are being evaluated we _never_ recursively evaluate substitutions. [That's it](https://github.com/apache/logging-log4j2/commit/806023265f8c905b2dd1d81fd2458f64b2ea0b5e). That means when `${lower:${event:Message}}` is evaluated for message `Hello, World!` the result is `hello, world!`, and when evaluated for `${java:version}` the result is the string literal `${java:version}` which itself is not evaluated.
16
17 -----
18
19 1. Note that I used `$${ctx:userAgent}` so the value itself is not evaluated, however even `${ctx:userAgent}` may be vulnerable because it's not likely that a thread-context value is set when the configuration itself is evaluated, in which case no replacement occurs and the value is equivalent to the `$${ctx:userAgent}` example.
20 2. Please use `%X{userAgent}` in the PatternLayout instead of `${ctx:userAgent}`. It's safer, more obvious, and more efficient. LogEventPatternConverters are pluggable, don't rely on stringly typed data, and are created when the pattern is parsed, not re-scanned on a per-LogEvent basis.
21
22 ## 3. Impact Upon Configuration
23
24 There are certainly cases in which this change impacts existing configurations, however I believe that the safety is well worth the trade-off.
25 For example, [this test configuration](https://github.com/apache/logging-log4j2/commit/806023265f8c905b2dd1d81fd2458f64b2ea0b5e#diff-f13a31d919bf2e7169ca936948aeef1cda6089f295be684d71f2bd5709248475) had to be updated because routes are created based on a log-event, thus we cannot allow recursive evaluation. An argument can be made that the inputs must already be sanitized to avoid path traversal, however the filename isn't the only place these lookups can be evaluated, and the type of sanitization differs dramatically between validating against string replacement data, and validating against unexpected path-based attacks.
26
27 In a perfect world I'd love to swap the types used for substitution to avoid stringly matching anything, using the type system to differentiate between trusted lookups and user-input data, however in such a large, widely-used framework, that's not something we can do, certainly not quickly or easily.
28
29 ### Configuration Impact: Examples
30
31 **Complex Lookups :heavy_check_mark: :heavy_check_mark: :heavy_check_mark:**
32
33 This example uses complex lookups based on the [ThreadContext](https://logging.apache.org/log4j/2.x/manual/thread-context.html) (aka MDC), however it continues to work as expected **and** prevents user-provided data from `key1` or `key2` from being substituted.
34
35 ```xml
36 <--
37 Note that lookups are all escaped to prevent them from being evaluated
38 immediately when the Pattern is constructed
39 -->
40 <PatternLayout pattern="%d %p %t %c $${lower:$${ctx:key1:-$${ctx:key2}}} %m%n"/>
41 ```
42
43
44 **Pattern Reuse Via Lookups :heavy_check_mark: :heavy_check_mark: :heavy_check_mark:**
45
46 This is not impacted either:
47
48 ```xml
49 <Properties>
50 <Property name="defaultPattern">%d %p %t %c %m%n</Property>
51 </Properties>
52 <Appenders>
53 <Console name="console">
54 <PatternLayout pattern="${defaultPattern}"/>
55 </Console>
56 </Appenders>
57 ```
58
59 **Lazy Pattern Lookups Which include Lazy Lookups :x::x::x:**
60
61 However, in this case, evaluation depends on a lazily-replaced property which itself is lazily evaluated:
62
63 ```xml
64 <Properties>
65 <Property name="messageFormat">$${event:Message}</Property>
66 </Properties>
67 <Appenders>
68 <Console name="console">
69 <PatternLayout pattern="%c $${messageFormat}%n"/>
70 </Console>
71 </Appenders>
72 ```
73
74 The upgrade to 2.17.0 would change the output for the following log line:
75
76 ```java
77 LogManager.getLogger(com.example.Main.class).info("example");
78 ```
79
80 ```diff
81 - com.example.Main example
82 + com.example.Main ${event:Message}
83 ```
84
85 This can be resolved by unescaping the property reference in the pattern, allowing the pattern itself to be fully evaluated when the configuration is loaded, but preventing message contents from being further interpolated due to the runtime-substitution protections.
86
87 Note that this example is contrived, and in practice one should use the `%m` pattern here rather than a lookup, however this example applies to a general shape of usage and some extrapolation may be required for your configuration.
88
89
90 ```diff
91 <Properties>
92 <Property name="messageFormat">$${event:Message}</Property>
93 </Properties>
94 <Appenders>
95 <Console name="console">
96 - <PatternLayout pattern="%c $${messageFormat}%n"/>
97 + <PatternLayout pattern="%c ${messageFormat}%n"/>
98 </Console>
99 </Appenders>
100 ```
101
102 **RoutingAppender with lazy property references in routes :x::x::x:**
103
104 RoutingAppender routes are lazily evaluated when they're needed, which means a LogEvent (thus potentially user-provided data) is available. Everything that could be represented before can still be done, however it's no longer possible to extract some pieces to shared properties.
105
106 Let's take the [example from the test liked above](https://github.com/apache/logging-log4j2/commit/806023265f8c905b2dd1d81fd2458f64b2ea0b5e#diff-f13a31d919bf2e7169ca936948aeef1cda6089f295be684d71f2bd5709248475)
107
108 ```xml
109 <Configuration status="WARN" name="RoutingTest">
110 <Properties>
111 <Property name="filename">target/routing1/routingtest-$${sd:type}.log</Property>
112 </Properties>
113 <Appenders>
114 <Routing name="Routing">
115 <Routes>
116 <Route>
117 <RollingFile name="Routing-${sd:type}" fileName="${filename}"
118 filePattern="target/routing1/test1-${sd:type}.%i.log.gz">
119 <PatternLayout>
120 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
121 </PatternLayout>
122 <SizeBasedTriggeringPolicy size="500" />
123 </RollingFile>
124 </Route>
125 </Routes>
126 </Routing>
127 </Appenders>
128 <Loggers>
129 <Root level="info">
130 <AppenderRef ref="Routing"/>
131 </Root>
132 </Loggers>
133 </Configuration>
134 ```
135
136 The reference to `fileName="${filename}"` is no longer evaluated recursively to `fileName="target/routing1/routingtest-${sd:type}.log"` however the `${sd:type}` is left as a string literal, not expanded as it was before.
137
138 The fix in this case is to inline the `fileName` property value into the `RollingFile` `filename` attribute, removing the extra`$` escaping the `${sd:type}` lookup like so:
139
140 ```diff
141 <Routing name="Routing">
142 <Routes>
143 <Route>
144 - <RollingFile name="Routing-${sd:type}" fileName="${filename}"
145 + <RollingFile name="Routing-${sd:type}" fileName="target/routing1/routingtest-${sd:type}.log"
146 filePattern="target/routing1/test1-${sd:type}.%i.log.gz">
147 <PatternLayout>
148 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
149 </PatternLayout>
150 <SizeBasedTriggeringPolicy size="500" />
151 </RollingFile>
152 </Route>
153 </Routes>
154 </Routing>
155 ```
0 This is a map of CVEs and Log4j *2* Versions.
1
2 | CVE | Affects | Fixed In | Java Required |
3 | -------------- | --------- | --------------- | --- |
4 | CVE-2021-45105 | 2.0-beta9 to 2.16.0, excluding 2.12.3 | 2.17.0<br>2.12.3<br>2.3.1 | Java 8<br>Java 7<br>Java 6 |
5 | CVE-2021-45046 | 2.0-beta9 to 2.15.0, excluding 2.12.2 | 2.16.0<br>2.12.2<br>2.3.1 | Java 8<br>Java 7<br>Java 6 |
6 | CVE-2021-44228 | 2.0-beta9 to 2.16.0, excluding 2.12.3 & 2.3.1 | 2.17.0<br>2.12.3<br>2.3.1 | Java 8<br>Java 7<br>Java 6 |
7 | CVE-2020-9488 | 2.0-alpha1 to 2.13.1 | 2.13.2<br>2.12.3 | Java 8<br>Java 7 |
8 | CVE-2017-5645 | 2.0-alpha1 to 2.8.1 | 2.8.2 | Java 7 |
9
10 This is a map of CVEs and Log4j *1* End-of-Life Versions.
11
12 | CVE | Affects | Fixed In | Java Required |
13 | -------------- | --------- | --------------- | --- |
14 | CVE-2019-17571 | 1.2 to 1.2.17 | Not fixed | Not fixed |
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-1.2-api</artifactId>
3232 }
3333
3434 @Override
35 public void start() {
36 filter.activateOptions();
37 }
38
39 @Override
4035 public Result filter(LogEvent event) {
4136 LoggingEvent loggingEvent = new LogEventAdapter(event);
4237 Filter next = filter;
5247 }
5348 return Result.NEUTRAL;
5449 }
50
51 /**
52 * Gets the actual filter.
53 *
54 * @return the actual filter.
55 * @since 2.17.1
56 */
57 public Filter getFilter() {
58 return filter;
59 }
60
61 @Override
62 public void start() {
63 filter.activateOptions();
64 }
5565 }
176176 final Filter filter, final boolean bufferedIo, boolean immediateFlush, final String fileName,
177177 final String level, final String maxSize, final String maxBackups) {
178178 org.apache.logging.log4j.core.Layout<?> fileLayout = null;
179 if (bufferedIo) {
179 if (!bufferedIo) {
180180 immediateFlush = true;
181181 }
182182 if (layout instanceof LayoutWrapper) {
2323 import java.util.HashMap;
2424 import java.util.List;
2525 import java.util.Map;
26 import java.util.Objects;
2627 import java.util.Properties;
2728 import java.util.SortedMap;
2829 import java.util.StringTokenizer;
329330 * Parse non-root elements, such non-root categories and renderers.
330331 */
331332 private void parseLoggers(Properties props) {
332 Enumeration enumeration = props.propertyNames();
333 Enumeration<?> enumeration = props.propertyNames();
333334 while (enumeration.hasMoreElements()) {
334 String key = (String) enumeration.nextElement();
335 String key = Objects.toString(enumeration.nextElement(), null);
335336 if (key.startsWith(CATEGORY_PREFIX) || key.startsWith(LOGGER_PREFIX)) {
336337 String loggerName = null;
337338 if (key.startsWith(CATEGORY_PREFIX)) {
3939 }
4040
4141 @Override
42 public Enumeration getAllAppenders() {
42 public Enumeration<Appender> getAllAppenders() {
4343 return Collections.enumeration(appenders.values());
4444 }
4545
1919 import org.apache.log4j.Level;
2020 import org.apache.logging.log4j.LogManager;
2121 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
2223 import org.apache.logging.log4j.util.LoaderUtil;
2324
2425 import java.io.InterruptedIOException;
289290 * @throws IllegalArgumentException if <code>val</code> is malformed.
290291 */
291292 public static String substVars(String val, Properties props) throws IllegalArgumentException {
292
293 StringBuilder sbuf = new StringBuilder();
294
295 int i = 0;
296 int j, k;
297
298 while (true) {
299 j = val.indexOf(DELIM_START, i);
300 if (j == -1) {
301 // no more variables
302 if (i == 0) { // this is a simple string
303 return val;
304 }
305 sbuf.append(val.substring(i, val.length()));
306 return sbuf.toString();
307 }
308 sbuf.append(val.substring(i, j));
309 k = val.indexOf(DELIM_STOP, j);
310 if (k == -1) {
311 throw new IllegalArgumentException('"' + val +
312 "\" has no closing brace. Opening brace at position " + j
313 + '.');
314 }
315 j += DELIM_START_LEN;
316 String key = val.substring(j, k);
317 // first try in System properties
318 String replacement = getSystemProperty(key, null);
319 // then try props parameter
320 if (replacement == null && props != null) {
321 replacement = props.getProperty(key);
322 }
323
324 if (replacement != null) {
325 // Do variable substitution on the replacement string
326 // such that we can solve "Hello ${x2}" as "Hello p1"
327 // the where the properties are
328 // x1=p1
329 // x2=${x1}
330 String recursiveReplacement = substVars(replacement, props);
331 sbuf.append(recursiveReplacement);
332 }
333 i = k + DELIM_STOP_LEN;
334 }
293 return StrSubstitutor.replace(val, props);
335294 }
336295
337296 public static org.apache.logging.log4j.Level convertLevel(String level,
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.config;
17
18 import org.apache.log4j.spi.Filter;
19 import org.apache.log4j.spi.LoggingEvent;
20
21 /**
22 * A test fixture used by {@code src/test/resources/LOG4J2-3247.properties}.
23 */
24 public class NeutralFilterFixture extends Filter {
25
26 @Override
27 public int decide(LoggingEvent event) {
28 return NEUTRAL;
29 }
30
31 }
2626 import org.apache.log4j.LogManager;
2727 import org.apache.log4j.Logger;
2828 import org.apache.log4j.bridge.AppenderAdapter;
29 import org.apache.log4j.bridge.FilterAdapter;
2930 import org.apache.log4j.spi.LoggingEvent;
3031 import org.apache.logging.log4j.core.Appender;
3132 import org.apache.logging.log4j.core.LoggerContext;
3233 import org.apache.logging.log4j.core.config.Configuration;
34 import org.apache.logging.log4j.core.filter.Filterable;
3335 import org.junit.Test;
3436
3537 /**
3840 public class PropertiesConfigurationTest {
3941
4042 @Test
43 public void testConfigureNullPointerException() throws Exception {
44 try (LoggerContext loggerContext = TestConfigurator.configure("target/test-classes/LOG4J2-3247.properties")) {
45 // [LOG4J2-3247] configure() should not throw an NPE.
46 Configuration configuration = loggerContext.getConfiguration();
47 assertNotNull(configuration);
48 Appender appender = configuration.getAppender("CONSOLE");
49 assertNotNull(appender);
50 }
51 }
52
53 @Test
4154 public void testFilter() throws Exception {
4255 try (LoggerContext loggerContext = TestConfigurator.configure("target/test-classes/LOG4J2-3247.properties")) {
43 // [LOG4J2-3247] configure() should not throw an NPE.
56 // LOG4J2-3281 PropertiesConfiguration.buildAppender not adding filters to appender
57 Configuration configuration = loggerContext.getConfiguration();
58 assertNotNull(configuration);
59 Appender appender = configuration.getAppender("CONSOLE");
60 assertNotNull(appender);
61 Filterable filterable = (Filterable) appender;
62 FilterAdapter filter = (FilterAdapter) filterable.getFilter();
63 assertNotNull(filter);
64 assertTrue(filter.getFilter() instanceof NeutralFilterFixture);
4465 }
4566 }
4667
+0
-29
log4j-1.2-api/src/test/java/org/apache/log4j/config/ZeroFilterFixture.java less more
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.config;
17
18 import org.apache.log4j.spi.Filter;
19 import org.apache.log4j.spi.LoggingEvent;
20
21 public class ZeroFilterFixture extends Filter {
22
23 @Override
24 public int decide(LoggingEvent event) {
25 return 0;
26 }
27
28 }
1414
1515
1616 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
17 log4j.appender.CONSOLE.filter.1=org.apache.log4j.config.ZeroFilterFixture
17 log4j.appender.CONSOLE.filter.1=org.apache.log4j.config.NeutralFilterFixture
18 log4j.appender.CONSOLE.filter.1.onMatch=neutral
1819 log4j.appender.CONSOLE.Target=System.out
1920 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
2021 log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-api</artifactId>
42664266 */
42674267 default void logMessage(Level level, Marker marker, String fqcn, StackTraceElement location, Message message,
42684268 Throwable throwable) {
4269
4269 // noop
42704270 }
42714271
42724272 /**
43344334
43354335 /**
43364336 * Construct a log event.
4337 * @param level Any level (ignoreed here).
43374338 * @return a LogBuilder.
43384339 * @since 2.13.0
43394340 */
29152915 public LogBuilder atLevel(Level level) {
29162916 if (isEnabled(level)) {
29172917 return getLogBuilder(level).reset(level);
2918 } else {
2919 return LogBuilder.NOOP;
2920 }
2918 }
2919 return LogBuilder.NOOP;
29212920 }
29222921
29232922 private DefaultLogBuilder getLogBuilder(Level level) {
217217 if (logger instanceof LocationAwareLogger && requiresLocation()) {
218218 ((LocationAwareLogger) logger).logMessage(level, marker, fqcn, StackLocatorUtil.calcLocation(fqcn),
219219 message, t);
220 } else {
221 logger.logMessage(fqcn, level, marker, message, t);
220222 }
221 logger.logMessage(fqcn, level, marker, message, t);
222223 }
223224 }
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-api-java9</artifactId>
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
2525 <description>Apache Log4j Bill of Materials</description>
2626 <groupId>org.apache.logging.log4j</groupId>
2727 <artifactId>log4j-bom</artifactId>
28 <version>2.17.0</version>
28 <version>2.17.1</version>
2929 <packaging>pom</packaging>
3030 <dependencyManagement>
3131 <dependencies>
216216 </build>
217217
218218 <scm>
219 <tag>log4j-2.17.0-rc1</tag>
219 <tag>log4j-2.17.1-rc1</tag>
220220 </scm>
221221 </project>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-core</artifactId>
186186 "code": "java.field.removedWithConstant",
187187 "old": "field org.apache.logging.log4j.core.net.JndiManager.ALLOWED_PROTOCOLS",
188188 "justification": "Removed allowing additional protocols"
189 },
190 {
191 "code": "java.method.removed",
192 "old": "method java.util.List<java.lang.String> org.apache.logging.log4j.core.util.NetUtils::getLocalIps()",
193 "justification": "method is no longer used."
189194 }
190195 ]
191196 }
1717
1818 import java.sql.Connection;
1919 import java.sql.SQLException;
20 import java.util.Objects;
2021
21 import javax.naming.InitialContext;
2222 import javax.naming.NamingException;
2323 import javax.sql.DataSource;
2424
2727 import org.apache.logging.log4j.core.config.plugins.Plugin;
2828 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2929 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30 import org.apache.logging.log4j.core.net.JndiManager;
3031 import org.apache.logging.log4j.status.StatusLogger;
3132 import org.apache.logging.log4j.util.Strings;
3233
4142 private final String description;
4243
4344 private DataSourceConnectionSource(final String dataSourceName, final DataSource dataSource) {
44 this.dataSource = dataSource;
45 this.dataSource = Objects.requireNonNull(dataSource, "dataSource");
4546 this.description = "dataSource{ name=" + dataSourceName + ", value=" + dataSource + " }";
4647 }
4748
5859 /**
5960 * Factory method for creating a connection source within the plugin manager.
6061 *
61 * @param jndiName The full JNDI path where the data source is bound. Should start with java:/comp/env or
62 * environment-equivalent.
62 * @param jndiName The full JNDI path where the data source is bound. Must start with java:/comp/env or environment-equivalent.
6363 * @return the created connection source.
6464 */
6565 @PluginFactory
6666 public static DataSourceConnectionSource createConnectionSource(@PluginAttribute("jndiName") final String jndiName) {
67 if (!JndiManager.isJndiJdbcEnabled()) {
68 LOGGER.error("JNDI must be enabled by setting log4j2.enableJndiJdbc=true");
69 return null;
70 }
6771 if (Strings.isEmpty(jndiName)) {
6872 LOGGER.error("No JNDI name provided.");
6973 return null;
7074 }
71
7275 try {
73 final InitialContext context = new InitialContext();
74 final DataSource dataSource = (DataSource) context.lookup(jndiName);
76 @SuppressWarnings("resource")
77 final DataSource dataSource = JndiManager.getDefaultManager(DataSourceConnectionSource.class.getCanonicalName()).lookup(jndiName);
7578 if (dataSource == null) {
76 LOGGER.error("No data source found with JNDI name [" + jndiName + "].");
79 LOGGER.error("No DataSource found with JNDI name [" + jndiName + "].");
7780 return null;
7881 }
79
8082 return new DataSourceConnectionSource(jndiName, dataSource);
8183 } catch (final NamingException e) {
8284 LOGGER.error(e.getMessage(), e);
130130 logger().error("Error creating JmsManager using JmsManagerConfiguration [{}]", data, e);
131131 return null;
132132 }
133 } else {
134 logger().error("JNDI must be enabled by setting log4j2.enableJndiJms=true");
135 return null;
136 }
133 }
134 logger().error("JNDI must be enabled by setting log4j2.enableJndiJms=true");
135 return null;
137136 }
138137 }
139138
352351 * @param object
353352 * The LogEvent or String message to wrap.
354353 * @return A new JMS message containing the provided object.
355 * @throws JMSException
354 * @throws JMSException if the JMS provider fails to create this message due to some internal error.
356355 */
357356 public Message createMessage(final Serializable object) throws JMSException {
358357 if (object instanceof String) {
373372 * Creates a MessageConsumer on this Destination using the current Session.
374373 *
375374 * @return A MessageConsumer on this Destination.
376 * @throws JMSException
375 * @throws JMSException if the session fails to create a consumer due to some internal error.
377376 */
378377 public MessageConsumer createMessageConsumer() throws JMSException {
379378 return this.session.createConsumer(this.destination);
387386 * @param destination
388387 * The JMS Destination for the MessageProducer
389388 * @return A MessageProducer on this Destination.
390 * @throws JMSException
389 * @throws JMSException if the session fails to create a MessageProducer due to some internal error.
391390 */
392391 public MessageProducer createMessageProducer(final Session session, final Destination destination)
393392 throws JMSException {
2121 import java.util.concurrent.ExecutionException;
2222 import java.util.concurrent.TimeUnit;
2323 import java.util.concurrent.TimeoutException;
24 import java.util.stream.Stream;
2425
2526 import org.apache.logging.log4j.core.AbstractLifeCycle;
2627 import org.apache.logging.log4j.core.Appender;
4243 @Plugin(name = "Kafka", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
4344 public final class KafkaAppender extends AbstractAppender {
4445
45 private final Integer retryCount;
46
47 /**
46 /**
4847 * Builds KafkaAppender instances.
4948 *
5049 * @param <B> The type to build
7877 getPropertyArray(), getRetryCount());
7978 }
8079
81 public String getTopic() {
82 return topic;
83 }
84
85 public boolean isSyncSend() {
86 return syncSend;
87 }
88
89 public B setTopic(final String topic) {
90 this.topic = topic;
91 return asBuilder();
92 }
93
94 public B setSyncSend(final boolean syncSend) {
95 this.syncSend = syncSend;
96 return asBuilder();
97 }
98
99 public B setKey(final String key) {
100 this.key = key;
101 return asBuilder();
102 }
103
10480 public Integer getRetryCount() {
10581 Integer intRetryCount = null;
10682 try {
11288
11389 }
11490
115 }
91 public String getTopic() {
92 return topic;
93 }
94
95 public boolean isSyncSend() {
96 return syncSend;
97 }
98
99 public B setKey(final String key) {
100 this.key = key;
101 return asBuilder();
102 }
103
104 public B setSyncSend(final boolean syncSend) {
105 this.syncSend = syncSend;
106 return asBuilder();
107 }
108
109 public B setTopic(final String topic) {
110 this.topic = topic;
111 return asBuilder();
112 }
113
114 }
115
116 private static final String[] KAFKA_CLIENT_PACKAGES = new String[] { "org.apache.kafka.common", "org.apache.kafka.clients" };
116117
117118 @Deprecated
118119 public static KafkaAppender createAppender(final Layout<? extends Serializable> layout, final Filter filter,
128129 properties, key);
129130 return new KafkaAppender(name, layout, filter, ignoreExceptions, kafkaManager, null, null);
130131 }
132
133 /**
134 * Tests if the given log event is from a Kafka Producer implementation.
135 *
136 * @param event The event to test.
137 * @return true to avoid recursion and skip logging, false to log.
138 */
139 private static boolean isRecursive(final LogEvent event) {
140 return Stream.of(KAFKA_CLIENT_PACKAGES).anyMatch(prefix -> event.getLoggerName().startsWith(prefix));
141 }
131142
132143 /**
133144 * Creates a builder for a KafkaAppender.
139150 return new Builder<B>().asBuilder();
140151 }
141152
153 private final Integer retryCount;
154
142155 private final KafkaManager manager;
143156
144157 private KafkaAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
151164
152165 @Override
153166 public void append(final LogEvent event) {
154 if (event.getLoggerName() != null && event.getLoggerName().startsWith("org.apache.kafka")) {
167 if (event.getLoggerName() != null && isRecursive(event)) {
155168 LOGGER.warn("Recursive logging from [{}] for appender [{}].", event.getLoggerName(), getName());
156169 } else {
157170 try {
173186 error("Unable to write to Kafka in appender [" + getName() + "]", event, e);
174187 }
175188 }
189 }
190
191 @Override
192 public void start() {
193 super.start();
194 manager.startup();
195 }
196
197 @Override
198 public boolean stop(final long timeout, final TimeUnit timeUnit) {
199 setStopping();
200 boolean stopped = super.stop(timeout, timeUnit, false);
201 stopped &= manager.stop(timeout, timeUnit);
202 setStopped();
203 return stopped;
204 }
205
206 @Override
207 public String toString() {
208 return "KafkaAppender{" + "name=" + getName() + ", state=" + getState() + ", topic=" + manager.getTopic() + '}';
176209 }
177210
178211 private void tryAppend(final LogEvent event) throws ExecutionException, InterruptedException, TimeoutException {
189222 }
190223 manager.send(data);
191224 }
192
193 @Override
194 public void start() {
195 super.start();
196 manager.startup();
197 }
198
199 @Override
200 public boolean stop(final long timeout, final TimeUnit timeUnit) {
201 setStopping();
202 boolean stopped = super.stop(timeout, timeUnit, false);
203 stopped &= manager.stop(timeout, timeUnit);
204 setStopped();
205 return stopped;
206 }
207
208 @Override
209 public String toString() {
210 return "KafkaAppender{" + "name=" + getName() + ", state=" + getState() + ", topic=" + manager.getTopic() + '}';
211 }
212225 }
5757 import org.apache.logging.log4j.core.layout.PatternLayout;
5858 import org.apache.logging.log4j.core.lookup.ConfigurationStrSubstitutor;
5959 import org.apache.logging.log4j.core.lookup.Interpolator;
60 import org.apache.logging.log4j.core.lookup.MapLookup;
60 import org.apache.logging.log4j.core.lookup.PropertiesLookup;
6161 import org.apache.logging.log4j.core.lookup.RuntimeStrSubstitutor;
6262 import org.apache.logging.log4j.core.lookup.StrLookup;
6363 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
632632 }
633633 } else {
634634 final Map<String, String> map = this.getComponent(CONTEXT_PROPERTIES);
635 final StrLookup lookup = map == null ? null : new MapLookup(map);
635 final StrLookup lookup = map == null ? null : new PropertiesLookup(map);
636636 Interpolator interpolator = new Interpolator(lookup, pluginPackages);
637637 subst.setVariableResolver(interpolator);
638638 configurationStrSubstitutor.setVariableResolver(interpolator);
2323 import org.apache.logging.log4j.core.config.plugins.PluginElement;
2424 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
2525 import org.apache.logging.log4j.core.lookup.Interpolator;
26 import org.apache.logging.log4j.core.lookup.MapLookup;
26 import org.apache.logging.log4j.core.lookup.PropertiesLookup;
2727 import org.apache.logging.log4j.core.lookup.StrLookup;
2828
2929 /**
5353 map.put(prop.getName(), prop.getValue());
5454 }
5555
56 return new Interpolator(new MapLookup(map), config.getPluginPackages());
56 return new Interpolator(new PropertiesLookup(map), config.getPluginPackages());
5757 }
5858 }
6969 * @since 2.1
7070 */
7171 public Interpolator(final StrLookup defaultLookup, final List<String> pluginPackages) {
72 this.defaultLookup = defaultLookup == null ? new MapLookup(new HashMap<String, String>()) : defaultLookup;
72 this.defaultLookup = defaultLookup == null ? new PropertiesLookup(new HashMap<String, String>()) : defaultLookup;
7373 final PluginManager manager = new PluginManager(CATEGORY);
7474 manager.collectPlugins(pluginPackages);
7575 final Map<String, PluginType<?>> plugins = manager.getPlugins();
9797 * Creates the Interpolator using only Lookups that work without an event and initial properties.
9898 */
9999 public Interpolator(final Map<String, String> properties) {
100 this.defaultLookup = new MapLookup(properties == null ? new HashMap<String, String>() : properties);
100 this.defaultLookup = new PropertiesLookup(properties);
101101 // TODO: this ought to use the PluginManager
102102 strLookupMap.put("log4j", new Log4jLookup());
103103 strLookupMap.put("sys", new SystemPropertiesLookup());
104104 strLookupMap.put("env", new EnvironmentLookup());
105105 strLookupMap.put("main", MainMapLookup.MAIN_SINGLETON);
106 strLookupMap.put("map", new MapLookup(properties));
106107 strLookupMap.put("marker", new MarkerLookup());
107108 strLookupMap.put("java", new JavaLookup());
108109 strLookupMap.put("lower", new LowerLookup());
127128 handleError(LOOKUP_KEY_JVMRUNARGS, e);
128129 }
129130 strLookupMap.put("date", new DateLookup());
130 strLookupMap.put("ctx", new ContextMapLookup());
131131 if (Constants.IS_WEB_APP) {
132132 try {
133133 strLookupMap.put(LOOKUP_KEY_WEB,
146146 }
147147 try {
148148 strLookupMap.put(LOOKUP_KEY_SPRING,
149 Loader.newCheckedInstanceOf("org.apache.logging.log4j.spring.cloud.config.client.SpringLookup", StrLookup.class));
149 Loader.newCheckedInstanceOf("org.apache.logging.log4j.spring.boot.SpringLookup", StrLookup.class));
150150 } catch (final Exception ignored) {
151151 handleError(LOOKUP_KEY_SPRING, ignored);
152152 }
1919 import java.util.List;
2020 import java.util.Map;
2121
22 import org.apache.logging.log4j.core.LogEvent;
2223 import org.apache.logging.log4j.core.config.plugins.Plugin;
2324
2425 /**
4748 super(map);
4849 }
4950
51 @Override
52 public String lookup(final LogEvent event, final String key) {
53 return lookup(key);
54 }
55
56 @Override
57 public String lookup(final String key) {
58 if (key == null) {
59 return null;
60 }
61 Map<String, String> map = getMap();
62 return map == null ? null : map.get(key);
63 }
5064 }
4242 }
4343
4444 /**
45 * Creates a new instance backed by a Map. Used by the default lookup.
45 * Creates a new instance backed by a Map.
4646 *
4747 * @param map
4848 * the map of keys to values, may be null
118118 @Override
119119 public String lookup(final LogEvent event, final String key) {
120120 final boolean isMapMessage = event != null && event.getMessage() instanceof MapMessage;
121 if (map == null && !isMapMessage) {
122 return null;
123 }
124 if (map != null && map.containsKey(key)) {
125 final String obj = map.get(key);
121 if (isMapMessage) {
122 final String obj = ((MapMessage) event.getMessage()).get(key);
126123 if (obj != null) {
127124 return obj;
128125 }
129126 }
130 if (isMapMessage) {
131 return ((MapMessage) event.getMessage()).get(key);
127 if (map != null) {
128 return map.get(key);
132129 }
133130 return null;
134131 }
145142 */
146143 @Override
147144 public String lookup(final String key) {
148 if (map == null) {
145 if (key == null || map == null) {
149146 return null;
150147 }
151148 return map.get(key);
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.lookup;
17
18 import org.apache.logging.log4j.core.LogEvent;
19
20 import java.util.Collections;
21 import java.util.Map;
22
23 /**
24 * A lookup designed for {@code Properties} defined in the configuration. This is similar
25 * to {@link MapLookup} without special handling for structured messages.
26 *
27 * Note that this lookup is not a plugin, but wired as a default lookup in the configuration.
28 */
29 public final class PropertiesLookup implements StrLookup {
30
31 /**
32 * Configuration from which to read properties.
33 */
34 private final Map<String, String> properties;
35
36 public PropertiesLookup(final Map<String, String> properties) {
37 this.properties = properties == null
38 ? Collections.emptyMap()
39 : properties;
40 }
41
42 @Override
43 public String lookup(
44 @SuppressWarnings("ignored") final LogEvent event,
45 final String key) {
46 return lookup(key);
47 }
48
49 /**
50 * Looks a value from configuration properties.
51 * <p>
52 * If the property is not defined, then null is returned.
53 * </p>
54 *
55 * @param key the key to be looked up, may be null
56 * @return the matching value, null if no match
57 */
58 @Override
59 public String lookup(final String key) {
60 return key == null ? null : properties.get(key);
61 }
62
63 @Override
64 public String toString() {
65 return "PropertiesLookup{properties=" + properties + '}';
66 }
67 }
226226 * @param valueMap the map with the variables' values, may be null
227227 */
228228 public StrSubstitutor(final Map<String, String> valueMap) {
229 this(new MapLookup(valueMap), DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE);
229 this(new PropertiesLookup(valueMap), DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE);
230230 }
231231
232232 /**
238238 * @throws IllegalArgumentException if the prefix or suffix is null
239239 */
240240 public StrSubstitutor(final Map<String, String> valueMap, final String prefix, final String suffix) {
241 this(new MapLookup(valueMap), prefix, suffix, DEFAULT_ESCAPE);
241 this(new PropertiesLookup(valueMap), prefix, suffix, DEFAULT_ESCAPE);
242242 }
243243
244244 /**
252252 */
253253 public StrSubstitutor(final Map<String, String> valueMap, final String prefix, final String suffix,
254254 final char escape) {
255 this(new MapLookup(valueMap), prefix, suffix, escape);
255 this(new PropertiesLookup(valueMap), prefix, suffix, escape);
256256 }
257257
258258 /**
267267 */
268268 public StrSubstitutor(final Map<String, String> valueMap, final String prefix, final String suffix,
269269 final char escape, final String valueDelimiter) {
270 this(new MapLookup(valueMap), prefix, suffix, escape, valueDelimiter);
270 this(new PropertiesLookup(valueMap), prefix, suffix, escape, valueDelimiter);
271271 }
272272
273273 /**
436436 */
437437 public static String replace(final Object source, final Properties valueProperties) {
438438 if (valueProperties == null) {
439 return source.toString();
439 return Objects.toString(source, null);
440440 }
441441 final Map<String, String> valueMap = new HashMap<>();
442442 final Enumeration<?> propNames = valueProperties.propertyNames();
4141 private static final String PREFIX = "log4j2.enableJndi";
4242 private static final String JAVA_SCHEME = "java";
4343
44 private static final boolean JNDI_CONTEXT_SELECTOR_ENABLED = isJndiEnabled("ContextSelector");
45 private static final boolean JNDI_JDBC_ENABLED = isJndiEnabled("Jdbc");
46 private static final boolean JNDI_JMS_ENABLED = isJndiEnabled("Jms");
47 private static final boolean JNDI_LOOKUP_ENABLED = isJndiEnabled("Lookup");
48
4449 private final InitialContext context;
4550
4651 private static boolean isJndiEnabled(final String subKey) {
4853 }
4954
5055 public static boolean isJndiEnabled() {
51 return isJndiContextSelectorEnabled() || isJndiJmsEnabled() || isJndiLookupEnabled();
56 return isJndiContextSelectorEnabled() || isJndiJdbcEnabled() || isJndiJmsEnabled() || isJndiLookupEnabled();
5257 }
5358
5459 public static boolean isJndiContextSelectorEnabled() {
55 return isJndiEnabled("ContextSelector");
60 return JNDI_CONTEXT_SELECTOR_ENABLED;
61 }
62
63 public static boolean isJndiJdbcEnabled() {
64 return JNDI_JDBC_ENABLED;
5665 }
5766
5867 public static boolean isJndiJmsEnabled() {
59 return isJndiEnabled("Jms");
68 return JNDI_JMS_ENABLED;
6069 }
6170
6271 public static boolean isJndiLookupEnabled() {
63 return isJndiEnabled("Lookup");
72 return JNDI_LOOKUP_ENABLED;
6473 }
6574
6675 private JndiManager(final String name, final InitialContext context) {
203212 }
204213 LOGGER.warn("Unsupported JNDI URI - {}", name);
205214 } catch (URISyntaxException ex) {
206 LOGGER.warn("Invalid JNDI URI - {}", name);
215 LOGGER.warn("Invalid JNDI URI - {}", name);
207216 }
208217 return null;
209218 }
1616 package org.apache.logging.log4j.core.util;
1717
1818 import java.io.File;
19 import java.net.Inet4Address;
20 import java.net.Inet6Address;
2119 import java.net.InetAddress;
2220 import java.net.MalformedURLException;
2321 import java.net.NetworkInterface;
2624 import java.net.URISyntaxException;
2725 import java.net.URL;
2826 import java.net.UnknownHostException;
29 import java.util.ArrayList;
3027 import java.util.Arrays;
3128 import java.util.Enumeration;
32 import java.util.List;
3329
3430 import org.apache.logging.log4j.Logger;
3531 import org.apache.logging.log4j.status.StatusLogger;
36 import org.apache.logging.log4j.util.Strings;
3732
3833 /**
3934 * Networking-related convenience methods.
8075 }
8176 LOGGER.error("Could not determine local host name", uhe);
8277 return UNKNOWN_LOCALHOST;
83 }
84 }
85
86 /**
87 * Returns all the local host names and ip addresses.
88 * @return The local host names and ip addresses.
89 */
90 public static List<String> getLocalIps() {
91 List<String> localIps = new ArrayList<>();
92 localIps.add("localhost");
93 localIps.add("127.0.0.1");
94 try {
95 final InetAddress addr = Inet4Address.getLocalHost();
96 setHostName(addr, localIps);
97 } catch (final UnknownHostException ex) {
98 // Ignore this.
99 }
100 try {
101 final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
102 if (interfaces != null) {
103 while (interfaces.hasMoreElements()) {
104 final NetworkInterface nic = interfaces.nextElement();
105 final Enumeration<InetAddress> addresses = nic.getInetAddresses();
106 while (addresses.hasMoreElements()) {
107 final InetAddress address = addresses.nextElement();
108 setHostName(address, localIps);
109 }
110 }
111 }
112 } catch (final SocketException se) {
113 // ignore.
114 }
115 return localIps;
116 }
117
118 private static void setHostName(InetAddress address, List<String> localIps) {
119 String[] parts = address.toString().split("\\s*/\\s*");
120 if (parts.length > 0) {
121 for (String part : parts) {
122 if (Strings.isNotBlank(part) && !localIps.contains(part)) {
123 localIps.add(part);
124 }
125 }
12678 }
12779 }
12880
2121
2222 import org.apache.logging.log4j.Level;
2323 import org.apache.logging.log4j.Logger;
24 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
2425 import org.apache.logging.log4j.status.StatusLogger;
25 import org.apache.logging.log4j.util.PropertiesUtil;
26 import org.apache.logging.log4j.util.Strings;
2726
2827 /**
2928 * A convenience class to convert property values to specific types.
3231
3332 private static final Logger LOGGER = StatusLogger.getLogger();
3433
35 private static final String DELIM_START = "${";
36 private static final char DELIM_STOP = '}';
37 private static final int DELIM_START_LEN = 2;
38 private static final int DELIM_STOP_LEN = 1;
3934 private static final int ONE_K = 1024;
4035
4136 /**
166161 if (hashIndex == -1) {
167162 if("NULL".equalsIgnoreCase(value)) {
168163 return null;
169 } else {
170 // no class name specified : use standard Level class
171 return Level.toLevel(value, defaultValue);
172 }
164 }
165 // no class name specified : use standard Level class
166 return Level.toLevel(value, defaultValue);
173167 }
174168
175169 Level result = defaultValue;
346340 */
347341 public static String substVars(final String val, final Properties props) throws
348342 IllegalArgumentException {
349
350 final StringBuilder sbuf = new StringBuilder();
351
352 int i = 0;
353 int j;
354 int k;
355
356 while (true) {
357 j = val.indexOf(DELIM_START, i);
358 if (j == -1) {
359 // no more variables
360 if (i == 0) { // this is a simple string
361 return val;
362 }
363 // add the tail string which contails no variables and return the result.
364 sbuf.append(val.substring(i, val.length()));
365 return sbuf.toString();
366 }
367 sbuf.append(val.substring(i, j));
368 k = val.indexOf(DELIM_STOP, j);
369 if (k == -1) {
370 throw new IllegalArgumentException(Strings.dquote(val)
371 + " has no closing brace. Opening brace at position " + j
372 + '.');
373 }
374 j += DELIM_START_LEN;
375 final String key = val.substring(j, k);
376 // first try in System properties
377 String replacement = PropertiesUtil.getProperties().getStringProperty(key, null);
378 // then try props parameter
379 if (replacement == null && props != null) {
380 replacement = props.getProperty(key);
381 }
382
383 if (replacement != null) {
384 // Do variable substitution on the replacement string
385 // such that we can solve "Hello ${x2}" as "Hello p1"
386 // the where the properties are
387 // x1=p1
388 // x2=${x1}
389 final String recursiveReplacement = substVars(replacement, props);
390 sbuf.append(recursiveReplacement);
391 }
392 i = k + DELIM_STOP_LEN;
393 }
343 return StrSubstitutor.replace(val, props);
394344 }
395345 }
1515 */
1616 package org.apache.logging.log4j.core.appender.db.jdbc;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.mockito.BDDMockito.given;
22 import static org.mockito.Mockito.mock;
23
1824 import java.io.ByteArrayOutputStream;
1925 import java.io.PrintWriter;
2026 import java.sql.Connection;
2127 import java.sql.ResultSet;
2228 import java.sql.SQLException;
2329 import java.sql.Statement;
30
2431 import javax.sql.DataSource;
2532
2633 import org.apache.logging.log4j.LogManager;
3441 import org.junit.Test;
3542 import org.junit.rules.RuleChain;
3643
37 import static org.junit.Assert.*;
38 import static org.mockito.BDDMockito.given;
39 import static org.mockito.Mockito.mock;
40
4144 /**
4245 * Abstract unit test for JdbcAppender using a {@link DataSource} configuration.
4346 */
44 public abstract class AbstractJdbcAppenderDataSourceTest {
47 public abstract class AbstractJdbcAppenderDataSourceTest extends AbstractJdbcDataSourceTest {
4548
4649 @Rule
4750 public final RuleChain rules;
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jdbc;
17
18 import javax.sql.DataSource;
19
20 import org.junit.AfterClass;
21 import org.junit.BeforeClass;
22
23 /**
24 * Abstract unit test for JDBC using a {@link DataSource} configuration.
25 */
26 public abstract class AbstractJdbcDataSourceTest {
27
28 @AfterClass
29 public static void afterClass() throws Exception {
30 System.clearProperty("log4j2.enableJndiJdbc");
31 }
32
33 @BeforeClass
34 public static void beforeClass() throws Exception {
35 System.setProperty("log4j2.enableJndiJdbc", "true");
36 }
37
38 }
3636 import org.junit.runners.Parameterized;
3737
3838 @RunWith(Parameterized.class)
39 public class DataSourceConnectionSourceTest {
39 public class DataSourceConnectionSourceTest extends AbstractJdbcDataSourceTest {
4040
4141 @Parameterized.Parameters(name = "{0}")
4242 public static Object[][] data() {
4545 /**
4646 * Unit tests {@link MapMessage}s for JdbcAppender using a {@link DataSource} configuration.
4747 */
48 public class JdbcAppenderMapMessageDataSourceTest {
48 public class JdbcAppenderMapMessageDataSourceTest extends AbstractJdbcDataSourceTest {
4949
5050 @Rule
5151 public final RuleChain rules;
4747 import org.apache.logging.log4j.message.Message;
4848 import org.apache.logging.log4j.message.SimpleMessage;
4949 import org.apache.logging.log4j.message.StringMapMessage;
50 import org.junit.AfterClass;
5051 import org.junit.Before;
5152 import org.junit.BeforeClass;
5253 import org.junit.Rule;
8384 @Rule
8485 public RuleChain rules = RuleChain.outerRule(jndiRule).around(ctx);
8586
86 @BeforeClass
87 @AfterClass
8788 public static void afterClass() throws Exception {
8889 System.clearProperty("log4j2.enableJndiJms");
8990 }
2626 public class RollingFileAppenderReconfigureTest {
2727
2828 @Rule
29 public final LoggerContextRule loggerContextRule = new LoggerContextRule("src/test/rolling-file-appender-reconfigure.xml");
29 public final LoggerContextRule loggerContextRule = new LoggerContextRule("rolling-file-appender-reconfigure.xml");
3030
3131 @Test
3232 public void testReconfigure() {
1616 package org.apache.logging.log4j.core.lookup;
1717
1818 import java.text.SimpleDateFormat;
19 import java.util.Collections;
1920 import java.util.Date;
2021 import java.util.HashMap;
2122 import java.util.Map;
2223
24 import org.apache.logging.log4j.Level;
2325 import org.apache.logging.log4j.ThreadContext;
26 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.Logger;
28 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2429 import org.apache.logging.log4j.junit.JndiRule;
25 import org.junit.BeforeClass;
30 import org.apache.logging.log4j.message.StringMapMessage;
2631 import org.junit.ClassRule;
2732 import org.junit.Test;
2833 import org.junit.rules.ExternalResource;
2934 import org.junit.rules.RuleChain;
3035
3136 import static org.junit.Assert.*;
37 import static org.junit.jupiter.api.Assertions.assertEquals;
38 import static org.junit.jupiter.api.Assertions.assertNull;
3239
3340 /**
3441 *
111118 assertLookupNotEmpty(lookup, "java:locale");
112119 assertLookupNotEmpty(lookup, "java:hw");
113120 }
121
122
123 @Test
124 public void testInterpolatorMapMessageWithNoPrefix() {
125 final HashMap<String, String> configProperties = new HashMap<>();
126 configProperties.put("key", "configProperties");
127 Interpolator interpolator = new Interpolator(configProperties);
128 final HashMap<String, String> map = new HashMap<>();
129 map.put("key", "mapMessage");
130 LogEvent event = Log4jLogEvent.newBuilder()
131 .setLoggerName(getClass().getName())
132 .setLoggerFqcn(Logger.class.getName())
133 .setLevel(Level.INFO)
134 .setMessage(new StringMapMessage(map))
135 .build();
136 assertEquals("configProperties", interpolator.lookup(event, "key"));
137 }
138
139 @Test
140 public void testInterpolatorMapMessageWithNoPrefixConfigDoesntMatch() {
141 Interpolator interpolator = new Interpolator(Collections.emptyMap());
142 final HashMap<String, String> map = new HashMap<>();
143 map.put("key", "mapMessage");
144 LogEvent event = Log4jLogEvent.newBuilder()
145 .setLoggerName(getClass().getName())
146 .setLoggerFqcn(Logger.class.getName())
147 .setLevel(Level.INFO)
148 .setMessage(new StringMapMessage(map))
149 .build();
150 assertNull(
151 interpolator.lookup(event, "key"),
152 "Values without a map prefix should not match MapMessages");
153 }
154
155 @Test
156 public void testInterpolatorMapMessageWithMapPrefix() {
157 final HashMap<String, String> configProperties = new HashMap<>();
158 configProperties.put("key", "configProperties");
159 Interpolator interpolator = new Interpolator(configProperties);
160 final HashMap<String, String> map = new HashMap<>();
161 map.put("key", "mapMessage");
162 LogEvent event = Log4jLogEvent.newBuilder()
163 .setLoggerName(getClass().getName())
164 .setLoggerFqcn(Logger.class.getName())
165 .setLevel(Level.INFO)
166 .setMessage(new StringMapMessage(map))
167 .build();
168 assertEquals("mapMessage", interpolator.lookup(event, "map:key"));
169 }
114170 }
1414 * limitations under the license.
1515 */
1616 package org.apache.logging.log4j.core.lookup;
17
18 import org.apache.logging.log4j.core.LogEvent;
1719
1820 import java.util.Map;
1921
5355 public MainInputArgumentsMapLookup(final Map<String, String> map) {
5456 super(map);
5557 }
58
59 @Override
60 public String lookup(final LogEvent event, final String key) {
61 return lookup(key);
62 }
63
64 @Override
65 public String lookup(final String key) {
66 if (key == null) {
67 return null;
68 }
69 Map<String, String> map = getMap();
70 return map == null ? null : map.get(key);
71 }
5672 }
9696 }
9797
9898 @Test
99 public void testLookupDefaultMapIsCheckedBeforeMapMessage() {
99 public void testLookupMapMessageIsCheckedBeforeDefaultMap() {
100100 final HashMap<String, String> map = new HashMap<>();
101101 map.put("A", "ADefault");
102 map.put("B", "BDefault");
102103 final HashMap<String, Object> eventMap = new HashMap<>();
103104 eventMap.put("A", "AEvent");
104105 final MapMessage message = new MapMessage<>(eventMap);
106107 .setMessage(message)
107108 .build();
108109 final MapLookup lookup = new MapLookup(map);
109 assertEquals("ADefault", lookup.lookup(event, "A"));
110 assertEquals("AEvent", lookup.lookup(event, "A"));
111 assertEquals("BDefault", lookup.lookup(event, "B"));
110112 }
111113
112114 @Test
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import static org.junit.jupiter.api.Assertions.assertEquals;
19 import static org.junit.jupiter.api.Assertions.assertNull;
20
1821 import java.util.HashMap;
1922 import java.util.Map;
23 import java.util.Properties;
2024
2125 import org.apache.logging.log4j.ThreadContext;
2226 import org.apache.logging.log4j.core.LogEvent;
2428 import org.junit.jupiter.api.BeforeAll;
2529 import org.junit.jupiter.api.Test;
2630
27 import static org.junit.jupiter.api.Assertions.*;
28
2931 public class StrSubstitutorTest {
3032
3133 private static final String TESTKEY = "TestKey";
3234 private static final String TESTVAL = "TestValue";
3335
36
37 @AfterAll
38 public static void after() {
39 System.clearProperty(TESTKEY);
40 }
3441
3542 @BeforeAll
3643 public static void before() {
3744 System.setProperty(TESTKEY, TESTVAL);
3845 }
3946
40 @AfterAll
41 public static void after() {
42 System.clearProperty(TESTKEY);
43 }
44
47
48 @Test
49 public void testDefault() {
50 final Map<String, String> map = new HashMap<>();
51 map.put(TESTKEY, TESTVAL);
52 final StrLookup lookup = new Interpolator(new MapLookup(map));
53 final StrSubstitutor subst = new StrSubstitutor(lookup);
54 ThreadContext.put(TESTKEY, TESTVAL);
55 //String value = subst.replace("${sys:TestKey1:-${ctx:TestKey}}");
56 final String value = subst.replace("${sys:TestKey1:-${ctx:TestKey}}");
57 assertEquals("TestValue", value);
58 }
59
60 @Test
61 public void testDefaultReferencesLookupValue() {
62 final Map<String, String> map = new HashMap<>();
63 map.put(TESTKEY, "${java:version}");
64 final StrLookup lookup = new Interpolator(new MapLookup(map));
65 final StrSubstitutor subst = new StrSubstitutor(lookup);
66 subst.setRecursiveEvaluationAllowed(false);
67 final String value = subst.replace("${sys:TestKey1:-${ctx:TestKey}}");
68 assertEquals("${java:version}", value);
69 }
70
71 @Test
72 public void testInfiniteSubstitutionOnString() {
73 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<>()));
74 final StrSubstitutor subst = new StrSubstitutor(lookup);
75 subst.setRecursiveEvaluationAllowed(true);
76 String infiniteSubstitution = "${${::-${::-$${::-j}}}}";
77 assertEquals(infiniteSubstitution, subst.replace(infiniteSubstitution));
78 }
79
80 @Test
81 public void testInfiniteSubstitutionOnStringBuilder() {
82 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<>()));
83 final StrSubstitutor subst = new StrSubstitutor(lookup);
84 subst.setRecursiveEvaluationAllowed(true);
85 String infiniteSubstitution = "${${::-${::-$${::-j}}}}";
86 assertEquals(infiniteSubstitution, subst.replace(null, new StringBuilder(infiniteSubstitution)));
87 }
4588
4689 @Test
4790 public void testLookup() {
64107 }
65108
66109 @Test
67 public void testDefault() {
68 final Map<String, String> map = new HashMap<>();
69 map.put(TESTKEY, TESTVAL);
70 final StrLookup lookup = new Interpolator(new MapLookup(map));
71 final StrSubstitutor subst = new StrSubstitutor(lookup);
72 ThreadContext.put(TESTKEY, TESTVAL);
73 //String value = subst.replace("${sys:TestKey1:-${ctx:TestKey}}");
74 final String value = subst.replace("${sys:TestKey1:-${ctx:TestKey}}");
75 assertEquals("TestValue", value);
76 }
77
78 @Test
79 public void testDefaultReferencesLookupValue() {
80 final Map<String, String> map = new HashMap<>();
81 map.put(TESTKEY, "${java:version}");
82 final StrLookup lookup = new Interpolator(new MapLookup(map));
83 final StrSubstitutor subst = new StrSubstitutor(lookup);
84 subst.setRecursiveEvaluationAllowed(false);
85 final String value = subst.replace("${sys:TestKey1:-${ctx:TestKey}}");
86 assertEquals("${java:version}", value);
87 }
88
89 @Test
90 public void testInfiniteSubstitutionOnString() {
91 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<>()));
92 final StrSubstitutor subst = new StrSubstitutor(lookup);
93 subst.setRecursiveEvaluationAllowed(true);
94 String infiniteSubstitution = "${${::-${::-$${::-j}}}}";
95 assertEquals(infiniteSubstitution, subst.replace(infiniteSubstitution));
96 }
97
98 @Test
99 public void testInfiniteSubstitutionOnStringBuilder() {
100 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<>()));
101 final StrSubstitutor subst = new StrSubstitutor(lookup);
102 subst.setRecursiveEvaluationAllowed(true);
103 String infiniteSubstitution = "${${::-${::-$${::-j}}}}";
104 assertEquals(infiniteSubstitution, subst.replace(null, new StringBuilder(infiniteSubstitution)));
105 }
106
107 @Test
108 public void testRecursiveSubstitution() {
109 final Map<String, String> map = new HashMap<>();
110 map.put("first", "${ctx:first}");
111 map.put("second", "secondValue");
112 final StrLookup lookup = new Interpolator(new MapLookup(map));
113 final StrSubstitutor subst = new StrSubstitutor(lookup);
114 subst.setRecursiveEvaluationAllowed(true);
115 assertEquals("${ctx:first} and secondValue", subst.replace("${ctx:first} and ${ctx:second}"));
116 }
117
118 @Test
119 public void testRecursiveWithDefault() {
120 final Map<String, String> map = new HashMap<>();
121 map.put("first", "${ctx:first:-default}");
122 final StrLookup lookup = new Interpolator(new MapLookup(map));
123 final StrSubstitutor subst = new StrSubstitutor(lookup);
124 subst.setRecursiveEvaluationAllowed(true);
125 assertEquals("default", subst.replace("${ctx:first}"));
126 }
127
128 @Test
129 public void testRecursiveWithRecursiveDefault() {
130 final Map<String, String> map = new HashMap<>();
131 map.put("first", "${ctx:first:-${ctx:first}}");
132 final StrLookup lookup = new Interpolator(new MapLookup(map));
133 final StrSubstitutor subst = new StrSubstitutor(lookup);
134 subst.setRecursiveEvaluationAllowed(true);
135 assertEquals("${ctx:first}", subst.replace("${ctx:first}"));
136 }
137
138 @Test
139 public void testNestedSelfReferenceWithRecursiveEvaluation() {
140 final Map<String, String> map = new HashMap<>();
141 map.put("first", "${${ctx:first}}");
142 final StrLookup lookup = new Interpolator(new MapLookup(map));
143 final StrSubstitutor subst = new StrSubstitutor(lookup);
144 subst.setRecursiveEvaluationAllowed(true);
145 assertEquals("${${ctx:first}}", subst.replace("${ctx:first}"));
146 }
147
148 @Test
149 public void testRandomWithRecursiveDefault() {
150 final Map<String, String> map = new HashMap<>();
151 map.put("first", "${env:RANDOM:-${ctx:first}}");
152 final StrLookup lookup = new Interpolator(new MapLookup(map));
153 final StrSubstitutor subst = new StrSubstitutor(lookup);
154 subst.setRecursiveEvaluationAllowed(true);
155 assertEquals("${ctx:first}", subst.replace("${ctx:first}"));
156 }
157
158 @Test
159 public void testNoRecursiveEvaluationWithDefault() {
160 final Map<String, String> map = new HashMap<>();
161 map.put("first", "${java:version}");
162 map.put("second", "${java:runtime}");
163 final StrLookup lookup = new Interpolator(new MapLookup(map));
164 final StrSubstitutor subst = new StrSubstitutor(lookup);
165 subst.setRecursiveEvaluationAllowed(false);
166 assertEquals("${java:version}", subst.replace("${ctx:first:-${ctx:second}}"));
167 }
168
169 @Test
170 public void testNoRecursiveEvaluationWithDepthOne() {
171 final Map<String, String> map = new HashMap<>();
172 map.put("first", "${java:version}");
173 final StrLookup lookup = new Interpolator(new MapLookup(map));
174 final StrSubstitutor subst = new StrSubstitutor(lookup);
175 subst.setRecursiveEvaluationAllowed(false);
176 assertEquals("${java:version}", subst.replace("${ctx:first}"));
177 }
178
179 @Test
180110 public void testLookupsNestedWithoutRecursiveEvaluation() {
181111 final Map<String, String> map = new HashMap<>();
182112 map.put("first", "${java:version}");
189119 @Test
190120 public void testLookupThrows() {
191121 final StrSubstitutor subst = new StrSubstitutor(new Interpolator(new StrLookup() {
122
123 @Override
124 public String lookup(LogEvent event, String key) {
125 return lookup(key);
126 }
192127
193128 @Override
194129 public String lookup(String key) {
197132 }
198133 return "success";
199134 }
200
201 @Override
202 public String lookup(LogEvent event, String key) {
203 return lookup(key);
204 }
205135 }));
206136 subst.setRecursiveEvaluationAllowed(false);
207137 assertEquals("success ${foo:throw} success", subst.replace("${foo:a} ${foo:throw} ${foo:c}"));
208138 }
139
140 @Test
141 public void testNestedSelfReferenceWithRecursiveEvaluation() {
142 final Map<String, String> map = new HashMap<>();
143 map.put("first", "${${ctx:first}}");
144 final StrLookup lookup = new Interpolator(new MapLookup(map));
145 final StrSubstitutor subst = new StrSubstitutor(lookup);
146 subst.setRecursiveEvaluationAllowed(true);
147 assertEquals("${${ctx:first}}", subst.replace("${ctx:first}"));
148 }
149
150 @Test
151 public void testNoRecursiveEvaluationWithDefault() {
152 final Map<String, String> map = new HashMap<>();
153 map.put("first", "${java:version}");
154 map.put("second", "${java:runtime}");
155 final StrLookup lookup = new Interpolator(new MapLookup(map));
156 final StrSubstitutor subst = new StrSubstitutor(lookup);
157 subst.setRecursiveEvaluationAllowed(false);
158 assertEquals("${java:version}", subst.replace("${ctx:first:-${ctx:second}}"));
159 }
160
161 @Test
162 public void testNoRecursiveEvaluationWithDepthOne() {
163 final Map<String, String> map = new HashMap<>();
164 map.put("first", "${java:version}");
165 final StrLookup lookup = new Interpolator(new MapLookup(map));
166 final StrSubstitutor subst = new StrSubstitutor(lookup);
167 subst.setRecursiveEvaluationAllowed(false);
168 assertEquals("${java:version}", subst.replace("${ctx:first}"));
169 }
170
171 @Test
172 public void testRandomWithRecursiveDefault() {
173 final Map<String, String> map = new HashMap<>();
174 map.put("first", "${env:RANDOM:-${ctx:first}}");
175 final StrLookup lookup = new Interpolator(new MapLookup(map));
176 final StrSubstitutor subst = new StrSubstitutor(lookup);
177 subst.setRecursiveEvaluationAllowed(true);
178 assertEquals("${ctx:first}", subst.replace("${ctx:first}"));
179 }
180
181 @Test
182 public void testRecursiveSubstitution() {
183 final Map<String, String> map = new HashMap<>();
184 map.put("first", "${ctx:first}");
185 map.put("second", "secondValue");
186 final StrLookup lookup = new Interpolator(new MapLookup(map));
187 final StrSubstitutor subst = new StrSubstitutor(lookup);
188 subst.setRecursiveEvaluationAllowed(true);
189 assertEquals("${ctx:first} and secondValue", subst.replace("${ctx:first} and ${ctx:second}"));
190 }
191
192 @Test
193 public void testRecursiveWithDefault() {
194 final Map<String, String> map = new HashMap<>();
195 map.put("first", "${ctx:first:-default}");
196 final StrLookup lookup = new Interpolator(new MapLookup(map));
197 final StrSubstitutor subst = new StrSubstitutor(lookup);
198 subst.setRecursiveEvaluationAllowed(true);
199 assertEquals("default", subst.replace("${ctx:first}"));
200 }
201
202 @Test
203 public void testRecursiveWithRecursiveDefault() {
204 final Map<String, String> map = new HashMap<>();
205 map.put("first", "${ctx:first:-${ctx:first}}");
206 final StrLookup lookup = new Interpolator(new MapLookup(map));
207 final StrSubstitutor subst = new StrSubstitutor(lookup);
208 subst.setRecursiveEvaluationAllowed(true);
209 assertEquals("${ctx:first}", subst.replace("${ctx:first}"));
210 }
211
212 @Test
213 public void testReplaceProperties() {
214 Properties properties = new Properties();
215 properties.put("a", "A");
216 assertNull(StrSubstitutor.replace((String) null, properties));
217 assertNull(StrSubstitutor.replace((String) null, (Properties) null));
218 assertEquals("A", StrSubstitutor.replace("${a}", properties));
219 assertEquals("${a}", StrSubstitutor.replace("${a}", (Properties) null));
220 }
221
222 @Test
223 public void testTopLevelLookupsWithoutRecursiveEvaluation() {
224 final Map<String, String> map = new HashMap<>();
225 map.put("key", "VaLuE");
226 final StrLookup lookup = new Interpolator(new MapLookup(map));
227 final StrSubstitutor subst = new StrSubstitutor(lookup);
228 subst.setRecursiveEvaluationAllowed(false);
229 assertEquals("value", subst.replace("${lower:${ctx:key}}"));
230 }
231
232 @Test
233 public void testTopLevelLookupsWithoutRecursiveEvaluation_doubleLower() {
234 final Map<String, String> map = new HashMap<>();
235 map.put("key", "VaLuE");
236 final StrLookup lookup = new Interpolator(new MapLookup(map));
237 final StrSubstitutor subst = new StrSubstitutor(lookup);
238 subst.setRecursiveEvaluationAllowed(false);
239 assertEquals("value", subst.replace("${lower:${lower:${ctx:key}}}"));
240 }
241
242 @Test
243 public void testTopLevelLookupsWithoutRecursiveEvaluationAndDefaultValueLookup() {
244 final Map<String, String> map = new HashMap<>();
245 map.put("key2", "TWO");
246 final StrLookup lookup = new Interpolator(new MapLookup(map));
247 final StrSubstitutor subst = new StrSubstitutor(lookup);
248 subst.setRecursiveEvaluationAllowed(false);
249 assertEquals("two", subst.replace("${lower:${ctx:key1:-${ctx:key2}}}"));
250 }
209251 }
2929 public class JndiManagerTest {
3030
3131 @Test
32 public void testIsJndiContextSelectorEnabled() {
33 assertFalse(JndiManager.isJndiContextSelectorEnabled());
34 }
35
36 @Test
3237 public void testIsJndiEnabled() {
3338 assertFalse(JndiManager.isJndiEnabled());
3439 }
3540
3641 @Test
37 public void testIsJndiContextSelectorEnabled() {
38 assertFalse(JndiManager.isJndiContextSelectorEnabled());
42 public void testIsJndiJdbcEnabled() {
43 assertFalse(JndiManager.isJndiJdbcEnabled());
3944 }
4045
4146 @Test
2727 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
2828 import org.apache.logging.log4j.core.net.TcpSocketManager.HostResolver;
2929 import org.apache.logging.log4j.status.StatusLogger;
30 import org.apache.logging.log4j.util.PropertiesUtil;
3130 import org.junit.jupiter.api.Test;
3231
3332 import java.io.BufferedReader;
199198 }
200199
201200 private static void awaitUntilSucceeds(final Runnable runnable) {
202 final long pollIntervalMillis;
203 final long timeoutSeconds;
204 final boolean osWindows = PropertiesUtil.getProperties().isOsWindows();
205 if (osWindows) {
206 // Windows-specific non-sense values.
207 // These figures are collected by trial-and-error on a friend's laptop which has Windows installed.
208 pollIntervalMillis = 1_000L;
209 timeoutSeconds = 15;
210 } else {
211 // Universally sensible values.
212 pollIntervalMillis = 1000;
213 timeoutSeconds = 3;
214 }
201 // These figures are collected via trial-and-error; nothing scientific to look for here.
202 final long pollIntervalMillis = 1_000L;
203 final long timeoutSeconds = 15L;
215204 await()
216205 .pollInterval(pollIntervalMillis, TimeUnit.MILLISECONDS)
217206 .atMost(timeoutSeconds, TimeUnit.SECONDS)
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.util;
17
18 import static org.junit.jupiter.api.Assertions.assertEquals;
19
20 import java.util.Properties;
21
22 import org.junit.jupiter.api.Test;
23
24 /**
25 * Tests {@link OptionConverter}.
26 */
27 public class OptionConverterTest {
28
29 @Test
30 public void testSubstVars() {
31 Properties props = new Properties();
32 props.setProperty("key", "${key}");
33 assertEquals("Value of key is ${key}.", OptionConverter.substVars("Value of key is ${key}.", props));
34 }
35 }
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-core-its</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-core-java9</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-distribution</artifactId>
492492 </execution> -->
493493 </executions>
494494 </plugin>
495 <!-- calculate checksums of source release for Apache dist area -->
496 <plugin>
497 <groupId>net.nicoulaj.maven.plugins</groupId>
498 <artifactId>checksum-maven-plugin</artifactId>
499 <version>1.11</version>
500 <executions>
501 <execution>
502 <id>calculate-checksums</id>
503 <goals>
504 <goal>files</goal>
505 </goals>
506 <!-- execute prior to maven-gpg-plugin:sign due to https://github.com/nicoulaj/checksum-maven-plugin/issues/112 -->
507 <phase>post-integration-test</phase>
508 <configuration>
509 <algorithms>
510 <algorithm>SHA-256</algorithm>
511 <algorithm>SHA-512</algorithm>
512 </algorithms>
513 <!-- https://maven.apache.org/apache-resource-bundles/#source-release-assembly-descriptor -->
514 <fileSets>
515 <fileSet>
516 <directory>${project.build.directory}</directory>
517 <includes>
518 <include>apache-log4j-${project.version}-src.zip</include>
519 <include>apache-log4j-${project.version}-src.tar.gz</include>
520 <include>apache-log4j-${project.version}-bin.zip</include>
521 <include>apache-log4j-${project.version}-bin.tar.gz</include>
522 </includes>
523 </fileSet>
524 </fileSets>
525 <csvSummary>false</csvSummary>
526 <appendFilename>true</appendFilename>
527 </configuration>
528 </execution>
529 </executions>
530 </plugin>
531 <plugin>
532 <groupId>org.apache.maven.plugins</groupId>
533 <artifactId>maven-gpg-plugin</artifactId>
534 <executions>
535 <execution>
536 <id>sign-release-artifacts</id>
537 <goals>
538 <goal>sign</goal>
539 </goals>
540 <configuration>
541 <keyname>${Log4jSigningUserName}</keyname>
542 </configuration>
543 </execution>
544 </executions>
545 </plugin>
495546 <plugin>
496547 <groupId>org.apache.maven.plugins</groupId>
497548 <artifactId>maven-site-plugin</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-docker</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-flume-ng</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-iostreams</artifactId>
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-jcl</artifactId>
1010 <parent>
1111 <groupId>org.apache.logging.log4j</groupId>
1212 <artifactId>log4j</artifactId>
13 <version>2.17.0</version>
13 <version>2.17.1</version>
1414 </parent>
1515 <modelVersion>4.0.0</modelVersion>
1616
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-jmx-gui</artifactId>
1010 <parent>
1111 <groupId>org.apache.logging.log4j</groupId>
1212 <artifactId>log4j</artifactId>
13 <version>2.17.0</version>
13 <version>2.17.1</version>
1414 </parent>
1515 <modelVersion>4.0.0</modelVersion>
1616
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <modelVersion>4.0.0</modelVersion>
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <modelVersion>4.0.0</modelVersion>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-kubernetes</artifactId>
2121 <parent>
2222 <groupId>org.apache.logging.log4j</groupId>
2323 <artifactId>log4j</artifactId>
24 <version>2.17.0</version>
24 <version>2.17.1</version>
2525 </parent>
2626
2727 <artifactId>log4j-layout-template-json</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-liquibase</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-osgi</artifactId>
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <artifactId>log4j-samples-configuration</artifactId>
2525 <packaging>jar</packaging>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-common</artifactId>
2525 <packaging>jar</packaging>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-embedded</artifactId>
2525 <packaging>war</packaging>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-remote</artifactId>
2525 <packaging>war</packaging>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <artifactId>log4j-samples-loggerProperties</artifactId>
2525 <packaging>jar</packaging>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <groupId>org.apache.logging.log4j.samples</groupId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-slf4j-impl</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-slf4j18-impl</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-spring-boot</artifactId>
1717
1818 import org.apache.logging.log4j.LogManager;
1919 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.lookup.Interpolator;
21 import org.apache.logging.log4j.core.lookup.StrLookup;
2022 import org.junit.Test;
2123 import org.springframework.mock.env.MockEnvironment;
2224
5658 assertNotNull("Did not find property", result);
5759 assertEquals("Incorrect property value", "test", result);
5860 }
61
62 @Test
63 public void testSpringLookupWithDefaultInterpolator() {
64 MockEnvironment env = new MockEnvironment();
65 env.setActiveProfiles("test");
66 env.setProperty("app.property", "test");
67 LoggerContext context = (LoggerContext) LogManager.getContext(false);
68 context.putObject(Log4j2CloudConfigLoggingSystem.ENVIRONMENT_KEY, env);
69
70 StrLookup lookup = new Interpolator();
71 String result = lookup.lookup("spring:profiles.active");
72 assertNotNull("No active profiles", result);
73 assertEquals("Incorrect active profile", "test", result);
74
75 result = lookup.lookup("spring:app.property");
76 assertNotNull("Did not find property", result);
77 assertEquals("Incorrect property value", "test", result);
78 }
5979 }
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j-spring-cloud-config</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-spring-cloud-config-client</artifactId>
2020 <parent>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
2222 <artifactId>log4j-spring-cloud-config-samples</artifactId>
23 <version>2.17.0</version>
23 <version>2.17.1</version>
2424 <relativePath>..</relativePath>
2525 </parent>
2626
2020 <groupId>org.apache.logging.log4j.samples</groupId>
2121 <artifactId>log4j-spring-cloud-config-sample-server</artifactId>
2222 <packaging>jar</packaging>
23 <version>2.17.0</version>
23 <version>2.17.1</version>
2424
2525 <name>Apache Log4j Sample Configuration Service</name>
2626 <description>Sample Cloud Config Server</description>
304304 </profiles>
305305
306306 <scm>
307 <tag>log4j-2.17.0-rc1</tag>
307 <tag>log4j-2.17.1-rc1</tag>
308308 </scm>
309309 </project>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j-spring-cloud-config</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <groupId>org.apache.logging.log4j.samples</groupId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <groupId>org.apache.logging.log4j</groupId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-taglib</artifactId>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-to-slf4j</artifactId>
2424 import org.slf4j.MarkerFactory;
2525 import org.slf4j.spi.LocationAwareLogger;
2626
27 /**
28 *
29 */
3027 public class SLF4JLogger extends AbstractLogger {
3128
3229 private static final long serialVersionUID = 1L;
8885 return locationAwareLogger != null ? locationAwareLogger : logger;
8986 }
9087
91 private org.slf4j.Marker getMarker(final Marker marker) {
92 if (marker == null) {
93 return null;
94 }
88 private static org.slf4j.Marker getMarker(final Marker marker) {
89 // No marker is provided in the common case, small methods
90 // are optimized more effectively.
91 return marker == null ? null : convertMarker(marker);
92 }
93
94 private static org.slf4j.Marker convertMarker(final Marker marker) {
9595 final org.slf4j.Marker slf4jMarker = MarkerFactory.getMarker(marker.getName());
9696 final Marker[] parents = marker.getParents();
9797 if (parents != null) {
224224
225225 @Override
226226 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message message, final Throwable t) {
227 org.slf4j.Marker slf4jMarker = getMarker(marker);
228 String formattedMessage = message.getFormattedMessage();
227229 if (locationAwareLogger != null) {
228230 if (message instanceof LoggerNameAwareMessage) {
229231 ((LoggerNameAwareMessage) message).setLoggerName(getName());
230232 }
231 locationAwareLogger.log(getMarker(marker), fqcn, convertLevel(level), message.getFormattedMessage(),
232 message.getParameters(), t);
233 locationAwareLogger.log(slf4jMarker, fqcn, convertLevel(level), formattedMessage, null, t);
233234 } else {
234235 switch (level.getStandardLevel()) {
235236 case DEBUG :
236 logger.debug(getMarker(marker), message.getFormattedMessage(), message.getParameters(), t);
237 logger.debug(slf4jMarker, formattedMessage, t);
237238 break;
238239 case TRACE :
239 logger.trace(getMarker(marker), message.getFormattedMessage(), message.getParameters(), t);
240 logger.trace(slf4jMarker, formattedMessage, t);
240241 break;
241242 case INFO :
242 logger.info(getMarker(marker), message.getFormattedMessage(), message.getParameters(), t);
243 logger.info(slf4jMarker, formattedMessage, t);
243244 break;
244245 case WARN :
245 logger.warn(getMarker(marker), message.getFormattedMessage(), message.getParameters(), t);
246 logger.warn(slf4jMarker, formattedMessage, t);
246247 break;
247248 case ERROR :
248 logger.error(getMarker(marker), message.getFormattedMessage(), message.getParameters(), t);
249 logger.error(slf4jMarker, formattedMessage, t);
249250 break;
250251 default :
251 logger.error(getMarker(marker), message.getFormattedMessage(), message.getParameters(), t);
252 logger.error(slf4jMarker, formattedMessage, t);
252253 break;
253254 }
254255 }
2121 import org.apache.logging.log4j.spi.LoggerRegistry;
2222 import org.slf4j.LoggerFactory;
2323
24 /**
25 *
26 */
2724 public class SLF4JLoggerContext implements LoggerContext {
2825 private final LoggerRegistry<ExtendedLogger> loggerRegistry = new LoggerRegistry<>();
2926
4239
4340 @Override
4441 public ExtendedLogger getLogger(final String name, final MessageFactory messageFactory) {
45 // FIXME according to LOG4J2-1180, the below line should be:
46 // FIXME if (!loggerRegistry.hasLogger(name, messageFactory)) {
47 if (!loggerRegistry.hasLogger(name)) {
48 // FIXME: should be loggerRegistry.putIfAbsent(name, messageFactory,
49 loggerRegistry.putIfAbsent(name, null,
42 if (!loggerRegistry.hasLogger(name, messageFactory)) {
43 loggerRegistry.putIfAbsent(name, messageFactory,
5044 new SLF4JLogger(name, messageFactory, LoggerFactory.getLogger(name)));
5145 }
52 // FIXME should be return loggerRegistry.getLogger(name, messageFactory);
53 return loggerRegistry.getLogger(name);
54
55 // TODO applying the above fixes causes (log4j-to-slf4j) LoggerTest to fail
46 return loggerRegistry.getLogger(name, messageFactory);
5647 }
5748
5849 @Override
2222 import org.apache.logging.log4j.status.StatusLogger;
2323 import org.apache.logging.log4j.util.LoaderUtil;
2424
25 /**
26 *
27 */
2825 public class SLF4JLoggerContextFactory implements LoggerContextFactory {
2926 private static final StatusLogger LOGGER = StatusLogger.getLogger();
3027 private static final LoggerContext context = new SLF4JLoggerContext();
1616 */
1717 package org.apache.logging.slf4j;
1818
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Proxy;
1921 import java.util.Date;
2022 import java.util.List;
2123
3739 import static org.hamcrest.Matchers.*;
3840 import static org.junit.Assert.*;
3941
40 /**
41 *
42 */
4342 public class LoggerTest {
4443
4544 private static final String CONFIG = "target/test-classes/logback-slf4j.xml";
124123
125124 @Test
126125 public void getLogger_String_MessageFactoryMismatchNull() {
127 final Logger testLogger = testMessageFactoryMismatch("getLogger_String_MessageFactoryMismatchNull",
126 final Logger testLogger = testMessageFactoryMismatch("getLogger_String_MessageFactoryMismatchNull",
128127 StringFormatterMessageFactory.INSTANCE, null);
129128 testLogger.debug("%,d", Integer.MAX_VALUE);
130129 assertThat(list.strList, hasSize(1));
136135 assertThat(testLogger, is(notNullValue()));
137136 checkMessageFactory(messageFactory1, testLogger);
138137 final Logger testLogger2 = LogManager.getLogger(name, messageFactory2);
139 checkMessageFactory(messageFactory1, testLogger2);
138 checkMessageFactory(messageFactory2, testLogger2);
140139 return testLogger;
141140 }
142141
162161 public void debugWithParms() {
163162 logger.debug("Hello, {}", "World");
164163 assertThat(list.strList, hasSize(1));
164 String message = list.strList.get(0);
165 assertEquals("Hello, World", message);
166 }
167
168 @Test
169 public void paramIncludesSubstitutionMarker_locationAware() {
170 logger.info("Hello, {}", "foo {} bar");
171 assertThat(list.strList, hasSize(1));
172 String message = list.strList.get(0);
173 assertEquals("Hello, foo {} bar", message);
174 }
175
176 @Test
177 public void paramIncludesSubstitutionMarker_nonLocationAware() {
178 final org.slf4j.Logger slf4jLogger = CTX.getLogger();
179 Logger nonLocationAwareLogger = new SLF4JLogger(
180 slf4jLogger.getName(),
181 (org.slf4j.Logger) Proxy.newProxyInstance(
182 getClass().getClassLoader(),
183 new Class<?>[]{org.slf4j.Logger.class},
184 (proxy, method, args) -> {
185 try {
186 return method.invoke(slf4jLogger, args);
187 } catch (InvocationTargetException e) {
188 throw e.getCause();
189 }
190 }));
191 nonLocationAwareLogger.info("Hello, {}", "foo {} bar");
192 assertThat(list.strList, hasSize(1));
193 String message = list.strList.get(0);
194 assertEquals("Hello, foo {} bar", message);
165195 }
166196
167197 @Test
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
1919 <artifactId>log4j</artifactId>
2020 <packaging>pom</packaging>
2121 <name>Apache Log4j 2</name>
22 <version>2.17.0</version>
22 <version>2.17.1</version>
2323 <parent>
2424 <groupId>org.apache.logging</groupId>
2525 <artifactId>logging-parent</artifactId>
182182 <connection>scm:git:https://gitbox.apache.org/repos/asf/logging-log4j2.git</connection>
183183 <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/logging-log4j2.git</developerConnection>
184184 <url>https://gitbox.apache.org/repos/asf?p=logging-log4j2.git</url>
185 <tag>log4j-2.17.0-rc1</tag>
185 <tag>log4j-2.17.1-rc1</tag>
186186 </scm>
187187 <properties>
188188 <!-- make sure to update these for each release! -->
189189 <log4jParentDir>${basedir}</log4jParentDir>
190 <Log4jReleaseVersion>2.17.0</Log4jReleaseVersion>
191 <Log4jReleaseVersionJava7>2.12.2</Log4jReleaseVersionJava7>
192 <Log4jReleaseVersionJava6>2.3</Log4jReleaseVersionJava6>
193 <!--Log4jReleaseManager>Ralph Goers</Log4jReleaseManager-->
194 <!--Log4jReleaseKey>B3D8E1BA</Log4jReleaseKey-->
195 <Log4jReleaseManager>Ralph Goers</Log4jReleaseManager>
196 <Log4jReleaseKey>B3D8E1BA</Log4jReleaseKey>
190 <Log4jReleaseVersion>2.17.1</Log4jReleaseVersion>
191 <Log4jReleaseVersionJava7>2.12.3</Log4jReleaseVersionJava7>
192 <Log4jReleaseVersionJava6>2.3.1</Log4jReleaseVersionJava6>
193 <Log4jReleaseManager>Matt Sicker</Log4jReleaseManager>
194 <Log4jReleaseKey>D7C92B70FA1C814D</Log4jReleaseKey>
195 <Log4jSigningUserName>mattsicker@apache.org</Log4jSigningUserName>
197196 <!-- note that any properties you want available in velocity templates must not use periods! -->
198197 <slf4jVersion>1.7.25</slf4jVersion>
199198 <logbackVersion>1.2.3</logbackVersion>
243242 <maven.compiler.target>1.8</maven.compiler.target>
244243 <maven.doap.skip>false</maven.doap.skip>
245244 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
245 <!-- See https://maven.apache.org/guides/mini/guide-reproducible-builds.html -->
246 <project.build.outputTimestamp>10</project.build.outputTimestamp>
246247 <docLabel>Site Documentation</docLabel>
247248 <projectDir />
248249 <commonsLoggingVersion>1.2</commonsLoggingVersion>
14511452 <webAccessUrl>${project.scm.url}</webAccessUrl>
14521453 <anonymousConnection>${project.scm.connection}</anonymousConnection>
14531454 <developerConnection>${project.scm.developerConnection}</developerConnection>
1454 <scmTag>log4j-${Log4jReleaseVersion}</scmTag>
1455 <scmTag>rel/${Log4jReleaseVersion}</scmTag>
14551456 </configuration>
14561457 </plugin>
14571458 <!-- Surefire report -->
132132
133133 ${project.url}
134134
135 ---
136
137 Earlier release notes are accessible in [Release History](${project.url}changes-report.html).
2828 - "update" - Change
2929 - "remove" - Removed
3030 -->
31 <release version="2.17.0" date="2021-MM-dd" description="GA Release 2.17.0">
31 <release version="2.17.1" date="2021-12-27" description="GA Release 2.17.1">
32 <!-- FIXES -->
33 <action issue="LOG4J2-3290" dev="rogers" type="fix">
34 Remove unused method.
35 </action>
36 <action issue="LOG4J2-3292" dev="ckozak" type="fix">
37 ExtendedLoggerWrapper.logMessage no longer double-logs when location is requested.
38 </action>
39 <action issue="LOG4J2-3289" dev="ckozak" type="fix">
40 log4j-to-slf4j no longer re-interpolates formatted message contents.
41 </action>
42 <action issue="LOG4J2-3204" dev="vy" type="fix" due-to="Francis-FY">
43 Correct SpringLookup package name in Interpolator.
44 </action>
45 <action issue="LOG4J2-3284" dev="ckozak" type="fix" due-to="Michael Vorburger">
46 log4j-to-slf4j takes the provided MessageFactory into account
47 </action>
48 <action issue="LOG4J2-3264" dev="ckozak" type="fix" due-to="Yanming Zhou">
49 Fix MapLookup to lookup MapMessage before DefaultMap
50 </action>
51 <action issue="LOG4J2-3274" dev="rgoers" type="fix" due-to="Faisal Khan Thayub Khan">
52 Buffered I/O checked had inverted logic in RollingFileAppenderBuidler.
53 </action>
54 <action dev="ggregory" type="fix">
55 Fix NPE when input is null in StrSubstitutor.replace(String, Properties).
56 </action>
57 <action issue="LOG4J2-3270" dev="ckozak" type="fix">
58 Lookups with no prefix only read values from the configuration properties as expected.
59 </action>
60 <action issue="LOG4J2-3256" dev="ggregory" type="fix" due-to="Lee Dongjin">
61 Reduce ignored package scope of KafkaAppender.
62 </action>
63 </release>
64 <release version="2.17.0" date="2021-12-17" description="GA Release 2.17.0">
3265 <action issue="LOG4J2-3230" dev="ckozak" type="fix">
3366 Fix string substitution recursion.
3467 </action>
3669 Limit JNDI to the java protocol only. JNDI will remain disabled by default. Rename JNDI enablement property from
3770 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
3871 </action>
39 <action issue="LOG4J2-3242" dev="rgoers" type="fix">
40 Limit JNDI to the java protocol only. JNDI will remain disabled by default. The enablement
41 property has been renamed to 'log4j2.enableJndiJava'
42 </action>
4372 <action issue="LOG4J2-3241" dev="rgoers" type="fix">
4473 Do not declare log4j-api-java9 and log4j-core-java9 as dependencies as it causes problems with the
4574 Maven enforcer plugin.
5584 </action>
5685 </release>
5786 <release version="2.16.0" date="2021-12-13" description="GA Release 2.16.0">
87 <!-- FIXES -->
5888 <action issue="LOG4J2-3208" dev="rgoers" type="fix">
5989 Disable JNDI by default. Require log4j2.enableJndi to be set to true to allow JNDI.
6090 </action>