Codebase list apache-log4j2 / aa58884
Import Upstream version 2.12.3 Markus Koschany 2 years ago
1386 changed file(s) with 18736 addition(s) and 69407 deletion(s). Raw diff Collapse all Expand all
+0
-24
.github/dependabot.yml 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 version: 2
17 updates:
18 - package-ecosystem: maven
19 directory: "/"
20 schedule:
21 interval: daily
22 time: '04:00'
23 open-pull-requests-limit: 10
+0
-253
.github/workflows/benchmark.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: benchmark
16
17 on: [ workflow_dispatch ]
18
19 jobs:
20
21 build:
22
23 if: github.repository == 'apache/logging-log4j2'
24
25 runs-on: ubuntu-latest
26
27 steps:
28
29 - name: Checkout repository
30 uses: actions/checkout@v2
31
32 # JDK 11 is needed for the build.
33 - name: Set up JDK 11
34 uses: actions/setup-java@v2.4.0
35 with:
36 distribution: temurin
37 java-version: 11
38 java-package: jdk
39 architecture: x64
40 cache: maven
41
42 # JDK 8 is needed for the build, and it is the primary bytecode target.
43 # Hence, JDK 8 is set up after 11, so that JAVA_HOME used by Maven during build will point to 8.
44 - name: Set up JDK 8
45 uses: actions/setup-java@v2.3.1
46 with:
47 distribution: temurin
48 java-version: 8
49 java-package: jdk
50 architecture: x64
51 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-
59
60 - name: Build with Maven
61 shell: bash
62 run: |
63 ./mvnw \
64 --show-version --batch-mode --errors --no-transfer-progress \
65 --global-toolchains .github/workflows/maven-toolchains.xml \
66 -DskipTests=true \
67 --projects log4j-perf \
68 --also-make \
69 package
70
71 - name: Upload built sources
72 uses: actions/upload-artifact@v2
73 with:
74 name: benchmarks.jar
75 path: log4j-perf/target/benchmarks.jar
76
77 run:
78
79 needs: build
80
81 runs-on: ${{ matrix.os }}
82
83 strategy:
84 matrix:
85 os: [ macos-latest, ubuntu-latest, windows-latest ]
86 jdk: [ 11, 17 ]
87 concurrency: [ 1, 8 ]
88 jmhCommand:
89 - "-t $CONCURRENCY -f 3 -wi 3 -w 10s -i 4 -r 20s -prof gc -rf json -rff results-layout-jtl.json '.*JsonTemplateLayoutBenchmark.*'"
90 - "-t $CONCURRENCY -f 3 -wi 3 -w 10s -i 4 -r 20s -prof gc -rf json -rff results-util-instant-format.json '.*InstantFormatBenchmark.*'"
91
92 steps:
93
94 - name: Checkout repository
95 uses: actions/checkout@v2
96
97 - name: Download built sources
98 uses: actions/download-artifact@v2
99 with:
100 name: benchmarks.jar
101 path: log4j-perf/target
102
103 - name: Set up JDK ${{ matrix.jdk }}
104 uses: actions/setup-java@v2.4.0
105 with:
106 distribution: temurin
107 java-version: ${{ matrix.jdk }}
108 java-package: jdk
109 architecture: x64
110 cache: maven
111
112 - name: Run benchmarks
113 timeout-minutes: 120
114 shell: bash
115 run: |
116 export CONCURRENCY=${{ matrix.concurrency }}
117 java \
118 -jar log4j-perf/target/benchmarks.jar \
119 ${{ matrix.jmhCommand }}
120
121 - name: Stage benchmark results for commit
122 shell: bash
123 run: |
124
125 # Determine the artifact version.
126 set -x
127 ./mvnw \
128 --batch-mode --quiet \
129 -DforceStdout=true \
130 -Dexpression=project.version \
131 help:evaluate \
132 | tee mvnw-project-version.out
133 echo
134
135 # Determine certain file path properties.
136 export REVISION=$(<mvnw-project-version.out)
137 export BRANCH_NAME=$(echo "$GITHUB_REF" | sed 's/refs\/heads\///g')
138 export INSTANT=$(date -u +%Y%m%d)
139 export OS_NAME=$(echo "${{ matrix.os }}" | sed 's/-latest//g')
140 export RUN_ID=$(printf "%020d" "$GITHUB_RUN_ID")
141
142 # Move and stage the result files.
143 for SRC_FILEPATH in results-*.json; do
144 export BENCHMARK_NAME=$(basename "$SRC_FILEPATH" | sed 's/^results-//g' | sed 's/\.json$//g')
145 export DST_FILEPATH="benchmark/results/$REVISION/$BRANCH_NAME-$INSTANT-$RUN_ID/$BENCHMARK_NAME-O$OS_NAME-J${{ matrix.jdk }}-C${{ matrix.concurrency }}.json"
146 mkdir -v -p $(dirname "$DST_FILEPATH")
147 mv -v "$SRC_FILEPATH" "$DST_FILEPATH"
148 git add "$DST_FILEPATH"
149 done
150
151 # Stash changes for commit.
152 git stash save
153 git clean -f
154
155 - name: Commit benchmark results
156 timeout-minutes: 1
157 shell: bash
158 run: |
159
160 # Checkout the results branch.
161 set -x
162 git fetch origin gh-pages
163 git checkout -B gh-pages origin/gh-pages
164
165 # Stage the stashed changes.
166 # (`show + apply` is preferred over `pop`, since the latter fails if file already exists.)
167 git stash show -p | git apply
168 git add benchmark/results
169 git status --porcelain
170 test $(git status --porcelain | wc -l) -gt 0 || exit 0
171
172 # Commit changes.
173 git config user.name github-actions
174 git config user.email github-actions@github.com
175 git commit -a -m "Add benchmark results for ${{ runner.os }}, JDK ${{ matrix.jdk }}, and concurrency ${{ matrix.concurrency }}."
176
177 # Push changes in a loop to allow concurrent repository modifications.
178 export RETRY=0
179 while [ 1 ]; do
180 set +e
181 git push origin gh-pages 2>&1 | tee git-push.out
182 if [ $? -eq 0 ]; then
183 exit 0
184 else
185 set -e
186 let RETRY+=1
187 echo "retry #$RETRY"
188 git pull -r origin gh-pages
189 fi
190 done
191
192 index:
193
194 runs-on: ubuntu-latest
195 needs: run
196
197 steps:
198
199 - name: Checkout repository
200 uses: actions/checkout@v2
201 with:
202 ref: gh-pages
203
204 - name: Setup Python 3
205 uses: actions/setup-python@v2
206 with:
207 python-version: 3.x
208
209 - name: Index benchmark results
210 timeout-minutes: 1
211 shell: bash
212 run: |
213
214 # Configure the git user.
215 git config user.name github-actions
216 git config user.email github-actions@github.com
217
218 # Push changes in a loop to allow concurrent repository modifications.
219 export RETRY=0
220 export INDEX_FILEPATH=benchmark/results/index.json
221 while [ 1 ]; do
222
223 # Generate the index file.
224 python -c '\
225 import json, os, re;\
226 filepaths=[re.sub("^benchmark/results/", "", os.path.join(root,filename)) \
227 for (root, dirs, filenames) in os.walk("benchmark/results") \
228 for filename in filenames]; \
229 filepaths.remove("index.json"); \
230 print(json.dumps(filepaths))' \
231 >"$INDEX_FILEPATH"
232
233 # Exit if there are no changes, that is, a concurrent job has indexed all results.
234 git diff --exit-code "$INDEX_FILEPATH" && exit 0
235
236 # Commit the index file.
237 git add "$INDEX_FILEPATH"
238 git commit "$INDEX_FILEPATH" -m "Update benchmark results index."
239
240 # Push the index file.
241 set +e
242 git push origin gh-pages 2>&1 | tee git-push.out
243 if [ $? -eq 0 ]; then
244 exit 0
245 else
246 set -e
247 let RETRY+=1
248 echo "retry #$RETRY"
249 git pull -r origin gh-pages
250 fi
251
252 done
+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
-37
.github/workflows/maven-toolchains.xml less more
0 <?xml version="1.0" encoding="UTF8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <toolchains>
18 <toolchain>
19 <type>jdk</type>
20 <provides>
21 <version>1.8</version>
22 </provides>
23 <configuration>
24 <jdkHome>${env.JAVA_HOME_8_X64}</jdkHome>
25 </configuration>
26 </toolchain>
27 <toolchain>
28 <type>jdk</type>
29 <provides>
30 <version>11</version>
31 </provides>
32 <configuration>
33 <jdkHome>${env.JAVA_HOME_11_X64}</jdkHome>
34 </configuration>
35 </toolchain>
36 </toolchains>
2626 velocity.log
2727 felix-cache/
2828 bin/
29 /.metadata/
+0
-1
.java-version less more
0 1.8
0 <?xml version="1.0" encoding="UTF8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18 xsi:schemaLocation="http://maven.apache.org/TOOLCHAINS/1.1.0 http://maven.apache.org/xsd/toolchains-1.1.0.xsd">
19 <toolchain>
20 <type>jdk</type>
21 <provides>
22 <id>java7</id>
23 <version>1.7</version>
24 <vendor>oracle</vendor>
25 </provides>
26 <configuration>
27 <jdkHome>/usr/lib/jvm/java-7-openjdk-amd64</jdkHome>
28 </configuration>
29 </toolchain>
30 <toolchain>
31 <type>jdk</type>
32 <provides>
33 <id>java8</id>
34 <version>1.8</version>
35 <vendor>oracle</vendor>
36 </provides>
37 <configuration>
38 <jdkHome>/usr/lib/jvm/java-8-oracle</jdkHome>
39 </configuration>
40 </toolchain>
41 <toolchain>
42 <type>jdk</type>
43 <provides>
44 <id>java9</id>
45 <version>9</version>
46 <vendor>oracle</vendor>
47 </provides>
48 <configuration>
49 <jdkHome>/usr/lib/jvm/java-9-oracle</jdkHome>
50 </configuration>
51 </toolchain>
52 <toolchain>
53 <type>jdk</type>
54 <provides>
55 <id>java11</id>
56 <version>11</version>
57 <vendor>openjdk</vendor>
58 </provides>
59 <configuration>
60 <jdkHome>/home/travis/openjdk11</jdkHome>
61 </configuration>
62 </toolchain>
63 </toolchains>
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 language: java
13 # sudo enabled because sudo vms have more memory: https://docs.travis-ci.com/user/ci-environment/
14 sudo: true
15 # trusty required for oraclejdk9
16 dist: trusty
17
18 jdk:
19 - openjdk8
20 - openjdk11
21
22 env:
23 global:
24 JAVA_OPTS=-Xmx4g
25
26 install:
27 - ./mvnw --toolchains=./.travis-toolchains.xml install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
28
29 script:
30 - ./mvnw --toolchains=./.travis-toolchains.xml test -B
31
32 after_success:
33 - ./mvnw --show-version -pl !log4j-bom jacoco:prepare-agent test jacoco:report coveralls:report
1414 limitations under the License.
1515 -->
1616 # Building Log4j 2
17
18 To build Log4j 2, you need a JDK implementation version 1.7 or greater, JDK
17
18 To build Log4j 2, you need a JDK implementation version 1.7 or greater, JDK
1919 version 9, and Apache Maven 3.x.
2020
21 Log4j 2.x uses the Java 9 compiler in addition to
21 Log4j 2.x uses the Java 9 compiler in addition to
2222 the Java version installed in the path. This is accomplished by using Maven's toolchains support.
23 Log4j 2 provides sample toolchains XML files in the root folder. This may be used by
24 modifying it and installing the file as toolchains.xml in the .m2 folder or by using the
23 Log4j 2 provides sample toolchains XML files in the root folder. This may be used by
24 modifying it and installing the file as toolchains.xml in the .m2 folder or by using the
2525 following when invoking Maven.
2626
2727 ```
28 [Macintosh] -t ./toolchains-sample-mac.xml
29 [Windows] -t ./toolchains-sample-win.xml
30 [Linux] -t ./toolchains-sample-linux.xml
28 [Macintosh] -t ./toolchains-sample-mac.xml
29 [Windows] -t ./toolchains-sample-win.xml
30 [Linux] -t ./toolchains-sample-linux.xml
3131 ```
3232
3333 To perform the license release audit, a.k.a. "RAT check", run.
3434
3535 mvn apache-rat:check
3636
37 To build the site with Java 7, make sure you give Maven enough memory using
38 `MAVEN_OPTS` with options appropriate for your JVM. Alternatively, you can
39 build with Java 8 and not deal with `MAVEN_OPTS`.
37 To build the site with Java 7, make sure you give Maven enough memory using
38 `MAVEN_OPTS` with options appropriate for your JVM. Alternatively, you can
39 build with Java 8 and not deal with `MAVEN_OPTS`.
4040
4141 To install the jars in your local Maven repository, from a command line, run:
4242
5050
5151 Next, to build the site:
5252
53 If Java 8 runs out of memory building the site, you will need:
53 If Java 7 runs out of memory building the site, you will need:
5454
5555 set MAVEN_OPTS=-Xmx2000m -XX:MaxPermSize=384m
5656
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).
00 Apache Log4j
1 Copyright 1999-2021 Apache Software Foundation
1 Copyright 1999-2017 Apache Software Foundation
22
33 This product includes software developed at
44 The Apache Software Foundation (http://www.apache.org/).
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.12.3 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.12.3 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.12.3 include:
4141
42 * Disable recursive evaluation of Lookups during log event processing. Recursive evaluation is still allwoed while
42 * Disable recursive evaluation of Lookups during log event processing. Recursive evaluation is still allowed 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.
48
49 ## GA Release 2.17.0
47 ## GA Release 2.12.3
5048
5149 Changes in this version include:
5250
5351
5452 ### Fixed Bugs
55 * [LOG4J2-3230](https://issues.apache.org/jira/browse/LOG4J2-3230):
53 * [LOG4J2-3230](https://issues.apache.org/jira/browse/LOG4J2-3230):
5654 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):
55 * [LOG4J2-3242](https://issues.apache.org/jira/browse/LOG4J2-3242):
56 Limit JNDI to the java protocol only. JNDI will remain disabled by default. Rename JNDI enablement property from 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
57 * [LOG4J2-3241](https://issues.apache.org/jira/browse/LOG4J2-3241):
58 Do not declare log4j-api-java9 and log4j-core-java9 as dependencies as it causes problems with the Maven enforcer plugin.
59 * [LOG4J2-3247](https://issues.apache.org/jira/browse/LOG4J2-3247):
6760 PropertiesConfiguration.parseAppenderFilters NPE when parsing properties file filters.
68 * [LOG4J2-3249](https://issues.apache.org/jira/browse/LOG4J2-3249):
61 * [LOG4J2-3249](https://issues.apache.org/jira/browse/LOG4J2-3249):
6962 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):
63 * [LOG4J2-3237](https://issues.apache.org/jira/browse/LOG4J2-3237):
7164 Log4j 1.2 bridge API hard codes the Syslog protocol to TCP.
7265
7366
7467 ---
7568
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
77 Java 7. Java 7 is not longer supported by the Log4j team.
69 Apache Log4j 2.12.3 requires a minimum of Java 7 to build and run. Log4j 2.3 was the
70 last release that supported Java 6.
71
72 Basic compatibility with Log4j 1.x is provided through the log4j-1.2-api component, however it
73 does not implement some of the very implementation specific classes and methods. The package
74 names and Maven groupId have been changed to org.apache.logging.log4j to avoid any conflicts
75 with log4j 1.x.
7876
7977 For complete information on Apache Log4j 2, including instructions on how to submit bug
8078 reports, patches, or suggestions for improvement, see the Apache Apache Log4j 2 website:
8179
8280 https://logging.apache.org/log4j/2.x/
83
+0
-13
SECURITY.md less more
0 # Security Policy
1
2 ## Supported Versions
3
4 Only the most recent release of Apache Log4j 2 is supported.
5
6 ## Reporting a Vulnerability
7
8 If you have encountered an unlisted security vulnerability or other unexpected behaviour that has security impact, please report them privately to the [Log4j Security Team](mailto:private@logging.apache.org).
9
10 ## Past Vulnerabilities
11
12 See [Apache Log4j Security Vulnerabilities](https://logging.apache.org/log4j/2.x/security.html).
125125 <release>
126126 <Version>
127127 <name>Latest stable release</name>
128 <revision>2.12.3</revision>
129 <file-release>https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j/2.12.3/log4j-2.12.3.pom</file-release>
130 <created>2016-10-06</created>
131 </Version>
132 </release>
133 <release>
134 <Version>
135 <name>Latest stable release</name>
136 <revision>2.12.2</revision>
137 <file-release>https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j/2.12.2/log4j-2.12.2.pom</file-release>
138 <created>2016-10-06</created>
139 </Version>
140 </release>
141 <release>
142 <Version>
143 <name>Latest stable release</name>
128144 <revision>2.7</revision>
129145 <file-release>https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j/2.7/log4j-2.7.pom</file-release>
130146 <created>2016-10-06</created>
170186 <name>Apache Log4j 2 - 2.4</name>
171187 <revision>2.4</revision>
172188 <file-release>https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j/2.4/log4j-2.4.pom</file-release>
189 </Version>
190 </release>
191 <release>
192 <Version>
193 <name>Apache Log4j 2 - 2.3.1</name>
194 <revision>2.3.1</revision>
195 <file-release>https://repo.maven.apache.org/maven2/org/apache/logging/log4j/log4j/2.3.1/log4j-2.3.1.pom</file-release>
173196 </Version>
174197 </release>
175198 <release>
+0
-51
jenkins-toolchains-win.xml less more
0 <?xml version="1.0" encoding="UTF8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <toolchains>
18 <!-- JDK toolchains -->
19 <toolchain>
20 <type>jdk</type>
21 <provides>
22 <version>1.7</version>
23 <vendor>sun</vendor>
24 </provides>
25 <configuration>
26 <jdkHome>F:\jenkins\tools\java\latest1.7</jdkHome>
27 </configuration>
28 </toolchain>
29 <toolchain>
30 <type>jdk</type>
31 <provides>
32 <version>1.8</version>
33 <vendor>sun</vendor>
34 </provides>
35 <configuration>
36 <jdkHome>F:\jenkins\tools\java\latest1.8</jdkHome>
37 </configuration>
38 </toolchain>
39 <toolchain>
40 <type>jdk</type>
41 <provides>
42 <version>9</version>
43 <vendor>sun</vendor>
44 </provides>
45 <configuration>
46 <jdkHome>F:\jenkins\tools\java\latest9</jdkHome>
47 </configuration>
48 </toolchain>
49 <!-- other toolchains -->
50 </toolchains>
4343 <vendor>sun</vendor>
4444 </provides>
4545 <configuration>
46 <jdkHome>/home/jenkins/tools/java/latest1.9</jdkHome>
46 <jdkHome>/home/jenkins/tools/java/jdk-9-b181</jdkHome>
4747 </configuration>
4848 </toolchain>
4949
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-1.2-api</artifactId>
26 <packaging>jar</packaging>
26 <packaging>bundle</packaging>
2727 <name>Apache Log4j 1.x Compatibility API</name>
2828 <description>The Apache Log4j 1.x Compatibility API</description>
2929 <properties>
3131 <docLabel>Log4j 1.2 Documentation</docLabel>
3232 <projectDir>/log4j12-api</projectDir>
3333 <module.name>org.apache.log4j</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
3534 </properties>
3635 <dependencies>
3736 <dependency>
38 <groupId>org.junit.vintage</groupId>
39 <artifactId>junit-vintage-engine</artifactId>
40 </dependency>
41 <dependency>
42 <groupId>org.junit.jupiter</groupId>
43 <artifactId>junit-jupiter-engine</artifactId>
37 <groupId>junit</groupId>
38 <artifactId>junit</artifactId>
39 <scope>test</scope>
4440 </dependency>
4541 <!-- Place Felix before Equinox because Felix is signed. -->
4642 <dependency>
6662 <dependency>
6763 <groupId>org.apache.logging.log4j</groupId>
6864 <artifactId>log4j-core</artifactId>
69 <optional>true</optional>
70 </dependency>
71 <!-- Used for JMS appenders (needs an implementation of course) -->
72 <dependency>
73 <groupId>org.jboss.spec.javax.jms</groupId>
74 <artifactId>jboss-jms-api_1.1_spec</artifactId>
75 <scope>provided</scope>
7665 <optional>true</optional>
7766 </dependency>
7867 <dependency>
181170 </reportSets>
182171 </plugin>
183172 <plugin>
184 <groupId>com.github.spotbugs</groupId>
185 <artifactId>spotbugs-maven-plugin</artifactId>
173 <groupId>org.codehaus.mojo</groupId>
174 <artifactId>findbugs-maven-plugin</artifactId>
175 <version>${findbugs.plugin.version}</version>
176 <configuration>
177 <fork>true</fork>
178 <jvmArgs>-Duser.language=en</jvmArgs>
179 <threshold>Normal</threshold>
180 <effort>Default</effort>
181 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
182 </configuration>
186183 </plugin>
187184 <plugin>
188185 <groupId>org.apache.maven.plugins</groupId>
4343 * Create new instance.
4444 */
4545 public AppenderSkeleton() {
46 super();
4647 }
4748
4849 protected AppenderSkeleton(final boolean isActive) {
50 super();
4951 }
5052
5153 @Override
111113 */
112114 @Override
113115 public void doAppend(final LoggingEvent event) {
114 append(event);
115116 }
116117
117118 /**
118 * Sets the {@link ErrorHandler} for this Appender.
119 * Set the {@link ErrorHandler} for this Appender.
119120 *
120121 * @since 0.9.0
121122 */
2424
2525 import org.apache.log4j.helpers.NullEnumeration;
2626 import org.apache.log4j.legacy.core.CategoryUtil;
27 import org.apache.log4j.or.ObjectRenderer;
28 import org.apache.log4j.or.RendererSupport;
2927 import org.apache.log4j.spi.LoggerFactory;
3028 import org.apache.log4j.spi.LoggingEvent;
31 import org.apache.logging.log4j.message.MapMessage;
32 import org.apache.logging.log4j.message.SimpleMessage;
3329 import org.apache.logging.log4j.spi.ExtendedLogger;
3430 import org.apache.logging.log4j.spi.LoggerContext;
3531 import org.apache.logging.log4j.message.LocalizedMessage;
5349
5450 private static final boolean isCoreAvailable;
5551
56 private final Map<Class<?>, ObjectRenderer> rendererMap;
5752
5853 static {
5954 boolean available;
8075 */
8176 protected Category(final LoggerContext context, final String name) {
8277 this.logger = context.getLogger(name);
83 rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
8478 }
8579
8680 /**
9387
9488 private Category(final org.apache.logging.log4j.Logger logger) {
9589 this.logger = logger;
96 rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
9790 }
9891
9992 public static Category getInstance(final String name) {
176169 }
177170
178171 /**
179 * Returns all the currently defined categories in the default hierarchy as an
180 * {@link java.util.Enumeration Enumeration}.
181 *
182 * <p>
183 * The root category is <em>not</em> included in the returned
184 * {@link Enumeration}.
185 * </p>
186 *
187 * @return and Enumeration of the Categories.
188 *
189 * @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
172 Returns all the currently defined categories in the default
173 hierarchy as an {@link java.util.Enumeration Enumeration}.
174
175 <p>The root category is <em>not</em> included in the returned
176 {@link Enumeration}.
177 @return and Enumeration of the Categories.
178
179 @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
190180 */
191181 @SuppressWarnings("rawtypes")
192182 @Deprecated
224214 return getEffectiveLevel();
225215 }
226216
227 private String getLevelStr(final Priority priority) {
228 return priority == null ? null : priority.levelStr;
229 }
230
231217 public void setLevel(final Level level) {
232 setLevel(getLevelStr(level));
218 setLevel(level.levelStr);
233219 }
234220
235221 public final Level getPriority() {
237223 }
238224
239225 public void setPriority(final Priority priority) {
240 setLevel(getLevelStr(priority));
226 setLevel(priority.levelStr);
241227 }
242228
243229 private void setLevel(final String levelStr) {
386372 public static void shutdown() {
387373 }
388374
375
389376 public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) {
390377 final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
378 final Message msg = message instanceof Message ? (Message) message : new ObjectMessage(message);
391379 if (logger instanceof ExtendedLogger) {
392 @SuppressWarnings("unchecked")
393 Message msg = message instanceof Message ? (Message) message : message instanceof Map ?
394 new MapMessage((Map) message) : new ObjectMessage(message);
395 ((ExtendedLogger) logger).logMessage(fqcn, lvl, null, msg, t);
380 ((ExtendedLogger) logger).logMessage(fqcn, lvl, null, new ObjectMessage(message), t);
396381 } else {
397 ObjectRenderer renderer = get(message.getClass());
398 final Message msg = message instanceof Message ? (Message) message : renderer != null ?
399 new RenderedMessage(renderer, message) : new ObjectMessage(message);
400382 logger.log(lvl, msg, t);
401383 }
402384 }
451433 }
452434
453435 /**
454 * If <code>assertion</code> parameter is {@code false}, then logs
455 * <code>msg</code> as an {@link #error(Object) error} statement.
456 *
457 * <p>
458 * The <code>assert</code> method has been renamed to <code>assertLog</code>
459 * because <code>assert</code> is a language reserved word in JDK 1.4.
460 * </p>
461 *
462 * @param assertion The assertion.
463 * @param msg The message to print if <code>assertion</code> is false.
464 *
465 * @since 1.2
436 If <code>assertion</code> parameter is {@code false}, then
437 logs <code>msg</code> as an {@link #error(Object) error} statement.
438
439 <p>The <code>assert</code> method has been renamed to
440 <code>assertLog</code> because <code>assert</code> is a language
441 reserved word in JDK 1.4.
442
443 @param assertion The assertion.
444 @param msg The message to print if <code>assertion</code> is
445 false.
446
447 @since 1.2
466448 */
467449 public void assertLog(final boolean assertion, final String msg) {
468450 if (!assertion) {
486468
487469 public void log(final Priority priority, final Object message, final Throwable t) {
488470 if (isEnabledFor(priority)) {
489 @SuppressWarnings("unchecked")
490 final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message);
471 final Message msg = new ObjectMessage(message);
491472 forcedLog(FQCN, priority, msg, t);
492473 }
493474 }
494475
495476 public void log(final Priority priority, final Object message) {
496477 if (isEnabledFor(priority)) {
497 @SuppressWarnings("unchecked")
498 final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message);
478 final Message msg = new ObjectMessage(message);
499479 forcedLog(FQCN, priority, msg, null);
500480 }
501481 }
507487 }
508488 }
509489
510 private void maybeLog(
511 final String fqcn,
512 final org.apache.logging.log4j.Level level,
513 final Object message,
514 final Throwable throwable) {
490 private void maybeLog(final String fqcn, final org.apache.logging.log4j.Level level,
491 final Object message, final Throwable throwable) {
515492 if (logger.isEnabled(level)) {
516 final Message msg;
517 if (message instanceof String) {
518 msg = new SimpleMessage((String) message);
519 }
520 // SimpleMessage treats String and CharSequence differently, hence
521 // this else-if block.
522 else if (message instanceof CharSequence) {
523 msg = new SimpleMessage((CharSequence) message);
524 } else if (message instanceof Map) {
525 @SuppressWarnings("unchecked")
526 final Map<String, ?> map = (Map<String, ?>) message;
527 msg = new MapMessage<>(map);
493 if (logger instanceof ExtendedLogger) {
494 ((ExtendedLogger) logger).logMessage(fqcn, level, null, new ObjectMessage(message), throwable);
528495 } else {
529 msg = new ObjectMessage(message);
530 }
531 if (logger instanceof ExtendedLogger) {
532 ((ExtendedLogger) logger).logMessage(fqcn, level, null, msg, throwable);
533 } else {
534 logger.log(level, msg, throwable);
496 logger.log(level, message, throwable);
535497 }
536498 }
537499 }
568530 return logger.isEnabled(level);
569531 }
570532
571 private <T> ObjectRenderer get(Class<T> clazz) {
572 ObjectRenderer renderer = null;
573 for (Class<? super T> c = clazz; c != null; c = c.getSuperclass()) {
574 renderer = rendererMap.get(c);
575 if (renderer != null) {
576 return renderer;
577 }
578 renderer = searchInterfaces(c);
579 if (renderer != null) {
580 return renderer;
581 }
582 }
583 return null;
584 }
585
586 ObjectRenderer searchInterfaces(Class<?> c) {
587 ObjectRenderer renderer = rendererMap.get(c);
588 if (renderer != null) {
589 return renderer;
590 }
591 Class<?>[] ia = c.getInterfaces();
592 for (Class<?> clazz : ia) {
593 renderer = searchInterfaces(clazz);
594 if (renderer != null) {
595 return renderer;
596 }
597 }
598 return null;
599 }
600
601533 }
2020 /**
2121 * Console-appender.
2222 */
23 public class ConsoleAppender extends AppenderSkeleton {
23 public class ConsoleAppender extends AppenderSkeleton
24 {
2425
25 /**
26 * {@inheritDoc}
27 */
28 @Override
29 public void close() {
30 }
26 /**
27 * {@inheritDoc}
28 */
29 @Override
30 public void close()
31 {
32 }
3133
32 /**
33 * {@inheritDoc}
34 */
35 @Override
36 public boolean requiresLayout() {
37 return false;
38 }
34 /**
35 * {@inheritDoc}
36 */
37 @Override
38 public boolean requiresLayout()
39 {
40 return false;
41 }
3942
40 /**
41 * {@inheritDoc}
42 */
43 @Override
44 protected void append(final LoggingEvent theEvent) {
45 }
43 /**
44 * {@inheritDoc}
45 */
46 @Override
47 protected void append(final LoggingEvent theEvent)
48 {
49 }
4650
4751 }
1616 package org.apache.log4j;
1717
1818 import java.util.Enumeration;
19 import java.util.HashMap;
20 import java.util.Map;
2119
2220 import org.apache.log4j.helpers.NullEnumeration;
2321 import org.apache.log4j.legacy.core.ContextUtil;
24 import org.apache.log4j.or.ObjectRenderer;
25 import org.apache.log4j.or.RendererSupport;
2622 import org.apache.log4j.spi.HierarchyEventListener;
2723 import org.apache.log4j.spi.LoggerFactory;
2824 import org.apache.log4j.spi.LoggerRepository;
149145 /**
150146 * The Repository.
151147 */
152 private static class Repository implements LoggerRepository, RendererSupport {
153
154 private final Map<Class<?>, ObjectRenderer> rendererMap = new HashMap<>();
155
156 @Override
157 public Map<Class<?>, ObjectRenderer> getRendererMap() {
158 return rendererMap;
159 }
160
148 private static class Repository implements LoggerRepository {
161149 @Override
162150 public void addHierarchyEventListener(final HierarchyEventListener listener) {
163151
2727 */
2828 public final class MDC {
2929
30
3031 private static ThreadLocal<Map<String, Object>> localMap =
3132 new InheritableThreadLocal<Map<String, Object>>() {
3233 @Override
3637
3738 @Override
3839 protected Map<String, Object> childValue(final Map<String, Object> parentValue) {
39 return parentValue == null ? new HashMap<>() : new HashMap<>(parentValue);
40 return parentValue == null ? new HashMap<String, Object>() : new HashMap<>(parentValue);
4041 }
4142 };
4243
+0
-60
log4j-1.2-api/src/main/java/org/apache/log4j/RenderedMessage.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;
17
18 import org.apache.log4j.or.ObjectRenderer;
19 import org.apache.logging.log4j.message.Message;
20
21 /**
22 * Implements object rendering for Log4j 1.x compatibility.
23 */
24 public class RenderedMessage implements Message {
25
26 private final ObjectRenderer renderer;
27 private final Object object;
28 private String rendered = null;
29
30 public RenderedMessage(ObjectRenderer renderer, Object object) {
31 this.renderer = renderer;
32 this.object = object;
33 }
34
35
36 @Override
37 public String getFormattedMessage() {
38 if (rendered == null) {
39 rendered = renderer.doRender(object);
40 }
41
42 return rendered;
43 }
44
45 @Override
46 public String getFormat() {
47 return getFormattedMessage();
48 }
49
50 @Override
51 public Object[] getParameters() {
52 return null;
53 }
54
55 @Override
56 public Throwable getThrowable() {
57 return null;
58 }
59 }
2121 /**
2222 * Simple-layout.
2323 */
24 public class SimpleLayout extends Layout {
24 public class SimpleLayout extends Layout
25 {
2526
26 /**
27 * {@inheritDoc}
28 */
29 @Override
30 public String format(final LoggingEvent theEvent) {
31 return Strings.EMPTY;
32 }
27 /**
28 * {@inheritDoc}
29 */
30 @Override
31 public String format(final LoggingEvent theEvent)
32 {
33 return Strings.EMPTY;
34 }
3335
34 /**
35 * {@inheritDoc}
36 */
37 @Override
38 public boolean ignoresThrowable() {
39 return true;
40 }
36 /**
37 * {@inheritDoc}
38 */
39 @Override
40 public boolean ignoresThrowable()
41 {
42 return true;
43 }
4144
4245 }
+0
-391
log4j-1.2-api/src/main/java/org/apache/log4j/WriterAppender.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
17 package org.apache.log4j;
18
19 import org.apache.log4j.helpers.QuietWriter;
20 import org.apache.log4j.spi.ErrorHandler;
21 import org.apache.log4j.spi.LoggingEvent;
22 import org.apache.logging.log4j.status.StatusLogger;
23
24 import java.io.IOException;
25 import java.io.InterruptedIOException;
26 import java.io.OutputStream;
27 import java.io.OutputStreamWriter;
28 import java.io.Writer;
29
30
31 /**
32 * WriterAppender appends log events to a {@link Writer} or an
33 * {@link OutputStream} depending on the user's choice.
34 */
35 public class WriterAppender extends AppenderSkeleton {
36 private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
37
38 /**
39 * Immediate flush means that the underlying writer or output stream
40 * will be flushed at the end of each append operation unless shouldFlush()
41 * is overridden. Immediate
42 * flush is slower but ensures that each append request is actually
43 * written. If <code>immediateFlush</code> is set to
44 * <code>false</code>, then there is a good chance that the last few
45 * logs events are not actually written to persistent media if and
46 * when the application crashes.
47 *
48 * <p>The <code>immediateFlush</code> variable is set to
49 * <code>true</code> by default.
50 */
51 protected boolean immediateFlush = true;
52
53 /**
54 * The encoding to use when writing. <p>The
55 * <code>encoding</code> variable is set to <code>null</null> by
56 * default which results in the utilization of the system's default
57 * encoding.
58 */
59 protected String encoding;
60
61 /**
62 * This is the {@link QuietWriter quietWriter} where we will write
63 * to.
64 */
65 protected QuietWriter qw;
66
67
68 /**
69 * This default constructor does nothing.
70 */
71 public WriterAppender() {
72 }
73
74 /**
75 * Instantiate a WriterAppender and set the output destination to a
76 * new {@link OutputStreamWriter} initialized with <code>os</code>
77 * as its {@link OutputStream}.
78 */
79 public WriterAppender(Layout layout, OutputStream os) {
80 this(layout, new OutputStreamWriter(os));
81 }
82
83 /**
84 * Instantiate a WriterAppender and set the output destination to
85 * <code>writer</code>.
86 *
87 * <p>The <code>writer</code> must have been previously opened by
88 * the user.
89 */
90 public WriterAppender(Layout layout, Writer writer) {
91 this.layout = layout;
92 this.setWriter(writer);
93 }
94
95 /**
96 * Returns value of the <b>ImmediateFlush</b> option.
97 * @return the value of the immediate flush setting.
98 */
99 public boolean getImmediateFlush() {
100 return immediateFlush;
101 }
102
103 /**
104 * If the <b>ImmediateFlush</b> option is set to
105 * <code>true</code>, the appender will flush at the end of each
106 * write. This is the default behavior. If the option is set to
107 * <code>false</code>, then the underlying stream can defer writing
108 * to physical medium to a later time.
109 *
110 * <p>Avoiding the flush operation at the end of each append results in
111 * a performance gain of 10 to 20 percent. However, there is safety
112 * tradeoff involved in skipping flushing. Indeed, when flushing is
113 * skipped, then it is likely that the last few log events will not
114 * be recorded on disk when the application exits. This is a high
115 * price to pay even for a 20% performance gain.
116 *
117 * @param value the value to set the immediate flush setting to.
118 */
119 public void setImmediateFlush(boolean value) {
120 immediateFlush = value;
121 }
122
123 /**
124 * Does nothing.
125 */
126 @Override
127 public void activateOptions() {
128 }
129
130
131 /**
132 * This method is called by the {@link AppenderSkeleton#doAppend}
133 * method.
134 *
135 * <p>If the output stream exists and is writable then write a log
136 * statement to the output stream. Otherwise, write a single warning
137 * message to <code>System.err</code>.
138 *
139 * <p>The format of the output will depend on this appender's
140 * layout.
141 */
142 @Override
143 public void append(LoggingEvent event) {
144
145 // Reminder: the nesting of calls is:
146 //
147 // doAppend()
148 // - check threshold
149 // - filter
150 // - append();
151 // - checkEntryConditions();
152 // - subAppend();
153
154 if (!checkEntryConditions()) {
155 return;
156 }
157 subAppend(event);
158 }
159
160 /**
161 * This method determines if there is a sense in attempting to append.
162 *
163 * <p>It checks whether there is a set output target and also if
164 * there is a set layout. If these checks fail, then the boolean
165 * value <code>false</code> is returned.
166 * @return true if appending is allowed, false otherwise.
167 */
168 protected boolean checkEntryConditions() {
169 if (this.closed) {
170 LOGGER.warn("Not allowed to write to a closed appender.");
171 return false;
172 }
173
174 if (this.qw == null) {
175 errorHandler.error("No output stream or file set for the appender named [" + name + "].");
176 return false;
177 }
178
179 if (this.layout == null) {
180 errorHandler.error("No layout set for the appender named [" + name + "].");
181 return false;
182 }
183 return true;
184 }
185
186
187 /**
188 * Close this appender instance. The underlying stream or writer is
189 * also closed.
190 *
191 * <p>Closed appenders cannot be reused.
192 *
193 * @see #setWriter
194 * @since 0.8.4
195 */
196 @Override
197 public synchronized void close() {
198 if (this.closed) {
199 return;
200 }
201 this.closed = true;
202 writeFooter();
203 reset();
204 }
205
206 /**
207 * Close the underlying {@link Writer}.
208 */
209 protected void closeWriter() {
210 if (qw != null) {
211 try {
212 qw.close();
213 } catch (IOException e) {
214 if (e instanceof InterruptedIOException) {
215 Thread.currentThread().interrupt();
216 }
217 // There is do need to invoke an error handler at this late
218 // stage.
219 LOGGER.error("Could not close " + qw, e);
220 }
221 }
222 }
223
224 /**
225 * Returns an OutputStreamWriter when passed an OutputStream. The
226 * encoding used will depend on the value of the
227 * <code>encoding</code> property. If the encoding value is
228 * specified incorrectly the writer will be opened using the default
229 * system encoding (an error message will be printed to the LOGGER.
230 * @param os The OutputStream.
231 * @return The OutputStreamWriter.
232 */
233 protected OutputStreamWriter createWriter(OutputStream os) {
234 OutputStreamWriter retval = null;
235
236 String enc = getEncoding();
237 if (enc != null) {
238 try {
239 retval = new OutputStreamWriter(os, enc);
240 } catch (IOException e) {
241 if (e instanceof InterruptedIOException) {
242 Thread.currentThread().interrupt();
243 }
244 LOGGER.warn("Error initializing output writer.");
245 LOGGER.warn("Unsupported encoding?");
246 }
247 }
248 if (retval == null) {
249 retval = new OutputStreamWriter(os);
250 }
251 return retval;
252 }
253
254 public String getEncoding() {
255 return encoding;
256 }
257
258 public void setEncoding(String value) {
259 encoding = value;
260 }
261
262
263 /**
264 * Set the {@link ErrorHandler} for this WriterAppender and also the
265 * underlying {@link QuietWriter} if any.
266 */
267 @Override
268 public synchronized void setErrorHandler(ErrorHandler eh) {
269 if (eh == null) {
270 LOGGER.warn("You have tried to set a null error-handler.");
271 } else {
272 this.errorHandler = eh;
273 if (this.qw != null) {
274 this.qw.setErrorHandler(eh);
275 }
276 }
277 }
278
279 /**
280 * <p>Sets the Writer where the log output will go. The
281 * specified Writer must be opened by the user and be
282 * writable.
283 *
284 * <p>The <code>java.io.Writer</code> will be closed when the
285 * appender instance is closed.
286 *
287 *
288 * <p><b>WARNING:</b> Logging to an unopened Writer will fail.
289 * <p>
290 *
291 * @param writer An already opened Writer.
292 */
293 public synchronized void setWriter(Writer writer) {
294 reset();
295 this.qw = new QuietWriter(writer, errorHandler);
296 //this.tp = new TracerPrintWriter(qw);
297 writeHeader();
298 }
299
300
301 /**
302 * Actual writing occurs here.
303 *
304 * <p>Most subclasses of <code>WriterAppender</code> will need to
305 * override this method.
306 * @param event The event to log.
307 *
308 * @since 0.9.0
309 */
310 protected void subAppend(LoggingEvent event) {
311 this.qw.write(this.layout.format(event));
312
313 if (layout.ignoresThrowable()) {
314 String[] s = event.getThrowableStrRep();
315 if (s != null) {
316 int len = s.length;
317 for (int i = 0; i < len; i++) {
318 this.qw.write(s[i]);
319 this.qw.write(Layout.LINE_SEP);
320 }
321 }
322 }
323
324 if (shouldFlush(event)) {
325 this.qw.flush();
326 }
327 }
328
329
330 /**
331 * The WriterAppender requires a layout. Hence, this method returns
332 * <code>true</code>.
333 */
334 @Override
335 public boolean requiresLayout() {
336 return true;
337 }
338
339 /**
340 * Clear internal references to the writer and other variables.
341 * <p>
342 * Subclasses can override this method for an alternate closing
343 * behavior.
344 */
345 protected void reset() {
346 closeWriter();
347 this.qw = null;
348 //this.tp = null;
349 }
350
351
352 /**
353 * Write a footer as produced by the embedded layout's {@link
354 * Layout#getFooter} method.
355 */
356 protected void writeFooter() {
357 if (layout != null) {
358 String f = layout.getFooter();
359 if (f != null && this.qw != null) {
360 this.qw.write(f);
361 this.qw.flush();
362 }
363 }
364 }
365
366 /**
367 * Write a header as produced by the embedded layout's {@link
368 * Layout#getHeader} method.
369 */
370 protected void writeHeader() {
371 if (layout != null) {
372 String h = layout.getHeader();
373 if (h != null && this.qw != null) {
374 this.qw.write(h);
375 }
376 }
377 }
378
379 /**
380 * Determines whether the writer should be flushed after
381 * this event is written.
382 * @param event The event to log.
383 * @return true if the writer should be flushed.
384 *
385 * @since 1.2.16
386 */
387 protected boolean shouldFlush(final LoggingEvent event) {
388 return immediateFlush;
389 }
390 }
+0
-87
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/AppenderAdapter.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.bridge;
17
18 import java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.apache.log4j.Appender;
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.Layout;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.appender.AbstractAppender;
27 import org.apache.logging.log4j.core.config.Property;
28 import org.apache.logging.log4j.core.filter.CompositeFilter;
29
30 /**
31 * Binds a Log4j 1.x Appender to Log4j 2.
32 */
33 public class AppenderAdapter {
34
35 private final Appender appender;
36 private final Adapter adapter;
37
38 /**
39 * Constructor.
40 * @param appender The Appender to wrap.
41 */
42 public AppenderAdapter(Appender appender) {
43 this.appender = appender;
44 org.apache.logging.log4j.core.Filter appenderFilter = null;
45 if (appender.getFilter() != null) {
46 if (appender.getFilter().getNext() != null) {
47 org.apache.log4j.spi.Filter filter = appender.getFilter();
48 List<org.apache.logging.log4j.core.Filter> filters = new ArrayList<>();
49 while (filter != null) {
50 filters.add(new FilterAdapter(filter));
51 filter = filter.getNext();
52 }
53 appenderFilter = CompositeFilter.createFilters(filters.toArray(Filter.EMPTY_ARRAY));
54 } else {
55 appenderFilter = new FilterAdapter(appender.getFilter());
56 }
57 }
58 this.adapter = new Adapter(appender.getName(), appenderFilter, null, true, null);
59 }
60
61 public Adapter getAdapter() {
62 return adapter;
63 }
64
65 public class Adapter extends AbstractAppender {
66
67 protected Adapter(final String name, final Filter filter, final Layout<? extends Serializable> layout,
68 final boolean ignoreExceptions, final Property[] properties) {
69 super(name, filter, layout, ignoreExceptions, properties);
70 }
71
72 @Override
73 public void append(LogEvent event) {
74 appender.doAppend(new LogEventAdapter(event));
75 }
76
77 @Override
78 public void stop() {
79 appender.close();
80 }
81
82 public Appender getAppender() {
83 return appender;
84 }
85 }
86 }
+0
-115
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/AppenderWrapper.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.bridge;
17
18 import org.apache.log4j.Appender;
19 import org.apache.log4j.Layout;
20 import org.apache.log4j.helpers.AppenderAttachableImpl;
21 import org.apache.log4j.spi.ErrorHandler;
22 import org.apache.log4j.spi.Filter;
23 import org.apache.log4j.spi.LoggingEvent;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.filter.AbstractFilterable;
26 import org.apache.logging.log4j.status.StatusLogger;
27
28 /**
29 * Holds a Log4j 2 Appender in an empty Log4j 1 Appender so it can be extracted when constructing the configuration.
30 * Allows a Log4j 1 Appender to reference a Log4j 2 Appender.
31 */
32 public class AppenderWrapper extends AppenderAttachableImpl implements Appender {
33
34 private static final Logger LOGGER = StatusLogger.getLogger();
35 private final org.apache.logging.log4j.core.Appender appender;
36
37 public AppenderWrapper(org.apache.logging.log4j.core.Appender appender) {
38 this.appender = appender;
39 }
40
41 public org.apache.logging.log4j.core.Appender getAppender() {
42 return appender;
43 }
44
45 @Override
46 public void addFilter(Filter newFilter) {
47 if (appender instanceof AbstractFilterable) {
48 if (newFilter instanceof FilterWrapper) {
49 ((AbstractFilterable) appender).addFilter(((FilterWrapper) newFilter).getFilter());
50 } else {
51 ((AbstractFilterable) appender).addFilter(new FilterAdapter(newFilter));
52 }
53 } else {
54 LOGGER.warn("Unable to add filter to appender {}, it does not support filters", appender.getName());
55 }
56 }
57
58 @Override
59 public Filter getFilter() {
60 return null;
61 }
62
63 @Override
64 public void clearFilters() {
65
66 }
67
68 @Override
69 public void close() {
70 // Not supported with Log4j 2.
71 }
72
73 @Override
74 public void doAppend(LoggingEvent event) {
75 if (event instanceof LogEventAdapter) {
76 appender.append(((LogEventAdapter) event).getEvent());
77 }
78 }
79
80 @Override
81 public String getName() {
82 return appender.getName();
83 }
84
85 @Override
86 public void setErrorHandler(ErrorHandler errorHandler) {
87 appender.setHandler(new ErrorHandlerAdapter(errorHandler));
88 }
89
90 @Override
91 public ErrorHandler getErrorHandler() {
92 return ((ErrorHandlerAdapter)appender.getHandler()).getHandler();
93 }
94
95 @Override
96 public void setLayout(Layout layout) {
97 // Log4j 2 doesn't support this.
98 }
99
100 @Override
101 public Layout getLayout() {
102 return new LayoutWrapper(appender.getLayout());
103 }
104
105 @Override
106 public void setName(String name) {
107 // Log4j 2 doesn't support this.
108 }
109
110 @Override
111 public boolean requiresLayout() {
112 return false;
113 }
114 }
+0
-59
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/ErrorHandlerAdapter.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.bridge;
17
18 import org.apache.log4j.spi.ErrorHandler;
19 import org.apache.logging.log4j.core.LogEvent;
20
21 /**
22 * Makes a Log4j 1 ErrorHandler usable by a Log4j 2 Appender.
23 */
24 public class ErrorHandlerAdapter implements org.apache.logging.log4j.core.ErrorHandler {
25
26 private final ErrorHandler errorHandler;
27
28 public ErrorHandlerAdapter(ErrorHandler errorHandler) {
29 this.errorHandler = errorHandler;
30 }
31
32 public ErrorHandler getHandler() {
33 return errorHandler;
34 }
35
36 @Override
37 public void error(String msg) {
38 errorHandler.error(msg);
39 }
40
41 @Override
42 public void error(String msg, Throwable t) {
43 if (t instanceof Exception) {
44 errorHandler.error(msg, (Exception) t, 0);
45 } else {
46 errorHandler.error(msg);
47 }
48 }
49
50 @Override
51 public void error(String msg, LogEvent event, Throwable t) {
52 if (t == null || t instanceof Exception) {
53 errorHandler.error(msg, (Exception) t, 0, new LogEventAdapter(event));
54 } else {
55 errorHandler.error(msg);
56 }
57 }
58 }
+0
-56
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/FilterAdapter.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.bridge;
17
18 import org.apache.log4j.spi.Filter;
19 import org.apache.log4j.spi.LoggingEvent;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.core.filter.AbstractFilter;
22
23 /**
24 * Binds a Log4j 1.x Filter with Log4j 2.
25 */
26 public class FilterAdapter extends AbstractFilter {
27
28 private final Filter filter;
29
30 public FilterAdapter(Filter filter) {
31 this.filter = filter;
32 }
33
34 @Override
35 public void start() {
36 filter.activateOptions();
37 }
38
39 @Override
40 public Result filter(LogEvent event) {
41 LoggingEvent loggingEvent = new LogEventAdapter(event);
42 Filter next = filter;
43 while (next != null) {
44 switch (filter.decide(loggingEvent)) {
45 case Filter.ACCEPT:
46 return Result.ACCEPT;
47 case Filter.DENY:
48 return Result.DENY;
49 default:
50 }
51 next = filter.getNext();
52 }
53 return Result.NEUTRAL;
54 }
55 }
+0
-47
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/FilterWrapper.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.bridge;
17
18 import org.apache.log4j.spi.Filter;
19 import org.apache.log4j.spi.LoggingEvent;
20
21 /**
22 * This acts as a container for Log4j 2 Filters to be attached to Log4j 1 components. However, the Log4j 2
23 * Filters will always be called directly so this class just acts as a container.
24 */
25 public class FilterWrapper extends Filter {
26
27 private final org.apache.logging.log4j.core.Filter filter;
28
29 public FilterWrapper(org.apache.logging.log4j.core.Filter filter) {
30 this.filter = filter;
31 }
32
33 public org.apache.logging.log4j.core.Filter getFilter() {
34 return filter;
35 }
36
37 /**
38 * This method is never called.
39 * @param event The LoggingEvent to decide upon.
40 * @return 0
41 */
42 @Override
43 public int decide(LoggingEvent event) {
44 return 0;
45 }
46 }
+0
-73
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LayoutAdapter.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.bridge;
17
18 import org.apache.log4j.Layout;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
21
22 import java.util.HashMap;
23 import java.util.Map;
24
25 /**
26 * Class Description goes here.
27 */
28 public class LayoutAdapter implements org.apache.logging.log4j.core.Layout<String> {
29 private Layout layout;
30
31 public LayoutAdapter(Layout layout) {
32 this.layout = layout;
33 }
34
35
36 @Override
37 public byte[] getFooter() {
38 return layout.getFooter() == null ? null : layout.getFooter().getBytes();
39 }
40
41 @Override
42 public byte[] getHeader() {
43 return layout.getHeader() == null ? null : layout.getHeader().getBytes();
44 }
45
46 @Override
47 public byte[] toByteArray(LogEvent event) {
48 String result = layout.format(new LogEventAdapter(event));
49 return result == null ? null : result.getBytes();
50 }
51
52 @Override
53 public String toSerializable(LogEvent event) {
54 return layout.format(new LogEventAdapter(event));
55 }
56
57 @Override
58 public String getContentType() {
59 return layout.getContentType();
60 }
61
62 @Override
63 public Map<String, String> getContentFormat() {
64 return new HashMap<>();
65 }
66
67 @Override
68 public void encode(LogEvent event, ByteBufferDestination destination) {
69 final byte[] data = toByteArray(event);
70 destination.writeBytes(data, 0, data.length);
71 }
72 }
+0
-46
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LayoutWrapper.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.bridge;
17
18 import org.apache.log4j.Layout;
19 import org.apache.log4j.spi.LoggingEvent;
20
21 /**
22 * Bridge between the Log4j 1 Layout and a Log4j 2 Layout.
23 */
24 public class LayoutWrapper extends Layout {
25
26 private final org.apache.logging.log4j.core.Layout<?> layout;
27
28 public LayoutWrapper(org.apache.logging.log4j.core.Layout<?> layout) {
29 this.layout = layout;
30 }
31
32 @Override
33 public String format(LoggingEvent event) {
34 return layout.toSerializable(((LogEventAdapter)event).getEvent()).toString();
35 }
36
37 @Override
38 public boolean ignoresThrowable() {
39 return false;
40 }
41
42 public org.apache.logging.log4j.core.Layout<?> getLayout() {
43 return this.layout;
44 }
45 }
+0
-232
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.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.bridge;
17
18 import org.apache.log4j.Category;
19 import org.apache.log4j.Level;
20 import org.apache.log4j.spi.LocationInfo;
21 import org.apache.log4j.spi.LoggingEvent;
22 import org.apache.log4j.spi.ThrowableInformation;
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.util.Loader;
25 import org.apache.logging.log4j.core.util.Throwables;
26 import org.apache.logging.log4j.spi.StandardLevel;
27 import org.apache.logging.log4j.status.StatusLogger;
28 import org.apache.logging.log4j.util.Strings;
29
30 import java.lang.reflect.Method;
31 import java.util.Map;
32 import java.util.Set;
33
34 /**
35 * Converts a Log4j 2 LogEvent into the components needed by a Log4j 1.x LoggingEvent.
36 * This class requires Log4j 2.
37 */
38 public class LogEventAdapter extends LoggingEvent {
39
40 private static final long JVM_START_TIME = initStartTime();
41
42 private final LogEvent event;
43
44 public LogEventAdapter(LogEvent event) {
45 this.event = event;
46 }
47
48 /**
49 * Returns the time when the application started, in milliseconds
50 * elapsed since 01.01.1970.
51 * @return the time when the JVM started.
52 */
53 public static long getStartTime() {
54 return JVM_START_TIME;
55 }
56
57 /**
58 * Returns the result of {@code ManagementFactory.getRuntimeMXBean().getStartTime()},
59 * or the current system time if JMX is not available.
60 */
61 private static long initStartTime() {
62 // We'd like to call ManagementFactory.getRuntimeMXBean().getStartTime(),
63 // but Google App Engine throws a java.lang.NoClassDefFoundError
64 // "java.lang.management.ManagementFactory is a restricted class".
65 // The reflection is necessary because without it, Google App Engine
66 // will refuse to initialize this class.
67 try {
68 final Class<?> factoryClass = Loader.loadSystemClass("java.lang.management.ManagementFactory");
69 final Method getRuntimeMXBean = factoryClass.getMethod("getRuntimeMXBean");
70 final Object runtimeMXBean = getRuntimeMXBean.invoke(null);
71
72 final Class<?> runtimeMXBeanClass = Loader.loadSystemClass("java.lang.management.RuntimeMXBean");
73 final Method getStartTime = runtimeMXBeanClass.getMethod("getStartTime");
74 return (Long) getStartTime.invoke(runtimeMXBean);
75 } catch (final Throwable t) {
76 StatusLogger.getLogger().error("Unable to call ManagementFactory.getRuntimeMXBean().getStartTime(), "
77 + "using system time for OnStartupTriggeringPolicy", t);
78 // We have little option but to declare "now" as the beginning of time.
79 return System.currentTimeMillis();
80 }
81 }
82
83 public LogEvent getEvent() {
84 return this.event;
85 }
86
87 /**
88 * Set the location information for this logging event. The collected
89 * information is cached for future use.
90 */
91 @Override
92 public LocationInfo getLocationInformation() {
93 return new LocationInfo(event.getSource());
94 }
95
96 /**
97 * Return the level of this event. Use this form instead of directly
98 * accessing the <code>level</code> field.
99 */
100 @Override
101 public Level getLevel() {
102 switch (StandardLevel.getStandardLevel(event.getLevel().intLevel())) {
103 case TRACE:
104 return Level.TRACE;
105 case DEBUG:
106 return Level.DEBUG;
107 case INFO:
108 return Level.INFO;
109 case WARN:
110 return Level.WARN;
111 case FATAL:
112 return Level.FATAL;
113 case OFF:
114 return Level.OFF;
115 case ALL:
116 return Level.ALL;
117 default:
118 return Level.ERROR;
119 }
120 }
121
122 /**
123 * Return the name of the logger. Use this form instead of directly
124 * accessing the <code>categoryName</code> field.
125 */
126 @Override
127 public String getLoggerName() {
128 return event.getLoggerName();
129 }
130
131 @Override
132 public long getTimeStamp() {
133 return event.getTimeMillis();
134 }
135
136 /**
137 * Gets the logger of the event.
138 */
139 @Override
140 public Category getLogger() {
141 return Category.getInstance(event.getLoggerName());
142 }
143
144 /*
145 Return the message for this logging event.
146 */
147 @Override
148 public Object getMessage() {
149 return event.getMessage();
150 }
151
152 /*
153 * This method returns the NDC for this event.
154 */
155 @Override
156 public String getNDC() {
157 return event.getContextStack().toString();
158 }
159
160 /*
161 Returns the context corresponding to the <code>key</code> parameter.
162 */
163 @Override
164 public Object getMDC(String key) {
165 if (event.getContextData() != null) {
166 return event.getContextData().getValue(key);
167 }
168 return null;
169 }
170
171 /**
172 * Obtain a copy of this thread's MDC prior to serialization or
173 * asynchronous logging.
174 */
175 @Override
176 public void getMDCCopy() {
177 }
178
179 @Override
180 public String getRenderedMessage() {
181 return event.getMessage().getFormattedMessage();
182 }
183
184 @Override
185 public String getThreadName() {
186 return event.getThreadName();
187 }
188
189 /**
190 * Returns the throwable information contained within this
191 * event. May be <code>null</code> if there is no such information.
192 *
193 * <p>Note that the {@link Throwable} object contained within a
194 * {@link ThrowableInformation} does not survive serialization.
195 *
196 * @since 1.1
197 */
198 @Override
199 public ThrowableInformation getThrowableInformation() {
200 if (event.getThrown() != null) {
201 return new ThrowableInformation(event.getThrown());
202 }
203 return null;
204 }
205
206 /**
207 * Return this event's throwable's string[] representaion.
208 */
209 @Override
210 public String[] getThrowableStrRep() {
211 if (event.getThrown() != null) {
212 return Throwables.toStringList(event.getThrown()).toArray(Strings.EMPTY_ARRAY);
213 }
214 return null;
215 }
216
217 @Override
218 public String getProperty(final String key) {
219 return event.getContextData().getValue(key);
220 }
221
222 @Override
223 public Set getPropertyKeySet() {
224 return event.getContextData().toMap().keySet();
225 }
226
227 @Override
228 public Map getProperties() {
229 return event.getContextData().toMap();
230 }
231 }
+0
-222
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.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.bridge;
17
18 import org.apache.log4j.NDC;
19 import org.apache.log4j.helpers.OptionConverter;
20 import org.apache.log4j.spi.LocationInfo;
21 import org.apache.log4j.spi.LoggingEvent;
22 import org.apache.log4j.spi.ThrowableInformation;
23 import org.apache.logging.log4j.Level;
24 import org.apache.logging.log4j.Marker;
25 import org.apache.logging.log4j.ThreadContext;
26 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.impl.ThrowableProxy;
28 import org.apache.logging.log4j.core.time.Instant;
29 import org.apache.logging.log4j.core.time.MutableInstant;
30 import org.apache.logging.log4j.message.Message;
31 import org.apache.logging.log4j.message.SimpleMessage;
32 import org.apache.logging.log4j.spi.MutableThreadContextStack;
33 import org.apache.logging.log4j.util.BiConsumer;
34 import org.apache.logging.log4j.util.ReadOnlyStringMap;
35 import org.apache.logging.log4j.util.TriConsumer;
36
37 import java.util.HashMap;
38 import java.util.Map;
39 import java.util.Objects;
40
41 /**
42 * Exposes a Log4j 1 logging event as a Log4j 2 LogEvent.
43 */
44 public class LogEventWrapper implements LogEvent {
45
46 private final LoggingEvent event;
47 private final ContextDataMap contextData;
48 private final MutableThreadContextStack contextStack;
49 private Thread thread;
50
51 public LogEventWrapper(LoggingEvent event) {
52 this.event = event;
53 this.contextData = new ContextDataMap(event.getProperties());
54 this.contextStack = new MutableThreadContextStack(NDC.cloneStack());
55 this.thread = Objects.equals(event.getThreadName(), Thread.currentThread().getName())
56 ? Thread.currentThread() : null;
57 }
58
59 @Override
60 public LogEvent toImmutable() {
61 return this;
62 }
63
64 @Override
65 public Map<String, String> getContextMap() {
66 return contextData;
67 }
68
69 @Override
70 public ReadOnlyStringMap getContextData() {
71 return contextData;
72 }
73
74 @Override
75 public ThreadContext.ContextStack getContextStack() {
76 return contextStack;
77 }
78
79 @Override
80 public String getLoggerFqcn() {
81 return null;
82 }
83
84 @Override
85 public Level getLevel() {
86 return OptionConverter.convertLevel(event.getLevel());
87 }
88
89 @Override
90 public String getLoggerName() {
91 return event.getLoggerName();
92 }
93
94 @Override
95 public Marker getMarker() {
96 return null;
97 }
98
99 @Override
100 public Message getMessage() {
101 return new SimpleMessage(event.getRenderedMessage());
102 }
103
104 @Override
105 public long getTimeMillis() {
106 return event.getTimeStamp();
107 }
108
109 @Override
110 public Instant getInstant() {
111 MutableInstant mutable = new MutableInstant();
112 mutable.initFromEpochMilli(event.getTimeStamp(), 0);
113 return mutable;
114 }
115
116 @Override
117 public StackTraceElement getSource() {
118 LocationInfo info = event.getLocationInformation();
119 return new StackTraceElement(info.getClassName(), info.getMethodName(), info.getFileName(),
120 Integer.parseInt(info.getLineNumber()));
121 }
122
123 @Override
124 public String getThreadName() {
125 return event.getThreadName();
126 }
127
128 @Override
129 public long getThreadId() {
130 Thread thread = getThread();
131 return thread != null ? thread.getId() : 0;
132 }
133
134 @Override
135 public int getThreadPriority() {
136 Thread thread = getThread();
137 return thread != null ? thread.getPriority() : 0;
138 }
139
140 private Thread getThread() {
141 if (thread == null && event.getThreadName() != null) {
142 for (Thread thread : Thread.getAllStackTraces().keySet()) {
143 if (thread.getName().equals(event.getThreadName())) {
144 this.thread = thread;
145 return thread;
146 }
147 }
148 }
149 return thread;
150 }
151
152 @Override
153 public Throwable getThrown() {
154 ThrowableInformation throwableInformation = event.getThrowableInformation();
155 return throwableInformation == null ? null : throwableInformation.getThrowable();
156 }
157
158 @Override
159 public ThrowableProxy getThrownProxy() {
160 return null;
161 }
162
163 @Override
164 public boolean isEndOfBatch() {
165 return false;
166 }
167
168 @Override
169 public boolean isIncludeLocation() {
170 return false;
171 }
172
173 @Override
174 public void setEndOfBatch(boolean endOfBatch) {
175
176 }
177
178 @Override
179 public void setIncludeLocation(boolean locationRequired) {
180
181 }
182
183 @Override
184 public long getNanoTime() {
185 return 0;
186 }
187
188 private static class ContextDataMap extends HashMap<String, String> implements ReadOnlyStringMap {
189
190 ContextDataMap(Map<String, String> map) {
191 if (map != null) {
192 super.putAll(map);
193 }
194 }
195
196 @Override
197 public Map<String, String> toMap() {
198 return this;
199 }
200
201 @Override
202 public boolean containsKey(String key) {
203 return super.containsKey(key);
204 }
205
206 @Override
207 public <V> void forEach(BiConsumer<String, ? super V> action) {
208 super.forEach((k,v) -> action.accept(k, (V) v));
209 }
210
211 @Override
212 public <V, S> void forEach(TriConsumer<String, ? super V, S> action, S state) {
213 super.forEach((k,v) -> action.accept(k, (V) v, state));
214 }
215
216 @Override
217 public <V> V getValue(String key) {
218 return (V) super.get(key);
219 }
220 }
221 }
+0
-48
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyAdapter.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.bridge;
17
18 import org.apache.log4j.rewrite.RewritePolicy;
19 import org.apache.log4j.spi.LoggingEvent;
20 import org.apache.logging.log4j.core.LogEvent;
21
22
23 /**
24 * Binds a Log4j 1.x RewritePolicy to Log4j 2.
25 */
26 public class RewritePolicyAdapter implements org.apache.logging.log4j.core.appender.rewrite.RewritePolicy {
27
28 private final RewritePolicy policy;
29
30 /**
31 * Constructor.
32 */
33 public RewritePolicyAdapter(RewritePolicy policy) {
34 this.policy = policy;
35 }
36
37 @Override
38 public LogEvent rewrite(LogEvent source) {
39 LoggingEvent event = policy.rewrite(new LogEventAdapter(source));
40 return event instanceof LogEventAdapter ? ((LogEventAdapter) event).getEvent() : new LogEventWrapper(event);
41 }
42
43 public RewritePolicy getPolicy() {
44 return this.policy;
45 }
46
47 }
+0
-44
log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyWrapper.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.bridge;
17
18 import org.apache.log4j.spi.LoggingEvent;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.log4j.rewrite.RewritePolicy;
21
22 /**
23 * Binds a Log4j 2 RewritePolicy to Log4j 1.
24 */
25 public class RewritePolicyWrapper implements RewritePolicy {
26
27 private final org.apache.logging.log4j.core.appender.rewrite.RewritePolicy policy;
28
29 public RewritePolicyWrapper(org.apache.logging.log4j.core.appender.rewrite.RewritePolicy policy) {
30 this.policy = policy;
31 }
32
33 @Override
34 public LoggingEvent rewrite(LoggingEvent source) {
35 LogEvent event = source instanceof LogEventAdapter ? ((LogEventAdapter) source).getEvent() :
36 new LogEventWrapper(source);
37 return new LogEventAdapter(policy.rewrite(event));
38 }
39
40 public org.apache.logging.log4j.core.appender.rewrite.RewritePolicy getPolicy() {
41 return policy;
42 }
43 }
+0
-129
log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.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.builders;
17
18 import org.apache.log4j.bridge.FilterAdapter;
19 import org.apache.log4j.bridge.FilterWrapper;
20 import org.apache.log4j.helpers.OptionConverter;
21 import org.apache.log4j.spi.Filter;
22 import org.apache.logging.log4j.Level;
23 import org.apache.logging.log4j.Logger;
24 import org.apache.logging.log4j.core.filter.CompositeFilter;
25 import org.apache.logging.log4j.core.filter.ThresholdFilter;
26 import org.apache.logging.log4j.core.lookup.ConfigurationStrSubstitutor;
27 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
28 import org.apache.logging.log4j.status.StatusLogger;
29
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Properties;
35
36 /**
37 * Base class for Log4j 1 component builders.
38 */
39 public abstract class AbstractBuilder {
40
41 private static Logger LOGGER = StatusLogger.getLogger();
42 protected static final String FILE_PARAM = "File";
43 protected static final String APPEND_PARAM = "Append";
44 protected static final String BUFFERED_IO_PARAM = "BufferedIO";
45 protected static final String BUFFER_SIZE_PARAM = "BufferSize";
46 protected static final String MAX_SIZE_PARAM = "MaxFileSize";
47 protected static final String MAX_BACKUP_INDEX = "MaxBackupIndex";
48 protected static final String RELATIVE = "RELATIVE";
49
50 private final String prefix;
51 private final Properties props;
52 private final StrSubstitutor strSubstitutor;
53
54 public AbstractBuilder() {
55 this.prefix = null;
56 this.props = new Properties();
57 strSubstitutor = new ConfigurationStrSubstitutor(System.getProperties());
58 }
59
60 public AbstractBuilder(String prefix, Properties props) {
61 this.prefix = prefix + ".";
62 this.props = props;
63 Map<String, String> map = new HashMap<>();
64 System.getProperties().forEach((k, v) -> map.put(k.toString(), v.toString()));
65 props.forEach((k, v) -> map.put(k.toString(), v.toString()));
66 strSubstitutor = new ConfigurationStrSubstitutor(map);
67 }
68
69 public String getProperty(String key) {
70 return strSubstitutor.replace(props.getProperty(prefix + key));
71 }
72
73 public String getProperty(String key, String defaultValue) {
74 return strSubstitutor.replace(props.getProperty(prefix + key, defaultValue));
75 }
76
77 public boolean getBooleanProperty(String key) {
78 return Boolean.parseBoolean(strSubstitutor.replace(props.getProperty(prefix + key, Boolean.FALSE.toString())));
79 }
80
81 public int getIntegerProperty(String key, int defaultValue) {
82 String value = getProperty(key);
83 try {
84 if (value != null) {
85 return Integer.parseInt(value);
86 }
87 } catch (Exception ex) {
88 LOGGER.warn("Error converting value {} of {} to an integer: {}", value, key, ex.getMessage());
89 }
90 return defaultValue;
91 }
92
93 public Properties getProperties() {
94 return props;
95 }
96
97
98 protected org.apache.logging.log4j.core.Filter buildFilters(String level, Filter filter) {
99 if (level != null && filter != null) {
100 List<org.apache.logging.log4j.core.Filter> filterList = new ArrayList<>();
101 org.apache.logging.log4j.core.Filter thresholdFilter =
102 ThresholdFilter.createFilter(OptionConverter.convertLevel(level, Level.TRACE),
103 org.apache.logging.log4j.core.Filter.Result.NEUTRAL,
104 org.apache.logging.log4j.core.Filter.Result.DENY);
105 filterList.add(thresholdFilter);
106 Filter f = filter;
107 while (f != null) {
108 if (filter instanceof FilterWrapper) {
109 filterList.add(((FilterWrapper) f).getFilter());
110 } else {
111 filterList.add(new FilterAdapter(f));
112 }
113 f = f.next;
114 }
115 return CompositeFilter.createFilters(filterList.toArray(new org.apache.logging.log4j.core.Filter[0]));
116 } else if (level != null) {
117 return ThresholdFilter.createFilter(OptionConverter.convertLevel(level, Level.TRACE),
118 org.apache.logging.log4j.core.Filter.Result.NEUTRAL,
119 org.apache.logging.log4j.core.Filter.Result.DENY);
120 } else if (filter != null) {
121 if (filter instanceof FilterWrapper) {
122 return ((FilterWrapper) filter).getFilter();
123 }
124 return new FilterAdapter(filter);
125 }
126 return null;
127 }
128 }
+0
-39
log4j-1.2-api/src/main/java/org/apache/log4j/builders/BooleanHolder.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.builders;
17
18 import java.util.concurrent.atomic.AtomicReference;
19
20 /**
21 * Holds Boolean values created inside of a Lambda expression.
22 *
23 * @deprecated Use {@link AtomicReference}.
24 */
25 @Deprecated
26 public class BooleanHolder extends Holder<Boolean> {
27
28 public BooleanHolder() {
29 super(Boolean.FALSE);
30 }
31
32 @Override
33 public void set(Boolean value) {
34 if (value != null) {
35 super.set(value);
36 }
37 }
38 }
+0
-170
log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.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.builders;
17
18 import org.apache.log4j.Appender;
19 import org.apache.log4j.Layout;
20 import org.apache.log4j.builders.appender.AppenderBuilder;
21 import org.apache.log4j.builders.filter.FilterBuilder;
22 import org.apache.log4j.builders.layout.LayoutBuilder;
23 import org.apache.log4j.builders.rewrite.RewritePolicyBuilder;
24 import org.apache.log4j.config.PropertiesConfiguration;
25 import org.apache.log4j.rewrite.RewritePolicy;
26 import org.apache.log4j.spi.Filter;
27 import org.apache.log4j.xml.XmlConfiguration;
28 import org.apache.logging.log4j.Logger;
29 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
30 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
31 import org.apache.logging.log4j.status.StatusLogger;
32 import org.apache.logging.log4j.util.LoaderUtil;
33 import org.w3c.dom.Element;
34
35 import java.lang.reflect.Constructor;
36 import java.lang.reflect.InvocationTargetException;
37 import java.util.Map;
38 import java.util.Properties;
39
40 /**
41 *
42 */
43 public class BuilderManager {
44
45 public static final String CATEGORY = "Log4j Builder";
46 private static final Logger LOGGER = StatusLogger.getLogger();
47 private final Map<String, PluginType<?>> plugins;
48 private static Class<?>[] constructorParams = new Class[] { String.class, Properties.class};
49
50 public BuilderManager() {
51 final PluginManager manager = new PluginManager(CATEGORY);
52 manager.collectPlugins();
53 plugins = manager.getPlugins();
54 }
55
56 public Appender parseAppender(String className, Element appenderElement, XmlConfiguration config) {
57 PluginType<?> plugin = plugins.get(className.toLowerCase());
58 if (plugin != null) {
59 try {
60 AppenderBuilder builder = (AppenderBuilder) LoaderUtil.newInstanceOf(plugin.getPluginClass());
61 return builder.parseAppender(appenderElement, config);
62 } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) {
63 LOGGER.warn("Unable to load plugin: {} due to: {}", plugin.getKey(), ex.getMessage());
64 }
65 }
66 return null;
67 }
68
69 public Appender parseAppender(String name, String className, String prefix, String layoutPrefix,
70 String filterPrefix, Properties props, PropertiesConfiguration config) {
71 PluginType<?> plugin = plugins.get(className.toLowerCase());
72 if (plugin != null) {
73 AppenderBuilder builder = createBuilder(plugin, prefix, props);
74 if (builder != null) {
75 return builder.parseAppender(name, prefix, layoutPrefix, filterPrefix, props, config);
76 }
77 }
78 return null;
79 }
80
81 public Filter parseFilter(String className, Element filterElement, XmlConfiguration config) {
82 PluginType<?> plugin = plugins.get(className.toLowerCase());
83 if (plugin != null) {
84 try {
85 FilterBuilder builder = (FilterBuilder) LoaderUtil.newInstanceOf(plugin.getPluginClass());
86 return builder.parseFilter(filterElement, config);
87 } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) {
88 LOGGER.warn("Unable to load plugin: {} due to: {}", plugin.getKey(), ex.getMessage());
89 }
90 }
91 return null;
92 }
93
94 public Filter parseFilter(String className, String filterPrefix, Properties props, PropertiesConfiguration config) {
95 PluginType<?> plugin = plugins.get(className.toLowerCase());
96 if (plugin != null) {
97 FilterBuilder builder = createBuilder(plugin, filterPrefix, props);
98 if (builder != null) {
99 return builder.parseFilter(config);
100 }
101 }
102 return null;
103 }
104
105 public Layout parseLayout(String className, Element layoutElement, XmlConfiguration config) {
106 PluginType<?> plugin = plugins.get(className.toLowerCase());
107 if (plugin != null) {
108 try {
109 LayoutBuilder builder = (LayoutBuilder) LoaderUtil.newInstanceOf(plugin.getPluginClass());
110 return builder.parseLayout(layoutElement, config);
111 } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) {
112 LOGGER.warn("Unable to load plugin: {} due to: {}", plugin.getKey(), ex.getMessage());
113 }
114 }
115 return null;
116 }
117 public Layout parseLayout(String className, String layoutPrefix, Properties props, PropertiesConfiguration config) {
118 PluginType<?> plugin = plugins.get(className.toLowerCase());
119 if (plugin != null) {
120 LayoutBuilder builder = createBuilder(plugin, layoutPrefix, props);
121 if (builder != null) {
122 return builder.parseLayout(config);
123 }
124 }
125 return null;
126 }
127
128 public RewritePolicy parseRewritePolicy(String className, Element rewriteElement, XmlConfiguration config) {
129 PluginType<?> plugin = plugins.get(className.toLowerCase());
130 if (plugin != null) {
131 try {
132 RewritePolicyBuilder builder = (RewritePolicyBuilder) LoaderUtil.newInstanceOf(plugin.getPluginClass());
133 return builder.parseRewritePolicy(rewriteElement, config);
134 } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) {
135 LOGGER.warn("Unable to load plugin: {} due to: {}", plugin.getKey(), ex.getMessage());
136 }
137 }
138 return null;
139 }
140 public RewritePolicy parseRewritePolicy(String className, String policyPrefix, Properties props, PropertiesConfiguration config) {
141 PluginType<?> plugin = plugins.get(className.toLowerCase());
142 if (plugin != null) {
143 RewritePolicyBuilder builder = createBuilder(plugin, policyPrefix, props);
144 if (builder != null) {
145 return builder.parseRewritePolicy(config);
146 }
147 }
148 return null;
149 }
150
151 private <T extends AbstractBuilder> T createBuilder(PluginType<?> plugin, String prefix, Properties props) {
152 try {
153 Class<?> clazz = plugin.getPluginClass();
154 if (AbstractBuilder.class.isAssignableFrom(clazz)) {
155 @SuppressWarnings("unchecked")
156 Constructor<T> constructor =
157 (Constructor<T>) clazz.getConstructor(constructorParams);
158 return constructor.newInstance(prefix, props);
159 }
160 @SuppressWarnings("unchecked")
161 T builder = (T) LoaderUtil.newInstanceOf(clazz);
162 return builder;
163 } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {
164 LOGGER.warn("Unable to load plugin: {} due to: {}", plugin.getKey(), ex.getMessage());
165 return null;
166 }
167 }
168
169 }
+0
-45
log4j-1.2-api/src/main/java/org/apache/log4j/builders/Holder.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.builders;
17
18 import java.util.concurrent.atomic.AtomicReference;
19
20 /**
21 * Provides a place to hold values generated inside of a Lambda expression.
22 *
23 * @param <V> The type of object referred to by this reference.
24 * @deprecated Use {@link AtomicReference}.
25 */
26 @Deprecated
27 public class Holder<V> {
28 private V value;
29
30 public Holder() {
31 }
32
33 public Holder(V defaultValue) {
34 this.value = defaultValue;
35 }
36
37 public void set(V value) {
38 this.value = value;
39 }
40
41 public V get() {
42 return value;
43 }
44 }
+0
-36
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.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.builders.appender;
17
18 import org.apache.log4j.Appender;
19 import org.apache.log4j.config.PropertiesConfiguration;
20 import org.apache.log4j.xml.XmlConfiguration;
21 import org.w3c.dom.Element;
22
23 import java.util.Properties;
24
25 /**
26 * Define an Appender Builder.
27 */
28 public interface AppenderBuilder {
29
30 Appender parseAppender(Element element, XmlConfiguration configuration);
31
32 Appender parseAppender(String name, String appenderPrefix, String layoutPrefix, String filterPrefix,
33 Properties props, PropertiesConfiguration configuration);
34
35 }
+0
-169
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.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.builders.appender;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.config.Log4j1Configuration.APPENDER_REF_TAG;
20 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
21 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
22 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
23 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
24 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
25
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Properties;
29 import java.util.concurrent.atomic.AtomicBoolean;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.log4j.Appender;
33 import org.apache.log4j.bridge.AppenderWrapper;
34 import org.apache.log4j.builders.AbstractBuilder;
35 import org.apache.log4j.config.Log4j1Configuration;
36 import org.apache.log4j.config.PropertiesConfiguration;
37 import org.apache.log4j.helpers.OptionConverter;
38 import org.apache.log4j.xml.XmlConfiguration;
39 import org.apache.logging.log4j.Logger;
40 import org.apache.logging.log4j.core.appender.AsyncAppender;
41 import org.apache.logging.log4j.core.config.AppenderRef;
42 import org.apache.logging.log4j.core.config.plugins.Plugin;
43 import org.apache.logging.log4j.status.StatusLogger;
44 import org.apache.logging.log4j.util.Strings;
45 import org.w3c.dom.Element;
46
47
48 /**
49 * Build an Asynch Appender
50 */
51 @Plugin(name = "org.apache.log4j.AsyncAppender", category = CATEGORY)
52 public class AsyncAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
53
54 private static final Logger LOGGER = StatusLogger.getLogger();
55 private static final String BLOCKING_PARAM = "Blocking";
56 private static final String INCLUDE_LOCATION_PARAM = "IncludeLocation";
57
58 public AsyncAppenderBuilder() {
59 }
60
61 public AsyncAppenderBuilder(String prefix, Properties props) {
62 super(prefix, props);
63 }
64
65 @Override
66 public Appender parseAppender(final Element appenderElement, final XmlConfiguration config) {
67 String name = appenderElement.getAttribute(NAME_ATTR);
68 AtomicReference<List<String>> appenderRefs = new AtomicReference<>(new ArrayList<>());
69 AtomicBoolean blocking = new AtomicBoolean();
70 AtomicBoolean includeLocation = new AtomicBoolean();
71 AtomicReference<String> level = new AtomicReference<>("trace");
72 AtomicReference<Integer> bufferSize = new AtomicReference<>(1024);
73 forEachElement(appenderElement.getChildNodes(), currentElement -> {
74 switch (currentElement.getTagName()) {
75 case APPENDER_REF_TAG:
76 Appender appender = config.findAppenderByReference(currentElement);
77 if (appender != null) {
78 appenderRefs.get().add(appender.getName());
79 }
80 break;
81 case PARAM_TAG: {
82 switch (currentElement.getAttribute(NAME_ATTR)) {
83 case BUFFER_SIZE_PARAM: {
84 String value = currentElement.getAttribute(VALUE_ATTR);
85 if (value == null) {
86 LOGGER.warn("No value supplied for BufferSize parameter. Defaulting to 1024.");
87 } else {
88 bufferSize.set(Integer.parseInt(value));
89 }
90 break;
91 }
92 case BLOCKING_PARAM: {
93 String value = currentElement.getAttribute(VALUE_ATTR);
94 if (value == null) {
95 LOGGER.warn("No value supplied for Blocking parameter. Defaulting to false.");
96 } else {
97 blocking.set(Boolean.parseBoolean(value));
98 }
99 break;
100 }
101 case INCLUDE_LOCATION_PARAM: {
102 String value = currentElement.getAttribute(VALUE_ATTR);
103 if (value == null) {
104 LOGGER.warn("No value supplied for IncludeLocation parameter. Defaulting to false.");
105 } else {
106 includeLocation.set(Boolean.parseBoolean(value));
107 }
108 break;
109 }
110 case THRESHOLD_PARAM: {
111 String value = currentElement.getAttribute(VALUE_ATTR);
112 if (value == null) {
113 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
114 } else {
115 level.set(value);
116 }
117 break;
118 }
119 }
120 break;
121 }
122 }
123 });
124 return createAppender(name, level.get(), appenderRefs.get().toArray(Strings.EMPTY_ARRAY), blocking.get(),
125 bufferSize.get(), includeLocation.get(), config);
126 }
127
128 @Override
129 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
130 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
131 String appenderRef = getProperty(APPENDER_REF_TAG);
132 boolean blocking = getBooleanProperty(BLOCKING_PARAM);
133 boolean includeLocation = getBooleanProperty(INCLUDE_LOCATION_PARAM);
134 String level = getProperty(THRESHOLD_PARAM);
135 int bufferSize = getIntegerProperty(BUFFER_SIZE_PARAM, 1024);
136 if (appenderRef == null) {
137 LOGGER.warn("No appender references configured for AsyncAppender {}", name);
138 return null;
139 }
140 Appender appender = configuration.parseAppender(props, appenderRef);
141 if (appender == null) {
142 LOGGER.warn("Cannot locate Appender {}", appenderRef);
143 return null;
144 }
145 return createAppender(name, level, new String[] {appenderRef}, blocking, bufferSize, includeLocation,
146 configuration);
147 }
148
149 private <T extends Log4j1Configuration> Appender createAppender(String name, String level,
150 String[] appenderRefs, boolean blocking, int bufferSize, boolean includeLocation,
151 T configuration) {
152 org.apache.logging.log4j.Level logLevel = OptionConverter.convertLevel(level,
153 org.apache.logging.log4j.Level.TRACE);
154 AppenderRef[] refs = new AppenderRef[appenderRefs.length];
155 int index = 0;
156 for (String appenderRef : appenderRefs) {
157 refs[index++] = AppenderRef.createAppenderRef(appenderRef, logLevel, null);
158 }
159 return new AppenderWrapper(AsyncAppender.newBuilder()
160 .setName(name)
161 .setAppenderRefs(refs)
162 .setBlocking(blocking)
163 .setBufferSize(bufferSize)
164 .setIncludeLocation(includeLocation)
165 .setConfiguration(configuration)
166 .build());
167 }
168 }
+0
-160
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/ConsoleAppenderBuilder.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.builders.appender;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
20 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
21 import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
22 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
23 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
24 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
25 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
26
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Properties;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.log4j.Appender;
33 import org.apache.log4j.Layout;
34 import org.apache.log4j.bridge.AppenderWrapper;
35 import org.apache.log4j.bridge.LayoutAdapter;
36 import org.apache.log4j.bridge.LayoutWrapper;
37 import org.apache.log4j.builders.AbstractBuilder;
38 import org.apache.log4j.config.Log4j1Configuration;
39 import org.apache.log4j.config.PropertiesConfiguration;
40 import org.apache.log4j.spi.Filter;
41 import org.apache.log4j.xml.XmlConfiguration;
42 import org.apache.logging.log4j.Logger;
43 import org.apache.logging.log4j.core.appender.ConsoleAppender;
44 import org.apache.logging.log4j.core.config.plugins.Plugin;
45 import org.apache.logging.log4j.status.StatusLogger;
46 import org.w3c.dom.Element;
47
48 /**
49 * Build a Console Appender
50 */
51 @Plugin(name = "org.apache.log4j.ConsoleAppender", category = CATEGORY)
52 public class ConsoleAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
53 private static final String SYSTEM_OUT = "System.out";
54 private static final String SYSTEM_ERR = "System.err";
55 private static final String TARGET = "target";
56
57 private static final Logger LOGGER = StatusLogger.getLogger();
58
59 public ConsoleAppenderBuilder() {
60 }
61
62 public ConsoleAppenderBuilder(String prefix, Properties props) {
63 super(prefix, props);
64 }
65
66 @Override
67 public Appender parseAppender(final Element appenderElement, final XmlConfiguration config) {
68 String name = appenderElement.getAttribute(NAME_ATTR);
69 AtomicReference<String> target = new AtomicReference<>(SYSTEM_OUT);
70 AtomicReference<Layout> layout = new AtomicReference<>();
71 AtomicReference<List<Filter>> filters = new AtomicReference<>(new ArrayList<>());
72 AtomicReference<String> level = new AtomicReference<>();
73 forEachElement(appenderElement.getChildNodes(), currentElement -> {
74 switch (currentElement.getTagName()) {
75 case LAYOUT_TAG:
76 layout.set(config.parseLayout(currentElement));
77 break;
78 case FILTER_TAG:
79 filters.get().add(config.parseFilters(currentElement));
80 break;
81 case PARAM_TAG: {
82 switch (currentElement.getAttribute(NAME_ATTR)) {
83 case TARGET: {
84 String value = currentElement.getAttribute(VALUE_ATTR);
85 if (value == null) {
86 LOGGER.warn("No value supplied for target parameter. Defaulting to System.out.");
87 } else {
88 switch (value) {
89 case SYSTEM_OUT:
90 target.set(SYSTEM_OUT);
91 break;
92 case SYSTEM_ERR:
93 target.set(SYSTEM_ERR);
94 break;
95 default:
96 LOGGER.warn("Invalid value \"{}\" for target parameter. Using default of System.out",
97 value);
98 }
99 }
100 break;
101 }
102 case THRESHOLD_PARAM: {
103 String value = currentElement.getAttribute(VALUE_ATTR);
104 if (value == null) {
105 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
106 } else {
107 level.set(value);
108 }
109 break;
110 }
111 }
112 break;
113 }
114 }
115 });
116 Filter head = null;
117 Filter current = null;
118 for (Filter f : filters.get()) {
119 if (head == null) {
120 head = f;
121 } else {
122 current.next = f;
123 }
124 current = f;
125 }
126 return createAppender(name, layout.get(), head, level.get(), target.get(), config);
127 }
128
129 @Override
130 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
131 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
132 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
133 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
134 String level = getProperty(THRESHOLD_PARAM);
135 String target = getProperty(TARGET);
136 return createAppender(name, layout, filter, level, target, configuration);
137 }
138
139 private <T extends Log4j1Configuration> Appender createAppender(String name, Layout layout, Filter filter,
140 String level, String target, T configuration) {
141 org.apache.logging.log4j.core.Layout<?> consoleLayout = null;
142
143 if (layout instanceof LayoutWrapper) {
144 consoleLayout = ((LayoutWrapper) layout).getLayout();
145 } else if (layout != null) {
146 consoleLayout = new LayoutAdapter(layout);
147 }
148 org.apache.logging.log4j.core.Filter consoleFilter = buildFilters(level, filter);
149 ConsoleAppender.Target consoleTarget = SYSTEM_ERR.equals(target)
150 ? ConsoleAppender.Target.SYSTEM_ERR : ConsoleAppender.Target.SYSTEM_OUT;
151 return new AppenderWrapper(ConsoleAppender.newBuilder()
152 .setName(name)
153 .setTarget(consoleTarget)
154 .setLayout(consoleLayout)
155 .setFilter(consoleFilter)
156 .setConfiguration(configuration)
157 .build());
158 }
159 }
+0
-191
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/DailyRollingFileAppenderBuilder.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.builders.appender;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
20 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
21 import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
22 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
23 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
24 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
25 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
26
27 import java.util.Properties;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.log4j.Appender;
33 import org.apache.log4j.Layout;
34 import org.apache.log4j.bridge.AppenderWrapper;
35 import org.apache.log4j.bridge.LayoutAdapter;
36 import org.apache.log4j.bridge.LayoutWrapper;
37 import org.apache.log4j.builders.AbstractBuilder;
38 import org.apache.log4j.config.Log4j1Configuration;
39 import org.apache.log4j.config.PropertiesConfiguration;
40 import org.apache.log4j.spi.Filter;
41 import org.apache.log4j.xml.XmlConfiguration;
42 import org.apache.logging.log4j.Logger;
43 import org.apache.logging.log4j.core.appender.RollingFileAppender;
44 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
45 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
46 import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
47 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
48 import org.apache.logging.log4j.core.config.plugins.Plugin;
49 import org.apache.logging.log4j.status.StatusLogger;
50 import org.w3c.dom.Element;
51
52
53 /**
54 * Build a Daily Rolling File Appender
55 */
56 @Plugin(name = "org.apache.log4j.DailyRollingFileAppender", category = CATEGORY)
57 public class DailyRollingFileAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
58
59 private static final Logger LOGGER = StatusLogger.getLogger();
60
61 public DailyRollingFileAppenderBuilder() {
62 }
63
64 public DailyRollingFileAppenderBuilder(String prefix, Properties props) {
65 super(prefix, props);
66 }
67
68
69 @Override
70 public Appender parseAppender(final Element appenderElement, final XmlConfiguration config) {
71 String name = appenderElement.getAttribute(NAME_ATTR);
72 AtomicReference<Layout> layout = new AtomicReference<>();
73 AtomicReference<Filter> filter = new AtomicReference<>();
74 AtomicReference<String> fileName = new AtomicReference<>();
75 AtomicReference<String> level = new AtomicReference<>();
76 AtomicBoolean immediateFlush = new AtomicBoolean();
77 AtomicBoolean append = new AtomicBoolean();
78 AtomicBoolean bufferedIo = new AtomicBoolean();
79 AtomicInteger bufferSize = new AtomicInteger(8192);
80 forEachElement(appenderElement.getChildNodes(), currentElement -> {
81 switch (currentElement.getTagName()) {
82 case LAYOUT_TAG:
83 layout.set(config.parseLayout(currentElement));
84 break;
85 case FILTER_TAG:
86 filter.set(config.parseFilters(currentElement));
87 break;
88 case PARAM_TAG: {
89 switch (currentElement.getAttribute(NAME_ATTR)) {
90 case FILE_PARAM:
91 fileName.set(currentElement.getAttribute(VALUE_ATTR));
92 break;
93 case APPEND_PARAM: {
94 String bool = currentElement.getAttribute(VALUE_ATTR);
95 if (bool != null) {
96 append.set(Boolean.parseBoolean(bool));
97 } else {
98 LOGGER.warn("No value provided for append parameter");
99 }
100 break;
101 }
102 case BUFFERED_IO_PARAM: {
103 String bool = currentElement.getAttribute(VALUE_ATTR);
104 if (bool != null) {
105 bufferedIo.set(Boolean.parseBoolean(bool));
106 } else {
107 LOGGER.warn("No value provided for bufferedIo parameter");
108 }
109 break;
110 }
111 case BUFFER_SIZE_PARAM: {
112 String size = currentElement.getAttribute(VALUE_ATTR);
113 if (size != null) {
114 bufferSize.set(Integer.parseInt(size));
115 } else {
116 LOGGER.warn("No value provide for bufferSize parameter");
117 }
118 break;
119 }
120 case THRESHOLD_PARAM: {
121 String value = currentElement.getAttribute(VALUE_ATTR);
122 if (value == null) {
123 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
124 } else {
125 level.set(value);
126 }
127 break;
128 }
129 }
130 break;
131 }
132 }
133 });
134 return createAppender(name, layout.get(), filter.get(), fileName.get(), append.get(), immediateFlush.get(),
135 level.get(), bufferedIo.get(), bufferSize.get(), config);
136 }
137
138 @Override
139 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
140 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
141 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
142 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
143 String fileName = getProperty(FILE_PARAM);
144 String level = getProperty(THRESHOLD_PARAM);
145 boolean append = getBooleanProperty(APPEND_PARAM);
146 boolean immediateFlush = false;
147 boolean bufferedIo = getBooleanProperty(BUFFERED_IO_PARAM);
148 int bufferSize = Integer.parseInt(getProperty(BUFFER_SIZE_PARAM, "8192"));
149 return createAppender(name, layout, filter, fileName, append, immediateFlush,
150 level, bufferedIo, bufferSize, configuration);
151 }
152
153 private <T extends Log4j1Configuration> Appender createAppender(final String name, final Layout layout,
154 final Filter filter, final String fileName, final boolean append, boolean immediateFlush,
155 final String level, final boolean bufferedIo, final int bufferSize, final T configuration) {
156
157 org.apache.logging.log4j.core.Layout<?> fileLayout = null;
158 if (bufferedIo) {
159 immediateFlush = true;
160 }
161 if (layout instanceof LayoutWrapper) {
162 fileLayout = ((LayoutWrapper) layout).getLayout();
163 } else if (layout != null) {
164 fileLayout = new LayoutAdapter(layout);
165 }
166 org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
167 if (fileName == null) {
168 LOGGER.warn("Unable to create File Appender, no file name provided");
169 return null;
170 }
171 String filePattern = fileName +"%d{yyy-MM-dd}";
172 TriggeringPolicy policy = TimeBasedTriggeringPolicy.newBuilder().withModulate(true).build();
173 RolloverStrategy strategy = DefaultRolloverStrategy.newBuilder()
174 .withConfig(configuration)
175 .withMax(Integer.toString(Integer.MAX_VALUE))
176 .build();
177 return new AppenderWrapper(RollingFileAppender.newBuilder()
178 .setName(name)
179 .setConfiguration(configuration)
180 .setLayout(fileLayout)
181 .setFilter(fileFilter)
182 .withFileName(fileName)
183 .withBufferSize(bufferSize)
184 .withImmediateFlush(immediateFlush)
185 .withFilePattern(filePattern)
186 .withPolicy(policy)
187 .withStrategy(strategy)
188 .build());
189 }
190 }
+0
-179
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/FileAppenderBuilder.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.builders.appender;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
20 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
21 import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
22 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
23 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
24 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
25 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
26
27 import java.util.Properties;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.log4j.Appender;
33 import org.apache.log4j.Layout;
34 import org.apache.log4j.bridge.AppenderWrapper;
35 import org.apache.log4j.bridge.LayoutAdapter;
36 import org.apache.log4j.bridge.LayoutWrapper;
37 import org.apache.log4j.builders.AbstractBuilder;
38 import org.apache.log4j.config.Log4j1Configuration;
39 import org.apache.log4j.config.PropertiesConfiguration;
40 import org.apache.log4j.spi.Filter;
41 import org.apache.log4j.xml.XmlConfiguration;
42 import org.apache.logging.log4j.Logger;
43 import org.apache.logging.log4j.core.appender.FileAppender;
44 import org.apache.logging.log4j.core.config.plugins.Plugin;
45 import org.apache.logging.log4j.status.StatusLogger;
46 import org.w3c.dom.Element;
47
48 /**
49 * Build a File Appender
50 */
51 @Plugin(name = "org.apache.log4j.FileAppender", category = CATEGORY)
52 public class FileAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
53
54 private static final Logger LOGGER = StatusLogger.getLogger();
55
56 public FileAppenderBuilder() {
57 }
58
59 public FileAppenderBuilder(String prefix, Properties props) {
60 super(prefix, props);
61 }
62
63 @Override
64 public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
65 String name = appenderElement.getAttribute(NAME_ATTR);
66 AtomicReference<Layout> layout = new AtomicReference<>();
67 AtomicReference<Filter> filter = new AtomicReference<>();
68 AtomicReference<String> fileName = new AtomicReference<>();
69 AtomicReference<String> level = new AtomicReference<>();
70 AtomicBoolean immediateFlush = new AtomicBoolean();
71 AtomicBoolean append = new AtomicBoolean();
72 AtomicBoolean bufferedIo = new AtomicBoolean();
73 AtomicInteger bufferSize = new AtomicInteger(8192);
74 forEachElement(appenderElement.getChildNodes(), currentElement -> {
75 switch (currentElement.getTagName()) {
76 case LAYOUT_TAG:
77 layout.set(config.parseLayout(currentElement));
78 break;
79 case FILTER_TAG:
80 filter.set(config.parseFilters(currentElement));
81 break;
82 case PARAM_TAG: {
83 switch (currentElement.getAttribute(NAME_ATTR)) {
84 case FILE_PARAM:
85 fileName.set(currentElement.getAttribute(VALUE_ATTR));
86 break;
87 case APPEND_PARAM: {
88 String bool = currentElement.getAttribute(VALUE_ATTR);
89 if (bool != null) {
90 append.set(Boolean.parseBoolean(bool));
91 } else {
92 LOGGER.warn("No value provided for append parameter");
93 }
94 break;
95 }
96 case BUFFERED_IO_PARAM: {
97 String bool = currentElement.getAttribute(VALUE_ATTR);
98 if (bool != null) {
99 bufferedIo.set(Boolean.parseBoolean(bool));
100 } else {
101 LOGGER.warn("No value provided for bufferedIo parameter");
102 }
103 break;
104 }
105 case BUFFER_SIZE_PARAM: {
106 String size = currentElement.getAttribute(VALUE_ATTR);
107 if (size != null) {
108 bufferSize.set(Integer.parseInt(size));
109 } else {
110 LOGGER.warn("No value provide for bufferSize parameter");
111 }
112 break;
113 }
114 case THRESHOLD_PARAM: {
115 String value = currentElement.getAttribute(VALUE_ATTR);
116 if (value == null) {
117 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
118 } else {
119 level.set(value);
120 }
121 break;
122 }
123 }
124 break;
125 }
126 }
127 });
128
129 return createAppender(name, config, layout.get(), filter.get(), fileName.get(), level.get(),
130 immediateFlush.get(), append.get(), bufferedIo.get(), bufferSize.get());
131 }
132
133
134 @Override
135 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
136 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
137 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
138 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
139 String level = getProperty(THRESHOLD_PARAM);
140 String fileName = getProperty(FILE_PARAM);
141 boolean append = getBooleanProperty(APPEND_PARAM);
142 boolean immediateFlush = false;
143 boolean bufferedIo = getBooleanProperty(BUFFERED_IO_PARAM);
144 int bufferSize = Integer.parseInt(getProperty(BUFFER_SIZE_PARAM, "8192"));
145 return createAppender(name, configuration, layout, filter, fileName, level, immediateFlush,
146 append, bufferedIo, bufferSize);
147 }
148
149 private Appender createAppender(final String name, final Log4j1Configuration configuration, final Layout layout,
150 final Filter filter, final String fileName, String level, boolean immediateFlush, final boolean append,
151 final boolean bufferedIo, final int bufferSize) {
152 org.apache.logging.log4j.core.Layout<?> fileLayout = null;
153 if (bufferedIo) {
154 immediateFlush = true;
155 }
156 if (layout instanceof LayoutWrapper) {
157 fileLayout = ((LayoutWrapper) layout).getLayout();
158 } else if (layout != null) {
159 fileLayout = new LayoutAdapter(layout);
160 }
161 org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
162 if (fileName == null) {
163 LOGGER.warn("Unable to create File Appender, no file name provided");
164 return null;
165 }
166 return new AppenderWrapper(FileAppender.newBuilder()
167 .setName(name)
168 .setConfiguration(configuration)
169 .setLayout(fileLayout)
170 .setFilter(fileFilter)
171 .withFileName(fileName)
172 .withImmediateFlush(immediateFlush)
173 .withAppend(append)
174 .withBufferedIo(bufferedIo)
175 .withBufferSize(bufferSize)
176 .build());
177 }
178 }
+0
-53
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/NullAppenderBuilder.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.builders.appender;
17
18 import org.apache.log4j.Appender;
19 import org.apache.log4j.bridge.AppenderWrapper;
20 import org.apache.log4j.config.PropertiesConfiguration;
21 import org.apache.log4j.xml.XmlConfiguration;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.core.appender.NullAppender;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.status.StatusLogger;
26 import org.w3c.dom.Element;
27
28 import java.util.Properties;
29
30 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
31
32 /**
33 * Build a Null Appender
34 */
35 @Plugin(name = "org.apache.log4j.varia.NullAppender", category = CATEGORY)
36 public class NullAppenderBuilder implements AppenderBuilder {
37
38 private static final Logger LOGGER = StatusLogger.getLogger();
39
40 @Override
41 public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
42 String name = appenderElement.getAttribute("name");
43 return new AppenderWrapper(NullAppender.createAppender(name));
44 }
45
46
47 @Override
48 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
49 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
50 return new AppenderWrapper(NullAppender.createAppender(name));
51 }
52 }
+0
-153
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RewriteAppenderBuilder.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.builders.appender;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.config.Log4j1Configuration.APPENDER_REF_TAG;
20 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
21 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
22 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
23 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
24 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
25 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
26
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Properties;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.log4j.Appender;
33 import org.apache.log4j.bridge.AppenderWrapper;
34 import org.apache.log4j.bridge.RewritePolicyAdapter;
35 import org.apache.log4j.bridge.RewritePolicyWrapper;
36 import org.apache.log4j.builders.AbstractBuilder;
37 import org.apache.log4j.config.Log4j1Configuration;
38 import org.apache.log4j.config.PropertiesConfiguration;
39 import org.apache.log4j.helpers.OptionConverter;
40 import org.apache.log4j.rewrite.RewritePolicy;
41 import org.apache.log4j.spi.Filter;
42 import org.apache.log4j.xml.XmlConfiguration;
43 import org.apache.logging.log4j.Logger;
44 import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
45 import org.apache.logging.log4j.core.config.AppenderRef;
46 import org.apache.logging.log4j.core.config.plugins.Plugin;
47 import org.apache.logging.log4j.status.StatusLogger;
48 import org.apache.logging.log4j.util.Strings;
49 import org.w3c.dom.Element;
50
51
52 /**
53 * Build an Asynch Appender
54 */
55 @Plugin(name = "org.apache.log4j.rewrite.RewriteAppender", category = CATEGORY)
56 public class RewriteAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
57
58 private static final Logger LOGGER = StatusLogger.getLogger();
59 private static final String REWRITE_POLICY_TAG = "rewritePolicy";
60
61 public RewriteAppenderBuilder() {
62 }
63
64 public RewriteAppenderBuilder(String prefix, Properties props) {
65 super(prefix, props);
66 }
67
68 @Override
69 public Appender parseAppender(final Element appenderElement, final XmlConfiguration config) {
70 String name = appenderElement.getAttribute(NAME_ATTR);
71 AtomicReference<List<String>> appenderRefs = new AtomicReference<>(new ArrayList<>());
72 AtomicReference<RewritePolicy> rewritePolicyHolder = new AtomicReference<>();
73 AtomicReference<String> level = new AtomicReference<>();
74 AtomicReference<Filter> filter = new AtomicReference<>();
75 forEachElement(appenderElement.getChildNodes(), currentElement -> {
76 switch (currentElement.getTagName()) {
77 case APPENDER_REF_TAG:
78 Appender appender = config.findAppenderByReference(currentElement);
79 if (appender != null) {
80 appenderRefs.get().add(appender.getName());
81 }
82 break;
83 case REWRITE_POLICY_TAG: {
84 RewritePolicy policy = config.parseRewritePolicy(currentElement);
85 if (policy != null) {
86 rewritePolicyHolder.set(policy);
87 }
88 break;
89 }
90 case FILTER_TAG: {
91 filter.set(config.parseFilters(currentElement));
92 break;
93 }
94 case PARAM_TAG: {
95 if (currentElement.getAttribute(NAME_ATTR).equalsIgnoreCase(THRESHOLD_PARAM)) {
96 String value = currentElement.getAttribute(VALUE_ATTR);
97 if (value == null) {
98 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
99 } else {
100 level.set(value);
101 }
102 }
103 break;
104 }
105 }
106 });
107 return createAppender(name, level.get(), appenderRefs.get().toArray(Strings.EMPTY_ARRAY), rewritePolicyHolder.get(),
108 filter.get(), config);
109 }
110
111 @Override
112 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
113 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
114 String appenderRef = getProperty(APPENDER_REF_TAG);
115 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
116 String policyPrefix = appenderPrefix + ".rewritePolicy";
117 String className = getProperty(policyPrefix);
118 RewritePolicy policy = configuration.getBuilderManager().parseRewritePolicy(className, policyPrefix,
119 props, configuration);
120 String level = getProperty(THRESHOLD_PARAM);
121 if (appenderRef == null) {
122 LOGGER.warn("No appender references configured for AsyncAppender {}", name);
123 return null;
124 }
125 Appender appender = configuration.parseAppender(props, appenderRef);
126 if (appender == null) {
127 LOGGER.warn("Cannot locate Appender {}", appenderRef);
128 return null;
129 }
130 return createAppender(name, level, new String[] {appenderRef}, policy, filter, configuration);
131 }
132
133 private <T extends Log4j1Configuration> Appender createAppender(String name, String level,
134 String[] appenderRefs, RewritePolicy policy, Filter filter, T configuration) {
135 org.apache.logging.log4j.Level logLevel = OptionConverter.convertLevel(level,
136 org.apache.logging.log4j.Level.TRACE);
137 AppenderRef[] refs = new AppenderRef[appenderRefs.length];
138 int index = 0;
139 for (String appenderRef : appenderRefs) {
140 refs[index++] = AppenderRef.createAppenderRef(appenderRef, logLevel, null);
141 }
142 org.apache.logging.log4j.core.Filter rewriteFilter = buildFilters(level, filter);
143 org.apache.logging.log4j.core.appender.rewrite.RewritePolicy rewritePolicy;
144 if (policy instanceof RewritePolicyWrapper) {
145 rewritePolicy = ((RewritePolicyWrapper) policy).getPolicy();
146 } else {
147 rewritePolicy = new RewritePolicyAdapter(policy);
148 }
149 return new AppenderWrapper(RewriteAppender.createAppender(name, "true", refs, configuration,
150 rewritePolicy, rewriteFilter));
151 }
152 }
+0
-214
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.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.builders.appender;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
20 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
21 import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
22 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
23 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
24 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
25 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
26
27 import java.util.Properties;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.log4j.Appender;
33 import org.apache.log4j.Layout;
34 import org.apache.log4j.bridge.AppenderWrapper;
35 import org.apache.log4j.bridge.LayoutAdapter;
36 import org.apache.log4j.bridge.LayoutWrapper;
37 import org.apache.log4j.builders.AbstractBuilder;
38 import org.apache.log4j.config.Log4j1Configuration;
39 import org.apache.log4j.config.PropertiesConfiguration;
40 import org.apache.log4j.spi.Filter;
41 import org.apache.log4j.xml.XmlConfiguration;
42 import org.apache.logging.log4j.Logger;
43 import org.apache.logging.log4j.core.appender.RollingFileAppender;
44 import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
45 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
46 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
47 import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
48 import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
49 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
50 import org.apache.logging.log4j.core.config.plugins.Plugin;
51 import org.apache.logging.log4j.status.StatusLogger;
52 import org.w3c.dom.Element;
53
54
55 /**
56 * Build a File Appender
57 */
58 @Plugin(name = "org.apache.log4j.RollingFileAppender", category = CATEGORY)
59 public class RollingFileAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
60
61 private static final Logger LOGGER = StatusLogger.getLogger();
62
63 public RollingFileAppenderBuilder() {
64 }
65
66 public RollingFileAppenderBuilder(String prefix, Properties props) {
67 super(prefix, props);
68 }
69
70 @Override
71 public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
72 String name = appenderElement.getAttribute(NAME_ATTR);
73 AtomicReference<Layout> layout = new AtomicReference<>();
74 AtomicReference<Filter> filter = new AtomicReference<>();
75 AtomicReference<String> fileName = new AtomicReference<>();
76 AtomicBoolean immediateFlush = new AtomicBoolean();
77 AtomicBoolean append = new AtomicBoolean();
78 AtomicBoolean bufferedIo = new AtomicBoolean();
79 AtomicInteger bufferSize = new AtomicInteger(8192);
80 AtomicReference<String> maxSize = new AtomicReference<>();
81 AtomicReference<String> maxBackups = new AtomicReference<>();
82 AtomicReference<String> level = new AtomicReference<>();
83 forEachElement(appenderElement.getChildNodes(), currentElement -> {
84 switch (currentElement.getTagName()) {
85 case LAYOUT_TAG:
86 layout.set(config.parseLayout(currentElement));
87 break;
88 case FILTER_TAG:
89 filter.set(config.parseFilters(currentElement));
90 break;
91 case PARAM_TAG: {
92 switch (currentElement.getAttribute(NAME_ATTR)) {
93 case FILE_PARAM:
94 fileName.set(currentElement.getAttribute(VALUE_ATTR));
95 break;
96 case APPEND_PARAM: {
97 String bool = currentElement.getAttribute(VALUE_ATTR);
98 if (bool != null) {
99 append.set(Boolean.parseBoolean(bool));
100 } else {
101 LOGGER.warn("No value provided for append parameter");
102 }
103 break;
104 }
105 case BUFFERED_IO_PARAM: {
106 String bool = currentElement.getAttribute(VALUE_ATTR);
107 if (bool != null) {
108 bufferedIo.set(Boolean.parseBoolean(bool));
109 } else {
110 LOGGER.warn("No value provided for bufferedIo parameter");
111 }
112 break;
113 }
114 case BUFFER_SIZE_PARAM: {
115 String size = currentElement.getAttribute(VALUE_ATTR);
116 if (size != null) {
117 bufferSize.set(Integer.parseInt(size));
118 } else {
119 LOGGER.warn("No value provide for bufferSize parameter");
120 }
121 break;
122 }
123 case MAX_BACKUP_INDEX: {
124 String size = currentElement.getAttribute(VALUE_ATTR);
125 if (size != null) {
126 maxBackups.set(size);
127 } else {
128 LOGGER.warn("No value provide for maxBackupIndex parameter");
129 }
130 break;
131 }
132 case MAX_SIZE_PARAM: {
133 String size = currentElement.getAttribute(VALUE_ATTR);
134 if (size != null) {
135 maxSize.set(size);
136 } else {
137 LOGGER.warn("No value provide for bufferSize parameter");
138 }
139 break;
140 }
141 case THRESHOLD_PARAM: {
142 String value = currentElement.getAttribute(VALUE_ATTR);
143 if (value == null) {
144 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
145 } else {
146 level.set(value);
147 }
148 break;
149 }
150 }
151 break;
152 }
153 }
154 });
155 return createAppender(name, config, layout.get(), filter.get(), bufferedIo.get(), immediateFlush.get(),
156 fileName.get(), level.get(), maxSize.get(), maxBackups.get());
157 }
158
159
160 @Override
161 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
162 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
163 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
164 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
165 String fileName = getProperty(FILE_PARAM);
166 String level = getProperty(THRESHOLD_PARAM);
167 boolean immediateFlush = false;
168 boolean bufferedIo = getBooleanProperty(BUFFERED_IO_PARAM);
169 String maxSize = getProperty(MAX_SIZE_PARAM);
170 String maxBackups = getProperty(MAX_BACKUP_INDEX);
171 return createAppender(name, configuration, layout, filter, bufferedIo, immediateFlush, fileName, level, maxSize,
172 maxBackups);
173 }
174
175 private Appender createAppender(final String name, final Log4j1Configuration config, final Layout layout,
176 final Filter filter, final boolean bufferedIo, boolean immediateFlush, final String fileName,
177 final String level, final String maxSize, final String maxBackups) {
178 org.apache.logging.log4j.core.Layout<?> fileLayout = null;
179 if (bufferedIo) {
180 immediateFlush = true;
181 }
182 if (layout instanceof LayoutWrapper) {
183 fileLayout = ((LayoutWrapper) layout).getLayout();
184 } else if (layout != null) {
185 fileLayout = new LayoutAdapter(layout);
186 }
187 org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
188 if (fileName == null) {
189 LOGGER.warn("Unable to create File Appender, no file name provided");
190 return null;
191 }
192 String filePattern = fileName +"%d{yyy-MM-dd}";
193 TriggeringPolicy timePolicy = TimeBasedTriggeringPolicy.newBuilder().withModulate(true).build();
194 SizeBasedTriggeringPolicy sizePolicy = SizeBasedTriggeringPolicy.createPolicy(maxSize);
195 CompositeTriggeringPolicy policy = CompositeTriggeringPolicy.createPolicy(sizePolicy, timePolicy);
196 RolloverStrategy strategy = DefaultRolloverStrategy.newBuilder()
197 .withConfig(config)
198 .withMax(maxBackups)
199 .build();
200 return new AppenderWrapper(RollingFileAppender.newBuilder()
201 .setName(name)
202 .setConfiguration(config)
203 .setLayout(fileLayout)
204 .setFilter(fileFilter)
205 .withBufferedIo(bufferedIo)
206 .withImmediateFlush(immediateFlush)
207 .withFileName(fileName)
208 .withFilePattern(filePattern)
209 .withPolicy(policy)
210 .withStrategy(strategy)
211 .build());
212 }
213 }
+0
-183
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/SyslogAppenderBuilder.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.builders.appender;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
20 import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
21 import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG;
22 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
23 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
24 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
25 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
26
27 import java.io.Serializable;
28 import java.util.Properties;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.log4j.Appender;
33 import org.apache.log4j.Layout;
34 import org.apache.log4j.bridge.AppenderWrapper;
35 import org.apache.log4j.bridge.LayoutAdapter;
36 import org.apache.log4j.bridge.LayoutWrapper;
37 import org.apache.log4j.builders.AbstractBuilder;
38 import org.apache.log4j.config.Log4j1Configuration;
39 import org.apache.log4j.config.PropertiesConfiguration;
40 import org.apache.log4j.spi.Filter;
41 import org.apache.log4j.xml.XmlConfiguration;
42 import org.apache.logging.log4j.Logger;
43 import org.apache.logging.log4j.core.appender.SocketAppender;
44 import org.apache.logging.log4j.core.config.plugins.Plugin;
45 import org.apache.logging.log4j.core.layout.SyslogLayout;
46 import org.apache.logging.log4j.core.net.Facility;
47 import org.apache.logging.log4j.core.net.Protocol;
48 import org.apache.logging.log4j.status.StatusLogger;
49 import org.w3c.dom.Element;
50
51 /**
52 * Build a File Appender
53 */
54 @Plugin(name = "org.apache.log4j.net.SyslogAppender", category = CATEGORY)
55 public class SyslogAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
56
57 private static final String DEFAULT_HOST = "localhost";
58 private static int DEFAULT_PORT = 514;
59 private static final String DEFAULT_FACILITY = "LOCAL0";
60
61 private static final Logger LOGGER = StatusLogger.getLogger();
62 private static final String FACILITY_PARAM = "Facility";
63 private static final String SYSLOG_HOST_PARAM = "SyslogHost";
64 private static final String PROTOCOL_PARAM = "protocol";
65
66
67 public SyslogAppenderBuilder() {
68 }
69
70 public SyslogAppenderBuilder(String prefix, Properties props) {
71 super(prefix, props);
72 }
73
74 @Override
75 public Appender parseAppender(Element appenderElement, XmlConfiguration config) {
76 String name = appenderElement.getAttribute(NAME_ATTR);
77 AtomicReference<Layout> layout = new AtomicReference<>();
78 AtomicReference<Filter> filter = new AtomicReference<>();
79 AtomicReference<String> facility = new AtomicReference<>();
80 AtomicReference<String> level = new AtomicReference<>();
81 AtomicReference<String> host = new AtomicReference<>();
82 AtomicReference<Protocol> protocol = new AtomicReference<>();
83 forEachElement(appenderElement.getChildNodes(), currentElement -> {
84 switch (currentElement.getTagName()) {
85 case LAYOUT_TAG:
86 layout.set(config.parseLayout(currentElement));
87 break;
88 case FILTER_TAG:
89 filter.set(config.parseFilters(currentElement));
90 break;
91 case PARAM_TAG: {
92 switch (currentElement.getAttribute(NAME_ATTR)) {
93 case SYSLOG_HOST_PARAM: {
94 host.set(currentElement.getAttribute(VALUE_ATTR));
95 break;
96 }
97 case FACILITY_PARAM:
98 facility.set(currentElement.getAttribute(VALUE_ATTR));
99 break;
100 case THRESHOLD_PARAM: {
101 String value = currentElement.getAttribute(VALUE_ATTR);
102 if (value == null) {
103 LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
104 } else {
105 level.set(value);
106 }
107 break;
108 }
109 case PROTOCOL_PARAM:
110 protocol.set(Protocol.valueOf(currentElement.getAttribute(VALUE_ATTR)));
111 break;
112 }
113 break;
114 }
115 }
116 });
117
118 return createAppender(name, config, layout.get(), facility.get(), filter.get(), host.get(), level.get(), protocol.get());
119 }
120
121
122 @Override
123 public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
124 final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
125 Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
126 Layout layout = configuration.parseLayout(layoutPrefix, name, props);
127 String level = getProperty(THRESHOLD_PARAM);
128 String facility = getProperty(FACILITY_PARAM, DEFAULT_FACILITY);
129 String syslogHost = getProperty(SYSLOG_HOST_PARAM, DEFAULT_HOST + ":" + DEFAULT_PORT);
130 String protocol = getProperty(PROTOCOL_PARAM, Protocol.TCP.name());
131
132 return createAppender(name, configuration, layout, facility, filter, syslogHost, level, Protocol.valueOf(protocol));
133 }
134
135 private Appender createAppender(final String name, final Log4j1Configuration configuration, Layout layout,
136 String facility, final Filter filter, final String syslogHost, final String level, final Protocol protocol) {
137 AtomicReference<String> host = new AtomicReference<>();
138 AtomicInteger port = new AtomicInteger();
139 resolveSyslogHost(syslogHost, host, port);
140 org.apache.logging.log4j.core.Layout<? extends Serializable> appenderLayout;
141 if (layout instanceof LayoutWrapper) {
142 appenderLayout = ((LayoutWrapper) layout).getLayout();
143 } else if (layout != null) {
144 appenderLayout = new LayoutAdapter(layout);
145 } else {
146 appenderLayout = SyslogLayout.newBuilder()
147 .setFacility(Facility.toFacility(facility))
148 .setConfiguration(configuration)
149 .build();
150 }
151
152 org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter);
153 return new AppenderWrapper(SocketAppender.newBuilder()
154 .setName(name)
155 .setConfiguration(configuration)
156 .setLayout(appenderLayout)
157 .setFilter(fileFilter)
158 .withPort(port.get())
159 .withProtocol(protocol)
160 .withHost(host.get())
161 .build());
162 }
163
164 private void resolveSyslogHost(String syslogHost, AtomicReference<String> host, AtomicInteger port) {
165 //
166 // If not an unbracketed IPv6 address then
167 // parse as a URL
168 //
169 String[] parts = syslogHost.split(":");
170 if (parts.length == 1) {
171 host.set(parts[0]);
172 port.set(DEFAULT_PORT);
173 } else if (parts.length == 2) {
174 host.set(parts[0]);
175 port.set(Integer.parseInt(parts[1]));
176 } else {
177 LOGGER.warn("Invalid {} setting: {}. Using default.", SYSLOG_HOST_PARAM, syslogHost);
178 host.set(DEFAULT_HOST);
179 port.set(DEFAULT_PORT);
180 }
181 }
182 }
+0
-48
log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/DenyAllFilterBuilder.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.builders.filter;
17
18 import org.apache.log4j.bridge.FilterWrapper;
19 import org.apache.log4j.config.PropertiesConfiguration;
20 import org.apache.log4j.spi.Filter;
21 import org.apache.log4j.xml.XmlConfiguration;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.filter.DenyAllFilter;
25 import org.apache.logging.log4j.status.StatusLogger;
26 import org.w3c.dom.Element;
27
28 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
29
30 /**
31 * Build a Pattern Layout
32 */
33 @Plugin(name = "org.apache.log4j.varia.DenyAllFilter", category = CATEGORY)
34 public class DenyAllFilterBuilder implements FilterBuilder {
35
36 private static final Logger LOGGER = StatusLogger.getLogger();
37
38 @Override
39 public Filter parseFilter(Element filterElement, XmlConfiguration config) {
40 return new FilterWrapper(DenyAllFilter.newBuilder().build());
41 }
42
43 @Override
44 public Filter parseFilter(PropertiesConfiguration config) {
45 return new FilterWrapper(DenyAllFilter.newBuilder().build());
46 }
47 }
+0
-33
log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/FilterBuilder.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.builders.filter;
17
18 import org.apache.log4j.config.PropertiesConfiguration;
19 import org.apache.log4j.spi.Filter;
20 import org.apache.log4j.xml.XmlConfiguration;
21 import org.w3c.dom.Element;
22
23 /**
24 * Define a Filter Builder.
25 */
26 public interface FilterBuilder {
27
28 Filter parseFilter(Element element, XmlConfiguration config);
29
30 Filter parseFilter(PropertiesConfiguration config);
31
32 }
+0
-97
log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelMatchFilterBuilder.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.builders.filter;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
20 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
21 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
22
23 import java.util.Properties;
24 import java.util.concurrent.atomic.AtomicBoolean;
25 import java.util.concurrent.atomic.AtomicReference;
26
27 import org.apache.log4j.bridge.FilterWrapper;
28 import org.apache.log4j.builders.AbstractBuilder;
29 import org.apache.log4j.config.PropertiesConfiguration;
30 import org.apache.log4j.spi.Filter;
31 import org.apache.log4j.xml.XmlConfiguration;
32 import org.apache.logging.log4j.Level;
33 import org.apache.logging.log4j.Logger;
34 import org.apache.logging.log4j.core.config.plugins.Plugin;
35 import org.apache.logging.log4j.core.filter.LevelMatchFilter;
36 import org.apache.logging.log4j.status.StatusLogger;
37 import org.w3c.dom.Element;
38
39 /**
40 * Build a Level match failter.
41 */
42 @Plugin(name = "org.apache.log4j.varia.LevelMatchFilter", category = CATEGORY)
43 public class LevelMatchFilterBuilder extends AbstractBuilder implements FilterBuilder {
44
45 private static final Logger LOGGER = StatusLogger.getLogger();
46 private static final String LEVEL = "LevelToMatch";
47 private static final String ACCEPT_ON_MATCH = "AcceptOnMatch";
48
49 public LevelMatchFilterBuilder() {
50 }
51
52 public LevelMatchFilterBuilder(String prefix, Properties props) {
53 super(prefix, props);
54 }
55
56 @Override
57 public Filter parseFilter(Element filterElement, XmlConfiguration config) {
58 final AtomicReference<String> level = new AtomicReference<>();
59 final AtomicBoolean acceptOnMatch = new AtomicBoolean();
60 forEachElement(filterElement.getElementsByTagName("param"), currentElement -> {
61 if (currentElement.getTagName().equals("param")) {
62 switch (currentElement.getAttribute(NAME_ATTR)) {
63 case LEVEL:
64 level.set(currentElement.getAttribute(VALUE_ATTR));
65 break;
66 case ACCEPT_ON_MATCH:
67 acceptOnMatch.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR)));
68 break;
69 }
70 }
71 });
72 return createFilter(level.get(), acceptOnMatch.get());
73 }
74
75 @Override
76 public Filter parseFilter(PropertiesConfiguration config) {
77 String level = getProperty(LEVEL);
78 boolean acceptOnMatch = getBooleanProperty(ACCEPT_ON_MATCH);
79 return createFilter(level, acceptOnMatch);
80 }
81
82 private Filter createFilter(String level, boolean acceptOnMatch) {
83 Level lvl = Level.ERROR;
84 if (level != null) {
85 lvl = Level.toLevel(level, Level.ERROR);
86 }
87 org.apache.logging.log4j.core.Filter.Result onMatch = acceptOnMatch
88 ? org.apache.logging.log4j.core.Filter.Result.ACCEPT
89 : org.apache.logging.log4j.core.Filter.Result.DENY;
90 return new FilterWrapper(LevelMatchFilter.newBuilder()
91 .setLevel(lvl)
92 .setOnMatch(onMatch)
93 .setOnMismatch(org.apache.logging.log4j.core.Filter.Result.NEUTRAL)
94 .build());
95 }
96 }
+0
-105
log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.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.builders.filter;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
20 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
21 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
22
23 import java.util.Properties;
24 import java.util.concurrent.atomic.AtomicBoolean;
25 import java.util.concurrent.atomic.AtomicReference;
26
27 import org.apache.log4j.bridge.FilterWrapper;
28 import org.apache.log4j.builders.AbstractBuilder;
29 import org.apache.log4j.config.PropertiesConfiguration;
30 import org.apache.log4j.spi.Filter;
31 import org.apache.log4j.xml.XmlConfiguration;
32 import org.apache.logging.log4j.Level;
33 import org.apache.logging.log4j.Logger;
34 import org.apache.logging.log4j.core.config.plugins.Plugin;
35 import org.apache.logging.log4j.core.filter.LevelRangeFilter;
36 import org.apache.logging.log4j.status.StatusLogger;
37 import org.w3c.dom.Element;
38
39 /**
40 * Build a Level match failter.
41 */
42 @Plugin(name = "org.apache.log4j.varia.LevelRangeFilter", category = CATEGORY)
43 public class LevelRangeFilterBuilder extends AbstractBuilder implements FilterBuilder {
44
45 private static final Logger LOGGER = StatusLogger.getLogger();
46 private static final String LEVEL_MAX = "LevelMax";
47 private static final String LEVEL_MIN = "LevelMin";
48 private static final String ACCEPT_ON_MATCH = "AcceptOnMatch";
49
50 public LevelRangeFilterBuilder() {
51 }
52
53 public LevelRangeFilterBuilder(String prefix, Properties props) {
54 super(prefix, props);
55 }
56
57 @Override
58 public Filter parseFilter(Element filterElement, XmlConfiguration config) {
59 final AtomicReference<String> levelMax = new AtomicReference<>();
60 final AtomicReference<String> levelMin = new AtomicReference<>();
61 final AtomicBoolean acceptOnMatch = new AtomicBoolean();
62 forEachElement(filterElement.getElementsByTagName("param"), currentElement -> {
63 if (currentElement.getTagName().equals("param")) {
64 switch (currentElement.getAttribute(NAME_ATTR)) {
65 case LEVEL_MAX:
66 levelMax.set(currentElement.getAttribute(VALUE_ATTR));
67 break;
68 case LEVEL_MIN:
69 levelMax.set(currentElement.getAttribute(VALUE_ATTR));
70 break;
71 case ACCEPT_ON_MATCH:
72 acceptOnMatch.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR)));
73 break;
74 }
75 }
76 });
77 return createFilter(levelMax.get(), levelMin.get(), acceptOnMatch.get());
78 }
79
80 @Override
81 public Filter parseFilter(PropertiesConfiguration config) {
82 String levelMax = getProperty(LEVEL_MAX);
83 String levelMin = getProperty(LEVEL_MIN);
84 boolean acceptOnMatch = getBooleanProperty(ACCEPT_ON_MATCH);
85 return createFilter(levelMax, levelMin, acceptOnMatch);
86 }
87
88 private Filter createFilter(String levelMax, String levelMin, boolean acceptOnMatch) {
89 Level max = Level.FATAL;
90 Level min = Level.TRACE;
91 if (levelMax != null) {
92 max = Level.toLevel(levelMax, Level.FATAL);
93 }
94 if (levelMin != null) {
95 min = Level.toLevel(levelMin, Level.DEBUG);
96 }
97 org.apache.logging.log4j.core.Filter.Result onMatch = acceptOnMatch
98 ? org.apache.logging.log4j.core.Filter.Result.ACCEPT
99 : org.apache.logging.log4j.core.Filter.Result.NEUTRAL;
100
101 return new FilterWrapper(LevelRangeFilter.createFilter(min, max, onMatch,
102 org.apache.logging.log4j.core.Filter.Result.DENY));
103 }
104 }
+0
-89
log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/StringMatchFilterBuilder.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.builders.filter;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
20 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
21 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
22
23 import java.util.concurrent.atomic.AtomicBoolean;
24 import java.util.concurrent.atomic.AtomicReference;
25
26 import org.apache.log4j.bridge.FilterWrapper;
27 import org.apache.log4j.builders.AbstractBuilder;
28 import org.apache.log4j.config.PropertiesConfiguration;
29 import org.apache.log4j.spi.Filter;
30 import org.apache.log4j.xml.XmlConfiguration;
31 import org.apache.logging.log4j.Logger;
32 import org.apache.logging.log4j.core.config.plugins.Plugin;
33 import org.apache.logging.log4j.core.filter.StringMatchFilter;
34 import org.apache.logging.log4j.status.StatusLogger;
35 import org.w3c.dom.Element;
36
37 /**
38 * Build a String match filter.
39 */
40 @Plugin(name = "org.apache.log4j.varia.StringMatchFilter", category = CATEGORY)
41 public class StringMatchFilterBuilder extends AbstractBuilder implements FilterBuilder {
42
43 private static final Logger LOGGER = StatusLogger.getLogger();
44 private static final String STRING_TO_MATCH = "StringToMatch";
45 private static final String ACCEPT_ON_MATCH = "AcceptOnMatch";
46
47 @Override
48 public Filter parseFilter(Element filterElement, XmlConfiguration config) {
49 final AtomicBoolean acceptOnMatch = new AtomicBoolean();
50 final AtomicReference<String> text = new AtomicReference<>();
51 forEachElement(filterElement.getElementsByTagName("param"), currentElement -> {
52 if (currentElement.getTagName().equals("param")) {
53 switch (currentElement.getAttribute(NAME_ATTR)) {
54 case STRING_TO_MATCH:
55 text.set(currentElement.getAttribute(VALUE_ATTR));
56 break;
57 case ACCEPT_ON_MATCH:
58 acceptOnMatch.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR)));
59 break;
60
61 }
62 }
63 });
64 return createFilter(text.get(), acceptOnMatch.get());
65 }
66
67 @Override
68 public Filter parseFilter(PropertiesConfiguration config) {
69 String text = getProperty(STRING_TO_MATCH);
70 boolean acceptOnMatch = getBooleanProperty(ACCEPT_ON_MATCH);
71 return createFilter(text, acceptOnMatch);
72 }
73
74 private Filter createFilter(String text, boolean acceptOnMatch) {
75 if (text == null) {
76 LOGGER.warn("No text provided for StringMatchFilter");
77 return null;
78 }
79 org.apache.logging.log4j.core.Filter.Result onMatch = acceptOnMatch
80 ? org.apache.logging.log4j.core.Filter.Result.ACCEPT
81 : org.apache.logging.log4j.core.Filter.Result.DENY;
82 return new FilterWrapper(StringMatchFilter.newBuilder()
83 .setMatchString(text)
84 .setOnMatch(onMatch)
85 .setOnMismatch(org.apache.logging.log4j.core.Filter.Result.NEUTRAL)
86 .build());
87 }
88 }
+0
-86
log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/HtmlLayoutBuilder.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.builders.layout;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
20 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
21
22 import java.util.Properties;
23 import java.util.concurrent.atomic.AtomicBoolean;
24 import java.util.concurrent.atomic.AtomicReference;
25
26 import org.apache.log4j.Layout;
27 import org.apache.log4j.bridge.LayoutWrapper;
28 import org.apache.log4j.builders.AbstractBuilder;
29 import org.apache.log4j.config.PropertiesConfiguration;
30 import org.apache.log4j.xml.XmlConfiguration;
31 import org.apache.logging.log4j.Logger;
32 import org.apache.logging.log4j.core.config.plugins.Plugin;
33 import org.apache.logging.log4j.core.layout.HtmlLayout;
34 import org.apache.logging.log4j.status.StatusLogger;
35 import org.w3c.dom.Element;
36
37 /**
38 * Build a Pattern Layout
39 */
40 @Plugin(name = "org.apache.log4j.HTMLLayout", category = CATEGORY)
41 public class HtmlLayoutBuilder extends AbstractBuilder implements LayoutBuilder {
42
43 private static final Logger LOGGER = StatusLogger.getLogger();
44
45 private static final String TITLE = "Title";
46 private static final String LOCATION_INFO = "LocationInfo";
47
48 public HtmlLayoutBuilder() {
49 }
50
51 public HtmlLayoutBuilder(String prefix, Properties props) {
52 super(prefix, props);
53 }
54
55
56 @Override
57 public Layout parseLayout(Element layoutElement, XmlConfiguration config) {
58 final AtomicReference<String> title = new AtomicReference<>();
59 final AtomicBoolean locationInfo = new AtomicBoolean();
60 forEachElement(layoutElement.getElementsByTagName("param"), currentElement -> {
61 if (currentElement.getTagName().equals(PARAM_TAG)) {
62 if (TITLE.equalsIgnoreCase(currentElement.getAttribute("name"))) {
63 title.set(currentElement.getAttribute("value"));
64 } else if (LOCATION_INFO.equalsIgnoreCase(currentElement.getAttribute("name"))) {
65 locationInfo.set(Boolean.parseBoolean(currentElement.getAttribute("value")));
66 }
67 }
68 });
69 return createLayout(title.get(), locationInfo.get());
70 }
71
72 @Override
73 public Layout parseLayout(PropertiesConfiguration config) {
74 String title = getProperty(TITLE);
75 boolean locationInfo = getBooleanProperty(LOCATION_INFO);
76 return createLayout(title, locationInfo);
77 }
78
79 private Layout createLayout(String title, boolean locationInfo) {
80 return new LayoutWrapper(HtmlLayout.newBuilder()
81 .withTitle(title)
82 .withLocationInfo(locationInfo)
83 .build());
84 }
85 }
+0
-32
log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.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.builders.layout;
17
18 import org.apache.log4j.Layout;
19 import org.apache.log4j.config.PropertiesConfiguration;
20 import org.apache.log4j.xml.XmlConfiguration;
21 import org.w3c.dom.Element;
22
23 /**
24 * Define a Layout Builder.
25 */
26 public interface LayoutBuilder {
27
28 Layout parseLayout(Element element, XmlConfiguration config);
29
30 Layout parseLayout(PropertiesConfiguration config);
31 }
+0
-105
log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/PatternLayoutBuilder.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.builders.layout;
17
18 import org.apache.log4j.Layout;
19 import org.apache.log4j.bridge.LayoutWrapper;
20 import org.apache.log4j.builders.AbstractBuilder;
21 import org.apache.log4j.config.Log4j1Configuration;
22 import org.apache.log4j.config.PropertiesConfiguration;
23 import org.apache.log4j.xml.XmlConfiguration;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
27 import org.apache.logging.log4j.core.layout.PatternLayout;
28 import org.apache.logging.log4j.status.StatusLogger;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32
33 import java.util.Properties;
34
35 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
36 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
37
38 /**
39 * Build a Pattern Layout
40 */
41 @Plugin(name = "org.apache.log4j.PatternLayout", category = CATEGORY)
42 @PluginAliases("org.apache.log4j.EnhancedPatternLayout")
43 public class PatternLayoutBuilder extends AbstractBuilder implements LayoutBuilder {
44
45 private static final Logger LOGGER = StatusLogger.getLogger();
46 private static final String PATTERN = "ConversionPattern";
47
48 public PatternLayoutBuilder() {
49 }
50
51 public PatternLayoutBuilder(String prefix, Properties props) {
52 super(prefix, props);
53 }
54
55 @Override
56 public Layout parseLayout(final Element layoutElement, final XmlConfiguration config) {
57 NodeList params = layoutElement.getElementsByTagName("param");
58 final int length = params.getLength();
59 String pattern = null;
60 for (int index = 0; index < length; ++ index) {
61 Node currentNode = params.item(index);
62 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
63 Element currentElement = (Element) currentNode;
64 if (currentElement.getTagName().equals(PARAM_TAG)) {
65 if (PATTERN.equalsIgnoreCase(currentElement.getAttribute("name"))) {
66 pattern = currentElement.getAttribute("value");
67 break;
68 }
69 }
70 }
71 }
72 return createLayout(pattern, config);
73 }
74
75 @Override
76 public Layout parseLayout(final PropertiesConfiguration config) {
77 String pattern = getProperty(PATTERN);
78 return createLayout(pattern, config);
79 }
80
81 private Layout createLayout(String pattern, final Log4j1Configuration config) {
82 if (pattern == null) {
83 LOGGER.info("No pattern provided for pattern layout, using default pattern");
84 pattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
85 }
86 return new LayoutWrapper(PatternLayout.newBuilder()
87 .withPattern(pattern
88 // Log4j 2's %x (NDC) is not compatible with Log4j 1's
89 // %x
90 // Log4j 1: "foo bar baz"
91 // Log4j 2: "[foo, bar, baz]"
92 // Use %ndc to get the Log4j 1 format
93 .replace("%x", "%ndc")
94
95 // Log4j 2's %X (MDC) is not compatible with Log4j 1's
96 // %X
97 // Log4j 1: "{{foo,bar}{hoo,boo}}"
98 // Log4j 2: "{foo=bar,hoo=boo}"
99 // Use %properties to get the Log4j 1 format
100 .replace("%X", "%properties"))
101 .withConfiguration(config)
102 .build());
103 }
104 }
+0
-54
log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/SimpleLayoutBuilder.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.builders.layout;
17
18 import org.apache.log4j.Layout;
19 import org.apache.log4j.bridge.LayoutWrapper;
20 import org.apache.log4j.config.PropertiesConfiguration;
21 import org.apache.log4j.xml.XmlConfiguration;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.layout.PatternLayout;
25 import org.apache.logging.log4j.status.StatusLogger;
26 import org.w3c.dom.Element;
27
28 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
29
30 /**
31 * Build a Pattern Layout
32 */
33 @Plugin(name = "org.apache.log4j.SimpleLayout", category = CATEGORY)
34 public class SimpleLayoutBuilder implements LayoutBuilder {
35
36 private static final Logger LOGGER = StatusLogger.getLogger();
37
38 @Override
39 public Layout parseLayout(Element layoutElement, XmlConfiguration config) {
40 return new LayoutWrapper(PatternLayout.newBuilder()
41 .withPattern("%level - %m%n")
42 .withConfiguration(config)
43 .build());
44 }
45
46 @Override
47 public Layout parseLayout(PropertiesConfiguration config) {
48 return new LayoutWrapper(PatternLayout.newBuilder()
49 .withPattern("%level - %m%n")
50 .withConfiguration(config)
51 .build());
52 }
53 }
+0
-136
log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/TTCCLayoutBuilder.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.builders.layout;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
20 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
21 import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
22 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
23
24 import java.util.Properties;
25 import java.util.concurrent.atomic.AtomicBoolean;
26 import java.util.concurrent.atomic.AtomicReference;
27
28 import org.apache.log4j.Layout;
29 import org.apache.log4j.bridge.LayoutWrapper;
30 import org.apache.log4j.builders.AbstractBuilder;
31 import org.apache.log4j.config.Log4j1Configuration;
32 import org.apache.log4j.config.PropertiesConfiguration;
33 import org.apache.log4j.xml.XmlConfiguration;
34 import org.apache.logging.log4j.Logger;
35 import org.apache.logging.log4j.core.config.plugins.Plugin;
36 import org.apache.logging.log4j.core.layout.PatternLayout;
37 import org.apache.logging.log4j.status.StatusLogger;
38 import org.w3c.dom.Element;
39
40 /**
41 * Build a Pattern Layout
42 */
43 @Plugin(name = "org.apache.log4j.TTCCLayout", category = CATEGORY)
44 public class TTCCLayoutBuilder extends AbstractBuilder implements LayoutBuilder {
45
46 private static final Logger LOGGER = StatusLogger.getLogger();
47
48 private static final String THREAD_PRINTING_PARAM = "ThreadPrinting";
49 private static final String CATEGORY_PREFIXING_PARAM = "CategoryPrefixing";
50 private static final String CONTEXT_PRINTING_PARAM = "ContextPrinting";
51 private static final String DATE_FORMAT_PARAM = "DateFormat";
52 private static final String TIMEZONE_FORMAT = "TimeZone";
53
54 public TTCCLayoutBuilder() {
55 }
56
57 public TTCCLayoutBuilder(String prefix, Properties props) {
58 super(prefix, props);
59 }
60
61 @Override
62 public Layout parseLayout(Element layoutElement, XmlConfiguration config) {
63 final AtomicBoolean threadPrinting = new AtomicBoolean();
64 final AtomicBoolean categoryPrefixing = new AtomicBoolean();
65 final AtomicBoolean contextPrinting = new AtomicBoolean();
66 final AtomicReference<String> dateFormat = new AtomicReference<>();
67 final AtomicReference<String> timezone = new AtomicReference<>();
68 forEachElement(layoutElement.getElementsByTagName("param"), currentElement -> {
69 if (currentElement.getTagName().equals(PARAM_TAG)) {
70 switch (currentElement.getAttribute(NAME_ATTR)) {
71 case THREAD_PRINTING_PARAM:
72 threadPrinting.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR)));
73 break;
74 case CATEGORY_PREFIXING_PARAM:
75 categoryPrefixing.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR)));
76 break;
77 case CONTEXT_PRINTING_PARAM:
78 contextPrinting.set(Boolean.parseBoolean(currentElement.getAttribute(VALUE_ATTR)));
79 break;
80 case DATE_FORMAT_PARAM:
81 dateFormat.set(currentElement.getAttribute(VALUE_ATTR));
82 break;
83 case TIMEZONE_FORMAT:
84 timezone.set(currentElement.getAttribute(VALUE_ATTR));
85 break;
86 }
87 }
88 });
89 return createLayout(threadPrinting.get(), categoryPrefixing.get(), contextPrinting.get(),
90 dateFormat.get(), timezone.get(), config);
91 }
92
93 @Override
94 public Layout parseLayout(PropertiesConfiguration config) {
95 boolean threadPrinting = getBooleanProperty(THREAD_PRINTING_PARAM);
96 boolean categoryPrefixing = getBooleanProperty(CATEGORY_PREFIXING_PARAM);
97 boolean contextPrinting = getBooleanProperty(CONTEXT_PRINTING_PARAM);
98 String dateFormat = getProperty(DATE_FORMAT_PARAM);
99 String timezone = getProperty(TIMEZONE_FORMAT);
100
101 return createLayout(threadPrinting, categoryPrefixing, contextPrinting,
102 dateFormat, timezone, config);
103 }
104
105 private Layout createLayout(boolean threadPrinting, boolean categoryPrefixing, boolean contextPrinting,
106 String dateFormat, String timezone, Log4j1Configuration config) {
107 StringBuilder sb = new StringBuilder();
108 if (dateFormat != null) {
109 if (RELATIVE.equalsIgnoreCase(dateFormat)) {
110 sb.append("%r ");
111 } else {
112 sb.append("%d{").append(dateFormat).append("}");
113 if (timezone != null) {
114 sb.append("{").append(timezone).append("}");
115 }
116 sb.append(" ");
117 }
118 }
119 if (threadPrinting) {
120 sb.append("[%t] ");
121 }
122 sb.append("%p ");
123 if (categoryPrefixing) {
124 sb.append("%c ");
125 }
126 if (contextPrinting) {
127 sb.append("%notEmpty{%ndc }");
128 }
129 sb.append("- %m%n");
130 return new LayoutWrapper(PatternLayout.newBuilder()
131 .withPattern(sb.toString())
132 .withConfiguration(config)
133 .build());
134 }
135 }
+0
-83
log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/XmlLayoutBuilder.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.builders.layout;
17
18 import static org.apache.log4j.builders.BuilderManager.CATEGORY;
19 import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
20 import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
21
22 import java.util.Properties;
23 import java.util.concurrent.atomic.AtomicBoolean;
24
25 import org.apache.log4j.Layout;
26 import org.apache.log4j.bridge.LayoutWrapper;
27 import org.apache.log4j.builders.AbstractBuilder;
28 import org.apache.log4j.config.PropertiesConfiguration;
29 import org.apache.log4j.xml.XmlConfiguration;
30 import org.apache.logging.log4j.Logger;
31 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.layout.XmlLayout;
33 import org.apache.logging.log4j.status.StatusLogger;
34 import org.w3c.dom.Element;
35
36 /**
37 * Build an XML Layout
38 */
39 @Plugin(name = "org.apache.log4j.xml.XMLLayout", category = CATEGORY)
40 public class XmlLayoutBuilder extends AbstractBuilder implements LayoutBuilder {
41
42 private static final Logger LOGGER = StatusLogger.getLogger();
43
44 private static final String LOCATION_INFO = "LocationInfo";
45 private static final String PROPERTIES = "Properties";
46
47 public XmlLayoutBuilder() {
48 }
49
50 public XmlLayoutBuilder(String prefix, Properties props) {
51 super(prefix, props);
52 }
53
54
55 @Override
56 public Layout parseLayout(Element layoutElement, XmlConfiguration config) {
57 final AtomicBoolean properties = new AtomicBoolean();
58 final AtomicBoolean locationInfo = new AtomicBoolean();
59 forEachElement(layoutElement.getElementsByTagName(PARAM_TAG), currentElement -> {
60 if (PROPERTIES.equalsIgnoreCase(currentElement.getAttribute("name"))) {
61 properties.set(Boolean.parseBoolean(currentElement.getAttribute("value")));
62 } else if (LOCATION_INFO.equalsIgnoreCase(currentElement.getAttribute("name"))) {
63 locationInfo.set(Boolean.parseBoolean(currentElement.getAttribute("value")));
64 }
65 });
66 return createLayout(properties.get(), locationInfo.get());
67 }
68
69 @Override
70 public Layout parseLayout(PropertiesConfiguration config) {
71 boolean properties = getBooleanProperty(PROPERTIES);
72 boolean locationInfo = getBooleanProperty(LOCATION_INFO);
73 return createLayout(properties, locationInfo);
74 }
75
76 private Layout createLayout(boolean properties, boolean locationInfo) {
77 return new LayoutWrapper(XmlLayout.newBuilder()
78 .setLocationInfo(locationInfo)
79 .setProperties(properties)
80 .build());
81 }
82 }
+0
-32
log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.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.builders.rewrite;
17
18 import org.apache.log4j.config.PropertiesConfiguration;
19 import org.apache.log4j.rewrite.RewritePolicy;
20 import org.apache.log4j.xml.XmlConfiguration;
21 import org.w3c.dom.Element;
22
23 /**
24 * Define a RewritePolicy Builder.
25 */
26 public interface RewritePolicyBuilder {
27
28 RewritePolicy parseRewritePolicy(Element element, XmlConfiguration config);
29
30 RewritePolicy parseRewritePolicy(PropertiesConfiguration config);
31 }
+0
-69
log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1Configuration.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.builders.BuilderManager;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.config.AbstractConfiguration;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.apache.logging.log4j.core.config.ConfigurationSource;
23 import org.apache.logging.log4j.core.config.Reconfigurable;
24
25 /**
26 * Class Description goes here.
27 */
28 public class Log4j1Configuration extends AbstractConfiguration implements Reconfigurable {
29
30 public static final String MONITOR_INTERVAL = "log4j1.monitorInterval";
31 public static final String APPENDER_REF_TAG = "appender-ref";
32 public static final String THRESHOLD_PARAM = "Threshold";
33
34 public static final String INHERITED = "inherited";
35
36 public static final String NULL = "null";
37
38 protected final BuilderManager manager;
39
40 public Log4j1Configuration(final LoggerContext loggerContext, final ConfigurationSource source,
41 int monitorIntervalSeconds) {
42 super(loggerContext, source);
43 manager = new BuilderManager();
44 initializeWatchers(this, source, monitorIntervalSeconds);
45 }
46
47 public BuilderManager getBuilderManager() {
48 return manager;
49 }
50
51 /**
52 * Initialize the configuration.
53 */
54 @Override
55 public void initialize() {
56 getStrSubstitutor().setConfiguration(this);
57 getConfigurationStrSubstitutor().setConfiguration(this);
58 super.getScheduler().start();
59 doConfigure();
60 setState(State.INITIALIZED);
61 LOGGER.debug("Configuration {} initialized", this);
62 }
63
64 @Override
65 public Configuration reconfigure() {
66 return null;
67 }
68 }
1515 */
1616 package org.apache.log4j.config;
1717
18 import java.io.ByteArrayInputStream;
19 import java.io.ByteArrayOutputStream;
2018 import java.io.IOException;
2119 import java.io.InputStream;
2220 import java.io.OutputStream;
2725 import java.nio.file.attribute.BasicFileAttributes;
2826 import java.util.concurrent.atomic.AtomicInteger;
2927
30 import javax.xml.transform.TransformerException;
31 import javax.xml.transform.stream.StreamResult;
32 import javax.xml.transform.stream.StreamSource;
33
3428 import org.apache.logging.log4j.core.config.ConfigurationException;
3529 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
3630 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
37 import org.apache.logging.log4j.core.config.builder.impl.DefaultConfigurationBuilder;
3831 import org.apache.logging.log4j.core.tools.BasicCommandLineArguments;
3932 import org.apache.logging.log4j.core.tools.picocli.CommandLine;
4033 import org.apache.logging.log4j.core.tools.picocli.CommandLine.Command;
181174 final int lastIndex = newFile.lastIndexOf(".");
182175 newFile = lastIndex < 0 ? newFile + FILE_EXT_XML
183176 : newFile.substring(0, lastIndex) + FILE_EXT_XML;
184 final Path resolvedPath = file.resolveSibling(newFile);
177 final Path resolved = file.resolveSibling(newFile);
185178 try (final InputStream input = new InputStreamWrapper(Files.newInputStream(file), file.toString());
186 final OutputStream output = Files.newOutputStream(resolvedPath)) {
179 final OutputStream output = Files.newOutputStream(resolved)) {
187180 try {
188 final ByteArrayOutputStream tmpOutput = new ByteArrayOutputStream();
189 convert(input, tmpOutput);
190 tmpOutput.close();
191 DefaultConfigurationBuilder.formatXml(
192 new StreamSource(new ByteArrayInputStream(tmpOutput.toByteArray())),
193 new StreamResult(output));
181 convert(input, output);
194182 countOKs.incrementAndGet();
195183 } catch (ConfigurationException | IOException e) {
196184 countFails.incrementAndGet();
198186 throw e;
199187 }
200188 e.printStackTrace();
201 } catch (TransformerException e) {
202 countFails.incrementAndGet();
203 if (cla.isFailFast()) {
204 throw new IOException(e);
205 }
206 e.printStackTrace();
207189 }
208 verbose("Wrote %s", resolvedPath);
190 verbose("Wrote %s", resolved);
209191 }
210192 }
211193 return FileVisitResult.CONTINUE;
3636 // @Order(50)
3737 public class Log4j1ConfigurationFactory extends ConfigurationFactory {
3838
39 private static final String[] SUFFIXES = { ".properties" };
39 private static final String[] SUFFIXES = {".properties"};
4040
4141 @Override
4242 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
4747 * Experimental parser for Log4j 1.2 properties configuration files.
4848 *
4949 * This class is not thread-safe.
50 *
50 *
5151 * <p>
5252 * From the Log4j 1.2 Javadocs:
5353 * </p>
102102 builder.setConfigurationName("Log4j1");
103103 // DEBUG
104104 final String debugValue = getLog4jValue("debug");
105 if (Boolean.parseBoolean(debugValue)) {
105 if (Boolean.valueOf(debugValue)) {
106106 builder.setStatusLevel(Level.DEBUG);
107107 }
108108 // Root
+0
-610
log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.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 java.io.IOException;
19 import java.io.InputStream;
20 import java.lang.reflect.InvocationTargetException;
21 import java.util.ArrayList;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Properties;
27 import java.util.SortedMap;
28 import java.util.StringTokenizer;
29 import java.util.TreeMap;
30
31 import org.apache.log4j.Appender;
32 import org.apache.log4j.Layout;
33 import org.apache.log4j.LogManager;
34 import org.apache.log4j.PatternLayout;
35 import org.apache.log4j.bridge.AppenderAdapter;
36 import org.apache.log4j.bridge.AppenderWrapper;
37 import org.apache.log4j.helpers.OptionConverter;
38 import org.apache.log4j.spi.ErrorHandler;
39 import org.apache.log4j.spi.Filter;
40 import org.apache.logging.log4j.core.LoggerContext;
41 import org.apache.logging.log4j.core.config.Configuration;
42 import org.apache.logging.log4j.core.config.ConfigurationSource;
43 import org.apache.logging.log4j.core.config.LoggerConfig;
44 import org.apache.logging.log4j.core.config.status.StatusConfiguration;
45 import org.apache.logging.log4j.util.LoaderUtil;
46
47 /**
48 * Construct a configuration based on Log4j 1 properties.
49 */
50 public class PropertiesConfiguration extends Log4j1Configuration {
51
52 private static final String CATEGORY_PREFIX = "log4j.category.";
53 private static final String LOGGER_PREFIX = "log4j.logger.";
54 private static final String ADDITIVITY_PREFIX = "log4j.additivity.";
55 private static final String ROOT_CATEGORY_PREFIX = "log4j.rootCategory";
56 private static final String ROOT_LOGGER_PREFIX = "log4j.rootLogger";
57 private static final String APPENDER_PREFIX = "log4j.appender.";
58 private static final String LOGGER_REF = "logger-ref";
59 private static final String ROOT_REF = "root-ref";
60 private static final String APPENDER_REF_TAG = "appender-ref";
61 public static final long DEFAULT_DELAY = 60000;
62 public static final String DEBUG_KEY="log4j.debug";
63
64 private static final String INTERNAL_ROOT_NAME = "root";
65
66 private final Map<String, Appender> registry;
67
68 /**
69 * Constructor.
70 * @param loggerContext The LoggerContext.
71 * @param source The ConfigurationSource.
72 * @param monitorIntervalSeconds The monitoring interval in seconds.
73 */
74 public PropertiesConfiguration(final LoggerContext loggerContext, final ConfigurationSource source,
75 int monitorIntervalSeconds) {
76 super(loggerContext, source, monitorIntervalSeconds);
77 registry = new HashMap<>();
78 }
79
80 @Override
81 public void doConfigure() {
82 InputStream is = getConfigurationSource().getInputStream();
83 Properties props = new Properties();
84 try {
85 props.load(is);
86 } catch (Exception e) {
87 LOGGER.error("Could not read configuration file [{}].", getConfigurationSource().toString(), e);
88 return;
89 }
90 // If we reach here, then the config file is alright.
91 doConfigure(props);
92 }
93
94 @Override
95 public Configuration reconfigure() {
96 try {
97 final ConfigurationSource source = getConfigurationSource().resetInputStream();
98 if (source == null) {
99 return null;
100 }
101 final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory();
102 final PropertiesConfiguration config =
103 (PropertiesConfiguration) factory.getConfiguration(getLoggerContext(), source);
104 return config == null || config.getState() != State.INITIALIZING ? null : config;
105 } catch (final IOException ex) {
106 LOGGER.error("Cannot locate file {}: {}", getConfigurationSource(), ex);
107 }
108 return null;
109 }
110
111 /**
112 * Read configuration from a file. <b>The existing configuration is
113 * not cleared nor reset.</b> If you require a different behavior,
114 * then call {@link LogManager#resetConfiguration
115 * resetConfiguration} method before calling
116 * <code>doConfigure</code>.
117 *
118 * <p>The configuration file consists of statements in the format
119 * <code>key=value</code>. The syntax of different configuration
120 * elements are discussed below.
121 *
122 * <p>The level value can consist of the string values OFF, FATAL,
123 * ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
124 * custom level value can be specified in the form
125 * level#classname. By default the repository-wide threshold is set
126 * to the lowest possible value, namely the level <code>ALL</code>.
127 * </p>
128 *
129 *
130 * <h3>Appender configuration</h3>
131 *
132 * <p>Appender configuration syntax is:
133 * <pre>
134 * # For appender named <i>appenderName</i>, set its class.
135 * # Note: The appender name can contain dots.
136 * log4j.appender.appenderName=fully.qualified.name.of.appender.class
137 *
138 * # Set appender specific options.
139 * log4j.appender.appenderName.option1=value1
140 * ...
141 * log4j.appender.appenderName.optionN=valueN
142 * </pre>
143 * <p>
144 * For each named appender you can configure its {@link Layout}. The
145 * syntax for configuring an appender's layout is:
146 * <pre>
147 * log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
148 * log4j.appender.appenderName.layout.option1=value1
149 * ....
150 * log4j.appender.appenderName.layout.optionN=valueN
151 * </pre>
152 * <p>
153 * The syntax for adding {@link Filter}s to an appender is:
154 * <pre>
155 * log4j.appender.appenderName.filter.ID=fully.qualified.name.of.filter.class
156 * log4j.appender.appenderName.filter.ID.option1=value1
157 * ...
158 * log4j.appender.appenderName.filter.ID.optionN=valueN
159 * </pre>
160 * The first line defines the class name of the filter identified by ID;
161 * subsequent lines with the same ID specify filter option - value
162 * pairs. Multiple filters are added to the appender in the lexicographic
163 * order of IDs.
164 * <p>
165 * The syntax for adding an {@link ErrorHandler} to an appender is:
166 * <pre>
167 * log4j.appender.appenderName.errorhandler=fully.qualified.name.of.errorhandler.class
168 * log4j.appender.appenderName.errorhandler.appender-ref=appenderName
169 * log4j.appender.appenderName.errorhandler.option1=value1
170 * ...
171 * log4j.appender.appenderName.errorhandler.optionN=valueN
172 * </pre>
173 *
174 * <h3>Configuring loggers</h3>
175 *
176 * <p>The syntax for configuring the root logger is:
177 * <pre>
178 * log4j.rootLogger=[level], appenderName, appenderName, ...
179 * </pre>
180 *
181 * <p>This syntax means that an optional <em>level</em> can be
182 * supplied followed by appender names separated by commas.
183 *
184 * <p>The level value can consist of the string values OFF, FATAL,
185 * ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
186 * custom level value can be specified in the form
187 * <code>level#classname</code>.
188 *
189 * <p>If a level value is specified, then the root level is set
190 * to the corresponding level. If no level value is specified,
191 * then the root level remains untouched.
192 *
193 * <p>The root logger can be assigned multiple appenders.
194 *
195 * <p>Each <i>appenderName</i> (separated by commas) will be added to
196 * the root logger. The named appender is defined using the
197 * appender syntax defined above.
198 *
199 * <p>For non-root categories the syntax is almost the same:
200 * <pre>
201 * log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, ...
202 * </pre>
203 *
204 * <p>The meaning of the optional level value is discussed above
205 * in relation to the root logger. In addition however, the value
206 * INHERITED can be specified meaning that the named logger should
207 * inherit its level from the logger hierarchy.
208 *
209 * <p>If no level value is supplied, then the level of the
210 * named logger remains untouched.
211 *
212 * <p>By default categories inherit their level from the
213 * hierarchy. However, if you set the level of a logger and later
214 * decide that that logger should inherit its level, then you should
215 * specify INHERITED as the value for the level value. NULL is a
216 * synonym for INHERITED.
217 *
218 * <p>Similar to the root logger syntax, each <i>appenderName</i>
219 * (separated by commas) will be attached to the named logger.
220 *
221 * <p>See the <a href="../../../../manual.html#additivity">appender
222 * additivity rule</a> in the user manual for the meaning of the
223 * <code>additivity</code> flag.
224 *
225 *
226 * # Set options for appender named "A1".
227 * # Appender "A1" will be a SyslogAppender
228 * log4j.appender.A1=org.apache.log4j.net.SyslogAppender
229 *
230 * # The syslog daemon resides on www.abc.net
231 * log4j.appender.A1.SyslogHost=www.abc.net
232 *
233 * # A1's layout is a PatternLayout, using the conversion pattern
234 * # <b>%r %-5p %c{2} %M.%L %x - %m\n</b>. Thus, the log output will
235 * # include # the relative time since the start of the application in
236 * # milliseconds, followed by the level of the log request,
237 * # followed by the two rightmost components of the logger name,
238 * # followed by the callers method name, followed by the line number,
239 * # the nested diagnostic context and finally the message itself.
240 * # Refer to the documentation of {@link PatternLayout} for further information
241 * # on the syntax of the ConversionPattern key.
242 * log4j.appender.A1.layout=org.apache.log4j.PatternLayout
243 * log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
244 *
245 * # Set options for appender named "A2"
246 * # A2 should be a RollingFileAppender, with maximum file size of 10 MB
247 * # using at most one backup file. A2's layout is TTCC, using the
248 * # ISO8061 date format with context printing enabled.
249 * log4j.appender.A2=org.apache.log4j.RollingFileAppender
250 * log4j.appender.A2.MaxFileSize=10MB
251 * log4j.appender.A2.MaxBackupIndex=1
252 * log4j.appender.A2.layout=org.apache.log4j.TTCCLayout
253 * log4j.appender.A2.layout.ContextPrinting=enabled
254 * log4j.appender.A2.layout.DateFormat=ISO8601
255 *
256 * # Root logger set to DEBUG using the A2 appender defined above.
257 * log4j.rootLogger=DEBUG, A2
258 *
259 * # Logger definitions:
260 * # The SECURITY logger inherits is level from root. However, it's output
261 * # will go to A1 appender defined above. It's additivity is non-cumulative.
262 * log4j.logger.SECURITY=INHERIT, A1
263 * log4j.additivity.SECURITY=false
264 *
265 * # Only warnings or above will be logged for the logger "SECURITY.access".
266 * # Output will go to A1.
267 * log4j.logger.SECURITY.access=WARN
268 *
269 *
270 * # The logger "class.of.the.day" inherits its level from the
271 * # logger hierarchy. Output will go to the appender's of the root
272 * # logger, A2 in this case.
273 * log4j.logger.class.of.the.day=INHERIT
274 * </pre>
275 *
276 * <p>Refer to the <b>setOption</b> method in each Appender and
277 * Layout for class specific options.
278 *
279 * <p>Use the <code>#</code> or <code>!</code> characters at the
280 * beginning of a line for comments.
281 *
282 * <p>
283 */
284 private void doConfigure(Properties properties) {
285 String status = "error";
286 String value = properties.getProperty(DEBUG_KEY);
287 if (value == null) {
288 value = properties.getProperty("log4j.configDebug");
289 if (value != null) {
290 LOGGER.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead.");
291 }
292 }
293
294 if (value != null) {
295 status = OptionConverter.toBoolean(value, false) ? "debug" : "error";
296 }
297
298 final StatusConfiguration statusConfig = new StatusConfiguration().withStatus(status);
299 statusConfig.initialize();
300
301 configureRoot(properties);
302 parseLoggers(properties);
303
304 LOGGER.debug("Finished configuring.");
305 }
306
307 // --------------------------------------------------------------------------
308 // Internal stuff
309 // --------------------------------------------------------------------------
310
311 private void configureRoot(Properties props) {
312 String effectiveFrefix = ROOT_LOGGER_PREFIX;
313 String value = OptionConverter.findAndSubst(ROOT_LOGGER_PREFIX, props);
314
315 if (value == null) {
316 value = OptionConverter.findAndSubst(ROOT_CATEGORY_PREFIX, props);
317 effectiveFrefix = ROOT_CATEGORY_PREFIX;
318 }
319
320 if (value == null) {
321 LOGGER.debug("Could not find root logger information. Is this OK?");
322 } else {
323 LoggerConfig root = getRootLogger();
324 parseLogger(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value);
325 }
326 }
327
328 /**
329 * Parse non-root elements, such non-root categories and renderers.
330 */
331 private void parseLoggers(Properties props) {
332 Enumeration enumeration = props.propertyNames();
333 while (enumeration.hasMoreElements()) {
334 String key = (String) enumeration.nextElement();
335 if (key.startsWith(CATEGORY_PREFIX) || key.startsWith(LOGGER_PREFIX)) {
336 String loggerName = null;
337 if (key.startsWith(CATEGORY_PREFIX)) {
338 loggerName = key.substring(CATEGORY_PREFIX.length());
339 } else if (key.startsWith(LOGGER_PREFIX)) {
340 loggerName = key.substring(LOGGER_PREFIX.length());
341 }
342 String value = OptionConverter.findAndSubst(key, props);
343 LoggerConfig loggerConfig = getLogger(loggerName);
344 if (loggerConfig == null) {
345 boolean additivity = getAdditivityForLogger(props, loggerName);
346 loggerConfig = new LoggerConfig(loggerName, org.apache.logging.log4j.Level.ERROR, additivity);
347 addLogger(loggerName, loggerConfig);
348 }
349 parseLogger(props, loggerConfig, key, loggerName, value);
350 }
351 }
352 }
353
354 /**
355 * Parse the additivity option for a non-root category.
356 */
357 private boolean getAdditivityForLogger(Properties props, String loggerName) {
358 boolean additivity = true;
359 String key = ADDITIVITY_PREFIX + loggerName;
360 String value = OptionConverter.findAndSubst(key, props);
361 LOGGER.debug("Handling {}=[{}]", key, value);
362 // touch additivity only if necessary
363 if ((value != null) && (!value.equals(""))) {
364 additivity = OptionConverter.toBoolean(value, true);
365 }
366 return additivity;
367 }
368
369 /**
370 * This method must work for the root category as well.
371 */
372 private void parseLogger(Properties props, LoggerConfig logger, String optionKey, String loggerName, String value) {
373
374 LOGGER.debug("Parsing for [{}] with value=[{}].", loggerName, value);
375 // We must skip over ',' but not white space
376 StringTokenizer st = new StringTokenizer(value, ",");
377
378 // If value is not in the form ", appender.." or "", then we should set the level of the logger.
379
380 if (!(value.startsWith(",") || value.equals(""))) {
381
382 // just to be on the safe side...
383 if (!st.hasMoreTokens()) {
384 return;
385 }
386
387 String levelStr = st.nextToken();
388 LOGGER.debug("Level token is [{}].", levelStr);
389
390 org.apache.logging.log4j.Level level = levelStr == null ? org.apache.logging.log4j.Level.ERROR :
391 OptionConverter.convertLevel(levelStr, org.apache.logging.log4j.Level.DEBUG);
392 logger.setLevel(level);
393 LOGGER.debug("Logger {} level set to {}", loggerName, level);
394 }
395
396 Appender appender;
397 String appenderName;
398 while (st.hasMoreTokens()) {
399 appenderName = st.nextToken().trim();
400 if (appenderName == null || appenderName.equals(",")) {
401 continue;
402 }
403 LOGGER.debug("Parsing appender named \"{}\".", appenderName);
404 appender = parseAppender(props, appenderName);
405 if (appender != null) {
406 LOGGER.debug("Adding appender named [{}] to loggerConfig [{}].", appenderName,
407 logger.getName());
408 logger.addAppender(getAppender(appenderName), null, null);
409 } else {
410 LOGGER.debug("Appender named [{}] not found.", appenderName);
411 }
412 }
413 }
414
415 public Appender parseAppender(Properties props, String appenderName) {
416 Appender appender = registry.get(appenderName);
417 if ((appender != null)) {
418 LOGGER.debug("Appender \"" + appenderName + "\" was already parsed.");
419 return appender;
420 }
421 // Appender was not previously initialized.
422 final String prefix = APPENDER_PREFIX + appenderName;
423 final String layoutPrefix = prefix + ".layout";
424 final String filterPrefix = APPENDER_PREFIX + appenderName + ".filter.";
425 String className = OptionConverter.findAndSubst(prefix, props);
426 appender = manager.parseAppender(appenderName, className, prefix, layoutPrefix, filterPrefix, props, this);
427 if (appender == null) {
428 appender = buildAppender(appenderName, className, prefix, layoutPrefix, filterPrefix, props);
429 } else {
430 registry.put(appenderName, appender);
431 if (appender instanceof AppenderWrapper) {
432 addAppender(((AppenderWrapper) appender).getAppender());
433 } else {
434 addAppender(new AppenderAdapter(appender).getAdapter());
435 }
436 }
437 return appender;
438 }
439
440 private Appender buildAppender(final String appenderName, final String className, final String prefix,
441 final String layoutPrefix, final String filterPrefix, final Properties props) {
442 Appender appender = newInstanceOf(className, "Appender");
443 if (appender == null) {
444 return null;
445 }
446 appender.setName(appenderName);
447 appender.setLayout(parseLayout(layoutPrefix, appenderName, props));
448 final String errorHandlerPrefix = prefix + ".errorhandler";
449 String errorHandlerClass = OptionConverter.findAndSubst(errorHandlerPrefix, props);
450 if (errorHandlerClass != null) {
451 ErrorHandler eh = parseErrorHandler(props, errorHandlerPrefix, errorHandlerClass, appender);
452 if (eh != null) {
453 appender.setErrorHandler(eh);
454 }
455 }
456 parseAppenderFilters(props, filterPrefix, appenderName);
457 String[] keys = new String[] {
458 layoutPrefix,
459 };
460 addProperties(appender, keys, props, prefix);
461 if (appender instanceof AppenderWrapper) {
462 addAppender(((AppenderWrapper) appender).getAppender());
463 } else {
464 addAppender(new AppenderAdapter(appender).getAdapter());
465 }
466 registry.put(appenderName, appender);
467 return appender;
468 }
469
470 public Layout parseLayout(String layoutPrefix, String appenderName, Properties props) {
471 String layoutClass = OptionConverter.findAndSubst(layoutPrefix, props);
472 if (layoutClass == null) {
473 return null;
474 }
475 Layout layout = manager.parseLayout(layoutClass, layoutPrefix, props, this);
476 if (layout == null) {
477 layout = buildLayout(layoutPrefix, layoutClass, appenderName, props);
478 }
479 return layout;
480 }
481
482 private Layout buildLayout(String layoutPrefix, String className, String appenderName, Properties props) {
483 Layout layout = newInstanceOf(className, "Layout");
484 if (layout == null) {
485 return null;
486 }
487 LOGGER.debug("Parsing layout options for \"{}\".", appenderName);
488 PropertySetter.setProperties(layout, props, layoutPrefix + ".");
489 LOGGER.debug("End of parsing for \"{}\".", appenderName);
490 return layout;
491 }
492
493 public ErrorHandler parseErrorHandler(final Properties props, final String errorHandlerPrefix,
494 final String errorHandlerClass, final Appender appender) {
495 ErrorHandler eh = newInstanceOf(errorHandlerClass, "ErrorHandler");
496 final String[] keys = new String[] {
497 errorHandlerPrefix + "." + ROOT_REF,
498 errorHandlerPrefix + "." + LOGGER_REF,
499 errorHandlerPrefix + "." + APPENDER_REF_TAG
500 };
501 addProperties(eh, keys, props, errorHandlerPrefix);
502 return eh;
503 }
504
505 public void addProperties(final Object obj, final String[] keys, final Properties props, final String prefix) {
506 final Properties edited = new Properties();
507 props.stringPropertyNames().stream().filter(name -> {
508 if (name.startsWith(prefix)) {
509 for (String key : keys) {
510 if (name.equals(key)) {
511 return false;
512 }
513 }
514 return true;
515 }
516 return false;
517 }).forEach(name -> edited.put(name, props.getProperty(name)));
518 PropertySetter.setProperties(obj, edited, prefix + ".");
519 }
520
521
522 public Filter parseAppenderFilters(Properties props, String filterPrefix, String appenderName) {
523 // extract filters and filter options from props into a hashtable mapping
524 // the property name defining the filter class to a list of pre-parsed
525 // name-value pairs associated to that filter
526 int fIdx = filterPrefix.length();
527 SortedMap<String, List<NameValue>> filters = new TreeMap<>();
528 Enumeration<?> e = props.keys();
529 String name = "";
530 while (e.hasMoreElements()) {
531 String key = (String) e.nextElement();
532 if (key.startsWith(filterPrefix)) {
533 int dotIdx = key.indexOf('.', fIdx);
534 String filterKey = key;
535 if (dotIdx != -1) {
536 filterKey = key.substring(0, dotIdx);
537 name = key.substring(dotIdx + 1);
538 }
539 List<NameValue> filterOpts = filters.computeIfAbsent(filterKey, k -> new ArrayList<>());
540 if (dotIdx != -1) {
541 String value = OptionConverter.findAndSubst(key, props);
542 filterOpts.add(new NameValue(name, value));
543 }
544 }
545 }
546
547 Filter head = null;
548 Filter next = null;
549 for (Map.Entry<String, List<NameValue>> entry : filters.entrySet()) {
550 String clazz = props.getProperty(entry.getKey());
551 Filter filter = null;
552 if (clazz != null) {
553 filter = manager.parseFilter(clazz, filterPrefix, props, this);
554 if (filter == null) {
555 LOGGER.debug("Filter key: [{}] class: [{}] props: {}", entry.getKey(), clazz, entry.getValue());
556 filter = buildFilter(clazz, appenderName, entry.getValue());
557 }
558 }
559 if (filter != null) {
560 if (head == null) {
561 head = filter;
562 } else {
563 next.setNext(filter);
564 }
565 next = filter;
566 }
567 }
568 return head;
569 }
570
571 private Filter buildFilter(String className, String appenderName, List<NameValue> props) {
572 Filter filter = newInstanceOf(className, "Filter");
573 if (filter != null) {
574 PropertySetter propSetter = new PropertySetter(filter);
575 for (NameValue property : props) {
576 propSetter.setProperty(property.key, property.value);
577 }
578 propSetter.activate();
579 }
580 return filter;
581 }
582
583
584 private static <T> T newInstanceOf(String className, String type) {
585 try {
586 return LoaderUtil.newInstanceOf(className);
587 } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException |
588 InstantiationException | InvocationTargetException ex) {
589 LOGGER.error("Unable to create {} {} due to {}:{}", type, className,
590 ex.getClass().getSimpleName(), ex.getMessage());
591 return null;
592 }
593 }
594
595 private static class NameValue {
596 String key, value;
597
598 NameValue(String key, String value) {
599 this.key = key;
600 this.value = value;
601 }
602
603 @Override
604 public String toString() {
605 return key + "=" + value;
606 }
607 }
608
609 }
+0
-75
log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.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
17 package org.apache.log4j.config;
18
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.config.Configuration;
21 import org.apache.logging.log4j.core.config.ConfigurationFactory;
22 import org.apache.logging.log4j.core.config.ConfigurationSource;
23 import org.apache.logging.log4j.core.config.Order;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.util.PropertiesUtil;
26
27 /**
28 * Configures Log4j from a log4j 1 format properties file.
29 */
30 @Plugin(name = "Log4j1PropertiesConfigurationFactory", category = ConfigurationFactory.CATEGORY)
31 @Order(2)
32 public class PropertiesConfigurationFactory extends ConfigurationFactory {
33
34 static final String FILE_EXTENSION = ".properties";
35
36 /**
37 * File name prefix for test configurations.
38 */
39 protected static final String TEST_PREFIX = "log4j-test";
40
41 /**
42 * File name prefix for standard configurations.
43 */
44 protected static final String DEFAULT_PREFIX = "log4j";
45
46 @Override
47 protected String[] getSupportedTypes() {
48 if (!PropertiesUtil.getProperties().getBooleanProperty(ConfigurationFactory.LOG4J1_EXPERIMENTAL, Boolean.FALSE)) {
49 return null;
50 }
51 return new String[] { FILE_EXTENSION };
52 }
53
54 @Override
55 public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source) {
56 int interval = PropertiesUtil.getProperties().getIntegerProperty(Log4j1Configuration.MONITOR_INTERVAL, 0);
57 return new PropertiesConfiguration(loggerContext, source, interval);
58 }
59
60 @Override
61 protected String getTestPrefix() {
62 return TEST_PREFIX;
63 }
64
65 @Override
66 protected String getDefaultPrefix() {
67 return DEFAULT_PREFIX;
68 }
69
70 @Override
71 protected String getVersion() {
72 return LOG4J1_VERSION;
73 }
74 }
00 /*
11 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
2 * contributor license agreements. See the NOTICE file distributed with
33 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
4 * The ASF licenses this file to You under the Apache license, Version 2.0
55 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
6 * the License. You may obtain a copy of the License at
77 *
88 * http://www.apache.org/licenses/LICENSE-2.0
99 *
1010 * Unless required by applicable law or agreed to in writing, software
1111 * distributed under the License is distributed on an "AS IS" BASIS,
1212 * 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.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
1515 */
16
17 // Contributors: Georg Lundesgaard
18
1916 package org.apache.log4j.config;
2017
21 import java.beans.BeanInfo;
22 import java.beans.IntrospectionException;
23 import java.beans.Introspector;
2418 import java.beans.PropertyDescriptor;
25 import java.io.InterruptedIOException;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
2819 import java.util.Properties;
2920
30 import org.apache.log4j.Appender;
31 import org.apache.log4j.Level;
32 import org.apache.log4j.Priority;
33 import org.apache.log4j.spi.ErrorHandler;
34 import org.apache.log4j.spi.OptionHandler;
35 import org.apache.logging.log4j.Logger;
36 import org.apache.logging.log4j.core.util.OptionConverter;
37 import org.apache.logging.log4j.status.StatusLogger;
38
3921 /**
40 * General purpose Object property setter. Clients repeatedly invokes
41 * {@link #setProperty setProperty(name,value)} in order to invoke setters
42 * on the Object specified in the constructor. This class relies on the
43 * JavaBeans {@link Introspector} to analyze the given Object Class using
44 * reflection.
4522 *
46 * <p>Usage:
47 * <pre>
48 * PropertySetter ps = new PropertySetter(anObject);
49 * ps.set("name", "Joe");
50 * ps.set("age", "32");
51 * ps.set("isMale", "true");
52 * </pre>
53 * will cause the invocations anObject.setName("Joe"), anObject.setAge(32),
54 * and setMale(true) if such methods exist with those signatures.
55 * Otherwise an {@link IntrospectionException} are thrown.
23 * @since 1.1
5624 */
5725 public class PropertySetter {
58 private static final PropertyDescriptor[] EMPTY_PROPERTY_DESCRIPTOR_ARRAY = {};
59 private static Logger LOGGER = StatusLogger.getLogger();
60 protected Object obj;
61 protected PropertyDescriptor[] props;
6226
6327 /**
6428 * Create a new PropertySetter for the specified Object. This is done
65 * in prepartion for invoking {@link #setProperty} one or more times.
29 * in preparation for invoking {@link #setProperty} one or more times.
6630 *
67 * @param obj the object for which to set properties
31 * @param obj the object for which to set properties
6832 */
69 public PropertySetter(Object obj) {
70 this.obj = obj;
33 public PropertySetter(final Object obj) {
7134 }
7235
73 /**
74 * Set the properties of an object passed as a parameter in one
75 * go. The <code>properties</code> are parsed relative to a
76 * <code>prefix</code>.
77 *
78 * @param obj The object to configure.
79 * @param properties A java.util.Properties containing keys and values.
80 * @param prefix Only keys having the specified prefix will be set.
81 */
82 public static void setProperties(Object obj, Properties properties, String prefix) {
83 new PropertySetter(obj).setProperties(properties, prefix);
84 }
8536
8637 /**
87 * Uses JavaBeans {@link Introspector} to computer setters of object to be
88 * configured.
38 * Set the properties for the object that match the <code>prefix</code> passed as parameter.
39 *
40 * @param properties The properties
41 * @param prefix The prefix
8942 */
90 protected void introspect() {
91 try {
92 BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
93 props = bi.getPropertyDescriptors();
94 } catch (IntrospectionException ex) {
95 LOGGER.error("Failed to introspect {}: {}", obj, ex.getMessage());
96 props = EMPTY_PROPERTY_DESCRIPTOR_ARRAY;
97 }
98 }
99
100 /**
101 * Set the properites for the object that match the
102 * <code>prefix</code> passed as parameter.
103 * @param properties The properties.
104 * @param prefix The prefix of the properties to use.
105 */
106 public void setProperties(Properties properties, String prefix) {
107 int len = prefix.length();
108
109 for (String key : properties.stringPropertyNames()) {
110
111 // handle only properties that start with the desired prefix.
112 if (key.startsWith(prefix)) {
113
114
115 // ignore key if it contains dots after the prefix
116 if (key.indexOf('.', len + 1) > 0) {
117 continue;
118 }
119
120 String value = OptionConverter.findAndSubst(key, properties);
121 key = key.substring(len);
122 if (("layout".equals(key) || "errorhandler".equals(key)) && obj instanceof Appender) {
123 continue;
124 }
125 //
126 // if the property type is an OptionHandler
127 // (for example, triggeringPolicy of org.apache.log4j.rolling.RollingFileAppender)
128 PropertyDescriptor prop = getPropertyDescriptor(Introspector.decapitalize(key));
129 if (prop != null
130 && OptionHandler.class.isAssignableFrom(prop.getPropertyType())
131 && prop.getWriteMethod() != null) {
132 OptionHandler opt = (OptionHandler)
133 OptionConverter.instantiateByKey(properties, prefix + key,
134 prop.getPropertyType(),
135 null);
136 PropertySetter setter = new PropertySetter(opt);
137 setter.setProperties(properties, prefix + key + ".");
138 try {
139 prop.getWriteMethod().invoke(this.obj, opt);
140 } catch (InvocationTargetException ex) {
141 if (ex.getTargetException() instanceof InterruptedException
142 || ex.getTargetException() instanceof InterruptedIOException) {
143 Thread.currentThread().interrupt();
144 }
145 LOGGER.warn("Failed to set property [{}] to value \"{}\".", key, value, ex);
146 } catch (IllegalAccessException | RuntimeException ex) {
147 LOGGER.warn("Failed to set property [{}] to value \"{}\".", key, value, ex);
148 }
149 continue;
150 }
151
152 setProperty(key, value);
153 }
154 }
155 activate();
43 public void setProperties(final Properties properties, final String prefix) {
15644 }
15745
15846 /**
16755 * to an int using new Integer(value). If the setter expects a boolean,
16856 * the conversion is by new Boolean(value).
16957 *
170 * @param name name of the property
171 * @param value String value of the property
58 * @param name name of the property
59 * @param value String value of the property
17260 */
173 public void setProperty(String name, String value) {
174 if (value == null) {
175 return;
176 }
177
178 name = Introspector.decapitalize(name);
179 PropertyDescriptor prop = getPropertyDescriptor(name);
180
181 //LOGGER.debug("---------Key: "+name+", type="+prop.getPropertyType());
182
183 if (prop == null) {
184 LOGGER.warn("No such property [" + name + "] in " +
185 obj.getClass().getName() + ".");
186 } else {
187 try {
188 setProperty(prop, name, value);
189 } catch (PropertySetterException ex) {
190 LOGGER.warn("Failed to set property [{}] to value \"{}\".", name, value, ex.rootCause);
191 }
192 }
61 public void setProperty(final String name, final String value) {
19362 }
19463
19564 /**
19665 * Set the named property given a {@link PropertyDescriptor}.
19766 *
198 * @param prop A PropertyDescriptor describing the characteristics
199 * of the property to set.
200 * @param name The named of the property to set.
67 * @param prop A PropertyDescriptor describing the characteristics of the property to set.
68 * @param name The named of the property to set.
20169 * @param value The value of the property.
202 * @throws PropertySetterException if no setter is available.
70 * @throws PropertySetterException (Never actually throws this exception. Kept for historical purposes.)
20371 */
204 public void setProperty(PropertyDescriptor prop, String name, String value)
205 throws PropertySetterException {
206 Method setter = prop.getWriteMethod();
207 if (setter == null) {
208 throw new PropertySetterException("No setter for property [" + name + "].");
209 }
210 Class<?>[] paramTypes = setter.getParameterTypes();
211 if (paramTypes.length != 1) {
212 throw new PropertySetterException("#params for setter != 1");
213 }
214
215 Object arg;
216 try {
217 arg = convertArg(value, paramTypes[0]);
218 } catch (Throwable t) {
219 throw new PropertySetterException("Conversion to type [" + paramTypes[0] +
220 "] failed. Reason: " + t);
221 }
222 if (arg == null) {
223 throw new PropertySetterException(
224 "Conversion to type [" + paramTypes[0] + "] failed.");
225 }
226 LOGGER.debug("Setting property [" + name + "] to [" + arg + "].");
227 try {
228 setter.invoke(obj, arg);
229 } catch (InvocationTargetException ex) {
230 if (ex.getTargetException() instanceof InterruptedException
231 || ex.getTargetException() instanceof InterruptedIOException) {
232 Thread.currentThread().interrupt();
233 }
234 throw new PropertySetterException(ex);
235 } catch (IllegalAccessException | RuntimeException ex) {
236 throw new PropertySetterException(ex);
237 }
72 public void setProperty(final PropertyDescriptor prop, final String name, final String value)
73 throws PropertySetterException {
23874 }
23975
240
24176 /**
242 * Convert <code>val</code> a String parameter to an object of a
243 * given type.
244 * @param val The value to convert.
245 * @param type The type of the value to convert to.
246 * @return The result of the conversion.
77 * Set the properties of an object passed as a parameter in one
78 * go. The <code>properties</code> are parsed relative to a
79 * <code>prefix</code>.
80 *
81 * @param obj The object to configure.
82 * @param properties A java.util.Properties containing keys and values.
83 * @param prefix Only keys having the specified prefix will be set.
24784 */
248 protected Object convertArg(String val, Class<?> type) {
249 if (val == null) {
250 return null;
251 }
252
253 String v = val.trim();
254 if (String.class.isAssignableFrom(type)) {
255 return val;
256 } else if (Integer.TYPE.isAssignableFrom(type)) {
257 return Integer.parseInt(v);
258 } else if (Long.TYPE.isAssignableFrom(type)) {
259 return Long.parseLong(v);
260 } else if (Boolean.TYPE.isAssignableFrom(type)) {
261 if ("true".equalsIgnoreCase(v)) {
262 return Boolean.TRUE;
263 } else if ("false".equalsIgnoreCase(v)) {
264 return Boolean.FALSE;
265 }
266 } else if (Priority.class.isAssignableFrom(type)) {
267 return org.apache.log4j.helpers.OptionConverter.toLevel(v, Level.DEBUG);
268 } else if (ErrorHandler.class.isAssignableFrom(type)) {
269 return OptionConverter.instantiateByClassName(v,
270 ErrorHandler.class, null);
271 }
272 return null;
273 }
274
275
276 protected PropertyDescriptor getPropertyDescriptor(String name) {
277 if (props == null) {
278 introspect();
279 }
280 for (PropertyDescriptor prop : props) {
281 if (name.equals(prop.getName())) {
282 return prop;
283 }
284 }
285 return null;
286 }
287
288 public void activate() {
289 if (obj instanceof OptionHandler) {
290 ((OptionHandler) obj).activateOptions();
291 }
85 public static void setProperties(final Object obj, final Properties properties, final String prefix) {
29286 }
29387 }
4444 * @param rootCause The root cause
4545 */
4646 public PropertySetterException(final Throwable rootCause) {
47 super();
4748 this.rootCause = rootCause;
4849 }
4950
+0
-89
log4j-1.2-api/src/main/java/org/apache/log4j/helpers/AppenderAttachableImpl.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.helpers;
17
18 import org.apache.log4j.Appender;
19 import org.apache.log4j.spi.AppenderAttachable;
20 import org.apache.log4j.spi.LoggingEvent;
21
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.concurrent.ConcurrentHashMap;
25 import java.util.concurrent.ConcurrentMap;
26
27 /**
28 * Allows Classes to attach Appenders.
29 */
30 public class AppenderAttachableImpl implements AppenderAttachable {
31
32 private final ConcurrentMap<String, Appender> appenders = new ConcurrentHashMap<>();
33
34 @Override
35 public void addAppender(Appender newAppender) {
36 if (newAppender != null) {
37 appenders.put(newAppender.getName(), newAppender);
38 }
39 }
40
41 @Override
42 public Enumeration getAllAppenders() {
43 return Collections.enumeration(appenders.values());
44 }
45
46 @Override
47 public Appender getAppender(String name) {
48 return appenders.get(name);
49 }
50
51 @Override
52 public boolean isAttached(Appender appender) {
53 return appenders.containsValue(appender);
54 }
55
56 @Override
57 public void removeAllAppenders() {
58 appenders.clear();
59 }
60
61 @Override
62 public void removeAppender(Appender appender) {
63 appenders.remove(appender.getName(), appender);
64 }
65
66 @Override
67 public void removeAppender(String name) {
68 appenders.remove(name);
69 }
70
71 /**
72 * Call the <code>doAppend</code> method on all attached appenders.
73 * @param event The event to log.
74 * @return The number of appenders.
75 */
76 public int appendLoopOnAppenders(LoggingEvent event) {
77 for (Appender appender : appenders.values()) {
78 appender.doAppend(event);
79 }
80 return appenders.size();
81 }
82
83 public void close() {
84 for (Appender appender : appenders.values()) {
85 appender.close();
86 }
87 }
88 }
+0
-419
log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.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
17 package org.apache.log4j.helpers;
18
19 import org.apache.log4j.Level;
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.util.LoaderUtil;
23
24 import java.io.InterruptedIOException;
25 import java.lang.reflect.InvocationTargetException;
26 import java.util.Properties;
27
28 /**
29 * A convenience class to convert property values to specific types.
30 */
31 public class OptionConverter {
32
33 static String DELIM_START = "${";
34 static char DELIM_STOP = '}';
35 static int DELIM_START_LEN = 2;
36 static int DELIM_STOP_LEN = 1;
37 private static final Logger LOGGER = LogManager.getLogger(OptionConverter.class);
38 private static final CharMap[] charMap = new CharMap[] {
39 new CharMap('n', '\n'),
40 new CharMap('r', '\r'),
41 new CharMap('t', '\t'),
42 new CharMap('f', '\f'),
43 new CharMap('\b', '\b'),
44 new CharMap('\"', '\"'),
45 new CharMap('\'', '\''),
46 new CharMap('\\', '\\')
47 };
48
49 /**
50 * OptionConverter is a static class.
51 */
52 private OptionConverter() {
53 }
54
55 public static String[] concatanateArrays(String[] l, String[] r) {
56 int len = l.length + r.length;
57 String[] a = new String[len];
58
59 System.arraycopy(l, 0, a, 0, l.length);
60 System.arraycopy(r, 0, a, l.length, r.length);
61
62 return a;
63 }
64
65 public static String convertSpecialChars(String s) {
66 char c;
67 int len = s.length();
68 StringBuilder sbuf = new StringBuilder(len);
69
70 int i = 0;
71 while (i < len) {
72 c = s.charAt(i++);
73 if (c == '\\') {
74 c = s.charAt(i++);
75 for (CharMap entry : charMap) {
76 if (entry.key == c) {
77 c = entry.replacement;
78 }
79 }
80 }
81 sbuf.append(c);
82 }
83 return sbuf.toString();
84 }
85
86
87 /**
88 * Very similar to <code>System.getProperty</code> except
89 * that the {@link SecurityException} is hidden.
90 *
91 * @param key The key to search for.
92 * @param def The default value to return.
93 * @return the string value of the system property, or the default
94 * value if there is no property with that key.
95 * @since 1.1
96 */
97 public static String getSystemProperty(String key, String def) {
98 try {
99 return System.getProperty(key, def);
100 } catch (Throwable e) { // MS-Java throws com.ms.security.SecurityExceptionEx
101 LOGGER.debug("Was not allowed to read system property \"{}\".", key);
102 return def;
103 }
104 }
105
106 /**
107 * If <code>value</code> is "true", then <code>true</code> is
108 * returned. If <code>value</code> is "false", then
109 * <code>true</code> is returned. Otherwise, <code>default</code> is
110 * returned.
111 *
112 * <p>Case of value is unimportant.
113 * @param value The value to convert.
114 * @param dEfault The default value.
115 * @return the value of the result.
116 */
117 public static boolean toBoolean(String value, boolean dEfault) {
118 if (value == null) {
119 return dEfault;
120 }
121 String trimmedVal = value.trim();
122 if ("true".equalsIgnoreCase(trimmedVal)) {
123 return true;
124 }
125 if ("false".equalsIgnoreCase(trimmedVal)) {
126 return false;
127 }
128 return dEfault;
129 }
130
131 /**
132 * Converts a standard or custom priority level to a Level
133 * object. <p> If <code>value</code> is of form
134 * "level#classname", then the specified class' toLevel method
135 * is called to process the specified level string; if no '#'
136 * character is present, then the default {@link org.apache.log4j.Level}
137 * class is used to process the level value.
138 *
139 * <p>As a special case, if the <code>value</code> parameter is
140 * equal to the string "NULL", then the value <code>null</code> will
141 * be returned.
142 *
143 * <p> If any error occurs while converting the value to a level,
144 * the <code>defaultValue</code> parameter, which may be
145 * <code>null</code>, is returned.
146 *
147 * <p> Case of <code>value</code> is insignificant for the level level, but is
148 * significant for the class name part, if present.
149 * @param value The value to convert.
150 * @param defaultValue The default value.
151 * @return the value of the result.
152 *
153 * @since 1.1
154 */
155 public static Level toLevel(String value, Level defaultValue) {
156 if (value == null) {
157 return defaultValue;
158 }
159
160 value = value.trim();
161
162 int hashIndex = value.indexOf('#');
163 if (hashIndex == -1) {
164 if ("NULL".equalsIgnoreCase(value)) {
165 return null;
166 }
167 // no class name specified : use standard Level class
168 return Level.toLevel(value, defaultValue);
169 }
170
171 Level result = defaultValue;
172
173 String clazz = value.substring(hashIndex + 1);
174 String levelName = value.substring(0, hashIndex);
175
176 // This is degenerate case but you never know.
177 if ("NULL".equalsIgnoreCase(levelName)) {
178 return null;
179 }
180
181 LOGGER.debug("toLevel" + ":class=[" + clazz + "]"
182 + ":pri=[" + levelName + "]");
183
184 try {
185 Class<?> customLevel = LoaderUtil.loadClass(clazz);
186
187 // get a ref to the specified class' static method
188 // toLevel(String, org.apache.log4j.Level)
189 Class<?>[] paramTypes = new Class[] { String.class, org.apache.log4j.Level.class };
190 java.lang.reflect.Method toLevelMethod =
191 customLevel.getMethod("toLevel", paramTypes);
192
193 // now call the toLevel method, passing level string + default
194 Object[] params = new Object[]{levelName, defaultValue};
195 Object o = toLevelMethod.invoke(null, params);
196
197 result = (Level) o;
198 } catch (ClassNotFoundException e) {
199 LOGGER.warn("custom level class [" + clazz + "] not found.");
200 } catch (NoSuchMethodException e) {
201 LOGGER.warn("custom level class [" + clazz + "]"
202 + " does not have a class function toLevel(String, Level)", e);
203 } catch (java.lang.reflect.InvocationTargetException e) {
204 if (e.getTargetException() instanceof InterruptedException
205 || e.getTargetException() instanceof InterruptedIOException) {
206 Thread.currentThread().interrupt();
207 }
208 LOGGER.warn("custom level class [" + clazz + "]"
209 + " could not be instantiated", e);
210 } catch (ClassCastException e) {
211 LOGGER.warn("class [" + clazz
212 + "] is not a subclass of org.apache.log4j.Level", e);
213 } catch (IllegalAccessException e) {
214 LOGGER.warn("class [" + clazz +
215 "] cannot be instantiated due to access restrictions", e);
216 } catch (RuntimeException e) {
217 LOGGER.warn("class [" + clazz + "], level [" + levelName +
218 "] conversion failed.", e);
219 }
220 return result;
221 }
222
223 /**
224 * Instantiate an object given a class name. Check that the
225 * <code>className</code> is a subclass of
226 * <code>superClass</code>. If that test fails or the object could
227 * not be instantiated, then <code>defaultValue</code> is returned.
228 *
229 * @param className The fully qualified class name of the object to instantiate.
230 * @param superClass The class to which the new object should belong.
231 * @param defaultValue The object to return in case of non-fulfillment
232 * @return The created object.
233 */
234 public static Object instantiateByClassName(String className, Class<?> superClass,
235 Object defaultValue) {
236 if (className != null) {
237 try {
238 Object obj = LoaderUtil.newInstanceOf(className);
239 if (!superClass.isAssignableFrom(obj.getClass())) {
240 LOGGER.error("A \"{}\" object is not assignable to a \"{}\" variable", className,
241 superClass.getName());
242 return defaultValue;
243 }
244 return obj;
245 } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
246 | InstantiationException | InvocationTargetException e) {
247 LOGGER.error("Could not instantiate class [" + className + "].", e);
248 }
249 }
250 return defaultValue;
251 }
252
253
254 /**
255 * Perform variable substitution in string <code>val</code> from the
256 * values of keys found in the system propeties.
257 *
258 * <p>The variable substitution delimeters are <b>${</b> and <b>}</b>.
259 *
260 * <p>For example, if the System properties contains "key=value", then
261 * the call
262 * <pre>
263 * String s = OptionConverter.substituteVars("Value of key is ${key}.");
264 * </pre>
265 * <p>
266 * will set the variable <code>s</code> to "Value of key is value.".
267 *
268 * <p>If no value could be found for the specified key, then the
269 * <code>props</code> parameter is searched, if the value could not
270 * be found there, then substitution defaults to the empty string.
271 *
272 * <p>For example, if system propeties contains no value for the key
273 * "inexistentKey", then the call
274 *
275 * <pre>
276 * String s = OptionConverter.subsVars("Value of inexistentKey is [${inexistentKey}]");
277 * </pre>
278 * will set <code>s</code> to "Value of inexistentKey is []"
279 *
280 * <p>An {@link IllegalArgumentException} is thrown if
281 * <code>val</code> contains a start delimeter "${" which is not
282 * balanced by a stop delimeter "}". </p>
283 *
284 * <p><b>Author</b> Avy Sharell</p>
285 *
286 * @param val The string on which variable substitution is performed.
287 * @param props The properties to use for the substitution.
288 * @return The substituted string.
289 * @throws IllegalArgumentException if <code>val</code> is malformed.
290 */
291 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 }
335 }
336
337 public static org.apache.logging.log4j.Level convertLevel(String level,
338 org.apache.logging.log4j.Level defaultLevel) {
339 Level l = toLevel(level, null);
340 return l != null ? convertLevel(l) : defaultLevel;
341 }
342
343 public static org.apache.logging.log4j.Level convertLevel(Level level) {
344 if (level == null) {
345 return org.apache.logging.log4j.Level.ERROR;
346 }
347 if (level.isGreaterOrEqual(Level.FATAL)) {
348 return org.apache.logging.log4j.Level.FATAL;
349 } else if (level.isGreaterOrEqual(Level.ERROR)) {
350 return org.apache.logging.log4j.Level.ERROR;
351 } else if (level.isGreaterOrEqual(Level.WARN)) {
352 return org.apache.logging.log4j.Level.WARN;
353 } else if (level.isGreaterOrEqual(Level.INFO)) {
354 return org.apache.logging.log4j.Level.INFO;
355 } else if (level.isGreaterOrEqual(Level.DEBUG)) {
356 return org.apache.logging.log4j.Level.DEBUG;
357 } else if (level.isGreaterOrEqual(Level.TRACE)) {
358 return org.apache.logging.log4j.Level.TRACE;
359 }
360 return org.apache.logging.log4j.Level.ALL;
361 }
362
363 public static Level convertLevel(org.apache.logging.log4j.Level level) {
364 if (level == null) {
365 return Level.ERROR;
366 }
367 switch (level.getStandardLevel()) {
368 case FATAL:
369 return Level.FATAL;
370 case WARN:
371 return Level.WARN;
372 case INFO:
373 return Level.INFO;
374 case DEBUG:
375 return Level.DEBUG;
376 case TRACE:
377 return Level.TRACE;
378 case ALL:
379 return Level.ALL;
380 case OFF:
381 return Level.OFF;
382 default:
383 return Level.ERROR;
384 }
385 }
386
387 /**
388 * Find the value corresponding to <code>key</code> in
389 * <code>props</code>. Then perform variable substitution on the
390 * found value.
391 * @param key The key used to locate the substitution string.
392 * @param props The properties to use in the substitution.
393 * @return The substituted string.
394 */
395 public static String findAndSubst(String key, Properties props) {
396 String value = props.getProperty(key);
397 if (value == null) {
398 return null;
399 }
400
401 try {
402 return substVars(value, props);
403 } catch (IllegalArgumentException e) {
404 LOGGER.error("Bad option value [{}].", value, e);
405 return value;
406 }
407 }
408
409 private static class CharMap {
410 final char key;
411 final char replacement;
412
413 public CharMap(char key, char replacement) {
414 this.key = key;
415 this.replacement = replacement;
416 }
417 }
418 }
+0
-70
log4j-1.2-api/src/main/java/org/apache/log4j/helpers/QuietWriter.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
17 package org.apache.log4j.helpers;
18
19 import org.apache.log4j.spi.ErrorCode;
20 import org.apache.log4j.spi.ErrorHandler;
21
22 import java.io.FilterWriter;
23 import java.io.Writer;
24
25
26 /**
27 * QuietWriter does not throw exceptions when things go
28 * wrong. Instead, it delegates error handling to its {@link ErrorHandler}.
29 */
30 public class QuietWriter extends FilterWriter {
31
32 protected ErrorHandler errorHandler;
33
34 public QuietWriter(Writer writer, ErrorHandler errorHandler) {
35 super(writer);
36 setErrorHandler(errorHandler);
37 }
38
39 @Override
40 public void write(String string) {
41 if (string != null) {
42 try {
43 out.write(string);
44 } catch (Exception e) {
45 errorHandler.error("Failed to write [" + string + "].", e,
46 ErrorCode.WRITE_FAILURE);
47 }
48 }
49 }
50
51 @Override
52 public void flush() {
53 try {
54 out.flush();
55 } catch (Exception e) {
56 errorHandler.error("Failed to flush writer,", e,
57 ErrorCode.FLUSH_FAILURE);
58 }
59 }
60
61
62 public void setErrorHandler(ErrorHandler eh) {
63 if (eh == null) {
64 // This is a programming error on the part of the enclosing appender.
65 throw new IllegalArgumentException("Attempted to set null ErrorHandler.");
66 }
67 this.errorHandler = eh;
68 }
69 }
1919 import java.io.StringWriter;
2020 import java.nio.charset.StandardCharsets;
2121 import java.util.List;
22 import java.util.Objects;
2322
2423 import org.apache.logging.log4j.core.Layout;
2524 import org.apache.logging.log4j.core.LogEvent;
3029 import org.apache.logging.log4j.core.layout.AbstractStringLayout;
3130 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
3231 import org.apache.logging.log4j.core.util.Transform;
32 import org.apache.logging.log4j.util.BiConsumer;
3333 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3434 import org.apache.logging.log4j.util.Strings;
3535
136136 final ReadOnlyStringMap contextMap = event.getContextData();
137137 if (!contextMap.isEmpty()) {
138138 buf.append("<log4j:properties>\r\n");
139 contextMap.forEach((key, val) -> {
140 if (val != null) {
141 buf.append("<log4j:data name=\"");
142 buf.append(Transform.escapeHtmlTags(key));
143 buf.append("\" value=\"");
144 buf.append(Transform.escapeHtmlTags(Objects.toString(val, null)));
145 buf.append("\"/>\r\n");
139 contextMap.forEach(new BiConsumer<String, String>() {
140 @Override
141 public void accept(final String key, final String val) {
142 if (val != null) {
143 buf.append("<log4j:data name=\"");
144 buf.append(Transform.escapeHtmlTags(key));
145 buf.append("\" value=\"");
146 buf.append(Transform.escapeHtmlTags(val));
147 buf.append("\"/>\r\n");
148 }
146149 }
147150 });
148151 buf.append("</log4j:properties>\r\n");
+0
-27
log4j-1.2-api/src/main/java/org/apache/log4j/or/ObjectRenderer.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.or;
17
18 /**
19 * Converts objects to Strings.
20 */
21 public interface ObjectRenderer {
22 /**
23 * Render the object passed as parameter as a String.
24 */
25 String doRender(Object o);
26 }
+0
-26
log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererSupport.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.or;
17
18 import java.util.Map;
19
20 /**
21 * Interface that indicates the Renderer Map is available. This interface differs
22 */
23 public interface RendererSupport {
24 Map<Class<?>, ObjectRenderer> getRendererMap();
25 }
+0
-57
log4j-1.2-api/src/main/java/org/apache/log4j/or/ThreadGroupRenderer.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.or;
17
18 import org.apache.log4j.Layout;
19
20 /**
21 */
22 public class ThreadGroupRenderer implements ObjectRenderer {
23
24 @Override
25 public
26 String doRender(Object obj) {
27 if(obj instanceof ThreadGroup) {
28 StringBuilder sb = new StringBuilder();
29 ThreadGroup threadGroup = (ThreadGroup) obj;
30 sb.append("java.lang.ThreadGroup[name=");
31 sb.append(threadGroup.getName());
32 sb.append(", maxpri=");
33 sb.append(threadGroup.getMaxPriority());
34 sb.append("]");
35 Thread[] threads = new Thread[threadGroup.activeCount()];
36 threadGroup.enumerate(threads);
37 for (Thread thread : threads) {
38 sb.append(Layout.LINE_SEP);
39 sb.append(" Thread=[");
40 sb.append(thread.getName());
41 sb.append(",");
42 sb.append(thread.getPriority());
43 sb.append(",");
44 sb.append(thread.isDaemon());
45 sb.append("]");
46 }
47 return sb.toString();
48 }
49 try {
50 // this is the best we can do
51 return obj.toString();
52 } catch(Exception ex) {
53 return ex.toString();
54 }
55 }
56 }
+0
-87
log4j-1.2-api/src/main/java/org/apache/log4j/or/jms/MessageRenderer.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.or.jms;
17
18 import org.apache.log4j.or.ObjectRenderer;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.status.StatusLogger;
21
22 import javax.jms.Message;
23 import javax.jms.JMSException;
24 import javax.jms.DeliveryMode;
25
26 /**
27 * Log4j 1.x JMS Message Renderer
28 */
29 public class MessageRenderer implements ObjectRenderer {
30 private static final Logger LOGGER = StatusLogger.getLogger();
31
32 /**
33 Render a {@link javax.jms.Message}.
34 */
35 @Override
36 public
37 String doRender(Object obj) {
38 if (obj instanceof Message) {
39 StringBuilder sb = new StringBuilder();
40 Message message = (Message) obj;
41 try {
42 sb.append("DeliveryMode=");
43 switch(message.getJMSDeliveryMode()) {
44 case DeliveryMode.NON_PERSISTENT :
45 sb.append("NON_PERSISTENT");
46 break;
47 case DeliveryMode.PERSISTENT :
48 sb.append("PERSISTENT");
49 break;
50 default: sb.append("UNKNOWN");
51 }
52 sb.append(", CorrelationID=");
53 sb.append(message.getJMSCorrelationID());
54
55 sb.append(", Destination=");
56 sb.append(message.getJMSDestination());
57
58 sb.append(", Expiration=");
59 sb.append(message.getJMSExpiration());
60
61 sb.append(", MessageID=");
62 sb.append(message.getJMSMessageID());
63
64 sb.append(", Priority=");
65 sb.append(message.getJMSPriority());
66
67 sb.append(", Redelivered=");
68 sb.append(message.getJMSRedelivered());
69
70 sb.append(", ReplyTo=");
71 sb.append(message.getJMSReplyTo());
72
73 sb.append(", Timestamp=");
74 sb.append(message.getJMSTimestamp());
75
76 sb.append(", Type=");
77 sb.append(message.getJMSType());
78
79 } catch(JMSException e) {
80 LOGGER.error("Could not parse Message.", e);
81 }
82 return sb.toString();
83 }
84 return obj.toString();
85 }
86 }
7878 }
7979 }
8080
81 private static TriConsumer<String, Object, StringBuilder> APPEND_EACH = (key, value, toAppendTo) -> toAppendTo.append('{').append(key).append(',').append(value).append('}');
81 private static TriConsumer<String, Object, StringBuilder> APPEND_EACH = new TriConsumer<String, Object, StringBuilder>() {
82 @Override
83 public void accept(final String key, final Object value, final StringBuilder toAppendTo) {
84 toAppendTo.append('{').append(key).append(',').append(value).append('}');
85 }
86 };
8287 }
+0
-123
log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/MapRewritePolicy.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.rewrite;
17
18 import org.apache.log4j.bridge.LogEventAdapter;
19 import org.apache.log4j.helpers.OptionConverter;
20 import org.apache.log4j.spi.LocationInfo;
21 import org.apache.log4j.spi.LoggingEvent;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
24 import org.apache.logging.log4j.message.MapMessage;
25 import org.apache.logging.log4j.message.Message;
26 import org.apache.logging.log4j.message.SimpleMessage;
27 import org.apache.logging.log4j.util.SortedArrayStringMap;
28
29 import java.util.HashMap;
30 import java.util.Map;
31
32 /**
33 * This policy rewrites events where the message of the
34 * original event implements java.util.Map.
35 * All other events are passed through unmodified.
36 * If the map contains a "message" entry, the value will be
37 * used as the message for the rewritten event. The rewritten
38 * event will have a property set that is the combination of the
39 * original property set and the other members of the message map.
40 * If both the original property set and the message map
41 * contain the same entry, the value from the message map
42 * will overwrite the original property set.
43 * <p>
44 * The combination of the RewriteAppender and this policy
45 * performs the same actions as the MapFilter from log4j 1.3.
46 * </p>
47 */
48 public class MapRewritePolicy implements RewritePolicy {
49 /**
50 * {@inheritDoc}
51 */
52 @Override
53 public LoggingEvent rewrite(final LoggingEvent source) {
54 Object msg = source.getMessage();
55 if (msg instanceof MapMessage || msg instanceof Map) {
56 Map<String, String> props = source.getProperties() != null ? new HashMap<>(source.getProperties())
57 : new HashMap<>();
58 @SuppressWarnings("unchecked")
59 Map<String, Object> eventProps = msg instanceof Map ? (Map) msg : ((MapMessage) msg).getData();
60 //
61 // if the map sent in the logging request
62 // has "message" entry, use that as the message body
63 // otherwise, use the entire map.
64 //
65 Message newMessage = null;
66 Object newMsg = eventProps.get("message");
67 if (newMsg != null) {
68 newMessage = new SimpleMessage(newMsg.toString());
69 for (Map.Entry<String, Object> entry : eventProps.entrySet()) {
70 if (!("message".equals(entry.getKey()))) {
71 props.put(entry.getKey(), entry.getValue().toString());
72 }
73 }
74 } else {
75 return source;
76 }
77
78 LogEvent event;
79 if (source instanceof LogEventAdapter) {
80 event = new Log4jLogEvent.Builder(((LogEventAdapter) source).getEvent())
81 .setMessage(newMessage)
82 .setContextData(new SortedArrayStringMap(props))
83 .build();
84 } else {
85 LocationInfo info = source.getLocationInformation();
86 StackTraceElement element = new StackTraceElement(info.getClassName(), info.getMethodName(),
87 info.getFileName(), Integer.parseInt(info.getLineNumber()));
88 Thread thread = getThread(source.getThreadName());
89 long threadId = thread != null ? thread.getId() : 0;
90 int threadPriority = thread != null ? thread.getPriority() : 0;
91 event = Log4jLogEvent.newBuilder()
92 .setContextData(new SortedArrayStringMap(props))
93 .setLevel(OptionConverter.convertLevel(source.getLevel()))
94 .setLoggerFqcn(source.getFQNOfLoggerClass())
95 .setMarker(null)
96 .setMessage(newMessage)
97 .setSource(element)
98 .setLoggerName(source.getLoggerName())
99 .setThreadName(source.getThreadName())
100 .setThreadId(threadId)
101 .setThreadPriority(threadPriority)
102 .setThrown(source.getThrowableInformation().getThrowable())
103 .setTimeMillis(source.getTimeStamp())
104 .setNanoTime(0)
105 .setThrownProxy(null)
106 .build();
107 }
108 return new LogEventAdapter(event);
109 }
110 return source;
111
112 }
113
114 private Thread getThread(String name) {
115 for (Thread thread : Thread.getAllStackTraces().keySet()) {
116 if (thread.getName().equals(name)) {
117 return thread;
118 }
119 }
120 return null;
121 }
122 }
+0
-126
log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/PropertyRewritePolicy.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.rewrite;
17
18 import org.apache.log4j.bridge.LogEventAdapter;
19 import org.apache.log4j.helpers.OptionConverter;
20 import org.apache.log4j.spi.LocationInfo;
21 import org.apache.log4j.spi.LoggingEvent;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
24 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.apache.logging.log4j.util.SortedArrayStringMap;
26
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.StringTokenizer;
31
32 /**
33 * This policy rewrites events by adding
34 * a user-specified list of properties to the event.
35 * Existing properties are not modified.
36 * <p>
37 * The combination of the RewriteAppender and this policy
38 * performs the same actions as the PropertyFilter from log4j 1.3.
39 * </p>
40 */
41 public class PropertyRewritePolicy implements RewritePolicy {
42 private Map<String, String> properties = Collections.EMPTY_MAP;
43
44 public PropertyRewritePolicy() {
45 }
46
47 /**
48 * Set a string representing the property name/value pairs.
49 * <p>
50 * Form:
51 * </p>
52 * <pre>
53 * propname1=propvalue1,propname2=propvalue2
54 * </pre>
55 *
56 * @param properties The properties.
57 */
58 public void setProperties(String properties) {
59 Map<String, String> newMap = new HashMap<>();
60 StringTokenizer pairs = new StringTokenizer(properties, ",");
61 while (pairs.hasMoreTokens()) {
62 StringTokenizer entry = new StringTokenizer(pairs.nextToken(), "=");
63 newMap.put(entry.nextElement().toString().trim(), entry.nextElement().toString().trim());
64 }
65 synchronized (this) {
66 this.properties = newMap;
67 }
68 }
69
70 /**
71 * {@inheritDoc}
72 */
73 @Override
74 public LoggingEvent rewrite(final LoggingEvent source) {
75 if (!properties.isEmpty()) {
76 Map<String, String> rewriteProps = source.getProperties() != null ? new HashMap<>(source.getProperties())
77 : new HashMap<>();
78 for (Map.Entry<String, String> entry : properties.entrySet()) {
79 if (!rewriteProps.containsKey(entry.getKey())) {
80 rewriteProps.put(entry.getKey(), entry.getValue());
81 }
82 }
83 LogEvent event;
84 if (source instanceof LogEventAdapter) {
85 event = new Log4jLogEvent.Builder(((LogEventAdapter) source).getEvent())
86 .setContextData(new SortedArrayStringMap(rewriteProps))
87 .build();
88 } else {
89 LocationInfo info = source.getLocationInformation();
90 StackTraceElement element = new StackTraceElement(info.getClassName(), info.getMethodName(),
91 info.getFileName(), Integer.parseInt(info.getLineNumber()));
92 Thread thread = getThread(source.getThreadName());
93 long threadId = thread != null ? thread.getId() : 0;
94 int threadPriority = thread != null ? thread.getPriority() : 0;
95 event = Log4jLogEvent.newBuilder()
96 .setContextData(new SortedArrayStringMap(rewriteProps))
97 .setLevel(OptionConverter.convertLevel(source.getLevel()))
98 .setLoggerFqcn(source.getFQNOfLoggerClass())
99 .setMarker(null)
100 .setMessage(new SimpleMessage(source.getRenderedMessage()))
101 .setSource(element)
102 .setLoggerName(source.getLoggerName())
103 .setThreadName(source.getThreadName())
104 .setThreadId(threadId)
105 .setThreadPriority(threadPriority)
106 .setThrown(source.getThrowableInformation().getThrowable())
107 .setTimeMillis(source.getTimeStamp())
108 .setNanoTime(0)
109 .setThrownProxy(null)
110 .build();
111 }
112 return new LogEventAdapter(event);
113 }
114 return source;
115 }
116
117 private Thread getThread(String name) {
118 for (Thread thread : Thread.getAllStackTraces().keySet()) {
119 if (thread.getName().equals(name)) {
120 return thread;
121 }
122 }
123 return null;
124 }
125 }
+0
-36
log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/RewritePolicy.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.rewrite;
17
18 import org.apache.log4j.spi.LoggingEvent;
19
20 /**
21 * This interface is implemented to provide a rewrite
22 * strategy for RewriteAppender. RewriteAppender will
23 * call the rewrite method with a source logging event.
24 * The strategy may return that event, create a new event
25 * or return null to suppress the logging request.
26 */
27 public interface RewritePolicy {
28 /**
29 * Rewrite a logging event.
30 * @param source a logging event that may be returned or
31 * used to create a new logging event.
32 * @return a logging event or null to suppress processing.
33 */
34 LoggingEvent rewrite(final LoggingEvent source);
35 }
+0
-78
log4j-1.2-api/src/main/java/org/apache/log4j/spi/AppenderAttachable.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
17 package org.apache.log4j.spi;
18
19 import org.apache.log4j.Appender;
20
21 import java.util.Enumeration;
22
23 /**
24 * Interface for attaching appenders to objects.
25 */
26 public interface AppenderAttachable {
27
28 /**
29 * Add an appender.
30 * @param newAppender The Appender to add.
31 */
32 void addAppender(Appender newAppender);
33
34 /**
35 * Get all previously added appenders as an Enumeration.
36 * @return The Enumeration of the Appenders.
37 */
38 Enumeration<Appender> getAllAppenders();
39
40 /**
41 * Get an appender by name.
42 * @param name The name of the Appender.
43 * @return The Appender.
44 */
45 Appender getAppender(String name);
46
47
48 /**
49 * Returns <code>true</code> if the specified appender is in list of
50 * attached attached, <code>false</code> otherwise.
51 * @param appender The Appender to check.
52 * @return true if the Appender is attached.
53 *
54 * @since 1.2
55 */
56 boolean isAttached(Appender appender);
57
58 /**
59 * Remove all previously added appenders.
60 */
61 void removeAllAppenders();
62
63
64 /**
65 * Remove the appender passed as parameter from the list of appenders.
66 * @param appender The Appender to remove.
67 */
68 void removeAppender(Appender appender);
69
70
71 /**
72 * Remove the appender with the name passed as parameter from the
73 * list of appenders.
74 * @param name The name of the Appender to remove.
75 */
76 void removeAppender(String name);
77 }
+0
-55
log4j-1.2-api/src/main/java/org/apache/log4j/spi/Configurator.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.spi;
17
18 import java.io.InputStream;
19 import java.net.URL;
20
21 import org.apache.logging.log4j.core.LoggerContext;
22
23 /**
24 * Log4j 1.x Configurator interface.
25 */
26 public interface Configurator {
27
28 public static final String INHERITED = "inherited";
29
30 public static final String NULL = "null";
31
32
33 /**
34 Interpret a resource pointed by a InputStream and set up log4j accordingly.
35
36 The configuration is done relative to the <code>hierarchy</code>
37 parameter.
38
39 @param inputStream The InputStream to parse
40
41 @since 1.2.17
42 */
43 void doConfigure(InputStream inputStream, final LoggerContext loggerContext);
44
45 /**
46 Interpret a resource pointed by a URL and set up log4j accordingly.
47
48 The configuration is done relative to the <code>hierarchy</code>
49 parameter.
50
51 @param url The URL to parse
52 */
53 void doConfigure(URL url, final LoggerContext loggerContext);
54 }
+0
-33
log4j-1.2-api/src/main/java/org/apache/log4j/spi/ErrorCode.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
17 package org.apache.log4j.spi;
18
19
20 /**
21 This interface defines commonly encoutered error codes.
22 */
23 public interface ErrorCode {
24
25 public final int GENERIC_FAILURE = 0;
26 public final int WRITE_FAILURE = 1;
27 public final int FLUSH_FAILURE = 2;
28 public final int CLOSE_FAILURE = 3;
29 public final int FILE_OPEN_FAILURE = 4;
30 public final int MISSING_LAYOUT = 5;
31 public final int ADDRESS_PARSE_FAILURE = 6;
32 }
4848
4949 /**
5050 * Equivalent to the {@link #error(String, Exception, int,
51 * LoggingEvent)} with the event parameter set to
51 * LoggingEvent)} with the the event parameter set to
5252 * <code>null</code>.
5353 *
5454 * @param message The message associated with the error.
1515 */
1616 package org.apache.log4j.spi;
1717
18 import org.apache.log4j.bridge.FilterAdapter;
19
2018 /**
2119 * @since 0.9.0
2220 */
2321 public abstract class Filter {
24 private final FilterAdapter adapter;
25
26 public Filter() {
27 FilterAdapter filterAdapter = null;
28 try {
29 Class.forName("org.apache.logging.log4j.core.Filter");
30 filterAdapter = new FilterAdapter(this);
31 } catch(ClassNotFoundException ex) {
32 // Ignore the exception. Log4j Core is not present.
33 }
34 this.adapter = filterAdapter;
35 }
3622
3723 /**
3824 * The log event must be dropped immediately without consulting
+0
-75
log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.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.spi;
17
18 /**
19 The internal representation of caller location information.
20
21 @since 0.8.3
22 */
23 public class LocationInfo implements java.io.Serializable {
24
25 private final StackTraceElement element;
26
27 public String fullInfo;
28
29 public LocationInfo(StackTraceElement element) {
30 this.element = element;
31 }
32
33 /**
34 When location information is not available the constant
35 <code>NA</code> is returned. Current value of this string
36 constant is <b>?</b>. */
37 public final static String NA = "?";
38
39 static final long serialVersionUID = -1325822038990805636L;
40
41
42 /**
43 Return the fully qualified class name of the caller making the
44 logging request.
45 */
46 public
47 String getClassName() {
48 return element.getClassName();
49 }
50
51 /**
52 Return the file name of the caller.
53 */
54 public
55 String getFileName() {
56 return element.getFileName();
57 }
58
59 /**
60 Returns the line number of the caller.
61 */
62 public
63 String getLineNumber() {
64 return Integer.toString(element.getLineNumber());
65 }
66
67 /**
68 Returns the method name of the caller.
69 */
70 public
71 String getMethodName() {
72 return element.getMethodName();
73 }
74 }
1515 */
1616 package org.apache.log4j.spi;
1717
18 import org.apache.log4j.Category;
19 import org.apache.log4j.Level;
20 import org.apache.log4j.bridge.LogEventAdapter;
21
22 import java.util.Map;
23 import java.util.Set;
24
2518 /**
26 * No-op version of Log4j 1.2 LoggingEvent. This class is not directly used by Log4j 1.x clients but is used by
27 * the Log4j 2 LogEvent adapter to be compatible with Log4j 1.x components.
19 * No-op version of Log4j 1.2 LoggingEvent.
2820 */
2921 public class LoggingEvent {
30
31 /**
32 Set the location information for this logging event. The collected
33 information is cached for future use.
34 @return Always returns null.
35 */
36 public LocationInfo getLocationInformation() {
37 return null;
38 }
39
40 /**
41 * Return the level of this event. Use this form instead of directly
42 * accessing the <code>level</code> field.
43 * @return Always returns null.
44 */
45 public Level getLevel() {
46 return null;
47 }
48
49 /**
50 * Return the name of the logger. Use this form instead of directly
51 * accessing the <code>categoryName</code> field.
52 * @return Always returns null.
53 */
54 public String getLoggerName() {
55 return null;
56 }
57
58 public String getFQNOfLoggerClass() {
59 return null;
60 }
61
62 public long getTimeStamp() {
63 return 0;
64 }
65
66 /**
67 * Gets the logger of the event.
68 * Use should be restricted to cloning events.
69 * @return Always returns null.
70 * @since 1.2.15
71 */
72 public Category getLogger() {
73 return null;
74 }
75
76 /**
77 Return the message for this logging event.
78
79 <p>Before serialization, the returned object is the message
80 passed by the user to generate the logging event. After
81 serialization, the returned value equals the String form of the
82 message possibly after object rendering.
83 @return Always returns null.
84 @since 1.1 */
85 public
86 Object getMessage() {
87 return null;
88 }
89
90 public
91 String getNDC() {
92 return null;
93 }
94
95 public
96 Object getMDC(String key) {
97 return null;
98 }
99
100 /**
101 Obtain a copy of this thread's MDC prior to serialization or
102 asynchronous logging.
103 */
104 public void getMDCCopy() {
105 }
106
107 public String getRenderedMessage() {
108 return null;
109 }
110
111 /**
112 Returns the time when the application started, in milliseconds
113 elapsed since 01.01.1970.
114 @return the JVM start time.
115 */
116 public static long getStartTime() {
117 return LogEventAdapter.getStartTime();
118 }
119
120 public String getThreadName() {
121 return null;
122 }
123
124 /**
125 Returns the throwable information contained within this
126 event. May be <code>null</code> if there is no such information.
127
128 <p>Note that the {@link Throwable} object contained within a
129 {@link ThrowableInformation} does not survive serialization.
130 @return Always returns null.
131 @since 1.1 */
132 public ThrowableInformation getThrowableInformation() {
133 return null;
134 }
135
136 /**
137 Return this event's throwable's string[] representaion.
138 @return Always returns null.
139 */
140 public String[] getThrowableStrRep() {
141 return null;
142 }
143
144 public void setProperty(final String propName,
145 final String propValue) {
146
147 }
148
149 public String getProperty(final String key) {
150 return null;
151 }
152
153 public Set getPropertyKeySet() {
154 return null;
155 }
156
157 public Map getProperties() {
158 return null;
159 }
160
161 public Object removeProperty(String propName) {
162 return null;
163 }
16422 }
+0
-66
log4j-1.2-api/src/main/java/org/apache/log4j/spi/ThrowableInformation.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.spi;
17
18 import java.lang.reflect.InvocationTargetException;
19 import java.lang.reflect.Method;
20 import java.util.List;
21
22 import org.apache.logging.log4j.util.Strings;
23
24 /**
25 * Class Description goes here.
26 */
27 public class ThrowableInformation implements java.io.Serializable {
28
29 static final long serialVersionUID = -4748765566864322735L;
30
31 private transient Throwable throwable;
32 private Method toStringList;
33
34 public ThrowableInformation(Throwable throwable) {
35 this.throwable = throwable;
36 Method method = null;
37 try {
38 Class<?> throwables = Class.forName("org.apache.logging.log4j.core.util.Throwables");
39 method = throwables.getMethod("toStringList", Throwable.class);
40 } catch (ClassNotFoundException | NoSuchMethodException ex) {
41 // Ignore the exception if Log4j-core is not present.
42 }
43 this.toStringList = method;
44 }
45
46 public Throwable getThrowable() {
47 return throwable;
48 }
49
50 public synchronized String[] getThrowableStrRep() {
51 if (toStringList != null && throwable != null) {
52 try {
53 @SuppressWarnings("unchecked")
54 List<String> elements = (List<String>) toStringList.invoke(null, throwable);
55 if (elements != null) {
56 return elements.toArray(Strings.EMPTY_ARRAY);
57 }
58 } catch (IllegalAccessException | InvocationTargetException ex) {
59 // Ignore the exception.
60 }
61 }
62 return null;
63 }
64 }
65
+0
-52
log4j-1.2-api/src/main/java/org/apache/log4j/xml/Log4jEntityResolver.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
17 package org.apache.log4j.xml;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.InputStream;
21
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.status.StatusLogger;
24 import org.apache.logging.log4j.util.Constants;
25 import org.xml.sax.EntityResolver;
26 import org.xml.sax.InputSource;
27
28 /**
29 * An {@link EntityResolver} specifically designed to return
30 * <code>log4j.dtd</code> which is embedded within the log4j jar
31 * file.
32 */
33 public class Log4jEntityResolver implements EntityResolver {
34 private static final Logger LOGGER = StatusLogger.getLogger();
35 private static final String PUBLIC_ID = "-//APACHE//DTD LOG4J 1.2//EN";
36
37 @Override
38 public InputSource resolveEntity(String publicId, String systemId) {
39 if (systemId.endsWith("log4j.dtd") || PUBLIC_ID.equals(publicId)) {
40 Class<?> clazz = getClass();
41 InputStream in = clazz.getResourceAsStream("/org/apache/log4j/xml/log4j.dtd");
42 if (in == null) {
43 LOGGER.warn("Could not find [log4j.dtd] using [{}] class loader, parsed without DTD.",
44 clazz.getClassLoader());
45 in = new ByteArrayInputStream(Constants.EMPTY_BYTE_ARRAY);
46 }
47 return new InputSource(in);
48 }
49 return null;
50 }
51 }
+0
-42
log4j-1.2-api/src/main/java/org/apache/log4j/xml/UnrecognizedElementHandler.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.xml;
17
18 import org.w3c.dom.Element;
19 import java.util.Properties;
20
21 /**
22 * When implemented by an object configured by DOMConfigurator,
23 * the handle method will be called when an unrecognized child
24 * element is encountered. Unrecognized child elements of
25 * the log4j:configuration element will be dispatched to
26 * the logger repository if it supports this interface.
27 *
28 * @since 1.2.15
29 */
30 public interface UnrecognizedElementHandler {
31 /**
32 * Called to inform a configured object when
33 * an unrecognized child element is encountered.
34 * @param element element, may not be null.
35 * @param props properties in force, may be null.
36 * @return true if configured object recognized the element
37 * @throws Exception throw an exception to prevent activation
38 * of the configured object.
39 */
40 boolean parseUnrecognizedElement(Element element, Properties props) throws Exception;
41 }
+0
-801
log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.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.xml;
17
18 import java.io.IOException;
19 import java.io.InterruptedIOException;
20 import java.lang.reflect.Method;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Properties;
24 import java.util.function.Consumer;
25
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.parsers.FactoryConfigurationError;
29
30 import org.apache.log4j.Appender;
31 import org.apache.log4j.Layout;
32 import org.apache.log4j.Level;
33 import org.apache.log4j.bridge.AppenderAdapter;
34 import org.apache.log4j.bridge.AppenderWrapper;
35 import org.apache.log4j.config.Log4j1Configuration;
36 import org.apache.log4j.config.PropertySetter;
37 import org.apache.log4j.helpers.OptionConverter;
38 import org.apache.log4j.rewrite.RewritePolicy;
39 import org.apache.log4j.spi.AppenderAttachable;
40 import org.apache.log4j.spi.ErrorHandler;
41 import org.apache.log4j.spi.Filter;
42 import org.apache.logging.log4j.core.LoggerContext;
43 import org.apache.logging.log4j.core.config.Configuration;
44 import org.apache.logging.log4j.core.config.ConfigurationSource;
45 import org.apache.logging.log4j.core.config.LoggerConfig;
46 import org.apache.logging.log4j.core.config.status.StatusConfiguration;
47 import org.apache.logging.log4j.status.StatusLogger;
48 import org.apache.logging.log4j.util.LoaderUtil;
49 import org.w3c.dom.Document;
50 import org.w3c.dom.Element;
51 import org.w3c.dom.NamedNodeMap;
52 import org.w3c.dom.Node;
53 import org.w3c.dom.NodeList;
54 import org.xml.sax.InputSource;
55 import org.xml.sax.SAXException;
56 import org.xml.sax.SAXParseException;
57
58 /**
59 * Class Description goes here.
60 */
61 public class XmlConfiguration extends Log4j1Configuration {
62
63 private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
64
65 private static final String CONFIGURATION_TAG = "log4j:configuration";
66 private static final String OLD_CONFIGURATION_TAG = "configuration";
67 private static final String RENDERER_TAG = "renderer";
68 private static final String APPENDER_TAG = "appender";
69 public static final String PARAM_TAG = "param";
70 public static final String LAYOUT_TAG = "layout";
71 private static final String CATEGORY = "category";
72 private static final String LOGGER_ELEMENT = "logger";
73 private static final String CATEGORY_FACTORY_TAG = "categoryFactory";
74 private static final String LOGGER_FACTORY_TAG = "loggerFactory";
75 public static final String NAME_ATTR = "name";
76 private static final String CLASS_ATTR = "class";
77 public static final String VALUE_ATTR = "value";
78 private static final String ROOT_TAG = "root";
79 private static final String LEVEL_TAG = "level";
80 private static final String PRIORITY_TAG = "priority";
81 public static final String FILTER_TAG = "filter";
82 private static final String ERROR_HANDLER_TAG = "errorHandler";
83 public static final String REF_ATTR = "ref";
84 private static final String ADDITIVITY_ATTR = "additivity";
85 private static final String CONFIG_DEBUG_ATTR = "configDebug";
86 private static final String INTERNAL_DEBUG_ATTR = "debug";
87 private static final String EMPTY_STR = "";
88 private static final Class<?>[] ONE_STRING_PARAM = new Class[] { String.class };
89 private static final String dbfKey = "javax.xml.parsers.DocumentBuilderFactory";
90 private static final String THROWABLE_RENDERER_TAG = "throwableRenderer";
91
92 public static final long DEFAULT_DELAY = 60000;
93
94 /**
95 * File name prefix for test configurations.
96 */
97 protected static final String TEST_PREFIX = "log4j-test";
98
99 /**
100 * File name prefix for standard configurations.
101 */
102 protected static final String DEFAULT_PREFIX = "log4j";
103
104 // key: appenderName, value: appender
105 private Map<String, Appender> appenderMap;
106
107 private Properties props = null;
108
109 public XmlConfiguration(final LoggerContext loggerContext, final ConfigurationSource source,
110 int monitorIntervalSeconds) {
111 super(loggerContext, source, monitorIntervalSeconds);
112 appenderMap = new HashMap<>();
113 }
114
115 public void addAppenderIfAbsent(Appender appender) {
116 appenderMap.putIfAbsent(appender.getName(), appender);
117 }
118
119 /**
120 * Configures log4j by reading in a log4j.dtd compliant XML
121 * configuration file.
122 */
123 @Override
124 public void doConfigure() throws FactoryConfigurationError {
125 ConfigurationSource source = getConfigurationSource();
126 ParseAction action = new ParseAction() {
127 @Override
128 public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
129 @SuppressWarnings("resource") // The ConfigurationSource and its caller manages the InputStream.
130 InputSource inputSource = new InputSource(source.getInputStream());
131 inputSource.setSystemId("dummy://log4j.dtd");
132 return parser.parse(inputSource);
133 }
134
135 @Override
136 public String toString() {
137 return getConfigurationSource().getLocation();
138 }
139 };
140 doConfigure(action);
141 }
142
143 private void doConfigure(final ParseAction action) throws FactoryConfigurationError {
144 DocumentBuilderFactory dbf;
145 try {
146 LOGGER.debug("System property is : {}", OptionConverter.getSystemProperty(dbfKey, null));
147 dbf = DocumentBuilderFactory.newInstance();
148 LOGGER.debug("Standard DocumentBuilderFactory search succeded.");
149 LOGGER.debug("DocumentBuilderFactory is: " + dbf.getClass().getName());
150 } catch (FactoryConfigurationError fce) {
151 Exception e = fce.getException();
152 LOGGER.debug("Could not instantiate a DocumentBuilderFactory.", e);
153 throw fce;
154 }
155
156 try {
157 dbf.setValidating(true);
158
159 DocumentBuilder docBuilder = dbf.newDocumentBuilder();
160
161 docBuilder.setErrorHandler(new SAXErrorHandler());
162 docBuilder.setEntityResolver(new Log4jEntityResolver());
163
164 Document doc = action.parse(docBuilder);
165 parse(doc.getDocumentElement());
166 } catch (Exception e) {
167 if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
168 Thread.currentThread().interrupt();
169 }
170 // I know this is miserable...
171 LOGGER.error("Could not parse " + action.toString() + ".", e);
172 }
173 }
174
175 @Override
176 public Configuration reconfigure() {
177 try {
178 final ConfigurationSource source = getConfigurationSource().resetInputStream();
179 if (source == null) {
180 return null;
181 }
182 final XmlConfigurationFactory factory = new XmlConfigurationFactory();
183 final XmlConfiguration config =
184 (XmlConfiguration) factory.getConfiguration(getLoggerContext(), source);
185 return config == null || config.getState() != State.INITIALIZING ? null : config;
186 } catch (final IOException ex) {
187 LOGGER.error("Cannot locate file {}: {}", getConfigurationSource(), ex);
188 }
189 return null;
190 }
191
192 /**
193 * Delegates unrecognized content to created instance if it supports UnrecognizedElementParser.
194 *
195 * @param instance instance, may be null.
196 * @param element element, may not be null.
197 * @param props properties
198 * @throws IOException thrown if configuration of owner object should be abandoned.
199 */
200 private void parseUnrecognizedElement(final Object instance, final Element element,
201 final Properties props) throws Exception {
202 boolean recognized = false;
203 if (instance instanceof UnrecognizedElementHandler) {
204 recognized = ((UnrecognizedElementHandler) instance).parseUnrecognizedElement(
205 element, props);
206 }
207 if (!recognized) {
208 LOGGER.warn("Unrecognized element {}", element.getNodeName());
209 }
210 }
211
212 /**
213 * Delegates unrecognized content to created instance if
214 * it supports UnrecognizedElementParser and catches and
215 * logs any exception.
216 *
217 * @param instance instance, may be null.
218 * @param element element, may not be null.
219 * @param props properties
220 * @since 1.2.15
221 */
222 private void quietParseUnrecognizedElement(final Object instance,
223 final Element element,
224 final Properties props) {
225 try {
226 parseUnrecognizedElement(instance, element, props);
227 } catch (Exception ex) {
228 if (ex instanceof InterruptedException || ex instanceof InterruptedIOException) {
229 Thread.currentThread().interrupt();
230 }
231 LOGGER.error("Error in extension content: ", ex);
232 }
233 }
234
235 /**
236 * Substitutes property value for any references in expression.
237 *
238 * @param value value from configuration file, may contain
239 * literal text, property references or both
240 * @param props properties.
241 * @return evaluated expression, may still contain expressions
242 * if unable to expand.
243 */
244 public String subst(final String value, final Properties props) {
245 try {
246 return OptionConverter.substVars(value, props);
247 } catch (IllegalArgumentException e) {
248 LOGGER.warn("Could not perform variable substitution.", e);
249 return value;
250 }
251 }
252
253 /**
254 * Sets a parameter based from configuration file content.
255 *
256 * @param elem param element, may not be null.
257 * @param propSetter property setter, may not be null.
258 * @param props properties
259 * @since 1.2.15
260 */
261 public void setParameter(final Element elem, final PropertySetter propSetter, final Properties props) {
262 String name = subst(elem.getAttribute("name"), props);
263 String value = (elem.getAttribute("value"));
264 value = subst(OptionConverter.convertSpecialChars(value), props);
265 propSetter.setProperty(name, value);
266 }
267
268 /**
269 * Creates an object and processes any nested param elements
270 * but does not call activateOptions. If the class also supports
271 * UnrecognizedElementParser, the parseUnrecognizedElement method
272 * will be call for any child elements other than param.
273 *
274 * @param element element, may not be null.
275 * @param props properties
276 * @param expectedClass interface or class expected to be implemented
277 * by created class
278 * @return created class or null.
279 * @throws Exception thrown if the contain object should be abandoned.
280 * @since 1.2.15
281 */
282 public Object parseElement(final Element element, final Properties props,
283 @SuppressWarnings("rawtypes") final Class expectedClass) throws Exception {
284 String clazz = subst(element.getAttribute("class"), props);
285 Object instance = OptionConverter.instantiateByClassName(clazz,
286 expectedClass, null);
287
288 if (instance != null) {
289 PropertySetter propSetter = new PropertySetter(instance);
290 NodeList children = element.getChildNodes();
291 final int length = children.getLength();
292
293 for (int loop = 0; loop < length; loop++) {
294 Node currentNode = children.item(loop);
295 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
296 Element currentElement = (Element) currentNode;
297 String tagName = currentElement.getTagName();
298 if (tagName.equals("param")) {
299 setParameter(currentElement, propSetter, props);
300 } else {
301 parseUnrecognizedElement(instance, currentElement, props);
302 }
303 }
304 }
305 return instance;
306 }
307 return null;
308 }
309
310 /**
311 * Used internally to parse appenders by IDREF name.
312 */
313 private Appender findAppenderByName(Document doc, String appenderName) {
314 Appender appender = appenderMap.get(appenderName);
315
316 if (appender != null) {
317 return appender;
318 }
319 // Endre's hack:
320 Element element = null;
321 NodeList list = doc.getElementsByTagName("appender");
322 for (int t = 0; t < list.getLength(); t++) {
323 Node node = list.item(t);
324 NamedNodeMap map = node.getAttributes();
325 Node attrNode = map.getNamedItem("name");
326 if (appenderName.equals(attrNode.getNodeValue())) {
327 element = (Element) node;
328 break;
329 }
330 }
331 // Hack finished.
332
333 if (element == null) {
334
335 LOGGER.error("No appender named [{}] could be found.", appenderName);
336 return null;
337 }
338 appender = parseAppender(element);
339 if (appender != null) {
340 appenderMap.put(appenderName, appender);
341 }
342 return appender;
343 }
344
345 /**
346 * Used internally to parse appenders by IDREF element.
347 */
348 public Appender findAppenderByReference(Element appenderRef) {
349 String appenderName = subst(appenderRef.getAttribute(REF_ATTR));
350 Document doc = appenderRef.getOwnerDocument();
351 return findAppenderByName(doc, appenderName);
352 }
353
354 /**
355 * Used internally to parse an appender element.
356 */
357 public Appender parseAppender(Element appenderElement) {
358 String className = subst(appenderElement.getAttribute(CLASS_ATTR));
359 LOGGER.debug("Class name: [" + className + ']');
360 Appender appender = manager.parseAppender(className, appenderElement, this);
361 if (appender == null) {
362 appender = buildAppender(className, appenderElement);
363 }
364 return appender;
365 }
366
367 private Appender buildAppender(String className, Element appenderElement) {
368 try {
369 Appender appender = LoaderUtil.newInstanceOf(className);
370 PropertySetter propSetter = new PropertySetter(appender);
371
372 appender.setName(subst(appenderElement.getAttribute(NAME_ATTR)));
373 forEachElement(appenderElement.getChildNodes(), currentElement -> {
374 // Parse appender parameters
375 switch (currentElement.getTagName()) {
376 case PARAM_TAG:
377 setParameter(currentElement, propSetter);
378 break;
379 case LAYOUT_TAG:
380 appender.setLayout(parseLayout(currentElement));
381 break;
382 case FILTER_TAG:
383 Filter filter = parseFilters(currentElement);
384 if (filter != null) {
385 LOGGER.debug("Adding filter of type [{}] to appender named [{}]",
386 filter.getClass(), appender.getName());
387 appender.addFilter(filter);
388 }
389 break;
390 case ERROR_HANDLER_TAG:
391 parseErrorHandler(currentElement, appender);
392 break;
393 case APPENDER_REF_TAG:
394 String refName = subst(currentElement.getAttribute(REF_ATTR));
395 if (appender instanceof AppenderAttachable) {
396 AppenderAttachable aa = (AppenderAttachable) appender;
397 Appender child = findAppenderByReference(currentElement);
398 LOGGER.debug("Attaching appender named [{}] to appender named [{}].", refName,
399 appender.getName());
400 aa.addAppender(child);
401 } else {
402 LOGGER.error("Requesting attachment of appender named [{}] to appender named [{}]"
403 + "which does not implement org.apache.log4j.spi.AppenderAttachable.",
404 refName, appender.getName());
405 }
406 break;
407 default:
408 try {
409 parseUnrecognizedElement(appender, currentElement, props);
410 } catch (Exception ex) {
411 throw new ConsumerException(ex);
412 }
413 }
414 });
415 propSetter.activate();
416 return appender;
417 } catch (ConsumerException ex) {
418 Throwable t = ex.getCause();
419 if (t instanceof InterruptedException || t instanceof InterruptedIOException) {
420 Thread.currentThread().interrupt();
421 }
422 LOGGER.error("Could not create an Appender. Reported error follows.", t);
423 } catch (Exception oops) {
424 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
425 Thread.currentThread().interrupt();
426 }
427 LOGGER.error("Could not create an Appender. Reported error follows.", oops);
428 }
429 return null;
430 }
431
432 public RewritePolicy parseRewritePolicy(Element rewritePolicyElement) {
433 String className = subst(rewritePolicyElement.getAttribute(CLASS_ATTR));
434 LOGGER.debug("Class name: [" + className + ']');
435 RewritePolicy policy = manager.parseRewritePolicy(className, rewritePolicyElement, this);
436 if (policy == null) {
437 policy = buildRewritePolicy(className, rewritePolicyElement);
438 }
439 return policy;
440 }
441
442 private RewritePolicy buildRewritePolicy(String className, Element element) {
443 try {
444 RewritePolicy policy = LoaderUtil.newInstanceOf(className);
445 PropertySetter propSetter = new PropertySetter(policy);
446
447 forEachElement(element.getChildNodes(), currentElement -> {
448 if (currentElement.getTagName().equalsIgnoreCase(PARAM_TAG)) {
449 setParameter(currentElement, propSetter);
450 }
451 });
452 propSetter.activate();
453 return policy;
454 } catch (ConsumerException ex) {
455 Throwable t = ex.getCause();
456 if (t instanceof InterruptedException || t instanceof InterruptedIOException) {
457 Thread.currentThread().interrupt();
458 }
459 LOGGER.error("Could not create an RewritePolicy. Reported error follows.", t);
460 } catch (Exception oops) {
461 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
462 Thread.currentThread().interrupt();
463 }
464 LOGGER.error("Could not create an RewritePolicy. Reported error follows.", oops);
465 }
466 return null;
467 }
468
469 /**
470 * Used internally to parse an {@link ErrorHandler} element.
471 */
472 private void parseErrorHandler(Element element, Appender appender) {
473 ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByClassName(
474 subst(element.getAttribute(CLASS_ATTR)),
475 ErrorHandler.class,
476 null);
477
478 if (eh != null) {
479 eh.setAppender(appender);
480
481 PropertySetter propSetter = new PropertySetter(eh);
482 forEachElement(element.getChildNodes(), currentElement -> {
483 String tagName = currentElement.getTagName();
484 if (tagName.equals(PARAM_TAG)) {
485 setParameter(currentElement, propSetter);
486 }
487 });
488 propSetter.activate();
489 appender.setErrorHandler(eh);
490 }
491 }
492
493 /**
494 * Used internally to parse a filter element.
495 */
496 public Filter parseFilters(Element filterElement) {
497 String className = subst(filterElement.getAttribute(CLASS_ATTR));
498 LOGGER.debug("Class name: [" + className + ']');
499 Filter filter = manager.parseFilter(className, filterElement, this);
500 if (filter == null) {
501 PropertySetter propSetter = new PropertySetter(filter);
502 forEachElement(filterElement.getChildNodes(), currentElement -> {
503 String tagName = currentElement.getTagName();
504 if (tagName.equals(PARAM_TAG)) {
505 setParameter(currentElement, propSetter);
506 } else {
507 quietParseUnrecognizedElement(filter, currentElement, props);
508 }
509 });
510 propSetter.activate();
511 }
512 return filter;
513 }
514
515 /**
516 * Used internally to parse an category element.
517 */
518 private void parseCategory(Element loggerElement) {
519 // Create a new org.apache.log4j.Category object from the <category> element.
520 String catName = subst(loggerElement.getAttribute(NAME_ATTR));
521 boolean additivity = OptionConverter.toBoolean(subst(loggerElement.getAttribute(ADDITIVITY_ATTR)), true);
522 LoggerConfig loggerConfig = getLogger(catName);
523 if (loggerConfig == null) {
524 loggerConfig = new LoggerConfig(catName, org.apache.logging.log4j.Level.ERROR, additivity);
525 addLogger(catName, loggerConfig);
526 } else {
527 loggerConfig.setAdditive(additivity);
528 }
529 parseChildrenOfLoggerElement(loggerElement, loggerConfig, false);
530 }
531
532 /**
533 * Used internally to parse the roor category element.
534 */
535 private void parseRoot(Element rootElement) {
536 LoggerConfig root = getRootLogger();
537 parseChildrenOfLoggerElement(rootElement, root, true);
538 }
539
540 /**
541 * Used internally to parse the children of a LoggerConfig element.
542 */
543 private void parseChildrenOfLoggerElement(Element catElement, LoggerConfig loggerConfig, boolean isRoot) {
544
545 final PropertySetter propSetter = new PropertySetter(loggerConfig);
546 loggerConfig.getAppenderRefs().clear();
547 forEachElement(catElement.getChildNodes(), currentElement -> {
548 switch (currentElement.getTagName()) {
549 case APPENDER_REF_TAG: {
550 Appender appender = findAppenderByReference(currentElement);
551 String refName = subst(currentElement.getAttribute(REF_ATTR));
552 if (appender != null) {
553 LOGGER.debug("Adding appender named [{}] to loggerConfig [{}].", refName,
554 loggerConfig.getName());
555 loggerConfig.addAppender(getAppender(refName), null, null);
556 } else {
557 LOGGER.debug("Appender named [{}] not found.", refName);
558 }
559 break;
560 }
561 case LEVEL_TAG: case PRIORITY_TAG: {
562 parseLevel(currentElement, loggerConfig, isRoot);
563 break;
564 }
565 case PARAM_TAG: {
566 setParameter(currentElement, propSetter);
567 break;
568 }
569 default: {
570 quietParseUnrecognizedElement(loggerConfig, currentElement, props);
571 }
572 }
573 });
574 propSetter.activate();
575 }
576
577 /**
578 * Used internally to parse a layout element.
579 */
580 public Layout parseLayout(Element layoutElement) {
581 String className = subst(layoutElement.getAttribute(CLASS_ATTR));
582 LOGGER.debug("Parsing layout of class: \"{}\"", className);
583 Layout layout = manager.parseLayout(className, layoutElement, this);
584 if (layout == null) {
585 layout = buildLayout(className, layoutElement);
586 }
587 return layout;
588 }
589
590 private Layout buildLayout(String className, Element layout_element) {
591 try {
592 Layout layout = LoaderUtil.newInstanceOf(className);
593 PropertySetter propSetter = new PropertySetter(layout);
594 forEachElement(layout_element.getChildNodes(), currentElement -> {
595 String tagName = currentElement.getTagName();
596 if (tagName.equals(PARAM_TAG)) {
597 setParameter(currentElement, propSetter);
598 } else {
599 try {
600 parseUnrecognizedElement(layout, currentElement, props);
601 } catch (Exception ex) {
602 throw new ConsumerException(ex);
603 }
604 }
605 });
606
607 propSetter.activate();
608 return layout;
609 } catch (ConsumerException ce) {
610 Throwable cause = ce.getCause();
611 if (cause instanceof InterruptedException || cause instanceof InterruptedIOException) {
612 Thread.currentThread().interrupt();
613 }
614 LOGGER.error("Could not create the Layout. Reported error follows.", cause);
615 } catch (Exception oops) {
616 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
617 Thread.currentThread().interrupt();
618 }
619 LOGGER.error("Could not create the Layout. Reported error follows.", oops);
620 }
621 return null;
622 }
623
624 /**
625 * Used internally to parse a level element.
626 */
627 private void parseLevel(Element element, LoggerConfig logger, boolean isRoot) {
628 String catName = logger.getName();
629 if (isRoot) {
630 catName = "root";
631 }
632
633 String priStr = subst(element.getAttribute(VALUE_ATTR));
634 LOGGER.debug("Level value for {} is [{}].", catName, priStr);
635
636 if (INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
637 if (isRoot) {
638 LOGGER.error("Root level cannot be inherited. Ignoring directive.");
639 } else {
640 logger.setLevel(null);
641 }
642 } else {
643 String className = subst(element.getAttribute(CLASS_ATTR));
644 if (EMPTY_STR.equals(className)) {
645 logger.setLevel(OptionConverter.convertLevel(priStr, org.apache.logging.log4j.Level.DEBUG));
646 } else {
647 LOGGER.debug("Desired Level sub-class: [{}]", className);
648 try {
649 Class<?> clazz = LoaderUtil.loadClass(className);
650 Method toLevelMethod = clazz.getMethod("toLevel", ONE_STRING_PARAM);
651 Level pri = (Level) toLevelMethod.invoke(null, priStr);
652 logger.setLevel(OptionConverter.convertLevel(pri));
653 } catch (Exception e) {
654 if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
655 Thread.currentThread().interrupt();
656 }
657 LOGGER.error("Could not create level [" + priStr +
658 "]. Reported error follows.", e);
659 return;
660 }
661 }
662 }
663 LOGGER.debug("{} level set to {}", catName, logger.getLevel());
664 }
665
666 private void setParameter(Element elem, PropertySetter propSetter) {
667 String name = subst(elem.getAttribute(NAME_ATTR));
668 String value = (elem.getAttribute(VALUE_ATTR));
669 value = subst(OptionConverter.convertSpecialChars(value));
670 propSetter.setProperty(name, value);
671 }
672
673 /**
674 * Used internally to configure the log4j framework by parsing a DOM
675 * tree of XML elements based on <a
676 * href="doc-files/log4j.dtd">log4j.dtd</a>.
677 */
678 private void parse(Element element) {
679 String rootElementName = element.getTagName();
680
681 if (!rootElementName.equals(CONFIGURATION_TAG)) {
682 if (rootElementName.equals(OLD_CONFIGURATION_TAG)) {
683 LOGGER.warn("The <" + OLD_CONFIGURATION_TAG +
684 "> element has been deprecated.");
685 LOGGER.warn("Use the <" + CONFIGURATION_TAG + "> element instead.");
686 } else {
687 LOGGER.error("DOM element is - not a <" + CONFIGURATION_TAG + "> element.");
688 return;
689 }
690 }
691
692
693 String debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR));
694
695 LOGGER.debug("debug attribute= \"" + debugAttrib + "\".");
696 // if the log4j.dtd is not specified in the XML file, then the
697 // "debug" attribute is returned as the empty string.
698 String status = "error";
699 if (!debugAttrib.equals("") && !debugAttrib.equals("null")) {
700 status = OptionConverter.toBoolean(debugAttrib, true) ? "debug" : "error";
701
702 } else {
703 LOGGER.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
704 }
705
706 String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
707 if (!confDebug.equals("") && !confDebug.equals("null")) {
708 LOGGER.warn("The \"" + CONFIG_DEBUG_ATTR + "\" attribute is deprecated.");
709 LOGGER.warn("Use the \"" + INTERNAL_DEBUG_ATTR + "\" attribute instead.");
710 status = OptionConverter.toBoolean(confDebug, true) ? "debug" : "error";
711 }
712
713 final StatusConfiguration statusConfig = new StatusConfiguration().withStatus(status);
714 statusConfig.initialize();
715
716 forEachElement(element.getChildNodes(), currentElement -> {
717 switch (currentElement.getTagName()) {
718 case CATEGORY:
719 case LOGGER_ELEMENT:
720 parseCategory(currentElement);
721 break;
722 case ROOT_TAG:
723 parseRoot(currentElement);
724 break;
725 case RENDERER_TAG:
726 LOGGER.warn("Renderers are not supported by Log4j 2 and will be ignored.");
727 break;
728 case THROWABLE_RENDERER_TAG:
729 LOGGER.warn("Throwable Renderers are not supported by Log4j 2 and will be ignored.");
730 break;
731 case CATEGORY_FACTORY_TAG:
732 case LOGGER_FACTORY_TAG:
733 LOGGER.warn("Log4j 1 Logger factories are not supported by Log4j 2 and will be ignored.");
734 break;
735 case APPENDER_TAG:
736 Appender appender = parseAppender(currentElement);
737 appenderMap.put(appender.getName(), appender);
738 if (appender instanceof AppenderWrapper) {
739 addAppender(((AppenderWrapper) appender).getAppender());
740 } else {
741 addAppender(new AppenderAdapter(appender).getAdapter());
742 }
743 break;
744 default:
745 quietParseUnrecognizedElement(null, currentElement, props);
746 }
747 });
748 }
749
750 private String subst(final String value) {
751 return getStrSubstitutor().replace(value);
752 }
753
754 public static void forEachElement(NodeList list, Consumer<Element> consumer) {
755 final int length = list.getLength();
756 for (int loop = 0; loop < length; loop++) {
757 Node currentNode = list.item(loop);
758
759 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
760 Element currentElement = (Element) currentNode;
761 consumer.accept(currentElement);
762 }
763 }
764 }
765
766 private interface ParseAction {
767 Document parse(final DocumentBuilder parser) throws SAXException, IOException;
768 }
769
770 private static class SAXErrorHandler implements org.xml.sax.ErrorHandler {
771 private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
772
773 @Override
774 public void error(final SAXParseException ex) {
775 emitMessage("Continuable parsing error ", ex);
776 }
777
778 @Override
779 public void fatalError(final SAXParseException ex) {
780 emitMessage("Fatal parsing error ", ex);
781 }
782
783 @Override
784 public void warning(final SAXParseException ex) {
785 emitMessage("Parsing warning ", ex);
786 }
787
788 private static void emitMessage(final String msg, final SAXParseException ex) {
789 LOGGER.warn("{} {} and column {}", msg, ex.getLineNumber(), ex.getColumnNumber());
790 LOGGER.warn(ex.getMessage(), ex.getException());
791 }
792 }
793
794 private static class ConsumerException extends RuntimeException {
795
796 ConsumerException(Exception ex) {
797 super(ex);
798 }
799 }
800 }
+0
-79
log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.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
17 package org.apache.log4j.xml;
18
19 import org.apache.log4j.config.Log4j1Configuration;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.apache.logging.log4j.core.config.ConfigurationFactory;
23 import org.apache.logging.log4j.core.config.ConfigurationSource;
24 import org.apache.logging.log4j.core.config.Order;
25 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.status.StatusLogger;
27 import org.apache.logging.log4j.util.PropertiesUtil;
28
29 /**
30 * Constructs a Configuration usable in Log4j 2 from a Log4j 1 configuration file.
31 */
32 @Plugin(name = "Log4j1XmlConfigurationFactory", category = ConfigurationFactory.CATEGORY)
33 @Order(2)
34 public class XmlConfigurationFactory extends ConfigurationFactory {
35
36 public static final String FILE_EXTENSION = ".xml";
37
38 private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
39
40 /**
41 * File name prefix for test configurations.
42 */
43 protected static final String TEST_PREFIX = "log4j-test";
44
45 /**
46 * File name prefix for standard configurations.
47 */
48 protected static final String DEFAULT_PREFIX = "log4j";
49
50 @Override
51 protected String[] getSupportedTypes() {
52 if (!PropertiesUtil.getProperties().getBooleanProperty(ConfigurationFactory.LOG4J1_EXPERIMENTAL, Boolean.FALSE)) {
53 return null;
54 }
55 return new String[] { FILE_EXTENSION };
56 }
57
58 @Override
59 public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source) {
60 int interval = PropertiesUtil.getProperties().getIntegerProperty(Log4j1Configuration.MONITOR_INTERVAL, 0);
61 return new XmlConfiguration(loggerContext, source, interval);
62 }
63
64 @Override
65 protected String getTestPrefix() {
66 return TEST_PREFIX;
67 }
68
69 @Override
70 protected String getDefaultPrefix() {
71 return DEFAULT_PREFIX;
72 }
73
74 @Override
75 protected String getVersion() {
76 return LOG4J1_VERSION;
77 }
78 }
+0
-237
log4j-1.2-api/src/main/resources/org/apache/log4j/xml/log4j.dtd less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17
18 <!-- Authors: Chris Taylor, Ceki Gulcu. -->
19
20 <!-- Version: 1.2 -->
21
22 <!-- A configuration element consists of optional renderer
23 elements,appender elements, categories and an optional root
24 element. -->
25
26 <!ELEMENT log4j:configuration (renderer*, throwableRenderer?,
27 appender*,plugin*, (category|logger)*,root?,
28 (categoryFactory|loggerFactory)?)>
29
30 <!-- The "threshold" attribute takes a level value below which -->
31 <!-- all logging statements are disabled. -->
32
33 <!-- Setting the "debug" enable the printing of internal log4j logging -->
34 <!-- statements. -->
35
36 <!-- By default, debug attribute is "null", meaning that we not do touch -->
37 <!-- internal log4j logging settings. The "null" value for the threshold -->
38 <!-- attribute can be misleading. The threshold field of a repository -->
39 <!-- cannot be set to null. The "null" value for the threshold attribute -->
40 <!-- simply means don't touch the threshold field, the threshold field -->
41 <!-- keeps its old value. -->
42
43 <!ATTLIST log4j:configuration
44 xmlns:log4j CDATA #FIXED "http://jakarta.apache.org/log4j/"
45 threshold (all|trace|debug|info|warn|error|fatal|off|null) "null"
46 debug (true|false|null) "null"
47 reset (true|false) "false"
48 >
49
50 <!-- renderer elements allow the user to customize the conversion of -->
51 <!-- message objects to String. -->
52
53 <!ELEMENT renderer EMPTY>
54 <!ATTLIST renderer
55 renderedClass CDATA #REQUIRED
56 renderingClass CDATA #REQUIRED
57 >
58
59 <!-- throwableRenderer allows the user to customize the conversion
60 of exceptions to a string representation. -->
61 <!ELEMENT throwableRenderer (param*)>
62 <!ATTLIST throwableRenderer
63 class CDATA #REQUIRED
64 >
65
66
67 <!-- Appenders must have a name and a class. -->
68 <!-- Appenders may contain an error handler, a layout, optional parameters -->
69 <!-- and filters. They may also reference (or include) other appenders. -->
70 <!ELEMENT appender (errorHandler?, param*,
71 rollingPolicy?, triggeringPolicy?, connectionSource?,
72 layout?, filter*, appender-ref*)>
73 <!ATTLIST appender
74 name CDATA #REQUIRED
75 class CDATA #REQUIRED
76 >
77
78 <!ELEMENT layout (param*)>
79 <!ATTLIST layout
80 class CDATA #REQUIRED
81 >
82
83 <!ELEMENT filter (param*)>
84 <!ATTLIST filter
85 class CDATA #REQUIRED
86 >
87
88 <!-- ErrorHandlers can be of any class. They can admit any number of -->
89 <!-- parameters. -->
90
91 <!ELEMENT errorHandler (param*, root-ref?, logger-ref*, appender-ref?)>
92 <!ATTLIST errorHandler
93 class CDATA #REQUIRED
94 >
95
96 <!ELEMENT root-ref EMPTY>
97
98 <!ELEMENT logger-ref EMPTY>
99 <!ATTLIST logger-ref
100 ref CDATA #REQUIRED
101 >
102
103 <!ELEMENT param EMPTY>
104 <!ATTLIST param
105 name CDATA #REQUIRED
106 value CDATA #REQUIRED
107 >
108
109
110 <!-- The priority class is org.apache.log4j.Level by default -->
111 <!ELEMENT priority (param*)>
112 <!ATTLIST priority
113 class CDATA #IMPLIED
114 value CDATA #REQUIRED
115 >
116
117 <!-- The level class is org.apache.log4j.Level by default -->
118 <!ELEMENT level (param*)>
119 <!ATTLIST level
120 class CDATA #IMPLIED
121 value CDATA #REQUIRED
122 >
123
124
125 <!-- If no level element is specified, then the configurator MUST not -->
126 <!-- touch the level of the named category. -->
127 <!ELEMENT category (param*,(priority|level)?,appender-ref*)>
128 <!ATTLIST category
129 class CDATA #IMPLIED
130 name CDATA #REQUIRED
131 additivity (true|false) "true"
132 >
133
134 <!-- If no level element is specified, then the configurator MUST not -->
135 <!-- touch the level of the named logger. -->
136 <!ELEMENT logger (param*,level?,appender-ref*)>
137 <!ATTLIST logger
138 class CDATA #IMPLIED
139 name CDATA #REQUIRED
140 additivity (true|false) "true"
141 >
142
143
144 <!ELEMENT categoryFactory (param*)>
145 <!ATTLIST categoryFactory
146 class CDATA #REQUIRED>
147
148 <!ELEMENT loggerFactory (param*)>
149 <!ATTLIST loggerFactory
150 class CDATA #REQUIRED>
151
152 <!ELEMENT appender-ref EMPTY>
153 <!ATTLIST appender-ref
154 ref CDATA #REQUIRED
155 >
156
157 <!-- plugins must have a name and class and can have optional parameters -->
158 <!ELEMENT plugin (param*, connectionSource?)>
159 <!ATTLIST plugin
160 name CDATA #REQUIRED
161 class CDATA #REQUIRED
162 >
163
164 <!ELEMENT connectionSource (dataSource?, param*)>
165 <!ATTLIST connectionSource
166 class CDATA #REQUIRED
167 >
168
169 <!ELEMENT dataSource (param*)>
170 <!ATTLIST dataSource
171 class CDATA #REQUIRED
172 >
173
174 <!ELEMENT triggeringPolicy ((param|filter)*)>
175 <!ATTLIST triggeringPolicy
176 name CDATA #IMPLIED
177 class CDATA #REQUIRED
178 >
179
180 <!ELEMENT rollingPolicy (param*)>
181 <!ATTLIST rollingPolicy
182 name CDATA #IMPLIED
183 class CDATA #REQUIRED
184 >
185
186
187 <!-- If no priority element is specified, then the configurator MUST not -->
188 <!-- touch the priority of root. -->
189 <!-- The root category always exists and cannot be subclassed. -->
190 <!ELEMENT root (param*, (priority|level)?, appender-ref*)>
191
192
193 <!-- ==================================================================== -->
194 <!-- A logging event -->
195 <!-- ==================================================================== -->
196 <!ELEMENT log4j:eventSet (log4j:event*)>
197 <!ATTLIST log4j:eventSet
198 xmlns:log4j CDATA #FIXED "http://jakarta.apache.org/log4j/"
199 version (1.1|1.2) "1.2"
200 includesLocationInfo (true|false) "true"
201 >
202
203
204
205 <!ELEMENT log4j:event (log4j:message, log4j:NDC?, log4j:throwable?,
206 log4j:locationInfo?, log4j:properties?) >
207
208 <!-- The timestamp format is application dependent. -->
209 <!ATTLIST log4j:event
210 logger CDATA #REQUIRED
211 level CDATA #REQUIRED
212 thread CDATA #REQUIRED
213 timestamp CDATA #REQUIRED
214 time CDATA #IMPLIED
215 >
216
217 <!ELEMENT log4j:message (#PCDATA)>
218 <!ELEMENT log4j:NDC (#PCDATA)>
219
220 <!ELEMENT log4j:throwable (#PCDATA)>
221
222 <!ELEMENT log4j:locationInfo EMPTY>
223 <!ATTLIST log4j:locationInfo
224 class CDATA #REQUIRED
225 method CDATA #REQUIRED
226 file CDATA #REQUIRED
227 line CDATA #REQUIRED
228 >
229
230 <!ELEMENT log4j:properties (log4j:data*)>
231
232 <!ELEMENT log4j:data EMPTY>
233 <!ATTLIST log4j:data
234 name CDATA #REQUIRED
235 value CDATA #REQUIRED
236 >
3535 | BasicConfigurator.configure() | NoOp | Reconfigures Log4j 2 |
3636
3737 If log4j-core is not present location information will not be accurate in calls using the Log4j 1.2 API. The config
38 package which attempts to convert Log4j 1.x configurations to Log4j 2 is not supported without Log4j 2.
38 package which attempts tp convert Log4j 1.x configurations to Log4j 2 is not supported without Log4j 2.
3939
4040 For more information, see [Runtime Dependencies](../runtime-dependencies.html).
4141
2121 import static org.junit.Assert.assertTrue;
2222
2323 import java.lang.reflect.Method;
24 import java.util.Collections;
2524 import java.util.List;
26 import java.util.Map;
27 import java.util.function.Consumer;
2825
2926 import org.apache.logging.log4j.core.Layout;
3027 import org.apache.logging.log4j.core.LogEvent;
3128 import org.apache.logging.log4j.core.LoggerContext;
3229 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3330 import org.apache.logging.log4j.core.layout.PatternLayout;
34 import org.apache.logging.log4j.message.MapMessage;
3531 import org.apache.logging.log4j.message.Message;
3632 import org.apache.logging.log4j.message.ObjectMessage;
37 import org.apache.logging.log4j.message.SimpleMessage;
3833 import org.apache.logging.log4j.test.appender.ListAppender;
39 import org.apache.logging.log4j.util.Constants;
4034 import org.apache.logging.log4j.util.Strings;
4135 import org.junit.AfterClass;
4236 import org.junit.Before;
4337 import org.junit.BeforeClass;
4438 import org.junit.Test;
4539
40
4641 /**
4742 * Tests of Category.
4843 */
6964 public void before() {
7065 appender.clear();
7166 }
72
67
7368 /**
7469 * Tests Category.forcedLog.
7570 */
122117 logger.setLevel(Level.ERROR);
123118 final Priority debug = Level.DEBUG;
124119 logger.l7dlog(debug, "Hello, World", null);
125 assertTrue(appender.getEvents().isEmpty());
120 assertTrue(appender.getEvents().size() == 0);
126121 }
127122
128123 /**
133128 final Logger logger = Logger.getLogger("org.example.foo");
134129 logger.setLevel(Level.ERROR);
135130 final Priority debug = Level.DEBUG;
136 logger.l7dlog(debug, "Hello, World", Constants.EMPTY_OBJECT_ARRAY, null);
137 assertTrue(appender.getEvents().isEmpty());
131 logger.l7dlog(debug, "Hello, World", new Object[0], null);
132 assertTrue(appender.getEvents().size() == 0);
138133 }
139134
140135 /**
152147 final Priority debug = Level.DEBUG;
153148 // the next line will throw an exception if the LogManager loggers
154149 // aren't supported by 1.2 Logger/Category
155 logger.l7dlog(debug, "Hello, World", Constants.EMPTY_OBJECT_ARRAY, null);
156 assertTrue(appender.getEvents().isEmpty());
150 logger.l7dlog(debug, "Hello, World", new Object[0], null);
151 assertTrue(appender.getEvents().size() == 0);
157152 }
158153
159154 /**
167162 final Logger logger = Logger.getLogger("org.example.foo");
168163 final Priority debug = Level.DEBUG;
169164 logger.setPriority(debug);
170 }
171
172 /**
173 * Tests setPriority(Priority).
174 *
175 * @deprecated
176 */
177 @Deprecated
178 @Test
179 public void testSetPriorityNull() {
180 Logger.getLogger("org.example.foo").setPriority(null);
181165 }
182166
183167 @Test
198182 assertTrue("Incorrect message " + Strings.dquote(msg) + " expected " + Strings.dquote(expected), msg.endsWith(expected));
199183 }
200184
201 @Test
202 public void testStringLog() {
203 final String payload = "payload";
204 testMessageImplementation(
205 payload,
206 SimpleMessage.class,
207 message -> assertEquals(message.getFormattedMessage(), payload));
208 }
209
210 @Test
211 public void testCharSequenceLog() {
212 final CharSequence payload = new CharSequence() {
213
214 @Override
215 public int length() {
216 return 3;
217 }
218
219 @Override
220 public char charAt(final int index) {
221 return "abc".charAt(index);
222 }
223
224 @Override
225 public CharSequence subSequence(final int start, final int end) {
226 return "abc".subSequence(start, end);
227 }
228
229 @Override
230 public String toString() {
231 return "abc";
232 }
233
234 };
235 testMessageImplementation(
236 payload,
237 SimpleMessage.class,
238 message -> assertEquals(message.getFormattedMessage(), payload.toString()));
239 }
240
241 @Test
242 public void testMapLog() {
243 final String key = "key";
244 final Object value = 0xDEADBEEF;
245 final Map<String, Object> payload = Collections.singletonMap(key, value);
246 testMessageImplementation(
247 payload,
248 MapMessage.class,
249 message -> assertEquals(message.getData(), payload));
250 }
251
252 @Test
253 public void testObjectLog() {
254 final Object payload = new Object();
255 testMessageImplementation(
256 payload,
257 ObjectMessage.class,
258 message -> assertEquals(message.getParameter(), payload));
259 }
260
261 private <M extends Message> void testMessageImplementation(
262 final Object messagePayload,
263 final Class<M> expectedMessageClass,
264 final Consumer<M> messageTester) {
265
266 // Setup the logger and the appender.
267 final Category category = Category.getInstance("TestCategory");
268 final org.apache.logging.log4j.core.Logger logger =
269 (org.apache.logging.log4j.core.Logger) category.getLogger();
270 logger.addAppender(appender);
271
272 // Log the message payload.
273 category.info(messagePayload);
274
275 // Verify collected log events.
276 final List<LogEvent> events = appender.getEvents();
277 assertEquals("was expecting a single event", 1, events.size());
278 final LogEvent logEvent = events.get(0);
279
280 // Verify the collected message.
281 final Message message = logEvent.getMessage();
282 final Class<? extends Message> actualMessageClass = message.getClass();
283 assertTrue(
284 "was expecting message to be instance of " + expectedMessageClass + ", found: " + actualMessageClass,
285 expectedMessageClass.isAssignableFrom(actualMessageClass));
286 @SuppressWarnings("unchecked")
287 final M typedMessage = (M) message;
288 messageTester.accept(typedMessage);
289
290 }
291
292185 /**
293186 * Derived category to check method signature of forcedLog.
294187 */
+0
-83
log4j-1.2-api/src/test/java/org/apache/log4j/ListAppender.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;
17
18 import org.apache.log4j.spi.LoggingEvent;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.concurrent.TimeUnit;
24
25 /**
26 * Used to test Log4j 1 support.
27 */
28 public class ListAppender extends AppenderSkeleton {
29 // Use Collections.synchronizedList rather than CopyOnWriteArrayList because we expect
30 // more frequent writes than reads.
31 final List<LoggingEvent> events = Collections.synchronizedList(new ArrayList<>());
32
33 private final List<String> messages = Collections.synchronizedList(new ArrayList<>());
34
35
36 private static final String WINDOWS_LINE_SEP = "\r\n";
37
38 @Override
39 protected void append(LoggingEvent event) {
40 Layout layout = getLayout();
41 if (layout != null) {
42 String result = layout.format(event);
43 if (result != null) {
44 messages.add(result);
45 }
46 } else {
47 events.add(event);
48 }
49 }
50
51 @Override
52 public void close() {
53
54 }
55
56 @Override
57 public boolean requiresLayout() {
58 return false;
59 }
60
61 /** Returns an immutable snapshot of captured log events */
62 public List<LoggingEvent> getEvents() {
63 return Collections.unmodifiableList(new ArrayList<>(events));
64 }
65
66 /** Returns an immutable snapshot of captured messages */
67 public List<String> getMessages() {
68 return Collections.unmodifiableList(new ArrayList<>(messages));
69 }
70
71 /**
72 * Polls the messages list for it to grow to a given minimum size at most timeout timeUnits and return a copy of
73 * what we have so far.
74 */
75 public List<String> getMessages(final int minSize, final long timeout, final TimeUnit timeUnit) throws InterruptedException {
76 final long endMillis = System.currentTimeMillis() + timeUnit.toMillis(timeout);
77 while (messages.size() < minSize && System.currentTimeMillis() < endMillis) {
78 Thread.sleep(100);
79 }
80 return getMessages();
81 }
82 }
44 * The ASF licenses this file to You under the Apache License, Version 2.0
55 * (the "License"); you may not use this file except in compliance with
66 * the License. You may obtain a copy of the License at
7 *
7 *
88 * http://www.apache.org/licenses/LICENSE-2.0
9 *
9 *
1010 * Unless required by applicable law or agreed to in writing, software
1111 * distributed under the License is distributed on an "AS IS" BASIS,
1212 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3333 public class VelocityTest {
3434
3535 private static LoggerContext context;
36
36
3737 @BeforeClass
3838 public static void setupClass() {
3939 context = LoggerContext.getContext(false);
4343 public static void tearDownClass() {
4444 Configurator.shutdown(context);
4545 StatusLogger.getLogger().reset();
46 }
47
46 }
47
4848 @Test
4949 public void testVelocity() {
5050 Velocity.init();
5151 final VelocityContext vContext = new VelocityContext();
52 vContext.put("name", "Velocity");
52 vContext.put("name", new String("Velocity"));
5353
5454 final Template template = Velocity.getTemplate("target/test-classes/hello.vm");
5555
+0
-50
log4j-1.2-api/src/test/java/org/apache/log4j/bridge/LogEventWrapperTest.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
17 package org.apache.log4j.bridge;
18
19 import org.apache.log4j.spi.LoggingEvent;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.junit.Test;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertSame;
25
26 public class LogEventWrapperTest {
27
28 @Test
29 public void testThread() {
30 Thread currentThread = Thread.currentThread();
31 String threadName = currentThread.getName();
32 LoggingEvent log4j1Event = new LoggingEvent() {
33
34 @Override
35 public String getThreadName() {
36 return threadName;
37 }
38 };
39 LogEvent log4j2Event = new LogEventWrapper(log4j1Event);
40 assertEquals(currentThread.getId(), log4j2Event.getThreadId());
41 assertEquals(currentThread.getPriority(), log4j2Event.getThreadPriority());
42 }
43
44 @Test
45 public void testToImmutable() {
46 LogEventWrapper wrapper = new LogEventWrapper(new LoggingEvent());
47 assertSame(wrapper, wrapper.toImmutable());
48 }
49 }
00 package org.apache.log4j.config;
1
2 import static org.junit.jupiter.api.Assertions.assertFalse;
31
42 import java.io.IOException;
53 import java.nio.file.FileVisitResult;
119 import java.util.ArrayList;
1210 import java.util.List;
1311
14 import javax.xml.parsers.DocumentBuilderFactory;
15 import javax.xml.parsers.ParserConfigurationException;
16
1712 import org.junit.Test;
1813 import org.junit.runner.RunWith;
1914 import org.junit.runners.Parameterized;
20 import org.xml.sax.SAXException;
2115
2216 /*
2317 * Licensed to the Apache Software Foundation (ASF) under one or more
5448 private final Path pathIn;
5549
5650 public AbstractLog4j1ConfigurationConverterTest(final Path path) {
51 super();
5752 this.pathIn = path;
5853 }
5954
6055 @Test
61 public void test() throws Exception {
56 public void test() throws IOException {
6257 final Path tempFile = Files.createTempFile("log4j2", ".xml");
6358 try {
6459 final Log4j1ConfigurationConverter.CommandLineArguments cla = new Log4j1ConfigurationConverter.CommandLineArguments();
6560 cla.setPathIn(pathIn);
6661 cla.setPathOut(tempFile);
6762 Log4j1ConfigurationConverter.run(cla);
68 checkWellFormedXml(tempFile);
69 checkUnnecessaryEscaping(tempFile);
7063 } finally {
7164 Files.deleteIfExists(tempFile);
7265 }
7366 }
74
75 private void checkUnnecessaryEscaping(Path tempFile) throws IOException {
76 for (String line : Files.readAllLines(tempFile)) {
77 assertFalse(line.endsWith("&#xd;"));
78 }
79
80 }
81
82 private void checkWellFormedXml(Path xmlFilePath) throws SAXException, IOException, ParserConfigurationException {
83 DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFilePath.toUri().toString());
84 }
8567 }
+0
-102
log4j-1.2-api/src/test/java/org/apache/log4j/config/AsyncAppenderTest.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 static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.InputStream;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.log4j.ListAppender;
28 import org.apache.log4j.LogManager;
29 import org.apache.log4j.Logger;
30 import org.apache.log4j.bridge.AppenderAdapter;
31 import org.apache.log4j.xml.XmlConfigurationFactory;
32 import org.apache.logging.log4j.core.Appender;
33 import org.apache.logging.log4j.core.LoggerContext;
34 import org.apache.logging.log4j.core.config.Configuration;
35 import org.apache.logging.log4j.core.config.ConfigurationSource;
36 import org.apache.logging.log4j.core.config.Configurator;
37 import org.apache.logging.log4j.spi.LoggerContextFactory;
38 import org.junit.Test;
39
40 /**
41 * Test configuration from XML.
42 */
43 public class AsyncAppenderTest {
44
45 @Test
46 public void testAsyncXml() throws Exception {
47 LoggerContext loggerContext = configure("target/test-classes/log4j1-async.xml");
48 Logger logger = LogManager.getLogger("test");
49 logger.debug("This is a test of the root logger");
50 Thread.sleep(50);
51 Configuration configuration = loggerContext.getConfiguration();
52 Map<String, Appender> appenders = configuration.getAppenders();
53 ListAppender messageAppender = null;
54 for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
55 if (entry.getKey().equals("list")) {
56 messageAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
57 }
58 }
59 assertNotNull("No Message Appender", messageAppender);
60 List<String> messages = messageAppender.getMessages();
61 assertTrue("No messages", messages != null && messages.size() > 0);
62 }
63
64 @Test
65 public void testAsyncProperties() throws Exception {
66 LoggerContext loggerContext = configure("target/test-classes/log4j1-async.properties");
67 Logger logger = LogManager.getLogger("test");
68 logger.debug("This is a test of the root logger");
69 Thread.sleep(50);
70 Configuration configuration = loggerContext.getConfiguration();
71 Map<String, Appender> appenders = configuration.getAppenders();
72 ListAppender messageAppender = null;
73 for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
74 if (entry.getKey().equals("list")) {
75 messageAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
76 }
77 }
78 assertNotNull("No Message Appender", messageAppender);
79 List<String> messages = messageAppender.getMessages();
80 assertTrue("No messages", messages != null && messages.size() > 0);
81 }
82
83
84 private LoggerContext configure(String configLocation) throws Exception {
85 File file = new File(configLocation);
86 InputStream is = new FileInputStream(file);
87 ConfigurationSource source = new ConfigurationSource(is, file);
88 LoggerContextFactory factory = org.apache.logging.log4j.LogManager.getFactory();
89 LoggerContext context = (LoggerContext) org.apache.logging.log4j.LogManager.getContext(false);
90 Configuration configuration;
91 if (configLocation.endsWith(".xml")) {
92 configuration = new XmlConfigurationFactory().getConfiguration(context, source);
93 } else {
94 configuration = new PropertiesConfigurationFactory().getConfiguration(context, source);
95 }
96 assertNotNull("No configuration created", configuration);
97 Configurator.reconfigure(configuration);
98 return context;
99 }
100
101 }
+0
-71
log4j-1.2-api/src/test/java/org/apache/log4j/config/AutoConfigTest.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 static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
21 import java.util.List;
22 import java.util.Map;
23
24 import org.apache.log4j.ListAppender;
25 import org.apache.log4j.LogManager;
26 import org.apache.log4j.Logger;
27 import org.apache.log4j.bridge.AppenderAdapter;
28 import org.apache.log4j.spi.LoggingEvent;
29 import org.apache.logging.log4j.core.Appender;
30 import org.apache.logging.log4j.core.config.Configuration;
31 import org.apache.logging.log4j.core.config.ConfigurationFactory;
32 import org.apache.logging.log4j.spi.LoggerContext;
33 import org.junit.BeforeClass;
34 import org.junit.Test;
35
36 /**
37 * Test configuration from XML.
38 */
39 public class AutoConfigTest {
40
41 @BeforeClass
42 public static void beforeClass() {
43 System.setProperty(ConfigurationFactory.LOG4J1_EXPERIMENTAL, "true");
44 }
45
46 @Test
47 public void testListAppender() {
48 Logger logger = LogManager.getLogger("test");
49 logger.debug("This is a test of the root logger");
50 LoggerContext loggerContext = org.apache.logging.log4j.LogManager.getContext(false);
51 Configuration configuration = ((org.apache.logging.log4j.core.LoggerContext) loggerContext).getConfiguration();
52 Map<String, Appender> appenders = configuration.getAppenders();
53 ListAppender eventAppender = null;
54 ListAppender messageAppender = null;
55 for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
56 if (entry.getKey().equals("list")) {
57 messageAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
58 } else if (entry.getKey().equals("events")) {
59 eventAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
60 }
61 }
62 assertNotNull("No Event Appender", eventAppender);
63 assertNotNull("No Message Appender", messageAppender);
64 List<LoggingEvent> events = eventAppender.getEvents();
65 assertTrue("No events", events != null && events.size() > 0);
66 List<String> messages = messageAppender.getMessages();
67 assertTrue("No messages", messages != null && messages.size() > 0);
68 }
69
70 }
5151
5252 public class Log4j1ConfigurationFactoryTest {
5353
54 static Configuration getConfiguration(final String configResource) throws URISyntaxException {
55 final URL configLocation = ClassLoader.getSystemResource(configResource);
56 assertNotNull(configResource, configLocation);
57 final Configuration configuration = new Log4j1ConfigurationFactory().getConfiguration(null, "test",
58 configLocation.toURI());
59 assertNotNull(configuration);
60 return configuration;
61 }
62
6354 private Layout<?> testConsole(final String configResource) throws Exception {
6455 final Configuration configuration = getConfiguration(configResource);
6556 final String name = "Console";
9081 return appender.getLayout();
9182 }
9283
84 private Configuration getConfiguration(final String configResource) throws URISyntaxException {
85 final URL configLocation = ClassLoader.getSystemResource(configResource);
86 assertNotNull(configResource, configLocation);
87 final Configuration configuration = new Log4j1ConfigurationFactory().getConfiguration(null, "test",
88 configLocation.toURI());
89 assertNotNull(configuration);
90 return configuration;
91 }
92
9393 @Test
9494 public void testConsoleEnhancedPatternLayout() throws Exception {
9595 final PatternLayout layout = (PatternLayout) testConsole(
168168 final Configuration configuration = getConfiguration("config-1.2/log4j-system-properties-1.properties");
169169 final RollingFileAppender appender = configuration.getAppender("RFA");
170170 appender.stop(10, TimeUnit.SECONDS);
171 // System.out.println("expected: " + tempFileName + " Actual: " + appender.getFileName());
171 System.out.println("expected: " + tempFileName + " Actual: " + appender.getFileName());
172172 assertEquals(tempFileName, appender.getFileName());
173173 } finally {
174174 try {
+0
-79
log4j-1.2-api/src/test/java/org/apache/log4j/config/MapRewriteAppenderTest.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 static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.log4j.ListAppender;
27 import org.apache.log4j.LogManager;
28 import org.apache.log4j.Logger;
29 import org.apache.log4j.bridge.AppenderAdapter;
30 import org.apache.log4j.spi.LoggingEvent;
31 import org.apache.logging.log4j.ThreadContext;
32 import org.apache.logging.log4j.core.Appender;
33 import org.apache.logging.log4j.core.LoggerContext;
34 import org.apache.logging.log4j.core.config.Configuration;
35 import org.apache.logging.log4j.core.config.ConfigurationFactory;
36 import org.junit.After;
37 import org.junit.BeforeClass;
38 import org.junit.Test;
39
40 /**
41 * Test RewriteAppender
42 */
43 public class MapRewriteAppenderTest {
44
45 @BeforeClass
46 public static void beforeClass() {
47 System.setProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY, "target/test-classes/log4j1-mapRewrite.xml");
48 }
49
50 @After
51 public void after() {
52 ThreadContext.clearMap();
53 }
54
55 @Test
56 public void testRewrite() throws Exception {
57 Logger logger = LogManager.getLogger("test");
58 Map<String, String> map = new HashMap<>();
59 map.put("message", "This is a test");
60 map.put("hello", "world");
61 logger.debug(map);
62 LoggerContext context = (LoggerContext) org.apache.logging.log4j.LogManager.getContext(false);
63 Configuration configuration = context.getConfiguration();
64 Map<String, Appender> appenders = configuration.getAppenders();
65 ListAppender eventAppender = null;
66 for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
67 if (entry.getKey().equals("events")) {
68 eventAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
69 }
70 }
71 assertNotNull("No Event Appender", eventAppender);
72 List<LoggingEvent> events = eventAppender.getEvents();
73 assertTrue("No events", events != null && events.size() > 0);
74 assertNotNull("No properties in the event", events.get(0).getProperties());
75 assertTrue("Key was not inserted", events.get(0).getProperties().containsKey("hello"));
76 assertEquals("Key value is incorrect", "world", events.get(0).getProperties().get("hello"));
77 }
78 }
+0
-51
log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationFactoryTest.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 static org.junit.Assert.assertTrue;
19
20 import java.io.File;
21
22 import org.apache.log4j.LogManager;
23 import org.apache.log4j.Logger;
24 import org.apache.logging.log4j.core.config.ConfigurationFactory;
25 import org.junit.BeforeClass;
26 import org.junit.Test;
27
28 /**
29 * Test configuration from Properties.
30 */
31 public class PropertiesConfigurationFactoryTest {
32
33 @BeforeClass
34 public static void beforeClass() {
35 System.setProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY, "target/test-classes/log4j1-file.properties");
36 }
37
38 @Test
39 public void testProperties() throws Exception {
40 Logger logger = LogManager.getLogger("test");
41 logger.debug("This is a test of the root logger");
42 File file = new File("target/temp.A1");
43 assertTrue("File A1 was not created", file.exists());
44 assertTrue("File A1 is empty", file.length() > 0);
45 file = new File("target/temp.A2");
46 assertTrue("File A2 was not created", file.exists());
47 assertTrue("File A2 is empty", file.length() > 0);
48 }
49
50 }
+0
-87
log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.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 static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
21 import java.io.File;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.log4j.ListAppender;
26 import org.apache.log4j.LogManager;
27 import org.apache.log4j.Logger;
28 import org.apache.log4j.bridge.AppenderAdapter;
29 import org.apache.log4j.spi.LoggingEvent;
30 import org.apache.logging.log4j.core.Appender;
31 import org.apache.logging.log4j.core.LoggerContext;
32 import org.apache.logging.log4j.core.config.Configuration;
33 import org.junit.Test;
34
35 /**
36 * Test configuration from Properties.
37 */
38 public class PropertiesConfigurationTest {
39
40 @Test
41 public void testFilter() throws Exception {
42 try (LoggerContext loggerContext = TestConfigurator.configure("target/test-classes/LOG4J2-3247.properties")) {
43 // [LOG4J2-3247] configure() should not throw an NPE.
44 }
45 }
46
47 @Test
48 public void testListAppender() throws Exception {
49 try (LoggerContext loggerContext = TestConfigurator.configure("target/test-classes/log4j1-list.properties")) {
50 Logger logger = LogManager.getLogger("test");
51 logger.debug("This is a test of the root logger");
52 Configuration configuration = loggerContext.getConfiguration();
53 Map<String, Appender> appenders = configuration.getAppenders();
54 ListAppender eventAppender = null;
55 ListAppender messageAppender = null;
56 for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
57 if (entry.getKey().equals("list")) {
58 messageAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
59 } else if (entry.getKey().equals("events")) {
60 eventAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
61 }
62 }
63 assertNotNull("No Event Appender", eventAppender);
64 assertNotNull("No Message Appender", messageAppender);
65 List<LoggingEvent> events = eventAppender.getEvents();
66 assertTrue("No events", events != null && events.size() > 0);
67 List<String> messages = messageAppender.getMessages();
68 assertTrue("No messages", messages != null && messages.size() > 0);
69 }
70 }
71
72 @Test
73 public void testProperties() throws Exception {
74 try (LoggerContext loggerContext = TestConfigurator.configure("target/test-classes/log4j1-file.properties")) {
75 Logger logger = LogManager.getLogger("test");
76 logger.debug("This is a test of the root logger");
77 File file = new File("target/temp.A1");
78 assertTrue("File A1 was not created", file.exists());
79 assertTrue("File A1 is empty", file.length() > 0);
80 file = new File("target/temp.A2");
81 assertTrue("File A2 was not created", file.exists());
82 assertTrue("File A2 is empty", file.length() > 0);
83 }
84 }
85
86 }
+0
-79
log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesReconfigurationTest.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 static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20 import static org.junit.Assert.fail;
21
22 import java.io.File;
23 import java.util.concurrent.CountDownLatch;
24 import java.util.concurrent.TimeUnit;
25
26 import org.apache.log4j.LogManager;
27 import org.apache.log4j.Logger;
28 import org.apache.logging.log4j.core.LoggerContext;
29 import org.apache.logging.log4j.core.config.Configuration;
30 import org.apache.logging.log4j.core.config.ConfigurationListener;
31 import org.apache.logging.log4j.core.config.Reconfigurable;
32 import org.junit.Test;
33
34 /**
35 * Test reconfiguring with an XML configuration.
36 */
37 public class PropertiesReconfigurationTest {
38
39 private static final String CONFIG = "target/test-classes/log4j1-file.properties";
40 private static final long FIVE_MINUTES = 5 * 60 * 1000;
41
42 private CountDownLatch toggle = new CountDownLatch(1);
43
44 @Test
45 public void testReconfiguration() throws Exception {
46 System.setProperty(Log4j1Configuration.MONITOR_INTERVAL, "1");
47 File file = new File(CONFIG);
48 assertNotNull("No Config file", file);
49 long configMillis = file.lastModified();
50 assertTrue("Unable to modified file time", file.setLastModified(configMillis - FIVE_MINUTES));
51 LoggerContext context = TestConfigurator.configure(file.toString());
52 Logger logger = LogManager.getLogger("test");
53 logger.info("Hello");
54 Configuration original = context.getConfiguration();
55 TestListener listener = new TestListener();
56 original.addListener(listener);
57 file.setLastModified(System.currentTimeMillis());
58 try {
59 if (!toggle.await(3, TimeUnit.SECONDS)) {
60 fail("Reconfiguration timed out");
61 }
62 // Allow reconfiguration to complete.
63 Thread.sleep(500);
64 } catch (InterruptedException ie) {
65 fail("Reconfiguration interupted");
66 }
67 Configuration updated = context.getConfiguration();
68 assertTrue("Configurations are the same", original != updated);
69 }
70
71 private class TestListener implements ConfigurationListener {
72
73 public synchronized void onChange(final Reconfigurable reconfigurable) {
74 toggle.countDown();
75 }
76
77 }
78 }
+0
-47
log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesRollingWithPropertiesTest.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 static org.junit.Assert.assertTrue;
19
20 import java.io.File;
21
22 import org.apache.log4j.LogManager;
23 import org.apache.log4j.Logger;
24 import org.junit.BeforeClass;
25 import org.junit.Test;
26
27 /**
28 * Test configuration from Properties.
29 */
30 public class PropertiesRollingWithPropertiesTest {
31
32 @BeforeClass
33 public static void setupClass() {
34 System.setProperty("log4j.configuration", "target/test-classes/log4j1-rolling-properties.properties");
35 }
36
37 @Test
38 public void testProperties() throws Exception {
39 Logger logger = LogManager.getLogger("test");
40 logger.debug("This is a test of the root logger");
41 File file = new File("target/rolling/somefile.log");
42 assertTrue("Log file was not created", file.exists());
43 assertTrue("Log file is empty", file.length() > 0);
44 }
45
46 }
+0
-79
log4j-1.2-api/src/test/java/org/apache/log4j/config/RewriteAppenderTest.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 static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.log4j.ListAppender;
26 import org.apache.log4j.LogManager;
27 import org.apache.log4j.Logger;
28 import org.apache.log4j.bridge.AppenderAdapter;
29 import org.apache.log4j.spi.LoggingEvent;
30 import org.apache.logging.log4j.ThreadContext;
31 import org.apache.logging.log4j.core.Appender;
32 import org.apache.logging.log4j.core.LoggerContext;
33 import org.apache.logging.log4j.core.config.Configuration;
34 import org.apache.logging.log4j.core.config.ConfigurationFactory;
35 import org.junit.After;
36 import org.junit.BeforeClass;
37 import org.junit.Test;
38
39 /**
40 * Test RewriteAppender
41 */
42 public class RewriteAppenderTest {
43
44 @BeforeClass
45 public static void beforeClass() {
46 System.setProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY, "target/test-classes/log4j1-rewrite.xml");
47 }
48
49 @After
50 public void after() {
51 ThreadContext.clearMap();
52 }
53
54 @Test
55 public void testRewrite() throws Exception {
56 Logger logger = LogManager.getLogger("test");
57 ThreadContext.put("key1", "This is a test");
58 ThreadContext.put("hello", "world");
59 long logTime = System.currentTimeMillis();
60 logger.debug("Say hello");
61 LoggerContext context = (LoggerContext) org.apache.logging.log4j.LogManager.getContext(false);
62 Configuration configuration = context.getConfiguration();
63 Map<String, Appender> appenders = configuration.getAppenders();
64 ListAppender eventAppender = null;
65 for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
66 if (entry.getKey().equals("events")) {
67 eventAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
68 }
69 }
70 assertNotNull("No Event Appender", eventAppender);
71 List<LoggingEvent> events = eventAppender.getEvents();
72 assertTrue("No events", events != null && events.size() > 0);
73 assertNotNull("No properties in the event", events.get(0).getProperties());
74 assertTrue("Key was not inserted", events.get(0).getProperties().containsKey("key2"));
75 assertEquals("Key value is incorrect", "Log4j", events.get(0).getProperties().get("key2"));
76 assertTrue("Timestamp is before point of logging", events.get(0).getTimeStamp() >= logTime);
77 }
78 }
+0
-86
log4j-1.2-api/src/test/java/org/apache/log4j/config/SyslogAppenderConfigurationTest.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 static org.junit.jupiter.api.Assertions.assertNotNull;
19 import static org.junit.jupiter.api.Assertions.assertTrue;
20
21 import java.io.IOException;
22 import java.util.Map;
23
24 import org.apache.logging.log4j.core.Appender;
25 import org.apache.logging.log4j.core.appender.SocketAppender;
26 import org.apache.logging.log4j.core.config.Configuration;
27 import org.apache.logging.log4j.core.net.AbstractSocketManager;
28 import org.apache.logging.log4j.core.net.Protocol;
29 import org.junit.Test;
30
31 /**
32 * Class Description goes here.
33 */
34 public class SyslogAppenderConfigurationTest {
35
36 private void checkProtocol(final Protocol expected, final Configuration configuration) {
37 final Map<String, Appender> appenders = configuration.getAppenders();
38 assertNotNull(appenders);
39 final String appenderName = "syslog";
40 final Appender appender = appenders.get(appenderName);
41 assertNotNull(appender, "Missing appender " + appenderName);
42 final SocketAppender socketAppender = (SocketAppender) appender;
43 @SuppressWarnings("resource")
44 final AbstractSocketManager manager = socketAppender.getManager();
45 assertTrue(manager.getName().startsWith(expected + ":"));
46 }
47
48 private void checkProtocolPropertiesConfig(final Protocol expected, final String xmlPath) throws IOException {
49 checkProtocol(expected, TestConfigurator.configure(xmlPath).getConfiguration());
50 }
51
52 private void checkProtocolXmlConfig(final Protocol expected, final String xmlPath) throws IOException {
53 checkProtocol(expected, TestConfigurator.configure(xmlPath).getConfiguration());
54 }
55
56 @Test
57 public void testPropertiesProtocolDefault() throws Exception {
58 checkProtocolPropertiesConfig(Protocol.TCP, "target/test-classes/log4j1-syslog-protocol-default.properties");
59 }
60
61 @Test
62 public void testPropertiesProtocolTcp() throws Exception {
63 checkProtocolPropertiesConfig(Protocol.TCP, "target/test-classes/log4j1-syslog-protocol-tcp.properties");
64 }
65
66 @Test
67 public void testPropertiesProtocolUdp() throws Exception {
68 checkProtocolPropertiesConfig(Protocol.UDP, "target/test-classes/log4j1-syslog-protocol-udp.properties");
69 }
70
71 @Test
72 public void testXmlProtocolDefault() throws Exception {
73 checkProtocolXmlConfig(Protocol.TCP, "target/test-classes/log4j1-syslog.xml");
74 }
75
76 @Test
77 public void testXmlProtocolTcp() throws Exception {
78 checkProtocolXmlConfig(Protocol.TCP, "target/test-classes/log4j1-syslog-protocol-tcp.xml");
79 }
80
81 @Test
82 public void testXmlProtocolUdp() throws Exception {
83 checkProtocolXmlConfig(Protocol.UDP, "target/test-classes/log4j1-syslog-protocol-udp.xml");
84 }
85 }
+0
-83
log4j-1.2-api/src/test/java/org/apache/log4j/config/SyslogAppenderTest.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 static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20
21 import java.io.IOException;
22 import java.util.List;
23
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.config.ConfigurationFactory;
27 import org.apache.logging.log4j.core.net.mock.MockSyslogServer;
28 import org.apache.logging.log4j.core.net.mock.MockSyslogServerFactory;
29 import org.junit.After;
30 import org.junit.AfterClass;
31 import org.junit.BeforeClass;
32 import org.junit.Test;
33
34
35 /**
36 * Class Description goes here.
37 */
38 public class SyslogAppenderTest {
39
40 private static final int PORTNUM = 9999;
41 private MockSyslogServer syslogServer;
42
43 @BeforeClass
44 public static void beforeClass() {
45 System.setProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY, "target/test-classes/log4j1-syslog.xml");
46 }
47
48 @AfterClass
49 public static void afterClass() {
50 System.clearProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY);
51 }
52
53 @After
54 public void teardown() {
55 if (syslogServer != null) {
56 syslogServer.shutdown();
57 }
58 }
59
60 @Test
61 public void sendMessage() throws Exception {
62 initTCPTestEnvironment(null);
63 Logger logger = LogManager.getLogger(SyslogAppenderTest.class);
64 logger.info("This is a test");
65 List<String> messages = null;
66 for (int i = 0; i < 5; ++i) {
67 Thread.sleep(250);
68 messages = syslogServer.getMessageList();
69 if (messages != null && messages.size() > 0) {
70 break;
71 }
72 }
73 assertNotNull("No messages received", messages);
74 assertEquals("Sent message not detected", 1, messages.size());
75 }
76
77
78 protected void initTCPTestEnvironment(final String messageFormat) throws IOException {
79 syslogServer = MockSyslogServerFactory.createTCPSyslogServer(1, PORTNUM);
80 syslogServer.start();
81 }
82 }
+0
-55
log4j-1.2-api/src/test/java/org/apache/log4j/config/TestConfigurator.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 static org.junit.Assert.assertNotNull;
19 import static org.junit.jupiter.api.Assertions.fail;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.nio.file.Files;
25 import java.nio.file.Paths;
26
27 import org.apache.log4j.xml.XmlConfigurationFactory;
28 import org.apache.logging.log4j.core.LoggerContext;
29 import org.apache.logging.log4j.core.config.Configuration;
30 import org.apache.logging.log4j.core.config.ConfigurationSource;
31 import org.apache.logging.log4j.core.config.Configurator;
32
33 public class TestConfigurator {
34
35 @SuppressWarnings("resource")
36 static LoggerContext configure(String configLocation) throws IOException {
37 File file = new File(configLocation);
38 InputStream is = Files.newInputStream(Paths.get(configLocation));
39 ConfigurationSource source = new ConfigurationSource(is, file);
40 LoggerContext context = (LoggerContext) org.apache.logging.log4j.LogManager.getContext(false);
41 Configuration configuration = null;
42 if (configLocation.endsWith(PropertiesConfigurationFactory.FILE_EXTENSION)) {
43 configuration = new PropertiesConfigurationFactory().getConfiguration(context, source);
44 } else if (configLocation.endsWith(XmlConfigurationFactory.FILE_EXTENSION)) {
45 configuration = new XmlConfigurationFactory().getConfiguration(context, source);
46 } else {
47 fail("Test infra does not support " + configLocation);
48 }
49 assertNotNull("No configuration created", configuration);
50 Configurator.reconfigure(configuration);
51 return context;
52 }
53
54 }
+0
-50
log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationFactoryTest.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 static org.junit.Assert.assertTrue;
19
20 import java.io.File;
21
22 import org.apache.log4j.LogManager;
23 import org.apache.log4j.Logger;
24 import org.apache.logging.log4j.core.config.ConfigurationFactory;
25 import org.junit.BeforeClass;
26 import org.junit.Test;
27
28 /**
29 * Test configuration from XML.
30 */
31 public class XmlConfigurationFactoryTest {
32
33 @BeforeClass
34 public static void beforeClass() {
35 System.setProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY, "target/test-classes/log4j1-file.xml");
36 }
37 @Test
38 public void testXML() throws Exception {
39 Logger logger = LogManager.getLogger("test");
40 logger.debug("This is a test of the root logger");
41 File file = new File("target/temp.A1");
42 assertTrue("File A1 was not created", file.exists());
43 assertTrue("File A1 is empty", file.length() > 0);
44 file = new File("target/temp.A2");
45 assertTrue("File A2 was not created", file.exists());
46 assertTrue("File A2 is empty", file.length() > 0);
47 }
48
49 }
+0
-78
log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.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 static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
21 import java.io.File;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.log4j.ListAppender;
26 import org.apache.log4j.LogManager;
27 import org.apache.log4j.Logger;
28 import org.apache.log4j.bridge.AppenderAdapter;
29 import org.apache.log4j.spi.LoggingEvent;
30 import org.apache.logging.log4j.core.Appender;
31 import org.apache.logging.log4j.core.LoggerContext;
32 import org.apache.logging.log4j.core.config.Configuration;
33 import org.junit.Test;
34
35 /**
36 * Test configuration from XML.
37 */
38 public class XmlConfigurationTest {
39
40 @Test
41 public void testListAppender() throws Exception {
42 final LoggerContext loggerContext = TestConfigurator.configure("target/test-classes/log4j1-list.xml");
43 final Logger logger = LogManager.getLogger("test");
44 logger.debug("This is a test of the root logger");
45 final Configuration configuration = loggerContext.getConfiguration();
46 final Map<String, Appender> appenders = configuration.getAppenders();
47 ListAppender eventAppender = null;
48 ListAppender messageAppender = null;
49 for (final Map.Entry<String, Appender> entry : appenders.entrySet()) {
50 if (entry.getKey().equals("list")) {
51 messageAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
52 } else if (entry.getKey().equals("events")) {
53 eventAppender = (ListAppender) ((AppenderAdapter.Adapter) entry.getValue()).getAppender();
54 }
55 }
56 assertNotNull("No Event Appender", eventAppender);
57 assertNotNull("No Message Appender", messageAppender);
58 final List<LoggingEvent> events = eventAppender.getEvents();
59 assertTrue("No events", events != null && events.size() > 0);
60 final List<String> messages = messageAppender.getMessages();
61 assertTrue("No messages", messages != null && messages.size() > 0);
62 }
63
64 @Test
65 public void testXML() throws Exception {
66 TestConfigurator.configure("target/test-classes/log4j1-file.xml");
67 final Logger logger = LogManager.getLogger("test");
68 logger.debug("This is a test of the root logger");
69 File file = new File("target/temp.A1");
70 assertTrue("File A1 was not created", file.exists());
71 assertTrue("File A1 is empty", file.length() > 0);
72 file = new File("target/temp.A2");
73 assertTrue("File A2 was not created", file.exists());
74 assertTrue("File A2 is empty", file.length() > 0);
75 }
76
77 }
+0
-79
log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlReconfigurationTest.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 static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20 import static org.junit.Assert.fail;
21
22 import java.io.File;
23 import java.util.concurrent.CountDownLatch;
24 import java.util.concurrent.TimeUnit;
25
26 import org.apache.log4j.LogManager;
27 import org.apache.log4j.Logger;
28 import org.apache.logging.log4j.core.LoggerContext;
29 import org.apache.logging.log4j.core.config.Configuration;
30 import org.apache.logging.log4j.core.config.ConfigurationListener;
31 import org.apache.logging.log4j.core.config.Reconfigurable;
32 import org.junit.Test;
33
34 /**
35 * Test reconfiguring with an XML configuration.
36 */
37 public class XmlReconfigurationTest {
38
39 private static final String CONFIG = "target/test-classes/log4j1-file.xml";
40 private static final long FIVE_MINUTES = 5 * 60 * 1000;
41
42 private CountDownLatch toggle = new CountDownLatch(1);
43
44 @Test
45 public void testReconfiguration() throws Exception {
46 System.setProperty(Log4j1Configuration.MONITOR_INTERVAL, "1");
47 File file = new File(CONFIG);
48 assertNotNull("No Config file", file);
49 long configMillis = file.lastModified();
50 assertTrue("Unable to modified file time", file.setLastModified(configMillis - FIVE_MINUTES));
51 LoggerContext context = TestConfigurator.configure(file.toString());
52 Logger logger = LogManager.getLogger("test");
53 logger.info("Hello");
54 Configuration original = context.getConfiguration();
55 TestListener listener = new TestListener();
56 original.addListener(listener);
57 file.setLastModified(System.currentTimeMillis());
58 try {
59 if (!toggle.await(3, TimeUnit.SECONDS)) {
60 fail("Reconfiguration timed out");
61 }
62 // Allow reconfiguration to complete.
63 Thread.sleep(500);
64 } catch (InterruptedException ie) {
65 fail("Reconfiguration interupted");
66 }
67 Configuration updated = context.getConfiguration();
68 assertTrue("Configurations are the same", original != updated);
69 }
70
71 private class TestListener implements ConfigurationListener {
72
73 public synchronized void onChange(final Reconfigurable reconfigurable) {
74 toggle.countDown();
75 }
76
77 }
78 }
+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 }
128128 for (int i = 0; i < endScan; i++) {
129129 if ((skipIndex < skip.length) && (skip[skipIndex] == i)) {
130130 skipIndex++;
131 } else if (expected[i] != actual[i]) {
132 assertEquals(
133 "Difference at offset " + i, expected[i], actual[i]);
131 } else {
132 if (expected[i] != actual[i]) {
133 assertEquals(
134 "Difference at offset " + i, expected[i], actual[i]);
135 }
134136 }
135137 }
136138 } else {
+0
-34
log4j-1.2-api/src/test/resources/LOG4J2-3247.properties 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
16 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
17 log4j.appender.CONSOLE.filter.1=org.apache.log4j.config.ZeroFilterFixture
18 log4j.appender.CONSOLE.Target=System.out
19 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
20 log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
21
22 log4j.appender.A1=org.apache.log4j.FileAppender
23 log4j.appender.A1.File=target/temp.A1
24 log4j.appender.A1.Append=false
25 log4j.appender.A1.layout=org.apache.log4j.PatternLayout
26 log4j.appender.A1.layout.ConversionPattern=%-5p %c{2} - %m%n
27 log4j.appender.A2=org.apache.log4j.FileAppender
28 log4j.appender.A2.File=target/temp.A2
29 log4j.appender.A2.Append=false
30 log4j.appender.A2.layout=org.apache.log4j.TTCCLayout
31 log4j.appender.A2.layout.DateFormat=ISO8601
32 log4j.logger.org.apache.log4j.xml=trace, A1
33 log4j.rootLogger=trace, CONSOLE, A1, A2
+0
-36
log4j-1.2-api/src/test/resources/log4j.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="list" class="org.apache.log4j.ListAppender">
21 <layout class="org.apache.log4j.PatternLayout">
22 <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
23 </layout>
24 </appender>
25
26 <appender name="events" class="org.apache.log4j.ListAppender">
27 </appender>
28
29 <root>
30 <priority value ="trace" />
31 <appender-ref ref="list" />
32 <appender-ref ref="events" />
33 </root>
34
35 </log4j:configuration>
+0
-21
log4j-1.2-api/src/test/resources/log4j1-async.properties 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 log4j.appender.list=org.apache.log4j.ListAppender
16 log4j.appender.list.layout=org.apache.log4j.PatternLayout
17 log4j.appender.list.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
18 log4j.appender.async=org.apache.log4j.AsyncAppender
19 log4j.appender.async.appender-ref=list
20 log4j.rootLogger=trace, async
+0
-35
log4j-1.2-api/src/test/resources/log4j1-async.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="list" class="org.apache.log4j.ListAppender">
21 <layout class="org.apache.log4j.PatternLayout">
22 <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
23 </layout>
24 </appender>
25 <appender name="async" class="org.apache.log4j.AsyncAppender">
26 <appender-ref ref="list"/>
27 </appender>
28
29 <root>
30 <priority value ="trace" />
31 <appender-ref ref="async" />
32 </root>
33
34 </log4j:configuration>
+0
-31
log4j-1.2-api/src/test/resources/log4j1-file.properties 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 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
16 log4j.appender.CONSOLE.Target=System.out
17 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
18 log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
19 log4j.appender.A1=org.apache.log4j.FileAppender
20 log4j.appender.A1.File=target/temp.A1
21 log4j.appender.A1.Append=false
22 log4j.appender.A1.layout=org.apache.log4j.PatternLayout
23 log4j.appender.A1.layout.ConversionPattern=%-5p %c{2} - %m%n
24 log4j.appender.A2=org.apache.log4j.FileAppender
25 log4j.appender.A2.File=target/temp.A2
26 log4j.appender.A2.Append=false
27 log4j.appender.A2.layout=org.apache.log4j.TTCCLayout
28 log4j.appender.A2.layout.DateFormat=ISO8601
29 log4j.logger.org.apache.log4j.xml=trace, A1
30 log4j.rootLogger=trace, A1, A2
+0
-57
log4j-1.2-api/src/test/resources/log4j1-file.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="console" class="org.apache.log4j.ConsoleAppender">
21 <param name="Target" value="System.out"/>
22 <layout class="org.apache.log4j.PatternLayout">
23 <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
24 </layout>
25 </appender>
26
27 <appender name="A1" class="org.apache.log4j.FileAppender">
28
29 <param name="File" value="target/temp.A1" />
30 <param name="Append" value="false" />
31
32 <layout class="org.apache.log4j.PatternLayout">
33 <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/>
34 </layout>
35 </appender>
36
37 <appender name="A2" class="org.apache.log4j.FileAppender">
38 <param name="File" value="target/temp.A2" />
39 <param name="Append" value="false" />
40 <layout class="org.apache.log4j.TTCCLayout">
41 <param name="DateFormat" value="ISO8601" />
42 </layout>
43 </appender>
44
45 <logger name="org.apache.log4j.xml">
46 <level value="trace" />
47 <appender-ref ref="A1" />
48 </logger>
49
50 <root>
51 <priority value ="trace" />
52 <appender-ref ref="A1" />
53 <appender-ref ref="A2" />
54 </root>
55
56 </log4j:configuration>
+0
-20
log4j-1.2-api/src/test/resources/log4j1-list.properties 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 log4j.appender.list=org.apache.log4j.ListAppender
16 log4j.appender.list.layout=org.apache.log4j.PatternLayout
17 log4j.appender.list.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
18 log4j.appender.events=org.apache.log4j.ListAppender
19 log4j.rootLogger=trace, list, events
+0
-36
log4j-1.2-api/src/test/resources/log4j1-list.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="list" class="org.apache.log4j.ListAppender">
21 <layout class="org.apache.log4j.PatternLayout">
22 <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
23 </layout>
24 </appender>
25
26 <appender name="events" class="org.apache.log4j.ListAppender">
27 </appender>
28
29 <root>
30 <priority value ="trace" />
31 <appender-ref ref="list" />
32 <appender-ref ref="events" />
33 </root>
34
35 </log4j:configuration>
+0
-35
log4j-1.2-api/src/test/resources/log4j1-mapRewrite.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!--<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">-->
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="events" class="org.apache.log4j.ListAppender">
21 </appender>
22
23 <appender name="rewrite" class="org.apache.log4j.rewrite.RewriteAppender">
24 <appender-ref ref="events"/>
25 <rewritePolicy class="org.apache.log4j.rewrite.MapRewritePolicy">
26 </rewritePolicy>
27 </appender>
28
29 <root>
30 <priority value ="trace" />
31 <appender-ref ref="rewrite" />
32 </root>
33
34 </log4j:configuration>
+0
-36
log4j-1.2-api/src/test/resources/log4j1-rewrite.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!--<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">-->
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="events" class="org.apache.log4j.ListAppender">
21 </appender>
22
23 <appender name="rewrite" class="org.apache.log4j.rewrite.RewriteAppender">
24 <appender-ref ref="events"/>
25 <rewritePolicy class="org.apache.log4j.rewrite.PropertyRewritePolicy">
26 <param name="properties" value="key2=Log4j"/>
27 </rewritePolicy>
28 </appender>
29
30 <root>
31 <priority value ="trace" />
32 <appender-ref ref="rewrite" />
33 </root>
34
35 </log4j:configuration>
+0
-31
log4j-1.2-api/src/test/resources/log4j1-rolling-properties.properties 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 log4j.debug=true
16
17 # Properties for substitution
18 somelogfile=target/rolling/somefile.log
19 maxfilesize=256MB
20 maxbackupindex=20
21
22 log4j.rootLogger=TRACE, RFA
23
24 # Appender configuration with variables
25 log4j.appender.RFA=org.apache.log4j.RollingFileAppender
26 log4j.appender.RFA.File=${somelogfile}
27 log4j.appender.RFA.MaxFileSize=${maxfilesize}
28 log4j.appender.RFA.MaxBackupIndex=${maxbackupindex}
29 log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
30 log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
+0
-9
log4j-1.2-api/src/test/resources/log4j1-syslog-protocol-default.properties less more
0 log4j.rootLogger=DEBUG,syslog
1 log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
2 log4j.appender.syslog.Threshold=DEBUG
3 log4j.appender.syslog.syslogHost=localhost
4 log4j.appender.syslog.port=9999
5 log4j.appender.syslog.header=true
6 log4j.appender.syslog.Facility=LOCAL3
7 log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
8 log4j.appender.syslog.layout.conversionPattern=Main[%pid] :%t: %c %-4p - %m\n
+0
-10
log4j-1.2-api/src/test/resources/log4j1-syslog-protocol-tcp.properties less more
0 log4j.rootLogger=DEBUG,syslog
1 log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
2 log4j.appender.syslog.Threshold=DEBUG
3 log4j.appender.syslog.syslogHost=localhost
4 log4j.appender.syslog.port=9999
5 log4j.appender.syslog.protocol=TCP
6 log4j.appender.syslog.header=true
7 log4j.appender.syslog.Facility=LOCAL3
8 log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
9 log4j.appender.syslog.layout.conversionPattern=Main[%pid] :%t: %c %-4p - %m\n
+0
-37
log4j-1.2-api/src/test/resources/log4j1-syslog-protocol-tcp.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="syslog" class="org.apache.log4j.net.SyslogAppender">
21 <param name="SyslogHost" value="localhost:9999"/>
22 <param name="Facility" value="USER"/>
23 <param name="FacilityPrinting" value="true"/>
24 <param name="Threshold" value="DEBUG"/>
25 <param name="protocol" value="TCP"/>
26 <layout class="org.apache.log4j.PatternLayout">
27 <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
28 </layout>
29 </appender>
30
31 <root>
32 <priority value ="trace" />
33 <appender-ref ref="syslog" />
34 </root>
35
36 </log4j:configuration>
+0
-10
log4j-1.2-api/src/test/resources/log4j1-syslog-protocol-udp.properties less more
0 log4j.rootLogger=DEBUG,syslog
1 log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
2 log4j.appender.syslog.Threshold=DEBUG
3 log4j.appender.syslog.syslogHost=localhost
4 log4j.appender.syslog.port=9999
5 log4j.appender.syslog.protocol=UDP
6 log4j.appender.syslog.header=true
7 log4j.appender.syslog.Facility=LOCAL3
8 log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
9 log4j.appender.syslog.layout.conversionPattern=Main[%pid] :%t: %c %-4p - %m\n
+0
-37
log4j-1.2-api/src/test/resources/log4j1-syslog-protocol-udp.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="syslog" class="org.apache.log4j.net.SyslogAppender">
21 <param name="SyslogHost" value="localhost:9999"/>
22 <param name="Facility" value="USER"/>
23 <param name="FacilityPrinting" value="true"/>
24 <param name="Threshold" value="DEBUG"/>
25 <param name="protocol" value="UDP"/>
26 <layout class="org.apache.log4j.PatternLayout">
27 <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
28 </layout>
29 </appender>
30
31 <root>
32 <priority value ="trace" />
33 <appender-ref ref="syslog" />
34 </root>
35
36 </log4j:configuration>
+0
-36
log4j-1.2-api/src/test/resources/log4j1-syslog.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
18
19 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
20 <appender name="syslog" class="org.apache.log4j.net.SyslogAppender">
21 <param name="SyslogHost" value="localhost:9999"/>
22 <param name="Facility" value="USER"/>
23 <param name="FacilityPrinting" value="true"/>
24 <param name="Threshold" value="DEBUG"/>
25 <layout class="org.apache.log4j.PatternLayout">
26 <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
27 </layout>
28 </appender>
29
30 <root>
31 <priority value ="trace" />
32 <appender-ref ref="syslog" />
33 </root>
34
35 </log4j:configuration>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-api</artifactId>
3030 <log4jParentDir>${basedir}/..</log4jParentDir>
3131 <docLabel>API Documentation</docLabel>
3232 <projectDir>/api</projectDir>
33 <maven.doap.skip>true</maven.doap.skip>
3433 </properties>
3534 <dependencies>
3635 <!-- Place Felix before Equinox because Felix is signed. / also place it before org.osgi.core so that its versions of the OSGi classes are used -->
4544 <scope>provided</scope>
4645 </dependency>
4746 <dependency>
48 <groupId>org.junit.vintage</groupId>
49 <artifactId>junit-vintage-engine</artifactId>
50 </dependency>
51 <dependency>
52 <groupId>org.junit.jupiter</groupId>
53 <artifactId>junit-jupiter-migrationsupport</artifactId>
54 </dependency>
55 <dependency>
56 <groupId>org.junit.jupiter</groupId>
57 <artifactId>junit-jupiter-params</artifactId>
58 </dependency>
59 <dependency>
60 <groupId>org.junit.jupiter</groupId>
61 <artifactId>junit-jupiter-engine</artifactId>
62 </dependency>
63 <dependency>
64 <groupId>org.assertj</groupId>
65 <artifactId>assertj-core</artifactId>
47 <groupId>junit</groupId>
48 <artifactId>junit</artifactId>
49 <scope>test</scope>
6650 </dependency>
6751 <dependency>
6852 <groupId>org.eclipse.tycho</groupId>
151135 <id>default-compile</id>
152136 <!-- recompile everything for target VM except the module-info.java -->
153137 <configuration>
154 <source>1.8</source>
155 <target>1.8</target>
156 </configuration>
157 </execution>
158 </executions>
159 </plugin>
160 <plugin>
161 <groupId>org.apache.maven.plugins</groupId>
162 <artifactId>maven-surefire-plugin</artifactId>
163 <configuration>
164 <properties>
165 <configurationParameters>
166 <!-- LOG4J2-2921: use parallel test execution by default -->
167 junit.jupiter.execution.parallel.enabled = true
168 junit.jupiter.execution.parallel.mode.default = concurrent
169 </configurationParameters>
170 </properties>
171 <reuseForks>true</reuseForks>
172 <redirectTestOutputToFile>true</redirectTestOutputToFile>
173 <excludedGroups>performance,smoke</excludedGroups>
174 </configuration>
138 <source>1.7</source>
139 <target>1.7</target>
140 </configuration>
141 </execution>
142 </executions>
175143 </plugin>
176144 <plugin>
177145 <groupId>org.apache.maven.plugins</groupId>
319287 </reportSets>
320288 </plugin>
321289 <plugin>
322 <groupId>com.github.spotbugs</groupId>
323 <artifactId>spotbugs-maven-plugin</artifactId>
290 <groupId>org.codehaus.mojo</groupId>
291 <artifactId>findbugs-maven-plugin</artifactId>
292 <version>${findbugs.plugin.version}</version>
293 <configuration>
294 <fork>true</fork>
295 <jvmArgs>-Duser.language=en</jvmArgs>
296 <threshold>Normal</threshold>
297 <effort>Default</effort>
298 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
299 </configuration>
324300 </plugin>
325301 <plugin>
326302 <groupId>org.apache.maven.plugins</groupId>
2828 "old": "method java.lang.String org.apache.logging.log4j.util.Strings::toRootUpperCase(java.lang.String)",
2929 "new": "method java.lang.String org.apache.logging.log4j.util.Strings::toRootUpperCase(java.lang.String)",
3030 "justification": "Method was inaccessible"
31 },
32 {
33 "code": "java.field.serialVersionUIDUnchanged",
34 "old": "field org.apache.logging.log4j.spi.AbstractLogger.serialVersionUID",
35 "new": "field org.apache.logging.log4j.spi.AbstractLogger.serialVersionUID",
36 "serialVersionUID": "2",
37 "justification": "LOG4J2-2639 - Add builder pattern to Logger interface"
38 },
39 {
40 "code": "java.class.noLongerImplementsInterface",
41 "old": "class org.apache.logging.log4j.internal.DefaultLogBuilder",
42 "new": "class org.apache.logging.log4j.internal.DefaultLogBuilder",
43 "interface": "java.io.Serializable",
44 "justification": "Internal class that should not be Serializable."
4531 }
4632 ]
4733 }
283283 if (name == null) {
284284 return defaultLevel;
285285 }
286 final Level level = LEVELS.get(toUpperCase(name.trim()));
286 final Level level = LEVELS.get(toUpperCase(name));
287287 return level == null ? defaultLevel : level;
288288 }
289289
311311 */
312312 public static Level valueOf(final String name) {
313313 Objects.requireNonNull(name, "No level name given.");
314 final String levelName = toUpperCase(name.trim());
314 final String levelName = toUpperCase(name);
315315 final Level level = LEVELS.get(levelName);
316316 if (level != null) {
317317 return level;
+0
-285
log4j-api/src/main/java/org/apache/logging/log4j/LogBuilder.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.logging.log4j;
17
18 import org.apache.logging.log4j.message.Message;
19 import org.apache.logging.log4j.util.Supplier;
20
21
22 /**
23 * Interface for constructing log events before logging them. Instances of LogBuilders should only be created
24 * by calling one of the Logger methods that return a LogBuilder.
25 */
26 public interface LogBuilder {
27
28 public static final LogBuilder NOOP = new LogBuilder() {};
29
30 /**
31 * Includes a Marker in the log event. Interface default method does nothing.
32 * @param marker The Marker to log.
33 * @return The LogBuilder.
34 */
35 default LogBuilder withMarker(Marker marker) {
36 return this;
37 }
38
39 /**
40 * Includes a Throwable in the log event. Interface default method does nothing.
41 * @param throwable The Throwable to log.
42 * @return the LogBuilder.
43 */
44 default LogBuilder withThrowable(Throwable throwable) {
45 return this;
46 }
47
48 /**
49 * An implementation will calculate the caller's stack frame and include it in the log event.
50 * Interface default method does nothing.
51 * @return The LogBuilder.
52 */
53 default LogBuilder withLocation() {
54 return this;
55 }
56
57 /**
58 * Adds the specified stack trace element to the log event. Interface default method does nothing.
59 * @param location The stack trace element to include in the log event.
60 * @return The LogBuilder.
61 */
62 default LogBuilder withLocation(StackTraceElement location) {
63 return this;
64 }
65
66 /**
67 * Causes all the data collected to be logged along with the message. Interface default method does nothing.
68 * @param message The message to log.
69 */
70 default void log(CharSequence message) {
71 }
72
73 /**
74 * Causes all the data collected to be logged along with the message. Interface default method does nothing.
75 * @param message The message to log.
76 */
77 default void log(String message) {
78 }
79
80 /**
81 * Logs a message with parameters. Interface default method does nothing.
82 *
83 * @param message the message to log; the format depends on the message factory.
84 * @param params parameters to the message.
85 *
86 * @see org.apache.logging.log4j.util.Unbox
87 */
88 default void log(String message, Object... params) {
89 }
90
91 /**
92 * Causes all the data collected to be logged along with the message and parameters.
93 * Interface default method does nothing.
94 * @param message The message.
95 * @param params Parameters to the message.
96 */
97 default void log(String message, Supplier<?>... params) {
98 }
99
100 /**
101 * Causes all the data collected to be logged along with the message. Interface default method does nothing.
102 * @param message The message to log.
103 */
104 default void log(Message message) {
105 }
106
107 /**
108 * Causes all the data collected to be logged along with the message. Interface default method does nothing.
109 * @param messageSupplier The supplier of the message to log.
110 */
111 default void log(Supplier<Message> messageSupplier) {
112 }
113
114 /**
115 * Causes all the data collected to be logged along with the message. Interface default method does nothing.
116 * @param message The message to log.
117 */
118 default void log(Object message) {
119 }
120
121 /**
122 * Logs a message with parameters. Interface default method does nothing.
123 *
124 * @param message the message to log; the format depends on the message factory.
125 * @param p0 parameter to the message.
126 *
127 * @see org.apache.logging.log4j.util.Unbox
128 */
129 default void log(String message, Object p0) {
130 }
131
132 /**
133 * Logs a message with parameters. Interface default method does nothing.
134 *
135 * @param message the message to log; the format depends on the message factory.
136 * @param p0 parameter to the message.
137 * @param p1 parameter to the message.
138 *
139 * @see org.apache.logging.log4j.util.Unbox
140 */
141 default void log(String message, Object p0, Object p1) {
142 }
143
144 /**
145 * Logs a message with parameters. Interface default method does nothing.
146 *
147 * @param message the message to log; the format depends on the message factory.
148 * @param p0 parameter to the message.
149 * @param p1 parameter to the message.
150 * @param p2 parameter to the message.
151 *
152 * @see org.apache.logging.log4j.util.Unbox
153 */
154 default void log(String message, Object p0, Object p1, Object p2) {
155 }
156
157 /**
158 * Logs a message with parameters. Interface default method does nothing.
159 *
160 * @param message the message to log; the format depends on the message factory.
161 * @param p0 parameter to the message.
162 * @param p1 parameter to the message.
163 * @param p2 parameter to the message.
164 * @param p3 parameter to the message.
165 *
166 * @see org.apache.logging.log4j.util.Unbox
167 */
168 default void log(String message, Object p0, Object p1, Object p2, Object p3) {
169 }
170
171 /**
172 * Logs a message with parameters. Interface default method does nothing.
173 *
174 * @param message the message to log; the format depends on the message factory.
175 * @param p0 parameter to the message.
176 * @param p1 parameter to the message.
177 * @param p2 parameter to the message.
178 * @param p3 parameter to the message.
179 * @param p4 parameter to the message.
180 *
181 * @see org.apache.logging.log4j.util.Unbox
182 */
183 default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {
184 }
185
186 /**
187 * Logs a message with parameters. Interface default method does nothing.
188 *
189 * @param message the message to log; the format depends on the message factory.
190 * @param p0 parameter to the message.
191 * @param p1 parameter to the message.
192 * @param p2 parameter to the message.
193 * @param p3 parameter to the message.
194 * @param p4 parameter to the message.
195 * @param p5 parameter to the message.
196 *
197 * @see org.apache.logging.log4j.util.Unbox
198 */
199 default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {
200 }
201
202 /**
203 * Logs a message with parameters.
204 *
205 * @param message the message to log; the format depends on the message factory.
206 * @param p0 parameter to the message.
207 * @param p1 parameter to the message.
208 * @param p2 parameter to the message.
209 * @param p3 parameter to the message.
210 * @param p4 parameter to the message.
211 * @param p5 parameter to the message.
212 * @param p6 parameter to the message.
213 *
214 * @see org.apache.logging.log4j.util.Unbox
215 */
216 default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {
217 }
218
219 /**
220 * Logs a message with parameters. Interface default method does nothing.
221 *
222 * @param message the message to log; the format depends on the message factory.
223 * @param p0 parameter to the message.
224 * @param p1 parameter to the message.
225 * @param p2 parameter to the message.
226 * @param p3 parameter to the message.
227 * @param p4 parameter to the message.
228 * @param p5 parameter to the message.
229 * @param p6 parameter to the message.
230 * @param p7 parameter to the message.
231 *
232 * @see org.apache.logging.log4j.util.Unbox
233 */
234 default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
235 Object p7) {
236 }
237
238 /**
239 * Logs a message with parameters. Interface default method does nothing.
240 *
241 * @param message the message to log; the format depends on the message factory.
242 * @param p0 parameter to the message.
243 * @param p1 parameter to the message.
244 * @param p2 parameter to the message.
245 * @param p3 parameter to the message.
246 * @param p4 parameter to the message.
247 * @param p5 parameter to the message.
248 * @param p6 parameter to the message.
249 * @param p7 parameter to the message.
250 * @param p8 parameter to the message.
251 *
252 * @see org.apache.logging.log4j.util.Unbox
253 */
254 default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
255 Object p7, Object p8) {
256 }
257
258 /**
259 * Logs a message with parameters. Interface default method does nothing.
260 *
261 * @param message the message to log; the format depends on the message factory.
262 * @param p0 parameter to the message.
263 * @param p1 parameter to the message.
264 * @param p2 parameter to the message.
265 * @param p3 parameter to the message.
266 * @param p4 parameter to the message.
267 * @param p5 parameter to the message.
268 * @param p6 parameter to the message.
269 * @param p7 parameter to the message.
270 * @param p8 parameter to the message.
271 * @param p9 parameter to the message.
272 *
273 * @see org.apache.logging.log4j.util.Unbox
274 */
275 default void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
276 Object p7, Object p8, Object p9) {
277 }
278
279 /**
280 * Causes all the data collected to be logged. Default implementatoin does nothing.
281 */
282 default void log() {
283 }
284 }
2020 import java.util.SortedMap;
2121 import java.util.TreeMap;
2222
23 import org.apache.logging.log4j.internal.LogManagerStatus;
2423 import org.apache.logging.log4j.message.MessageFactory;
2524 import org.apache.logging.log4j.message.StringFormatterMessageFactory;
2625 import org.apache.logging.log4j.simple.SimpleLoggerContextFactory;
121120 + "Please add log4j-core to the classpath. Using SimpleLogger to log to the console...");
122121 factory = new SimpleLoggerContextFactory();
123122 }
124 LogManagerStatus.setInitialized(true);
125123 }
126124 }
127125
388386 * @since 2.6
389387 */
390388 public static void shutdown(final boolean currentContext) {
391 factory.shutdown(FQCN, null, currentContext, false);
389 shutdown(getContext(currentContext));
392390 }
393391
394392 /**
395393 * Shutdown the logging system if the logging system supports it.
396 * This is equivalent to calling {@code LogManager.shutdown(LogManager.getContext(currentContext))}.
397394 *
398395 * This call is synchronous and will block until shut down is complete.
399396 * This may include flushing pending log events over network connections.
400397 *
401 * @param currentContext if true a default LoggerContext (may not be the LoggerContext used to create a Logger
402 * for the calling class) will be used.
403 * If false the LoggerContext appropriate for the caller of this method is used. For
404 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
405 * used and if the caller is a class in the container's classpath then a different LoggerContext may
406 * be used.
407 * @param allContexts if true all LoggerContexts that can be located will be shutdown.
408 * @since 2.13.0
409 */
410 public static void shutdown(final boolean currentContext, final boolean allContexts) {
411 factory.shutdown(FQCN, null, currentContext, allContexts);
412 }
413
414
415 /**
416 * Shutdown the logging system if the logging system supports it.
417 *
418 * This call is synchronous and will block until shut down is complete.
419 * This may include flushing pending log events over network connections.
420 *
421398 * @param context the LoggerContext.
422399 * @since 2.6
423400 */
424401 public static void shutdown(final LoggerContext context) {
425 if (context instanceof Terminable) {
402 if (context != null && context instanceof Terminable) {
426403 ((Terminable) context).terminate();
427404 }
405 }
406
407 private static String toLoggerName(final Class<?> cls) {
408 final String canonicalName = cls.getCanonicalName();
409 return canonicalName != null ? canonicalName : cls.getName();
428410 }
429411
430412 /**
595577 */
596578 public static Logger getLogger(final Class<?> clazz) {
597579 final Class<?> cls = callerClass(clazz);
598 return getContext(cls.getClassLoader(), false).getLogger(cls);
580 return getContext(cls.getClassLoader(), false).getLogger(toLoggerName(cls));
599581 }
600582
601583 /**
611593 */
612594 public static Logger getLogger(final Class<?> clazz, final MessageFactory messageFactory) {
613595 final Class<?> cls = callerClass(clazz);
614 return getContext(cls.getClassLoader(), false).getLogger(cls, messageFactory);
596 return getContext(cls.getClassLoader(), false).getLogger(toLoggerName(cls), messageFactory);
615597 }
616598
617599 /**
6868 * </pre>
6969 *
7070 * <p>
71 * Note that although {@link MessageSupplier} is provided, using {@link Supplier {@code Supplier<Message>}} works just the
71 * Note that although {@link MessageSupplier} is provided, using {@link Supplier Supplier<Message>} works just the
7272 * same. MessageSupplier was deprecated in 2.6 and un-deprecated in 2.8.1. Anonymous class usage of these APIs
7373 * should prefer using Supplier instead.
7474 * </p>
7676 public interface Logger {
7777
7878 /**
79 * Logs a {@link Throwable} that has been caught to a specific logging level.
79 * Logs an exception or error that has been caught to a specific logging level.
8080 *
8181 * @param level The logging Level.
82 * @param throwable the Throwable.
83 */
84 void catching(Level level, Throwable throwable);
85
86 /**
87 * Logs a {@link Throwable} that has been caught at the {@link Level#ERROR ERROR} level.
88 * Normally, one may wish to provide additional information with an exception while logging it;
89 * in these cases, one would not use this method.
90 * In other cases where simply logging the fact that an exception was swallowed somewhere
91 * (e.g., at the top of the stack trace in a {@code main()} method),
92 * this method is ideal for it.
93 *
94 * @param throwable the Throwable.
95 */
96 void catching(Throwable throwable);
82 * @param t The Throwable.
83 */
84 void catching(Level level, Throwable t);
85
86 /**
87 * Logs an exception or error that has been caught. Normally, one may wish to provide additional information with an
88 * exception while logging it; in these cases, one would not use this method. In other cases where simply logging
89 * the fact that an exception was swallowed somewhere (e.g., at the top of the stack trace in a {@code main()}
90 * method), this method is ideal for it.
91 *
92 * @param t The Throwable.
93 */
94 void catching(Throwable t);
9795
9896 /**
9997 * Logs a message with the specific Marker at the {@link Level#DEBUG DEBUG} level.
10098 *
10199 * @param marker the marker data specific to this log statement
102 * @param message the message string to be logged
103 */
104 void debug(Marker marker, Message message);
100 * @param msg the message string to be logged
101 */
102 void debug(Marker marker, Message msg);
105103
106104 /**
107105 * Logs a message with the specific Marker at the {@link Level#DEBUG DEBUG} level.
108106 *
109107 * @param marker the marker data specific to this log statement
110 * @param message the message string to be logged
111 * @param throwable A Throwable or null.
112 */
113 void debug(Marker marker, Message message, Throwable throwable);
108 * @param msg the message string to be logged
109 * @param t A Throwable or null.
110 */
111 void debug(Marker marker, Message msg, Throwable t);
114112
115113 /**
116114 * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level with
118116 * {@code Message}.
119117 *
120118 * @param marker the marker data specific to this log statement
121 * @param messageSupplier A function, which when called, produces the desired log message.
122 * @since 2.4
123 */
124 void debug(Marker marker, MessageSupplier messageSupplier);
119 * @param msgSupplier A function, which when called, produces the desired log message.
120 * @since 2.4
121 */
122 void debug(Marker marker, MessageSupplier msgSupplier);
125123
126124 /**
127125 * Logs a message (only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level) with the
128 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The
126 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter. The
129127 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
130128 *
131129 * @param marker the marker data specific to this log statement
132 * @param messageSupplier A function, which when called, produces the desired log message.
133 * @param throwable A Throwable or null.
134 * @since 2.4
135 */
136 void debug(Marker marker, MessageSupplier messageSupplier, Throwable throwable);
130 * @param msgSupplier A function, which when called, produces the desired log message.
131 * @param t A Throwable or null.
132 * @since 2.4
133 */
134 void debug(Marker marker, MessageSupplier msgSupplier, Throwable t);
137135
138136 /**
139137 * Logs a message CharSequence with the {@link Level#DEBUG DEBUG} level.
145143
146144 /**
147145 * Logs a message CharSequence at the {@link Level#DEBUG DEBUG} level including the stack trace of the
148 * {@link Throwable} <code>throwable</code> passed as parameter.
146 * {@link Throwable} <code>t</code> passed as parameter.
149147 *
150148 * @param marker the marker data specific to this log statement
151149 * @param message the message CharSequence to log.
152 * @param throwable the {@code Throwable} to log, including its stack trace.
153 */
154 void debug(Marker marker, CharSequence message, Throwable throwable);
150 * @param t the exception to log, including its stack trace.
151 */
152 void debug(Marker marker, CharSequence message, Throwable t);
155153
156154 /**
157155 * Logs a message object with the {@link Level#DEBUG DEBUG} level.
163161
164162 /**
165163 * Logs a message at the {@link Level#DEBUG DEBUG} level including the stack trace of the {@link Throwable}
166 * <code>throwable</code> passed as parameter.
164 * <code>t</code> passed as parameter.
167165 *
168166 * @param marker the marker data specific to this log statement
169167 * @param message the message to log.
170 * @param throwable the {@code Throwable} to log, including its stack trace.
171 */
172 void debug(Marker marker, Object message, Throwable throwable);
168 * @param t the exception to log, including its stack trace.
169 */
170 void debug(Marker marker, Object message, Throwable t);
173171
174172 /**
175173 * Logs a message object with the {@link Level#DEBUG DEBUG} level.
202200
203201 /**
204202 * Logs a message at the {@link Level#DEBUG DEBUG} level including the stack trace of the {@link Throwable}
205 * <code>throwable</code> passed as parameter.
203 * <code>t</code> passed as parameter.
206204 *
207205 * @param marker the marker data specific to this log statement
208206 * @param message the message to log.
209 * @param throwable the {@code Throwable} to log, including its stack trace.
210 */
211 void debug(Marker marker, String message, Throwable throwable);
207 * @param t the exception to log, including its stack trace.
208 */
209 void debug(Marker marker, String message, Throwable t);
212210
213211 /**
214212 * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level with
215213 * the specified Marker.
216214 *
217215 * @param marker the marker data specific to this log statement
218 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
216 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
219217 * message factory.
220218 * @since 2.4
221219 */
222 void debug(Marker marker, Supplier<?> messageSupplier);
220 void debug(Marker marker, Supplier<?> msgSupplier);
223221
224222 /**
225223 * Logs a message (only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level) with the
226 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
227 *
228 * @param marker the marker data specific to this log statement
229 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
224 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
225 *
226 * @param marker the marker data specific to this log statement
227 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
230228 * message factory.
231 * @param throwable A Throwable or null.
232 * @since 2.4
233 */
234 void debug(Marker marker, Supplier<?> messageSupplier, Throwable throwable);
229 * @param t A Throwable or null.
230 * @since 2.4
231 */
232 void debug(Marker marker, Supplier<?> msgSupplier, Throwable t);
235233
236234 /**
237235 * Logs a message with the specific Marker at the {@link Level#DEBUG DEBUG} level.
238236 *
239 * @param message the message string to be logged
240 */
241 void debug(Message message);
237 * @param msg the message string to be logged
238 */
239 void debug(Message msg);
242240
243241 /**
244242 * Logs a message with the specific Marker at the {@link Level#DEBUG DEBUG} level.
245243 *
246 * @param message the message string to be logged
247 * @param throwable A Throwable or null.
248 */
249 void debug(Message message, Throwable throwable);
244 * @param msg the message string to be logged
245 * @param t A Throwable or null.
246 */
247 void debug(Message msg, Throwable t);
250248
251249 /**
252250 * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level. The
253251 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
254252 *
255 * @param messageSupplier A function, which when called, produces the desired log message.
256 * @since 2.4
257 */
258 void debug(MessageSupplier messageSupplier);
253 * @param msgSupplier A function, which when called, produces the desired log message.
254 * @since 2.4
255 */
256 void debug(MessageSupplier msgSupplier);
259257
260258 /**
261259 * Logs a message (only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level) including the
262 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier} may or may
260 * stack trace of the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier} may or may
263261 * not use the {@link MessageFactory} to construct the {@code Message}.
264262 *
265 * @param messageSupplier A function, which when called, produces the desired log message.
266 * @param throwable the {@code Throwable} to log, including its stack trace.
267 * @since 2.4
268 */
269 void debug(MessageSupplier messageSupplier, Throwable throwable);
263 * @param msgSupplier A function, which when called, produces the desired log message.
264 * @param t the exception to log, including its stack trace.
265 * @since 2.4
266 */
267 void debug(MessageSupplier msgSupplier, Throwable t);
270268
271269 /**
272270 * Logs a message CharSequence with the {@link Level#DEBUG DEBUG} level.
277275
278276 /**
279277 * Logs a CharSequence at the {@link Level#DEBUG DEBUG} level including the stack trace of the {@link Throwable}
280 * <code>throwable</code> passed as parameter.
278 * <code>t</code> passed as parameter.
281279 *
282280 * @param message the message CharSequence to log.
283 * @param throwable the {@code Throwable} to log, including its stack trace.
284 */
285 void debug(CharSequence message, Throwable throwable);
281 * @param t the exception to log, including its stack trace.
282 */
283 void debug(CharSequence message, Throwable t);
286284
287285 /**
288286 * Logs a message object with the {@link Level#DEBUG DEBUG} level.
293291
294292 /**
295293 * Logs a message at the {@link Level#DEBUG DEBUG} level including the stack trace of the {@link Throwable}
296 * <code>throwable</code> passed as parameter.
294 * <code>t</code> passed as parameter.
297295 *
298296 * @param message the message to log.
299 * @param throwable the {@code Throwable} to log, including its stack trace.
300 */
301 void debug(Object message, Throwable throwable);
297 * @param t the exception to log, including its stack trace.
298 */
299 void debug(Object message, Throwable t);
302300
303301 /**
304302 * Logs a message object with the {@link Level#DEBUG DEBUG} level.
328326
329327 /**
330328 * Logs a message at the {@link Level#DEBUG DEBUG} level including the stack trace of the {@link Throwable}
331 * <code>throwable</code> passed as parameter.
329 * <code>t</code> passed as parameter.
332330 *
333331 * @param message the message to log.
334 * @param throwable the {@code Throwable} to log, including its stack trace.
335 */
336 void debug(String message, Throwable throwable);
332 * @param t the exception to log, including its stack trace.
333 */
334 void debug(String message, Throwable t);
337335
338336 /**
339337 * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level.
340338 *
341 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
339 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
342340 * message factory.
343341 * @since 2.4
344342 */
345 void debug(Supplier<?> messageSupplier);
343 void debug(Supplier<?> msgSupplier);
346344
347345 /**
348346 * Logs a message (only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level) including the
349 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
350 *
351 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
347 * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
348 *
349 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
352350 * message factory.
353 * @param throwable the {@code Throwable} to log, including its stack trace.
354 * @since 2.4
355 */
356 void debug(Supplier<?> messageSupplier, Throwable throwable);
351 * @param t the exception to log, including its stack trace.
352 * @since 2.4
353 */
354 void debug(Supplier<?> msgSupplier, Throwable t);
357355
358356 /**
359357 * Logs a message with parameters at debug level.
655653 * Logs a message with the specific Marker at the {@link Level#ERROR ERROR} level.
656654 *
657655 * @param marker the marker data specific to this log statement
658 * @param message the message string to be logged
659 */
660 void error(Marker marker, Message message);
656 * @param msg the message string to be logged
657 */
658 void error(Marker marker, Message msg);
661659
662660 /**
663661 * Logs a message with the specific Marker at the {@link Level#ERROR ERROR} level.
664662 *
665663 * @param marker the marker data specific to this log statement
666 * @param message the message string to be logged
667 * @param throwable A Throwable or null.
668 */
669 void error(Marker marker, Message message, Throwable throwable);
664 * @param msg the message string to be logged
665 * @param t A Throwable or null.
666 */
667 void error(Marker marker, Message msg, Throwable t);
670668
671669 /**
672670 * Logs a message which is only to be constructed if the logging level is the {@link Level#ERROR ERROR} level with
674672 * {@code Message}.
675673 *
676674 * @param marker the marker data specific to this log statement
677 * @param messageSupplier A function, which when called, produces the desired log message.
678 * @since 2.4
679 */
680 void error(Marker marker, MessageSupplier messageSupplier);
675 * @param msgSupplier A function, which when called, produces the desired log message.
676 * @since 2.4
677 */
678 void error(Marker marker, MessageSupplier msgSupplier);
681679
682680 /**
683681 * Logs a message (only to be constructed if the logging level is the {@link Level#ERROR ERROR} level) with the
684 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The
682 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter. The
685683 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
686684 *
687685 * @param marker the marker data specific to this log statement
688 * @param messageSupplier A function, which when called, produces the desired log message.
689 * @param throwable A Throwable or null.
690 * @since 2.4
691 */
692 void error(Marker marker, MessageSupplier messageSupplier, Throwable throwable);
686 * @param msgSupplier A function, which when called, produces the desired log message.
687 * @param t A Throwable or null.
688 * @since 2.4
689 */
690 void error(Marker marker, MessageSupplier msgSupplier, Throwable t);
693691
694692 /**
695693 * Logs a message CharSequence with the {@link Level#ERROR ERROR} level.
701699
702700 /**
703701 * Logs a CharSequence at the {@link Level#ERROR ERROR} level including the stack trace of the {@link Throwable}
704 * <code>throwable</code> passed as parameter.
702 * <code>t</code> passed as parameter.
705703 *
706704 * @param marker the marker data specific to this log statement.
707705 * @param message the message CharSequence to log.
708 * @param throwable the {@code Throwable} to log, including its stack trace.
709 */
710 void error(Marker marker, CharSequence message, Throwable throwable);
706 * @param t the exception to log, including its stack trace.
707 */
708 void error(Marker marker, CharSequence message, Throwable t);
711709
712710 /**
713711 * Logs a message object with the {@link Level#ERROR ERROR} level.
719717
720718 /**
721719 * Logs a message at the {@link Level#ERROR ERROR} level including the stack trace of the {@link Throwable}
722 * <code>throwable</code> passed as parameter.
720 * <code>t</code> passed as parameter.
723721 *
724722 * @param marker the marker data specific to this log statement.
725723 * @param message the message object to log.
726 * @param throwable the {@code Throwable} to log, including its stack trace.
727 */
728 void error(Marker marker, Object message, Throwable throwable);
724 * @param t the exception to log, including its stack trace.
725 */
726 void error(Marker marker, Object message, Throwable t);
729727
730728 /**
731729 * Logs a message object with the {@link Level#ERROR ERROR} level.
758756
759757 /**
760758 * Logs a message at the {@link Level#ERROR ERROR} level including the stack trace of the {@link Throwable}
761 * <code>throwable</code> passed as parameter.
759 * <code>t</code> passed as parameter.
762760 *
763761 * @param marker the marker data specific to this log statement.
764762 * @param message the message object to log.
765 * @param throwable the {@code Throwable} to log, including its stack trace.
766 */
767 void error(Marker marker, String message, Throwable throwable);
763 * @param t the exception to log, including its stack trace.
764 */
765 void error(Marker marker, String message, Throwable t);
768766
769767 /**
770768 * Logs a message which is only to be constructed if the logging level is the {@link Level#ERROR ERROR} level with
771769 * the specified Marker.
772770 *
773771 * @param marker the marker data specific to this log statement
774 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
772 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
775773 * message factory.
776774 * @since 2.4
777775 */
778 void error(Marker marker, Supplier<?> messageSupplier);
776 void error(Marker marker, Supplier<?> msgSupplier);
779777
780778 /**
781779 * Logs a message (only to be constructed if the logging level is the {@link Level#ERROR ERROR} level) with the
782 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
783 *
784 * @param marker the marker data specific to this log statement
785 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
780 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
781 *
782 * @param marker the marker data specific to this log statement
783 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
786784 * message factory.
787 * @param throwable A Throwable or null.
788 * @since 2.4
789 */
790 void error(Marker marker, Supplier<?> messageSupplier, Throwable throwable);
785 * @param t A Throwable or null.
786 * @since 2.4
787 */
788 void error(Marker marker, Supplier<?> msgSupplier, Throwable t);
791789
792790 /**
793791 * Logs a message with the specific Marker at the {@link Level#ERROR ERROR} level.
794792 *
795 * @param message the message string to be logged
796 */
797 void error(Message message);
793 * @param msg the message string to be logged
794 */
795 void error(Message msg);
798796
799797 /**
800798 * Logs a message with the specific Marker at the {@link Level#ERROR ERROR} level.
801799 *
802 * @param message the message string to be logged
803 * @param throwable A Throwable or null.
804 */
805 void error(Message message, Throwable throwable);
800 * @param msg the message string to be logged
801 * @param t A Throwable or null.
802 */
803 void error(Message msg, Throwable t);
806804
807805 /**
808806 * Logs a message which is only to be constructed if the logging level is the {@link Level#ERROR ERROR} level. The
809807 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
810808 *
811 * @param messageSupplier A function, which when called, produces the desired log message.
812 * @since 2.4
813 */
814 void error(MessageSupplier messageSupplier);
809 * @param msgSupplier A function, which when called, produces the desired log message.
810 * @since 2.4
811 */
812 void error(MessageSupplier msgSupplier);
815813
816814 /**
817815 * Logs a message (only to be constructed if the logging level is the {@link Level#ERROR ERROR} level) including the
818 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier} may or may
816 * stack trace of the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier} may or may
819817 * not use the {@link MessageFactory} to construct the {@code Message}.
820818 *
821 * @param messageSupplier A function, which when called, produces the desired log message.
822 * @param throwable the {@code Throwable} to log, including its stack trace.
823 * @since 2.4
824 */
825 void error(MessageSupplier messageSupplier, Throwable throwable);
819 * @param msgSupplier A function, which when called, produces the desired log message.
820 * @param t the exception to log, including its stack trace.
821 * @since 2.4
822 */
823 void error(MessageSupplier msgSupplier, Throwable t);
826824
827825 /**
828826 * Logs a message CharSequence with the {@link Level#ERROR ERROR} level.
833831
834832 /**
835833 * Logs a CharSequence at the {@link Level#ERROR ERROR} level including the stack trace of the {@link Throwable}
836 * <code>throwable</code> passed as parameter.
834 * <code>t</code> passed as parameter.
837835 *
838836 * @param message the message CharSequence to log.
839 * @param throwable the {@code Throwable} to log, including its stack trace.
840 */
841 void error(CharSequence message, Throwable throwable);
837 * @param t the exception to log, including its stack trace.
838 */
839 void error(CharSequence message, Throwable t);
842840
843841 /**
844842 * Logs a message object with the {@link Level#ERROR ERROR} level.
849847
850848 /**
851849 * Logs a message at the {@link Level#ERROR ERROR} level including the stack trace of the {@link Throwable}
852 * <code>throwable</code> passed as parameter.
850 * <code>t</code> passed as parameter.
853851 *
854852 * @param message the message object to log.
855 * @param throwable the {@code Throwable} to log, including its stack trace.
856 */
857 void error(Object message, Throwable throwable);
853 * @param t the exception to log, including its stack trace.
854 */
855 void error(Object message, Throwable t);
858856
859857 /**
860858 * Logs a message object with the {@link Level#ERROR ERROR} level.
884882
885883 /**
886884 * Logs a message at the {@link Level#ERROR ERROR} level including the stack trace of the {@link Throwable}
887 * <code>throwable</code> passed as parameter.
885 * <code>t</code> passed as parameter.
888886 *
889887 * @param message the message object to log.
890 * @param throwable the {@code Throwable} to log, including its stack trace.
891 */
892 void error(String message, Throwable throwable);
888 * @param t the exception to log, including its stack trace.
889 */
890 void error(String message, Throwable t);
893891
894892 /**
895893 * Logs a message which is only to be constructed if the logging level is the {@link Level#ERROR ERROR} level.
896894 *
897 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
895 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
898896 * message factory.
899897 * @since 2.4
900898 */
901 void error(Supplier<?> messageSupplier);
899 void error(Supplier<?> msgSupplier);
902900
903901 /**
904902 * Logs a message (only to be constructed if the logging level is the {@link Level#ERROR ERROR} level) including the
905 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
906 *
907 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
903 * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
904 *
905 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
908906 * message factory.
909 * @param throwable the {@code Throwable} to log, including its stack trace.
910 * @since 2.4
911 */
912 void error(Supplier<?> messageSupplier, Throwable throwable);
907 * @param t the exception to log, including its stack trace.
908 * @since 2.4
909 */
910 void error(Supplier<?> msgSupplier, Throwable t);
913911
914912 /**
915913 * Logs a message with parameters at error level.
12031201 * Logs a message with the specific Marker at the {@link Level#FATAL FATAL} level.
12041202 *
12051203 * @param marker the marker data specific to this log statement
1206 * @param message the message string to be logged
1207 */
1208 void fatal(Marker marker, Message message);
1204 * @param msg the message string to be logged
1205 */
1206 void fatal(Marker marker, Message msg);
12091207
12101208 /**
12111209 * Logs a message with the specific Marker at the {@link Level#FATAL FATAL} level.
12121210 *
12131211 * @param marker the marker data specific to this log statement
1214 * @param message the message string to be logged
1215 * @param throwable A Throwable or null.
1216 */
1217 void fatal(Marker marker, Message message, Throwable throwable);
1212 * @param msg the message string to be logged
1213 * @param t A Throwable or null.
1214 */
1215 void fatal(Marker marker, Message msg, Throwable t);
12181216
12191217 /**
12201218 * Logs a message which is only to be constructed if the logging level is the {@link Level#FATAL FATAL} level with
12221220 * {@code Message}.
12231221 *
12241222 * @param marker the marker data specific to this log statement
1225 * @param messageSupplier A function, which when called, produces the desired log message.
1226 * @since 2.4
1227 */
1228 void fatal(Marker marker, MessageSupplier messageSupplier);
1223 * @param msgSupplier A function, which when called, produces the desired log message.
1224 * @since 2.4
1225 */
1226 void fatal(Marker marker, MessageSupplier msgSupplier);
12291227
12301228 /**
12311229 * Logs a message (only to be constructed if the logging level is the {@link Level#FATAL FATAL} level) with the
1232 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The
1230 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter. The
12331231 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
12341232 *
12351233 * @param marker the marker data specific to this log statement
1236 * @param messageSupplier A function, which when called, produces the desired log message.
1237 * @param throwable A Throwable or null.
1238 * @since 2.4
1239 */
1240 void fatal(Marker marker, MessageSupplier messageSupplier, Throwable throwable);
1234 * @param msgSupplier A function, which when called, produces the desired log message.
1235 * @param t A Throwable or null.
1236 * @since 2.4
1237 */
1238 void fatal(Marker marker, MessageSupplier msgSupplier, Throwable t);
12411239
12421240 /**
12431241 * Logs a message CharSequence with the {@link Level#FATAL FATAL} level.
12491247
12501248 /**
12511249 * Logs a CharSequence at the {@link Level#FATAL FATAL} level including the stack trace of the {@link Throwable}
1252 * <code>throwable</code> passed as parameter.
1250 * <code>t</code> passed as parameter.
12531251 *
12541252 * @param marker The marker data specific to this log statement.
12551253 * @param message the message CharSequence to log.
1256 * @param throwable the {@code Throwable} to log, including its stack trace.
1257 */
1258 void fatal(Marker marker, CharSequence message, Throwable throwable);
1254 * @param t the exception to log, including its stack trace.
1255 */
1256 void fatal(Marker marker, CharSequence message, Throwable t);
12591257
12601258 /**
12611259 * Logs a message object with the {@link Level#FATAL FATAL} level.
12671265
12681266 /**
12691267 * Logs a message at the {@link Level#FATAL FATAL} level including the stack trace of the {@link Throwable}
1270 * <code>throwable</code> passed as parameter.
1268 * <code>t</code> passed as parameter.
12711269 *
12721270 * @param marker The marker data specific to this log statement.
12731271 * @param message the message object to log.
1274 * @param throwable the {@code Throwable} to log, including its stack trace.
1275 */
1276 void fatal(Marker marker, Object message, Throwable throwable);
1272 * @param t the exception to log, including its stack trace.
1273 */
1274 void fatal(Marker marker, Object message, Throwable t);
12771275
12781276 /**
12791277 * Logs a message object with the {@link Level#FATAL FATAL} level.
13061304
13071305 /**
13081306 * Logs a message at the {@link Level#FATAL FATAL} level including the stack trace of the {@link Throwable}
1309 * <code>throwable</code> passed as parameter.
1307 * <code>t</code> passed as parameter.
13101308 *
13111309 * @param marker The marker data specific to this log statement.
13121310 * @param message the message object to log.
1313 * @param throwable the {@code Throwable} to log, including its stack trace.
1314 */
1315 void fatal(Marker marker, String message, Throwable throwable);
1311 * @param t the exception to log, including its stack trace.
1312 */
1313 void fatal(Marker marker, String message, Throwable t);
13161314
13171315 /**
13181316 * Logs a message which is only to be constructed if the logging level is the {@link Level#FATAL FATAL} level with
13191317 * the specified Marker.
13201318 *
13211319 * @param marker the marker data specific to this log statement
1322 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
1320 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
13231321 * message factory.
13241322 * @since 2.4
13251323 */
1326 void fatal(Marker marker, Supplier<?> messageSupplier);
1324 void fatal(Marker marker, Supplier<?> msgSupplier);
13271325
13281326 /**
13291327 * Logs a message (only to be constructed if the logging level is the {@link Level#FATAL FATAL} level) with the
1330 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
1331 *
1332 * @param marker the marker data specific to this log statement
1333 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
1328 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
1329 *
1330 * @param marker the marker data specific to this log statement
1331 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
13341332 * message factory.
1335 * @param throwable A Throwable or null.
1336 * @since 2.4
1337 */
1338 void fatal(Marker marker, Supplier<?> messageSupplier, Throwable throwable);
1333 * @param t A Throwable or null.
1334 * @since 2.4
1335 */
1336 void fatal(Marker marker, Supplier<?> msgSupplier, Throwable t);
13391337
13401338 /**
13411339 * Logs a message with the specific Marker at the {@link Level#FATAL FATAL} level.
13421340 *
1343 * @param message the message string to be logged
1344 */
1345 void fatal(Message message);
1341 * @param msg the message string to be logged
1342 */
1343 void fatal(Message msg);
13461344
13471345 /**
13481346 * Logs a message with the specific Marker at the {@link Level#FATAL FATAL} level.
13491347 *
1350 * @param message the message string to be logged
1351 * @param throwable A Throwable or null.
1352 */
1353 void fatal(Message message, Throwable throwable);
1348 * @param msg the message string to be logged
1349 * @param t A Throwable or null.
1350 */
1351 void fatal(Message msg, Throwable t);
13541352
13551353 /**
13561354 * Logs a message which is only to be constructed if the logging level is the {@link Level#FATAL FATAL} level. The
13571355 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
13581356 *
1359 * @param messageSupplier A function, which when called, produces the desired log message.
1360 * @since 2.4
1361 */
1362 void fatal(MessageSupplier messageSupplier);
1357 * @param msgSupplier A function, which when called, produces the desired log message.
1358 * @since 2.4
1359 */
1360 void fatal(MessageSupplier msgSupplier);
13631361
13641362 /**
13651363 * Logs a message (only to be constructed if the logging level is the {@link Level#FATAL FATAL} level) including the
1366 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier} may or may
1364 * stack trace of the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier} may or may
13671365 * not use the {@link MessageFactory} to construct the {@code Message}.
13681366 *
1369 * @param messageSupplier A function, which when called, produces the desired log message.
1370 * @param throwable the {@code Throwable} to log, including its stack trace.
1371 * @since 2.4
1372 */
1373 void fatal(MessageSupplier messageSupplier, Throwable throwable);
1367 * @param msgSupplier A function, which when called, produces the desired log message.
1368 * @param t the exception to log, including its stack trace.
1369 * @since 2.4
1370 */
1371 void fatal(MessageSupplier msgSupplier, Throwable t);
13741372
13751373 /**
13761374 * Logs a message CharSequence with the {@link Level#FATAL FATAL} level.
13811379
13821380 /**
13831381 * Logs a CharSequence at the {@link Level#FATAL FATAL} level including the stack trace of the {@link Throwable}
1384 * <code>throwable</code> passed as parameter.
1382 * <code>t</code> passed as parameter.
13851383 *
13861384 * @param message the message CharSequence to log.
1387 * @param throwable the {@code Throwable} to log, including its stack trace.
1388 */
1389 void fatal(CharSequence message, Throwable throwable);
1385 * @param t the exception to log, including its stack trace.
1386 */
1387 void fatal(CharSequence message, Throwable t);
13901388
13911389 /**
13921390 * Logs a message object with the {@link Level#FATAL FATAL} level.
13971395
13981396 /**
13991397 * Logs a message at the {@link Level#FATAL FATAL} level including the stack trace of the {@link Throwable}
1400 * <code>throwable</code> passed as parameter.
1398 * <code>t</code> passed as parameter.
14011399 *
14021400 * @param message the message object to log.
1403 * @param throwable the {@code Throwable} to log, including its stack trace.
1404 */
1405 void fatal(Object message, Throwable throwable);
1401 * @param t the exception to log, including its stack trace.
1402 */
1403 void fatal(Object message, Throwable t);
14061404
14071405 /**
14081406 * Logs a message object with the {@link Level#FATAL FATAL} level.
14321430
14331431 /**
14341432 * Logs a message at the {@link Level#FATAL FATAL} level including the stack trace of the {@link Throwable}
1435 * <code>throwable</code> passed as parameter.
1433 * <code>t</code> passed as parameter.
14361434 *
14371435 * @param message the message object to log.
1438 * @param throwable the {@code Throwable} to log, including its stack trace.
1439 */
1440 void fatal(String message, Throwable throwable);
1436 * @param t the exception to log, including its stack trace.
1437 */
1438 void fatal(String message, Throwable t);
14411439
14421440 /**
14431441 * Logs a message which is only to be constructed if the logging level is the {@link Level#FATAL FATAL} level.
14441442 *
1445 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
1443 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
14461444 * message factory.
14471445 * @since 2.4
14481446 */
1449 void fatal(Supplier<?> messageSupplier);
1447 void fatal(Supplier<?> msgSupplier);
14501448
14511449 /**
14521450 * Logs a message (only to be constructed if the logging level is the {@link Level#FATAL FATAL} level) including the
1453 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
1454 *
1455 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
1451 * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
1452 *
1453 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
14561454 * message factory.
1457 * @param throwable the {@code Throwable} to log, including its stack trace.
1458 * @since 2.4
1459 */
1460 void fatal(Supplier<?> messageSupplier, Throwable throwable);
1455 * @param t the exception to log, including its stack trace.
1456 * @since 2.4
1457 */
1458 void fatal(Supplier<?> msgSupplier, Throwable t);
14611459
14621460 /**
14631461 * Logs a message with parameters at fatal level.
17561754 * Logs a message with the specific Marker at the {@link Level#INFO INFO} level.
17571755 *
17581756 * @param marker the marker data specific to this log statement
1759 * @param message the message string to be logged
1760 */
1761 void info(Marker marker, Message message);
1757 * @param msg the message string to be logged
1758 */
1759 void info(Marker marker, Message msg);
17621760
17631761 /**
17641762 * Logs a message with the specific Marker at the {@link Level#INFO INFO} level.
17651763 *
17661764 * @param marker the marker data specific to this log statement
1767 * @param message the message string to be logged
1768 * @param throwable A Throwable or null.
1769 */
1770 void info(Marker marker, Message message, Throwable throwable);
1765 * @param msg the message string to be logged
1766 * @param t A Throwable or null.
1767 */
1768 void info(Marker marker, Message msg, Throwable t);
17711769
17721770 /**
17731771 * Logs a message which is only to be constructed if the logging level is the {@link Level#INFO INFO} level with the
17751773 * {@code Message}.
17761774 *
17771775 * @param marker the marker data specific to this log statement
1778 * @param messageSupplier A function, which when called, produces the desired log message.
1779 * @since 2.4
1780 */
1781 void info(Marker marker, MessageSupplier messageSupplier);
1776 * @param msgSupplier A function, which when called, produces the desired log message.
1777 * @since 2.4
1778 */
1779 void info(Marker marker, MessageSupplier msgSupplier);
17821780
17831781 /**
17841782 * Logs a message (only to be constructed if the logging level is the {@link Level#INFO INFO} level) with the
1785 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The
1783 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter. The
17861784 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
17871785 *
17881786 * @param marker the marker data specific to this log statement
1789 * @param messageSupplier A function, which when called, produces the desired log message.
1790 * @param throwable A Throwable or null.
1791 * @since 2.4
1792 */
1793 void info(Marker marker, MessageSupplier messageSupplier, Throwable throwable);
1787 * @param msgSupplier A function, which when called, produces the desired log message.
1788 * @param t A Throwable or null.
1789 * @since 2.4
1790 */
1791 void info(Marker marker, MessageSupplier msgSupplier, Throwable t);
17941792
17951793 /**
17961794 * Logs a message CharSequence with the {@link Level#INFO INFO} level.
18021800
18031801 /**
18041802 * Logs a CharSequence at the {@link Level#INFO INFO} level including the stack trace of the {@link Throwable}
1805 * <code>throwable</code> passed as parameter.
1803 * <code>t</code> passed as parameter.
18061804 *
18071805 * @param marker the marker data specific to this log statement
18081806 * @param message the message CharSequence to log.
1809 * @param throwable the {@code Throwable} to log, including its stack trace.
1810 */
1811 void info(Marker marker, CharSequence message, Throwable throwable);
1807 * @param t the exception to log, including its stack trace.
1808 */
1809 void info(Marker marker, CharSequence message, Throwable t);
18121810
18131811 /**
18141812 * Logs a message object with the {@link Level#INFO INFO} level.
18201818
18211819 /**
18221820 * Logs a message at the {@link Level#INFO INFO} level including the stack trace of the {@link Throwable}
1823 * <code>throwable</code> passed as parameter.
1821 * <code>t</code> passed as parameter.
18241822 *
18251823 * @param marker the marker data specific to this log statement
18261824 * @param message the message object to log.
1827 * @param throwable the {@code Throwable} to log, including its stack trace.
1828 */
1829 void info(Marker marker, Object message, Throwable throwable);
1825 * @param t the exception to log, including its stack trace.
1826 */
1827 void info(Marker marker, Object message, Throwable t);
18301828
18311829 /**
18321830 * Logs a message object with the {@link Level#INFO INFO} level.
18591857
18601858 /**
18611859 * Logs a message at the {@link Level#INFO INFO} level including the stack trace of the {@link Throwable}
1862 * <code>throwable</code> passed as parameter.
1860 * <code>t</code> passed as parameter.
18631861 *
18641862 * @param marker the marker data specific to this log statement
18651863 * @param message the message object to log.
1866 * @param throwable the {@code Throwable} to log, including its stack trace.
1867 */
1868 void info(Marker marker, String message, Throwable throwable);
1864 * @param t the exception to log, including its stack trace.
1865 */
1866 void info(Marker marker, String message, Throwable t);
18691867
18701868 /**
18711869 * Logs a message which is only to be constructed if the logging level is the {@link Level#INFO INFO} level with the
18721870 * specified Marker.
18731871 *
18741872 * @param marker the marker data specific to this log statement
1875 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
1873 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
18761874 * message factory.
18771875 * @since 2.4
18781876 */
1879 void info(Marker marker, Supplier<?> messageSupplier);
1877 void info(Marker marker, Supplier<?> msgSupplier);
18801878
18811879 /**
18821880 * Logs a message (only to be constructed if the logging level is the {@link Level#INFO INFO} level) with the
1883 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
1884 *
1885 * @param marker the marker data specific to this log statement
1886 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
1881 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
1882 *
1883 * @param marker the marker data specific to this log statement
1884 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
18871885 * message factory.
1888 * @param throwable A Throwable or null.
1889 * @since 2.4
1890 */
1891 void info(Marker marker, Supplier<?> messageSupplier, Throwable throwable);
1886 * @param t A Throwable or null.
1887 * @since 2.4
1888 */
1889 void info(Marker marker, Supplier<?> msgSupplier, Throwable t);
18921890
18931891 /**
18941892 * Logs a message with the specific Marker at the {@link Level#INFO INFO} level.
18951893 *
1896 * @param message the message string to be logged
1897 */
1898 void info(Message message);
1894 * @param msg the message string to be logged
1895 */
1896 void info(Message msg);
18991897
19001898 /**
19011899 * Logs a message with the specific Marker at the {@link Level#INFO INFO} level.
19021900 *
1903 * @param message the message string to be logged
1904 * @param throwable A Throwable or null.
1905 */
1906 void info(Message message, Throwable throwable);
1901 * @param msg the message string to be logged
1902 * @param t A Throwable or null.
1903 */
1904 void info(Message msg, Throwable t);
19071905
19081906 /**
19091907 * Logs a message which is only to be constructed if the logging level is the {@link Level#INFO INFO} level. The
19101908 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
19111909 *
1912 * @param messageSupplier A function, which when called, produces the desired log message.
1913 * @since 2.4
1914 */
1915 void info(MessageSupplier messageSupplier);
1910 * @param msgSupplier A function, which when called, produces the desired log message.
1911 * @since 2.4
1912 */
1913 void info(MessageSupplier msgSupplier);
19161914
19171915 /**
19181916 * Logs a message (only to be constructed if the logging level is the {@link Level#INFO INFO} level) including the
1919 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier} may or may
1917 * stack trace of the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier} may or may
19201918 * not use the {@link MessageFactory} to construct the {@code Message}.
19211919 *
1922 * @param messageSupplier A function, which when called, produces the desired log message.
1923 * @param throwable the {@code Throwable} to log, including its stack trace.
1924 * @since 2.4
1925 */
1926 void info(MessageSupplier messageSupplier, Throwable throwable);
1920 * @param msgSupplier A function, which when called, produces the desired log message.
1921 * @param t the exception to log, including its stack trace.
1922 * @since 2.4
1923 */
1924 void info(MessageSupplier msgSupplier, Throwable t);
19271925
19281926 /**
19291927 * Logs a message CharSequence with the {@link Level#INFO INFO} level.
19341932
19351933 /**
19361934 * Logs a CharSequence at the {@link Level#INFO INFO} level including the stack trace of the {@link Throwable}
1937 * <code>throwable</code> passed as parameter.
1935 * <code>t</code> passed as parameter.
19381936 *
19391937 * @param message the message CharSequence to log.
1940 * @param throwable the {@code Throwable} to log, including its stack trace.
1941 */
1942 void info(CharSequence message, Throwable throwable);
1938 * @param t the exception to log, including its stack trace.
1939 */
1940 void info(CharSequence message, Throwable t);
19431941
19441942 /**
19451943 * Logs a message object with the {@link Level#INFO INFO} level.
19501948
19511949 /**
19521950 * Logs a message at the {@link Level#INFO INFO} level including the stack trace of the {@link Throwable}
1953 * <code>throwable</code> passed as parameter.
1951 * <code>t</code> passed as parameter.
19541952 *
19551953 * @param message the message object to log.
1956 * @param throwable the {@code Throwable} to log, including its stack trace.
1957 */
1958 void info(Object message, Throwable throwable);
1954 * @param t the exception to log, including its stack trace.
1955 */
1956 void info(Object message, Throwable t);
19591957
19601958 /**
19611959 * Logs a message object with the {@link Level#INFO INFO} level.
19851983
19861984 /**
19871985 * Logs a message at the {@link Level#INFO INFO} level including the stack trace of the {@link Throwable}
1988 * <code>throwable</code> passed as parameter.
1986 * <code>t</code> passed as parameter.
19891987 *
19901988 * @param message the message object to log.
1991 * @param throwable the {@code Throwable} to log, including its stack trace.
1992 */
1993 void info(String message, Throwable throwable);
1989 * @param t the exception to log, including its stack trace.
1990 */
1991 void info(String message, Throwable t);
19941992
19951993 /**
19961994 * Logs a message which is only to be constructed if the logging level is the {@link Level#INFO INFO} level.
19971995 *
1998 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
1996 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
19991997 * message factory.
20001998 * @since 2.4
20011999 */
2002 void info(Supplier<?> messageSupplier);
2000 void info(Supplier<?> msgSupplier);
20032001
20042002 /**
20052003 * Logs a message (only to be constructed if the logging level is the {@link Level#INFO INFO} level) including the
2006 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
2007 *
2008 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
2004 * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
2005 *
2006 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
20092007 * message factory.
2010 * @param throwable the {@code Throwable} to log, including its stack trace.
2011 * @since 2.4
2012 */
2013 void info(Supplier<?> messageSupplier, Throwable throwable);
2008 * @param t the exception to log, including its stack trace.
2009 * @since 2.4
2010 */
2011 void info(Supplier<?> msgSupplier, Throwable t);
20142012
20152013 /**
20162014 * Logs a message with parameters at info level.
23992397 *
24002398 * @param level the logging level
24012399 * @param marker the marker data specific to this log statement
2402 * @param message the message string to be logged
2403 */
2404 void log(Level level, Marker marker, Message message);
2400 * @param msg the message string to be logged
2401 */
2402 void log(Level level, Marker marker, Message msg);
24052403
24062404 /**
24072405 * Logs a message with the specific Marker at the given level.
24082406 *
24092407 * @param level the logging level
24102408 * @param marker the marker data specific to this log statement
2411 * @param message the message string to be logged
2412 * @param throwable A Throwable or null.
2413 */
2414 void log(Level level, Marker marker, Message message, Throwable throwable);
2409 * @param msg the message string to be logged
2410 * @param t A Throwable or null.
2411 */
2412 void log(Level level, Marker marker, Message msg, Throwable t);
24152413
24162414 /**
24172415 * Logs a message which is only to be constructed if the logging level is the specified level with the specified
24202418 *
24212419 * @param level the logging level
24222420 * @param marker the marker data specific to this log statement
2423 * @param messageSupplier A function, which when called, produces the desired log message.
2424 * @since 2.4
2425 */
2426 void log(Level level, Marker marker, MessageSupplier messageSupplier);
2421 * @param msgSupplier A function, which when called, produces the desired log message.
2422 * @since 2.4
2423 */
2424 void log(Level level, Marker marker, MessageSupplier msgSupplier);
24272425
24282426 /**
24292427 * Logs a message (only to be constructed if the logging level is the specified level) with the specified Marker and
2430 * including the stack log of the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier}
2428 * including the stack log of the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier}
24312429 * may or may not use the {@link MessageFactory} to construct the {@code Message}.
24322430 *
24332431 * @param level the logging level
24342432 * @param marker the marker data specific to this log statement
2435 * @param messageSupplier A function, which when called, produces the desired log message.
2436 * @param throwable A Throwable or null.
2437 * @since 2.4
2438 */
2439 void log(Level level, Marker marker, MessageSupplier messageSupplier, Throwable throwable);
2433 * @param msgSupplier A function, which when called, produces the desired log message.
2434 * @param t A Throwable or null.
2435 * @since 2.4
2436 */
2437 void log(Level level, Marker marker, MessageSupplier msgSupplier, Throwable t);
24402438
24412439 /**
24422440 * Logs a message CharSequence with the given level.
24482446 void log(Level level, Marker marker, CharSequence message);
24492447
24502448 /**
2451 * Logs a CharSequence at the given level including the stack trace of the {@link Throwable} <code>throwable</code> passed as
2449 * Logs a CharSequence at the given level including the stack trace of the {@link Throwable} <code>t</code> passed as
24522450 * parameter.
24532451 *
24542452 * @param level the logging level
24552453 * @param marker the marker data specific to this log statement
24562454 * @param message the message CharSequence to log.
2457 * @param throwable the {@code Throwable} to log, including its stack trace.
2458 */
2459 void log(Level level, Marker marker, CharSequence message, Throwable throwable);
2455 * @param t the exception to log, including its stack trace.
2456 */
2457 void log(Level level, Marker marker, CharSequence message, Throwable t);
24602458
24612459 /**
24622460 * Logs a message object with the given level.
24682466 void log(Level level, Marker marker, Object message);
24692467
24702468 /**
2471 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>throwable</code> passed as
2469 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>t</code> passed as
24722470 * parameter.
24732471 *
24742472 * @param level the logging level
24752473 * @param marker the marker data specific to this log statement
24762474 * @param message the message to log.
2477 * @param throwable the {@code Throwable} to log, including its stack trace.
2478 */
2479 void log(Level level, Marker marker, Object message, Throwable throwable);
2475 * @param t the exception to log, including its stack trace.
2476 */
2477 void log(Level level, Marker marker, Object message, Throwable t);
24802478
24812479 /**
24822480 * Logs a message object with the given level.
25102508 void log(Level level, Marker marker, String message, Supplier<?>... paramSuppliers);
25112509
25122510 /**
2513 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>throwable</code> passed as
2511 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>t</code> passed as
25142512 * parameter.
25152513 *
25162514 * @param level the logging level
25172515 * @param marker the marker data specific to this log statement
25182516 * @param message the message to log.
2519 * @param throwable the {@code Throwable} to log, including its stack trace.
2520 */
2521 void log(Level level, Marker marker, String message, Throwable throwable);
2517 * @param t the exception to log, including its stack trace.
2518 */
2519 void log(Level level, Marker marker, String message, Throwable t);
25222520
25232521 /**
25242522 * Logs a message (only to be constructed if the logging level is the specified level) with the specified Marker.
25252523 *
25262524 * @param level the logging level
25272525 * @param marker the marker data specific to this log statement
2528 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
2526 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
25292527 * message factory.
25302528 * @since 2.4
25312529 */
2532 void log(Level level, Marker marker, Supplier<?> messageSupplier);
2530 void log(Level level, Marker marker, Supplier<?> msgSupplier);
25332531
25342532 /**
25352533 * Logs a message (only to be constructed if the logging level is the specified level) with the specified Marker and
2536 * including the stack log of the {@link Throwable} <code>throwable</code> passed as parameter.
2537 *
2538 * @param level the logging level
2539 * @param marker the marker data specific to this log statement
2540 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
2534 * including the stack log of the {@link Throwable} <code>t</code> passed as parameter.
2535 *
2536 * @param level the logging level
2537 * @param marker the marker data specific to this log statement
2538 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
25412539 * message factory.
2542 * @param throwable A Throwable or null.
2543 * @since 2.4
2544 */
2545 void log(Level level, Marker marker, Supplier<?> messageSupplier, Throwable throwable);
2540 * @param t A Throwable or null.
2541 * @since 2.4
2542 */
2543 void log(Level level, Marker marker, Supplier<?> msgSupplier, Throwable t);
25462544
25472545 /**
25482546 * Logs a message with the specific Marker at the given level.
25492547 *
25502548 * @param level the logging level
2551 * @param message the message string to be logged
2552 */
2553 void log(Level level, Message message);
2549 * @param msg the message string to be logged
2550 */
2551 void log(Level level, Message msg);
25542552
25552553 /**
25562554 * Logs a message with the specific Marker at the given level.
25572555 *
25582556 * @param level the logging level
2559 * @param message the message string to be logged
2560 * @param throwable A Throwable or null.
2561 */
2562 void log(Level level, Message message, Throwable throwable);
2557 * @param msg the message string to be logged
2558 * @param t A Throwable or null.
2559 */
2560 void log(Level level, Message msg, Throwable t);
25632561
25642562 /**
25652563 * Logs a message which is only to be constructed if the logging level is the specified level. The
25662564 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
25672565 *
25682566 * @param level the logging level
2569 * @param messageSupplier A function, which when called, produces the desired log message.
2570 * @since 2.4
2571 */
2572 void log(Level level, MessageSupplier messageSupplier);
2567 * @param msgSupplier A function, which when called, produces the desired log message.
2568 * @since 2.4
2569 */
2570 void log(Level level, MessageSupplier msgSupplier);
25732571
25742572 /**
25752573 * Logs a message (only to be constructed if the logging level is the specified level) including the stack log of
2576 * the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier} may or may not use the
2574 * the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier} may or may not use the
25772575 * {@link MessageFactory} to construct the {@code Message}.
25782576 *
25792577 * @param level the logging level
2580 * @param messageSupplier A function, which when called, produces the desired log message.
2581 * @param throwable the {@code Throwable} to log, including its stack log.
2582 * @since 2.4
2583 */
2584 void log(Level level, MessageSupplier messageSupplier, Throwable throwable);
2578 * @param msgSupplier A function, which when called, produces the desired log message.
2579 * @param t the exception to log, including its stack log.
2580 * @since 2.4
2581 */
2582 void log(Level level, MessageSupplier msgSupplier, Throwable t);
25852583
25862584 /**
25872585 * Logs a message CharSequence with the given level.
25922590 void log(Level level, CharSequence message);
25932591
25942592 /**
2595 * Logs a CharSequence at the given level including the stack trace of the {@link Throwable} <code>throwable</code> passed as
2593 * Logs a CharSequence at the given level including the stack trace of the {@link Throwable} <code>t</code> passed as
25962594 * parameter.
25972595 *
25982596 * @param level the logging level
25992597 * @param message the message CharSequence to log.
2600 * @param throwable the {@code Throwable} to log, including its stack trace.
2601 */
2602 void log(Level level, CharSequence message, Throwable throwable);
2598 * @param t the exception to log, including its stack trace.
2599 */
2600 void log(Level level, CharSequence message, Throwable t);
26032601
26042602 /**
26052603 * Logs a message object with the given level.
26102608 void log(Level level, Object message);
26112609
26122610 /**
2613 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>throwable</code> passed as
2611 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>t</code> passed as
26142612 * parameter.
26152613 *
26162614 * @param level the logging level
26172615 * @param message the message to log.
2618 * @param throwable the {@code Throwable} to log, including its stack trace.
2619 */
2620 void log(Level level, Object message, Throwable throwable);
2616 * @param t the exception to log, including its stack trace.
2617 */
2618 void log(Level level, Object message, Throwable t);
26212619
26222620 /**
26232621 * Logs a message object with the given level.
26482646 void log(Level level, String message, Supplier<?>... paramSuppliers);
26492647
26502648 /**
2651 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>throwable</code> passed as
2649 * Logs a message at the given level including the stack trace of the {@link Throwable} <code>t</code> passed as
26522650 * parameter.
26532651 *
26542652 * @param level the logging level
26552653 * @param message the message to log.
2656 * @param throwable the {@code Throwable} to log, including its stack trace.
2657 */
2658 void log(Level level, String message, Throwable throwable);
2654 * @param t the exception to log, including its stack trace.
2655 */
2656 void log(Level level, String message, Throwable t);
26592657
26602658 /**
26612659 * Logs a message which is only to be constructed if the logging level is the specified level.
26622660 *
26632661 * @param level the logging level
2664 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
2662 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
26652663 * message factory.
26662664 * @since 2.4
26672665 */
2668 void log(Level level, Supplier<?> messageSupplier);
2666 void log(Level level, Supplier<?> msgSupplier);
26692667
26702668 /**
26712669 * Logs a message (only to be constructed if the logging level is the specified level) including the stack log of
2672 * the {@link Throwable} <code>throwable</code> passed as parameter.
2673 *
2674 * @param level the logging level
2675 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
2670 * the {@link Throwable} <code>t</code> passed as parameter.
2671 *
2672 * @param level the logging level
2673 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
26762674 * message factory.
2677 * @param throwable the {@code Throwable} to log, including its stack log.
2678 * @since 2.4
2679 */
2680 void log(Level level, Supplier<?> messageSupplier, Throwable throwable);
2675 * @param t the exception to log, including its stack log.
2676 * @since 2.4
2677 */
2678 void log(Level level, Supplier<?> msgSupplier, Throwable t);
26812679
26822680 /**
26832681 * Logs a message with parameters at the specified level.
29852983 void printf(Level level, String format, Object... params);
29862984
29872985 /**
2988 * Logs a {@link Throwable} to be thrown. This may be coded as:
2986 * Logs an exception or error to be thrown. This may be coded as:
29892987 *
29902988 * <pre>
29912989 * throw logger.throwing(Level.DEBUG, myException);
29932991 *
29942992 * @param <T> the Throwable type.
29952993 * @param level The logging Level.
2996 * @param throwable The Throwable.
2994 * @param t The Throwable.
29972995 * @return the Throwable.
29982996 */
2999 <T extends Throwable> T throwing(Level level, T throwable);
3000
3001 /**
3002 * Logs a {@link Throwable} to be thrown at the {@link Level#ERROR ERROR} level.
3003 * This may be coded as:
2997 <T extends Throwable> T throwing(Level level, T t);
2998
2999 /**
3000 * Logs an exception or error to be thrown. This may be coded as:
30043001 *
30053002 * <pre>
30063003 * throw logger.throwing(myException);
30073004 * </pre>
30083005 *
30093006 * @param <T> the Throwable type.
3010 * @param throwable The Throwable.
3007 * @param t The Throwable.
30113008 * @return the Throwable.
30123009 */
3013 <T extends Throwable> T throwing(T throwable);
3010 <T extends Throwable> T throwing(T t);
30143011
30153012 /**
30163013 * Logs a message with the specific Marker at the {@link Level#TRACE TRACE} level.
30173014 *
30183015 * @param marker the marker data specific to this log statement
3019 * @param message the message string to be logged
3020 */
3021 void trace(Marker marker, Message message);
3016 * @param msg the message string to be logged
3017 */
3018 void trace(Marker marker, Message msg);
30223019
30233020 /**
30243021 * Logs a message with the specific Marker at the {@link Level#TRACE TRACE} level.
30253022 *
30263023 * @param marker the marker data specific to this log statement
3027 * @param message the message string to be logged
3028 * @param throwable A Throwable or null.
3029 */
3030 void trace(Marker marker, Message message, Throwable throwable);
3024 * @param msg the message string to be logged
3025 * @param t A Throwable or null.
3026 */
3027 void trace(Marker marker, Message msg, Throwable t);
30313028
30323029 /**
30333030 * Logs a message which is only to be constructed if the logging level is the {@link Level#TRACE TRACE} level with
30353032 * {@code Message}.
30363033 *
30373034 * @param marker the marker data specific to this log statement
3038 * @param messageSupplier A function, which when called, produces the desired log message.
3039 * @since 2.4
3040 */
3041 void trace(Marker marker, MessageSupplier messageSupplier);
3035 * @param msgSupplier A function, which when called, produces the desired log message.
3036 * @since 2.4
3037 */
3038 void trace(Marker marker, MessageSupplier msgSupplier);
30423039
30433040 /**
30443041 * Logs a message (only to be constructed if the logging level is the {@link Level#TRACE TRACE} level) with the
3045 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The
3042 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter. The
30463043 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
30473044 *
30483045 * @param marker the marker data specific to this log statement
3049 * @param messageSupplier A function, which when called, produces the desired log message.
3050 * @param throwable A Throwable or null.
3051 * @since 2.4
3052 */
3053 void trace(Marker marker, MessageSupplier messageSupplier, Throwable throwable);
3046 * @param msgSupplier A function, which when called, produces the desired log message.
3047 * @param t A Throwable or null.
3048 * @since 2.4
3049 */
3050 void trace(Marker marker, MessageSupplier msgSupplier, Throwable t);
30543051
30553052 /**
30563053 * Logs a message CharSequence with the {@link Level#TRACE TRACE} level.
30623059
30633060 /**
30643061 * Logs a CharSequence at the {@link Level#TRACE TRACE} level including the stack trace of the {@link Throwable}
3065 * <code>throwable</code> passed as parameter.
3062 * <code>t</code> passed as parameter.
30663063 *
30673064 * @param marker the marker data specific to this log statement
30683065 * @param message the message CharSequence to log.
3069 * @param throwable the {@code Throwable} to log, including its stack trace.
3066 * @param t the exception to log, including its stack trace.
30703067 * @see #debug(String)
30713068 */
3072 void trace(Marker marker, CharSequence message, Throwable throwable);
3069 void trace(Marker marker, CharSequence message, Throwable t);
30733070
30743071 /**
30753072 * Logs a message object with the {@link Level#TRACE TRACE} level.
30813078
30823079 /**
30833080 * Logs a message at the {@link Level#TRACE TRACE} level including the stack trace of the {@link Throwable}
3084 * <code>throwable</code> passed as parameter.
3081 * <code>t</code> passed as parameter.
30853082 *
30863083 * @param marker the marker data specific to this log statement
30873084 * @param message the message object to log.
3088 * @param throwable the {@code Throwable} to log, including its stack trace.
3085 * @param t the exception to log, including its stack trace.
30893086 * @see #debug(String)
30903087 */
3091 void trace(Marker marker, Object message, Throwable throwable);
3088 void trace(Marker marker, Object message, Throwable t);
30923089
30933090 /**
30943091 * Logs a message object with the {@link Level#TRACE TRACE} level.
31213118
31223119 /**
31233120 * Logs a message at the {@link Level#TRACE TRACE} level including the stack trace of the {@link Throwable}
3124 * <code>throwable</code> passed as parameter.
3121 * <code>t</code> passed as parameter.
31253122 *
31263123 * @param marker the marker data specific to this log statement
31273124 * @param message the message object to log.
3128 * @param throwable the {@code Throwable} to log, including its stack trace.
3125 * @param t the exception to log, including its stack trace.
31293126 * @see #debug(String)
31303127 */
3131 void trace(Marker marker, String message, Throwable throwable);
3128 void trace(Marker marker, String message, Throwable t);
31323129
31333130 /**
31343131 * Logs a message which is only to be constructed if the logging level is the {@link Level#TRACE TRACE} level with
31353132 * the specified Marker.
31363133 *
31373134 * @param marker the marker data specific to this log statement
3138 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3135 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
31393136 * message factory.
31403137 * @since 2.4
31413138 */
3142 void trace(Marker marker, Supplier<?> messageSupplier);
3139 void trace(Marker marker, Supplier<?> msgSupplier);
31433140
31443141 /**
31453142 * Logs a message (only to be constructed if the logging level is the {@link Level#TRACE TRACE} level) with the
3146 * specified Marker and including the stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
3147 *
3148 * @param marker the marker data specific to this log statement
3149 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3143 * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
3144 *
3145 * @param marker the marker data specific to this log statement
3146 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
31503147 * message factory.
3151 * @param throwable A Throwable or null.
3152 * @since 2.4
3153 */
3154 void trace(Marker marker, Supplier<?> messageSupplier, Throwable throwable);
3148 * @param t A Throwable or null.
3149 * @since 2.4
3150 */
3151 void trace(Marker marker, Supplier<?> msgSupplier, Throwable t);
31553152
31563153 /**
31573154 * Logs a message with the specific Marker at the {@link Level#TRACE TRACE} level.
31583155 *
3159 * @param message the message string to be logged
3160 */
3161 void trace(Message message);
3156 * @param msg the message string to be logged
3157 */
3158 void trace(Message msg);
31623159
31633160 /**
31643161 * Logs a message with the specific Marker at the {@link Level#TRACE TRACE} level.
31653162 *
3166 * @param message the message string to be logged
3167 * @param throwable A Throwable or null.
3168 */
3169 void trace(Message message, Throwable throwable);
3163 * @param msg the message string to be logged
3164 * @param t A Throwable or null.
3165 */
3166 void trace(Message msg, Throwable t);
31703167
31713168 /**
31723169 * Logs a message which is only to be constructed if the logging level is the {@link Level#TRACE TRACE} level. The
31733170 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
31743171 *
3175 * @param messageSupplier A function, which when called, produces the desired log message.
3176 * @since 2.4
3177 */
3178 void trace(MessageSupplier messageSupplier);
3172 * @param msgSupplier A function, which when called, produces the desired log message.
3173 * @since 2.4
3174 */
3175 void trace(MessageSupplier msgSupplier);
31793176
31803177 /**
31813178 * Logs a message (only to be constructed if the logging level is the {@link Level#TRACE TRACE} level) including the
3182 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier} may or may
3179 * stack trace of the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier} may or may
31833180 * not use the {@link MessageFactory} to construct the {@code Message}.
31843181 *
3185 * @param messageSupplier A function, which when called, produces the desired log message.
3186 * @param throwable the {@code Throwable} to log, including its stack trace.
3187 * @since 2.4
3188 */
3189 void trace(MessageSupplier messageSupplier, Throwable throwable);
3182 * @param msgSupplier A function, which when called, produces the desired log message.
3183 * @param t the exception to log, including its stack trace.
3184 * @since 2.4
3185 */
3186 void trace(MessageSupplier msgSupplier, Throwable t);
31903187
31913188 /**
31923189 * Logs a message CharSequence with the {@link Level#TRACE TRACE} level.
31973194
31983195 /**
31993196 * Logs a CharSequence at the {@link Level#TRACE TRACE} level including the stack trace of the {@link Throwable}
3200 * <code>throwable</code> passed as parameter.
3197 * <code>t</code> passed as parameter.
32013198 *
32023199 * @param message the message CharSequence to log.
3203 * @param throwable the {@code Throwable} to log, including its stack trace.
3200 * @param t the exception to log, including its stack trace.
32043201 * @see #debug(String)
32053202 */
3206 void trace(CharSequence message, Throwable throwable);
3203 void trace(CharSequence message, Throwable t);
32073204
32083205 /**
32093206 * Logs a message object with the {@link Level#TRACE TRACE} level.
32143211
32153212 /**
32163213 * Logs a message at the {@link Level#TRACE TRACE} level including the stack trace of the {@link Throwable}
3217 * <code>throwable</code> passed as parameter.
3214 * <code>t</code> passed as parameter.
32183215 *
32193216 * @param message the message object to log.
3220 * @param throwable the {@code Throwable} to log, including its stack trace.
3217 * @param t the exception to log, including its stack trace.
32213218 * @see #debug(String)
32223219 */
3223 void trace(Object message, Throwable throwable);
3220 void trace(Object message, Throwable t);
32243221
32253222 /**
32263223 * Logs a message object with the {@link Level#TRACE TRACE} level.
32503247
32513248 /**
32523249 * Logs a message at the {@link Level#TRACE TRACE} level including the stack trace of the {@link Throwable}
3253 * <code>throwable</code> passed as parameter.
3250 * <code>t</code> passed as parameter.
32543251 *
32553252 * @param message the message object to log.
3256 * @param throwable the {@code Throwable} to log, including its stack trace.
3253 * @param t the exception to log, including its stack trace.
32573254 * @see #debug(String)
32583255 */
3259 void trace(String message, Throwable throwable);
3256 void trace(String message, Throwable t);
32603257
32613258 /**
32623259 * Logs a message which is only to be constructed if the logging level is the {@link Level#TRACE TRACE} level.
32633260 *
3264 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3261 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
32653262 * message factory.
32663263 * @since 2.4
32673264 */
3268 void trace(Supplier<?> messageSupplier);
3265 void trace(Supplier<?> msgSupplier);
32693266
32703267 /**
32713268 * Logs a message (only to be constructed if the logging level is the {@link Level#TRACE TRACE} level) including the
3272 * stack trace of the {@link Throwable} <code>throwable</code> passed as parameter.
3273 *
3274 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3269 * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
3270 *
3271 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
32753272 * message factory.
3276 * @param throwable the {@code Throwable} to log, including its stack trace.
3277 * @since 2.4
3278 */
3279 void trace(Supplier<?> messageSupplier, Throwable throwable);
3273 * @param t the exception to log, including its stack trace.
3274 * @since 2.4
3275 */
3276 void trace(Supplier<?> msgSupplier, Throwable t);
32803277
32813278 /**
32823279 * Logs a message with parameters at trace level.
37313728 * Logs a message with the specific Marker at the {@link Level#WARN WARN} level.
37323729 *
37333730 * @param marker the marker data specific to this log statement
3734 * @param message the message string to be logged
3735 */
3736 void warn(Marker marker, Message message);
3731 * @param msg the message string to be logged
3732 */
3733 void warn(Marker marker, Message msg);
37373734
37383735 /**
37393736 * Logs a message with the specific Marker at the {@link Level#WARN WARN} level.
37403737 *
37413738 * @param marker the marker data specific to this log statement
3742 * @param message the message string to be logged
3743 * @param throwable A Throwable or null.
3744 */
3745 void warn(Marker marker, Message message, Throwable throwable);
3739 * @param msg the message string to be logged
3740 * @param t A Throwable or null.
3741 */
3742 void warn(Marker marker, Message msg, Throwable t);
37463743
37473744 /**
37483745 * Logs a message which is only to be constructed if the logging level is the {@link Level#WARN WARN} level with the
37503747 * {@code Message}.
37513748 *
37523749 * @param marker the marker data specific to this log statement
3753 * @param messageSupplier A function, which when called, produces the desired log message.
3754 * @since 2.4
3755 */
3756 void warn(Marker marker, MessageSupplier messageSupplier);
3750 * @param msgSupplier A function, which when called, produces the desired log message.
3751 * @since 2.4
3752 */
3753 void warn(Marker marker, MessageSupplier msgSupplier);
37573754
37583755 /**
37593756 * Logs a message (only to be constructed if the logging level is the {@link Level#WARN WARN} level) with the
3760 * specified Marker and including the stack warn of the {@link Throwable} <code>throwable</code> passed as parameter. The
3757 * specified Marker and including the stack warn of the {@link Throwable} <code>t</code> passed as parameter. The
37613758 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
37623759 *
37633760 * @param marker the marker data specific to this log statement
3764 * @param messageSupplier A function, which when called, produces the desired log message.
3765 * @param throwable A Throwable or null.
3766 * @since 2.4
3767 */
3768 void warn(Marker marker, MessageSupplier messageSupplier, Throwable throwable);
3761 * @param msgSupplier A function, which when called, produces the desired log message.
3762 * @param t A Throwable or null.
3763 * @since 2.4
3764 */
3765 void warn(Marker marker, MessageSupplier msgSupplier, Throwable t);
37693766
37703767 /**
37713768 * Logs a message CharSequence with the {@link Level#WARN WARN} level.
37773774
37783775 /**
37793776 * Logs a CharSequence at the {@link Level#WARN WARN} level including the stack trace of the {@link Throwable}
3780 * <code>throwable</code> passed as parameter.
3777 * <code>t</code> passed as parameter.
37813778 *
37823779 * @param marker the marker data specific to this log statement
37833780 * @param message the message CharSequence to log.
3784 * @param throwable the {@code Throwable} to log, including its stack trace.
3785 */
3786 void warn(Marker marker, CharSequence message, Throwable throwable);
3781 * @param t the exception to log, including its stack trace.
3782 */
3783 void warn(Marker marker, CharSequence message, Throwable t);
37873784
37883785 /**
37893786 * Logs a message object with the {@link Level#WARN WARN} level.
37953792
37963793 /**
37973794 * Logs a message at the {@link Level#WARN WARN} level including the stack trace of the {@link Throwable}
3798 * <code>throwable</code> passed as parameter.
3795 * <code>t</code> passed as parameter.
37993796 *
38003797 * @param marker the marker data specific to this log statement
38013798 * @param message the message object to log.
3802 * @param throwable the {@code Throwable} to log, including its stack trace.
3803 */
3804 void warn(Marker marker, Object message, Throwable throwable);
3799 * @param t the exception to log, including its stack trace.
3800 */
3801 void warn(Marker marker, Object message, Throwable t);
38053802
38063803 /**
38073804 * Logs a message object with the {@link Level#WARN WARN} level.
38343831
38353832 /**
38363833 * Logs a message at the {@link Level#WARN WARN} level including the stack trace of the {@link Throwable}
3837 * <code>throwable</code> passed as parameter.
3834 * <code>t</code> passed as parameter.
38383835 *
38393836 * @param marker the marker data specific to this log statement
38403837 * @param message the message object to log.
3841 * @param throwable the {@code Throwable} to log, including its stack trace.
3842 */
3843 void warn(Marker marker, String message, Throwable throwable);
3838 * @param t the exception to log, including its stack trace.
3839 */
3840 void warn(Marker marker, String message, Throwable t);
38443841
38453842 /**
38463843 * Logs a message which is only to be constructed if the logging level is the {@link Level#WARN WARN} level with the
38473844 * specified Marker.
38483845 *
38493846 * @param marker the marker data specific to this log statement
3850 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3847 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
38513848 * message factory.
38523849 * @since 2.4
38533850 */
3854 void warn(Marker marker, Supplier<?> messageSupplier);
3851 void warn(Marker marker, Supplier<?> msgSupplier);
38553852
38563853 /**
38573854 * Logs a message (only to be constructed if the logging level is the {@link Level#WARN WARN} level) with the
3858 * specified Marker and including the stack warn of the {@link Throwable} <code>throwable</code> passed as parameter.
3859 *
3860 * @param marker the marker data specific to this log statement
3861 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3855 * specified Marker and including the stack warn of the {@link Throwable} <code>t</code> passed as parameter.
3856 *
3857 * @param marker the marker data specific to this log statement
3858 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
38623859 * message factory.
3863 * @param throwable A Throwable or null.
3864 * @since 2.4
3865 */
3866 void warn(Marker marker, Supplier<?> messageSupplier, Throwable throwable);
3860 * @param t A Throwable or null.
3861 * @since 2.4
3862 */
3863 void warn(Marker marker, Supplier<?> msgSupplier, Throwable t);
38673864
38683865 /**
38693866 * Logs a message with the specific Marker at the {@link Level#WARN WARN} level.
38703867 *
3871 * @param message the message string to be logged
3872 */
3873 void warn(Message message);
3868 * @param msg the message string to be logged
3869 */
3870 void warn(Message msg);
38743871
38753872 /**
38763873 * Logs a message with the specific Marker at the {@link Level#WARN WARN} level.
38773874 *
3878 * @param message the message string to be logged
3879 * @param throwable A Throwable or null.
3880 */
3881 void warn(Message message, Throwable throwable);
3875 * @param msg the message string to be logged
3876 * @param t A Throwable or null.
3877 */
3878 void warn(Message msg, Throwable t);
38823879
38833880 /**
38843881 * Logs a message which is only to be constructed if the logging level is the {@link Level#WARN WARN} level. The
38853882 * {@code MessageSupplier} may or may not use the {@link MessageFactory} to construct the {@code Message}.
38863883 *
3887 * @param messageSupplier A function, which when called, produces the desired log message.
3888 * @since 2.4
3889 */
3890 void warn(MessageSupplier messageSupplier);
3884 * @param msgSupplier A function, which when called, produces the desired log message.
3885 * @since 2.4
3886 */
3887 void warn(MessageSupplier msgSupplier);
38913888
38923889 /**
38933890 * Logs a message (only to be constructed if the logging level is the {@link Level#WARN WARN} level) including the
3894 * stack warn of the {@link Throwable} <code>throwable</code> passed as parameter. The {@code MessageSupplier} may or may
3891 * stack warn of the {@link Throwable} <code>t</code> passed as parameter. The {@code MessageSupplier} may or may
38953892 * not use the {@link MessageFactory} to construct the {@code Message}.
38963893 *
3897 * @param messageSupplier A function, which when called, produces the desired log message.
3898 * @param throwable the {@code Throwable} to log, including its stack warn.
3899 * @since 2.4
3900 */
3901 void warn(MessageSupplier messageSupplier, Throwable throwable);
3894 * @param msgSupplier A function, which when called, produces the desired log message.
3895 * @param t the exception to log, including its stack warn.
3896 * @since 2.4
3897 */
3898 void warn(MessageSupplier msgSupplier, Throwable t);
39023899
39033900 /**
39043901 * Logs a message CharSequence with the {@link Level#WARN WARN} level.
39093906
39103907 /**
39113908 * Logs a CharSequence at the {@link Level#WARN WARN} level including the stack trace of the {@link Throwable}
3912 * <code>throwable</code> passed as parameter.
3909 * <code>t</code> passed as parameter.
39133910 *
39143911 * @param message the message CharSequence to log.
3915 * @param throwable the {@code Throwable} to log, including its stack trace.
3916 */
3917 void warn(CharSequence message, Throwable throwable);
3912 * @param t the exception to log, including its stack trace.
3913 */
3914 void warn(CharSequence message, Throwable t);
39183915
39193916 /**
39203917 * Logs a message object with the {@link Level#WARN WARN} level.
39253922
39263923 /**
39273924 * Logs a message at the {@link Level#WARN WARN} level including the stack trace of the {@link Throwable}
3928 * <code>throwable</code> passed as parameter.
3925 * <code>t</code> passed as parameter.
39293926 *
39303927 * @param message the message object to log.
3931 * @param throwable the {@code Throwable} to log, including its stack trace.
3932 */
3933 void warn(Object message, Throwable throwable);
3928 * @param t the exception to log, including its stack trace.
3929 */
3930 void warn(Object message, Throwable t);
39343931
39353932 /**
39363933 * Logs a message object with the {@link Level#WARN WARN} level.
39603957
39613958 /**
39623959 * Logs a message at the {@link Level#WARN WARN} level including the stack trace of the {@link Throwable}
3963 * <code>throwable</code> passed as parameter.
3960 * <code>t</code> passed as parameter.
39643961 *
39653962 * @param message the message object to log.
3966 * @param throwable the {@code Throwable} to log, including its stack trace.
3967 */
3968 void warn(String message, Throwable throwable);
3963 * @param t the exception to log, including its stack trace.
3964 */
3965 void warn(String message, Throwable t);
39693966
39703967 /**
39713968 * Logs a message which is only to be constructed if the logging level is the {@link Level#WARN WARN} level.
39723969 *
3973 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3970 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
39743971 * message factory.
39753972 * @since 2.4
39763973 */
3977 void warn(Supplier<?> messageSupplier);
3974 void warn(Supplier<?> msgSupplier);
39783975
39793976 /**
39803977 * Logs a message (only to be constructed if the logging level is the {@link Level#WARN WARN} level) including the
3981 * stack warn of the {@link Throwable} <code>throwable</code> passed as parameter.
3982 *
3983 * @param messageSupplier A function, which when called, produces the desired log message; the format depends on the
3978 * stack warn of the {@link Throwable} <code>t</code> passed as parameter.
3979 *
3980 * @param msgSupplier A function, which when called, produces the desired log message; the format depends on the
39843981 * message factory.
3985 * @param throwable the {@code Throwable} to log, including its stack warn.
3986 * @since 2.4
3987 */
3988 void warn(Supplier<?> messageSupplier, Throwable throwable);
3982 * @param t the exception to log, including its stack warn.
3983 * @since 2.4
3984 */
3985 void warn(Supplier<?> msgSupplier, Throwable t);
39893986
39903987 /**
39913988 * Logs a message with parameters at warn level.
42534250 void warn(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7,
42544251 Object p8, Object p9);
42554252
4256 /**
4257 * Logs a Message.
4258 * @param level The logging Level to check.
4259 * @param marker A Marker or null.
4260 * @param fqcn The fully qualified class name of the logger entry point, used to determine the caller class and
4261 * method when location information needs to be logged.
4262 * @param location The location of the caller.
4263 * @param message The message format.
4264 * @param throwable the {@code Throwable} to log, including its stack trace.
4265 * @since 2.13.0
4266 */
4267 default void logMessage(Level level, Marker marker, String fqcn, StackTraceElement location, Message message,
4268 Throwable throwable) {
4269
4270 }
4271
4272 /**
4273 * Construct a trace log event.
4274 * @return a LogBuilder.
4275 * @since 2.13.0
4276 */
4277 default LogBuilder atTrace() {
4278 return LogBuilder.NOOP;
4279 }
4280
4281 /**
4282 * Construct a trace log event.
4283 * @return a LogBuilder.
4284 * @since 2.13.0
4285 */
4286 default LogBuilder atDebug() {
4287 return LogBuilder.NOOP;
4288 }
4289
4290 /**
4291 * Construct a trace log event.
4292 * @return a LogBuilder.
4293 * @since 2.13.0
4294 */
4295 default LogBuilder atInfo() {
4296 return LogBuilder.NOOP;
4297 }
4298
4299 /**
4300 * Construct a trace log event.
4301 * @return a LogBuilder.
4302 * @since 2.13.0
4303 */
4304 default LogBuilder atWarn() {
4305 return LogBuilder.NOOP;
4306 }
4307
4308 /**
4309 * Construct a trace log event.
4310 * @return a LogBuilder.
4311 * @since 2.13.0
4312 */
4313 default LogBuilder atError() {
4314 return LogBuilder.NOOP;
4315 }
4316
4317 /**
4318 * Construct a trace log event.
4319 * @return a LogBuilder.
4320 * @since 2.13.0
4321 */
4322 default LogBuilder atFatal() {
4323 return LogBuilder.NOOP;
4324 }
4325
4326 /**
4327 * Construct a log event that will always be logged.
4328 * @return a LogBuilder.
4329 * @since 2.13.0
4330 */
4331 default LogBuilder always() {
4332 return LogBuilder.NOOP;
4333 }
4334
4335 /**
4336 * Construct a log event.
4337 * @return a LogBuilder.
4338 * @since 2.13.0
4339 */
4340 default LogBuilder atLevel(Level level) {
4341 return LogBuilder.NOOP;
4342 }
4343
43444253 }
230230
231231 @Override
232232 public Marker[] getParents() {
233 Marker[] parentsSnapshot = parents;
234 if (parentsSnapshot == null) {
233 if (this.parents == null) {
235234 return null;
236235 }
237 return Arrays.copyOf(parentsSnapshot, parentsSnapshot.length);
236 return Arrays.copyOf(this.parents, this.parents.length);
238237 }
239238
240239 @Override
4141 * The ThreadContext allows applications to store information either in a Map or a Stack.
4242 * <p>
4343 * <b><em>The MDC is managed on a per thread basis</em></b>. To enable automatic inheritance of <i>copies</i> of the MDC
44 * to newly created threads, enable the {@value org.apache.logging.log4j.spi.DefaultThreadContextMap#INHERITABLE_MAP}
45 * Log4j system property.
44 * to newly created threads, enable the {@value DefaultThreadContextMap#INHERITABLE_MAP} Log4j system property.
4645 * </p>
4746 * @see <a href="https://logging.apache.org/log4j/2.x/manual/thread-context.html">Thread Context Manual</a>
4847 */
192191 private static final String DISABLE_STACK = "disableThreadContextStack";
193192 private static final String DISABLE_ALL = "disableThreadContext";
194193
194 private static boolean disableAll;
195 private static boolean useMap;
195196 private static boolean useStack;
196197 private static ThreadContextMap contextMap;
197198 private static ThreadContextStack contextStack;
212213 ThreadContextMapFactory.init();
213214 contextMap = null;
214215 final PropertiesUtil managerProps = PropertiesUtil.getProperties();
215 boolean disableAll = managerProps.getBooleanProperty(DISABLE_ALL);
216 disableAll = managerProps.getBooleanProperty(DISABLE_ALL);
216217 useStack = !(managerProps.getBooleanProperty(DISABLE_STACK) || disableAll);
217 boolean useMap = !(managerProps.getBooleanProperty(DISABLE_MAP) || disableAll);
218 useMap = !(managerProps.getBooleanProperty(DISABLE_MAP) || disableAll);
218219
219220 contextStack = new DefaultThreadContextStack(useStack);
220221 if (!useMap) {
242243 */
243244 public static void put(final String key, final String value) {
244245 contextMap.put(key, value);
245 }
246
247 /**
248 * Puts a context value (the <code>value</code> parameter) as identified with the <code>key</code> parameter into
249 * the current thread's context map if the key does not exist.
250 *
251 * <p>
252 * If the current thread does not have a context map it is created as a side effect.
253 * </p>
254 *
255 * @param key The key name.
256 * @param value The key value.
257 * @since 2.13.0
258 */
259 public static void putIfNull(final String key, final String value) {
260 if(!contextMap.containsKey(key)) {
261 contextMap.put(key, value);
262 }
263246 }
264247
265248 /**
+0
-253
log4j-api/src/main/java/org/apache/logging/log4j/internal/DefaultLogBuilder.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.logging.log4j.internal;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogBuilder;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.Marker;
22 import org.apache.logging.log4j.message.Message;
23 import org.apache.logging.log4j.message.SimpleMessage;
24 import org.apache.logging.log4j.status.StatusLogger;
25 import org.apache.logging.log4j.util.LambdaUtil;
26 import org.apache.logging.log4j.util.StackLocatorUtil;
27 import org.apache.logging.log4j.util.Supplier;
28
29
30 /**
31 * Collects data for a log event and then logs it. This class should be considered private.
32 */
33 public class DefaultLogBuilder implements LogBuilder {
34
35 private static Message EMPTY_MESSAGE = new SimpleMessage("");
36 private static final String FQCN = DefaultLogBuilder.class.getName();
37 private static final Logger LOGGER = StatusLogger.getLogger();
38
39 private final Logger logger;
40 private Level level;
41 private Marker marker;
42 private Throwable throwable;
43 private StackTraceElement location;
44 private volatile boolean inUse;
45 private long threadId;
46
47 public DefaultLogBuilder(Logger logger, Level level) {
48 this.logger = logger;
49 this.level = level;
50 this.threadId = Thread.currentThread().getId();
51 this.inUse = true;
52 }
53
54 public DefaultLogBuilder(Logger logger) {
55 this.logger = logger;
56 this.inUse = false;
57 this.threadId = Thread.currentThread().getId();
58 }
59
60 /**
61 * This method should be considered internal. It is used to reset the LogBuilder for a new log message.
62 * @param level The logging level for this event.
63 * @return This LogBuilder instance.
64 */
65 public LogBuilder reset(Level level) {
66 this.inUse = true;
67 this.level = level;
68 this.marker = null;
69 this.throwable = null;
70 this.location = null;
71 return this;
72 }
73
74 @Override
75 public LogBuilder withMarker(Marker marker) {
76 this.marker = marker;
77 return this;
78 }
79
80 @Override
81 public LogBuilder withThrowable(Throwable throwable) {
82 this.throwable = throwable;
83 return this;
84 }
85
86 @Override
87 public LogBuilder withLocation() {
88 location = StackLocatorUtil.getStackTraceElement(2);
89 return this;
90 }
91
92 @Override
93 public LogBuilder withLocation(StackTraceElement location) {
94 this.location = location;
95 return this;
96 }
97
98 public boolean isInUse() {
99 return inUse;
100 }
101
102 @Override
103 public void log(Message message) {
104 if (isValid()) {
105 logMessage(message);
106 }
107 }
108
109 @Override
110 public void log(CharSequence message) {
111 if (isValid()) {
112 logMessage(logger.getMessageFactory().newMessage(message));
113 }
114 }
115
116 @Override
117 public void log(String message) {
118 if (isValid()) {
119 logMessage(logger.getMessageFactory().newMessage(message));
120 }
121 }
122
123 @Override
124 public void log(String message, Object... params) {
125 if (isValid()) {
126 logMessage(logger.getMessageFactory().newMessage(message, params));
127 }
128 }
129
130 @Override
131 public void log(String message, Supplier<?>... params) {
132 if (isValid()) {
133 logMessage(logger.getMessageFactory().newMessage(message, LambdaUtil.getAll(params)));
134 }
135 }
136
137 @Override
138 public void log(Supplier<Message> messageSupplier) {
139 if (isValid()) {
140 logMessage(messageSupplier.get());
141 }
142 }
143
144 @Override
145 public void log(Object message) {
146 if (isValid()) {
147 logMessage(logger.getMessageFactory().newMessage(message));
148 }
149 }
150
151 @Override
152 public void log(String message, Object p0) {
153 if (isValid()) {
154 logMessage(logger.getMessageFactory().newMessage(message, p0));
155 }
156 }
157
158 @Override
159 public void log(String message, Object p0, Object p1) {
160 if (isValid()) {
161 logMessage(logger.getMessageFactory().newMessage(message, p0, p1));
162 }
163 }
164
165 @Override
166 public void log(String message, Object p0, Object p1, Object p2) {
167 if (isValid()) {
168 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2));
169 }
170 }
171
172 @Override
173 public void log(String message, Object p0, Object p1, Object p2, Object p3) {
174 if (isValid()) {
175 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3));
176 }
177 }
178
179 @Override
180 public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {
181 if (isValid()) {
182 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4));
183 }
184 }
185
186 @Override
187 public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {
188 if (isValid()) {
189 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5));
190 }
191 }
192
193 @Override
194 public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {
195 if (isValid()) {
196 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6));
197 }
198 }
199
200 @Override
201 public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
202 Object p7) {
203 if (isValid()) {
204 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7));
205 }
206 }
207
208 @Override
209 public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
210 Object p7, Object p8) {
211 if (isValid()) {
212 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7, p8));
213 }
214 }
215
216 @Override
217 public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6,
218 Object p7, Object p8, Object p9) {
219 if (isValid()) {
220 logMessage(logger.getMessageFactory().newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));
221 }
222 }
223
224 @Override
225 public void log() {
226 if (isValid()) {
227 logMessage(EMPTY_MESSAGE);
228 }
229 }
230
231 private void logMessage(Message message) {
232 try {
233 logger.logMessage(level, marker, FQCN, location, message, throwable);
234 } finally {
235 inUse = false;
236 }
237 }
238
239 private boolean isValid() {
240 if (!inUse) {
241 LOGGER.warn("Attempt to reuse LogBuilder was ignored. {}",
242 StackLocatorUtil.getCallerClass(2));
243 return false ;
244 }
245 if (this.threadId != Thread.currentThread().getId()) {
246 LOGGER.warn("LogBuilder can only be used on the owning thread. {}",
247 StackLocatorUtil.getCallerClass(2));
248 return false;
249 }
250 return true;
251 }
252 }
+0
-33
log4j-api/src/main/java/org/apache/logging/log4j/internal/LogManagerStatus.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.logging.log4j.internal;
17
18 /**
19 * Keeps track of LogManager initialization status;
20 */
21 public class LogManagerStatus {
22
23 private static boolean initialized = false;
24
25 public static void setInitialized(boolean managerStatus) {
26 initialized = managerStatus;
27 }
28
29 public static boolean isInitialized() {
30 return initialized;
31 }
32 }
+0
-20
log4j-api/src/main/java/org/apache/logging/log4j/internal/package-info.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 /**
17 * This package should be considered private.
18 */
19 package org.apache.logging.log4j.internal;
4444 * @param exitText the text to use for trace exit, like {@code "Exit"}.
4545 */
4646 public DefaultFlowMessageFactory(final String entryText, final String exitText) {
47 super();
4748 this.entryText = entryText;
4849 this.exitText = exitText;
4950 }
3232 * Constructs a message factory with default flow strings.
3333 */
3434 public FormattedMessageFactory() {
35 super();
3536 }
3637
3738 /**
356356 .append(data.getKeyAt(i))
357357 .append("\">");
358358 final int size = sb.length();
359 ParameterFormatter.recursiveDeepToString(data.getValueAt(i), sb);
359 ParameterFormatter.recursiveDeepToString(data.getValueAt(i), sb, null);
360360 StringBuilders.escapeXml(sb, size);
361361 sb.append("</Entry>\n");
362362 }
406406 sb.append(' ');
407407 }
408408 sb.append(data.getKeyAt(i)).append(Chars.EQ).append(Chars.DQUOTE);
409 ParameterFormatter.recursiveDeepToString(data.getValueAt(i), sb);
409 ParameterFormatter.recursiveDeepToString(data.getValueAt(i), sb, null);
410410 sb.append(Chars.DQUOTE);
411411 }
412412 }
413413
414414 protected void asJson(final StringBuilder sb) {
415 MapMessageJsonFormatter.format(sb, data);
415 sb.append('{');
416 for (int i = 0; i < data.size(); i++) {
417 if (i > 0) {
418 sb.append(", ");
419 }
420 sb.append(Chars.DQUOTE);
421 int start = sb.length();
422 sb.append(data.getKeyAt(i));
423 StringBuilders.escapeJson(sb, start);
424 sb.append(Chars.DQUOTE).append(':').append(Chars.DQUOTE);
425 start = sb.length();
426 ParameterFormatter.recursiveDeepToString(data.getValueAt(i), sb, null);
427 StringBuilders.escapeJson(sb, start);
428 sb.append(Chars.DQUOTE);
429 }
430 sb.append('}');
416431 }
417432
418433 protected void asJavaUnquoted(final StringBuilder sb) {
433448 if (quoted) {
434449 sb.append(Chars.DQUOTE);
435450 }
436 ParameterFormatter.recursiveDeepToString(data.getValueAt(i), sb);
451 ParameterFormatter.recursiveDeepToString(data.getValueAt(i), sb, null);
437452 if (quoted) {
438453 sb.append(Chars.DQUOTE);
439454 }
+0
-419
log4j-api/src/main/java/org/apache/logging/log4j/message/MapMessageJsonFormatter.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.logging.log4j.message;
17
18 import org.apache.logging.log4j.util.IndexedStringMap;
19 import org.apache.logging.log4j.util.PropertiesUtil;
20 import org.apache.logging.log4j.util.StringBuilderFormattable;
21 import org.apache.logging.log4j.util.StringBuilders;
22
23 import java.math.BigDecimal;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 /**
30 * The default JSON formatter for {@link MapMessage}s.
31 * <p>
32 * The following types have specific handlers:
33 * <p>
34 * <ul>
35 * <li>{@link Map}
36 * <li>{@link Collection} ({@link List}, {@link Set}, etc.)
37 * <li>{@link Number} ({@link BigDecimal}, {@link Double}, {@link Long}, {@link Byte}, etc.)
38 * <li>{@link Boolean}
39 * <li>{@link StringBuilderFormattable}
40 * <li><tt>char/boolean/byte/short/int/long/float/double/Object</tt> arrays
41 * <li>{@link String}
42 * </ul>
43 * <p>
44 * It supports nesting up to a maximum depth of 8, which is set by
45 * <tt>log4j2.mapMessage.jsonFormatter.maxDepth</tt> property.
46 */
47 enum MapMessageJsonFormatter {;
48
49 public static final int MAX_DEPTH = readMaxDepth();
50
51 private static final char DQUOTE = '"';
52
53 private static final char RBRACE = ']';
54
55 private static final char LBRACE = '[';
56
57 private static final char COMMA = ',';
58
59 private static final char RCURLY = '}';
60
61 private static final char LCURLY = '{';
62
63 private static final char COLON = ':';
64
65 private static int readMaxDepth() {
66 final int maxDepth = PropertiesUtil
67 .getProperties()
68 .getIntegerProperty("log4j2.mapMessage.jsonFormatter.maxDepth", 8);
69 if (maxDepth < 0) {
70 throw new IllegalArgumentException(
71 "was expecting a positive maxDepth, found: " + maxDepth);
72 }
73 return maxDepth;
74 }
75
76 static void format(final StringBuilder sb, final Object object) {
77 format(sb, object, 0);
78 }
79
80 private static void format(
81 final StringBuilder sb,
82 final Object object,
83 final int depth) {
84
85 if (depth >= MAX_DEPTH) {
86 throw new IllegalArgumentException("maxDepth has been exceeded");
87 }
88
89 // null
90 if (object == null) {
91 sb.append("null");
92 }
93
94 // map
95 else if (object instanceof IndexedStringMap) {
96 final IndexedStringMap map = (IndexedStringMap) object;
97 formatIndexedStringMap(sb, map, depth);
98 } else if (object instanceof Map) {
99 @SuppressWarnings("unchecked")
100 final Map<Object, Object> map = (Map<Object, Object>) object;
101 formatMap(sb, map, depth);
102 }
103
104 // list & collection
105 else if (object instanceof List) {
106 @SuppressWarnings("unchecked")
107 final List<Object> list = (List<Object>) object;
108 formatList(sb, list, depth);
109 } else if (object instanceof Collection) {
110 @SuppressWarnings("unchecked")
111 final Collection<Object> collection = (Collection<Object>) object;
112 formatCollection(sb, collection, depth);
113 }
114
115 // number & boolean
116 else if (object instanceof Number) {
117 final Number number = (Number) object;
118 formatNumber(sb, number);
119 } else if (object instanceof Boolean) {
120 final boolean booleanValue = (boolean) object;
121 formatBoolean(sb, booleanValue);
122 }
123
124 // formattable
125 else if (object instanceof StringBuilderFormattable) {
126 final StringBuilderFormattable formattable = (StringBuilderFormattable) object;
127 formatFormattable(sb, formattable);
128 }
129
130 // arrays
131 else if (object instanceof char[]) {
132 final char[] charValues = (char[]) object;
133 formatCharArray(sb, charValues);
134 } else if (object instanceof boolean[]) {
135 final boolean[] booleanValues = (boolean[]) object;
136 formatBooleanArray(sb, booleanValues);
137 } else if (object instanceof byte[]) {
138 final byte[] byteValues = (byte[]) object;
139 formatByteArray(sb, byteValues);
140 } else if (object instanceof short[]) {
141 final short[] shortValues = (short[]) object;
142 formatShortArray(sb, shortValues);
143 } else if (object instanceof int[]) {
144 final int[] intValues = (int[]) object;
145 formatIntArray(sb, intValues);
146 } else if (object instanceof long[]) {
147 final long[] longValues = (long[]) object;
148 formatLongArray(sb, longValues);
149 } else if (object instanceof float[]) {
150 final float[] floatValues = (float[]) object;
151 formatFloatArray(sb, floatValues);
152 } else if (object instanceof double[]) {
153 final double[] doubleValues = (double[]) object;
154 formatDoubleArray(sb, doubleValues);
155 } else if (object instanceof Object[]) {
156 final Object[] objectValues = (Object[]) object;
157 formatObjectArray(sb, objectValues, depth);
158 }
159
160 // string
161 else {
162 formatString(sb, object);
163 }
164
165 }
166
167 private static void formatIndexedStringMap(
168 final StringBuilder sb,
169 final IndexedStringMap map,
170 final int depth) {
171 sb.append(LCURLY);
172 final int nextDepth = depth + 1;
173 for (int entryIndex = 0; entryIndex < map.size(); entryIndex++) {
174 final String key = map.getKeyAt(entryIndex);
175 final Object value = map.getValueAt(entryIndex);
176 if (entryIndex > 0) {
177 sb.append(COMMA);
178 }
179 sb.append(DQUOTE);
180 final int keyStartIndex = sb.length();
181 sb.append(key);
182 StringBuilders.escapeJson(sb, keyStartIndex);
183 sb.append(DQUOTE).append(COLON);
184 format(sb, value, nextDepth);
185 }
186 sb.append(RCURLY);
187 }
188
189 private static void formatMap(
190 final StringBuilder sb,
191 final Map<Object, Object> map,
192 final int depth) {
193 sb.append(LCURLY);
194 final int nextDepth = depth + 1;
195 final boolean[] firstEntry = {true};
196 map.forEach((final Object key, final Object value) -> {
197 if (key == null) {
198 throw new IllegalArgumentException("null keys are not allowed");
199 }
200 if (firstEntry[0]) {
201 firstEntry[0] = false;
202 } else {
203 sb.append(COMMA);
204 }
205 sb.append(DQUOTE);
206 final String keyString = String.valueOf(key);
207 final int keyStartIndex = sb.length();
208 sb.append(keyString);
209 StringBuilders.escapeJson(sb, keyStartIndex);
210 sb.append(DQUOTE).append(COLON);
211 format(sb, value, nextDepth);
212 });
213 sb.append(RCURLY);
214 }
215
216 private static void formatList(
217 final StringBuilder sb,
218 final List<Object> items,
219 final int depth) {
220 sb.append(LBRACE);
221 final int nextDepth = depth + 1;
222 for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) {
223 if (itemIndex > 0) {
224 sb.append(COMMA);
225 }
226 final Object item = items.get(itemIndex);
227 format(sb, item, nextDepth);
228 }
229 sb.append(RBRACE);
230 }
231
232 private static void formatCollection(
233 final StringBuilder sb,
234 final Collection<Object> items,
235 final int depth) {
236 sb.append(LBRACE);
237 final int nextDepth = depth + 1;
238 final boolean[] firstItem = {true};
239 items.forEach((final Object item) -> {
240 if (firstItem[0]) {
241 firstItem[0] = false;
242 } else {
243 sb.append(COMMA);
244 }
245 format(sb, item, nextDepth);
246 });
247 sb.append(RBRACE);
248 }
249
250 private static void formatNumber(final StringBuilder sb, final Number number) {
251 if (number instanceof BigDecimal) {
252 final BigDecimal decimalNumber = (BigDecimal) number;
253 sb.append(decimalNumber.toString());
254 } else if (number instanceof Double) {
255 final double doubleNumber = (Double) number;
256 sb.append(doubleNumber);
257 } else if (number instanceof Float) {
258 final float floatNumber = (float) number;
259 sb.append(floatNumber);
260 } else if (number instanceof Byte ||
261 number instanceof Short ||
262 number instanceof Integer ||
263 number instanceof Long) {
264 final long longNumber = number.longValue();
265 sb.append(longNumber);
266 } else {
267 final long longNumber = number.longValue();
268 final double doubleValue = number.doubleValue();
269 if (Double.compare(longNumber, doubleValue) == 0) {
270 sb.append(longNumber);
271 } else {
272 sb.append(doubleValue);
273 }
274 }
275 }
276
277 private static void formatBoolean(final StringBuilder sb, final boolean booleanValue) {
278 sb.append(booleanValue);
279 }
280
281 private static void formatFormattable(
282 final StringBuilder sb,
283 final StringBuilderFormattable formattable) {
284 sb.append(DQUOTE);
285 final int startIndex = sb.length();
286 formattable.formatTo(sb);
287 StringBuilders.escapeJson(sb, startIndex);
288 sb.append(DQUOTE);
289 }
290
291 private static void formatCharArray(final StringBuilder sb, final char[] items) {
292 sb.append(LBRACE);
293 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
294 if (itemIndex > 0) {
295 sb.append(COMMA);
296 }
297 final char item = items[itemIndex];
298 sb.append(DQUOTE);
299 final int startIndex = sb.length();
300 sb.append(item);
301 StringBuilders.escapeJson(sb, startIndex);
302 sb.append(DQUOTE);
303 }
304 sb.append(RBRACE);
305 }
306
307 private static void formatBooleanArray(final StringBuilder sb, final boolean[] items) {
308 sb.append(LBRACE);
309 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
310 if (itemIndex > 0) {
311 sb.append(COMMA);
312 }
313 final boolean item = items[itemIndex];
314 sb.append(item);
315 }
316 sb.append(RBRACE);
317 }
318
319 private static void formatByteArray(final StringBuilder sb, final byte[] items) {
320 sb.append(LBRACE);
321 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
322 if (itemIndex > 0) {
323 sb.append(COMMA);
324 }
325 final byte item = items[itemIndex];
326 sb.append(item);
327 }
328 sb.append(RBRACE);
329 }
330
331 private static void formatShortArray(final StringBuilder sb, final short[] items) {
332 sb.append(LBRACE);
333 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
334 if (itemIndex > 0) {
335 sb.append(COMMA);
336 }
337 final short item = items[itemIndex];
338 sb.append(item);
339 }
340 sb.append(RBRACE);
341 }
342
343 private static void formatIntArray(final StringBuilder sb, final int[] items) {
344 sb.append(LBRACE);
345 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
346 if (itemIndex > 0) {
347 sb.append(COMMA);
348 }
349 final int item = items[itemIndex];
350 sb.append(item);
351 }
352 sb.append(RBRACE);
353 }
354
355 private static void formatLongArray(final StringBuilder sb, final long[] items) {
356 sb.append(LBRACE);
357 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
358 if (itemIndex > 0) {
359 sb.append(COMMA);
360 }
361 final long item = items[itemIndex];
362 sb.append(item);
363 }
364 sb.append(RBRACE);
365 }
366
367 private static void formatFloatArray(final StringBuilder sb, final float[] items) {
368 sb.append(LBRACE);
369 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
370 if (itemIndex > 0) {
371 sb.append(COMMA);
372 }
373 final float item = items[itemIndex];
374 sb.append(item);
375 }
376 sb.append(RBRACE);
377 }
378
379 private static void formatDoubleArray(
380 final StringBuilder sb,
381 final double[] items) {
382 sb.append(LBRACE);
383 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
384 if (itemIndex > 0) {
385 sb.append(COMMA);
386 }
387 final double item = items[itemIndex];
388 sb.append(item);
389 }
390 sb.append(RBRACE);
391 }
392
393 private static void formatObjectArray(
394 final StringBuilder sb,
395 final Object[] items,
396 final int depth) {
397 sb.append(LBRACE);
398 final int nextDepth = depth + 1;
399 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
400 if (itemIndex > 0) {
401 sb.append(COMMA);
402 }
403 final Object item = items[itemIndex];
404 format(sb, item, nextDepth);
405 }
406 sb.append(RBRACE);
407 }
408
409 private static void formatString(final StringBuilder sb, final Object value) {
410 sb.append(DQUOTE);
411 final int startIndex = sb.length();
412 final String valueString = String.valueOf(value);
413 sb.append(valueString);
414 StringBuilders.escapeJson(sb, startIndex);
415 sb.append(DQUOTE);
416 }
417
418 }
3131 * Constructs a message factory with default flow strings.
3232 */
3333 public MessageFormatMessageFactory() {
34 super();
3435 }
3536
3637 /**
2020 import java.io.ObjectOutputStream;
2121 import java.util.Arrays;
2222
23 import org.apache.logging.log4j.util.Constants;
24
2523 /**
2624 * Handles messages that contain an Object[].
2725 * <p>
3533 */
3634 public final class ObjectArrayMessage implements Message {
3735
36 private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
37
3838 private static final long serialVersionUID = -5903272448334166185L;
3939
4040 private transient Object[] array;
4747 * The Object to format.
4848 */
4949 public ObjectArrayMessage(final Object... obj) {
50 this.array = obj == null ? Constants.EMPTY_OBJECT_ARRAY : obj;
50 this.array = obj == null ? EMPTY_OBJECT_ARRAY : obj;
5151 }
5252
5353 private boolean equalObjectsOrStrings(final Object[] left, final Object[] right) {
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.apache.logging.log4j.util.StringBuilders;
19
2018 import java.text.SimpleDateFormat;
2119 import java.util.Arrays;
2220 import java.util.Collection;
23 import java.util.Collections;
2421 import java.util.Date;
25 import java.util.IdentityHashMap;
22 import java.util.HashSet;
2623 import java.util.Map;
2724 import java.util.Set;
25
26 import org.apache.logging.log4j.util.StringBuilders;
2827
2928 /**
3029 * Supports parameter formatting as used in ParameterizedMessage and ReusableParameterizedMessage.
6059 private static final char DELIM_STOP = '}';
6160 private static final char ESCAPE_CHAR = '\\';
6261
63 private static final ThreadLocal<SimpleDateFormat> SIMPLE_DATE_FORMAT_REF =
64 ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
62 private static ThreadLocal<SimpleDateFormat> threadLocalSimpleDateFormat = new ThreadLocal<>();
6563
6664 private ParameterFormatter() {
6765 }
187185 for (int i = 0; i < argCount; i++) {
188186 buffer.append(messagePattern, previous, indices[i]);
189187 previous = indices[i] + 2;
190 recursiveDeepToString(arguments[i], buffer);
188 recursiveDeepToString(arguments[i], buffer, null);
191189 }
192190 buffer.append(messagePattern, previous, messagePattern.length());
193191 }
212210 for (int i = 0; i < argCount; i++) {
213211 buffer.append(messagePattern, previous, indices[i]);
214212 previous = indices[i] + 2;
215 recursiveDeepToString(arguments[i], buffer);
213 recursiveDeepToString(arguments[i], buffer, null);
216214 }
217215 buffer.append(messagePattern, previous, patternLength);
218216 }
364362 private static void writeArgOrDelimPair(final Object[] arguments, final int argCount, final int currentArgument,
365363 final StringBuilder buffer) {
366364 if (currentArgument < argCount) {
367 recursiveDeepToString(arguments[currentArgument], buffer);
365 recursiveDeepToString(arguments[currentArgument], buffer, null);
368366 } else {
369367 writeDelimPair(buffer);
370368 }
421419 return Byte.toString((Byte) o);
422420 }
423421 final StringBuilder str = new StringBuilder();
424 recursiveDeepToString(o, str);
422 recursiveDeepToString(o, str, null);
425423 return str.toString();
426424 }
427425
428426 /**
429 * This method performs a deep {@code toString()} of the given {@code Object}.
427 * This method performs a deep toString of the given Object.
428 * Primitive arrays are converted using their respective Arrays.toString methods while
429 * special handling is implemented for "container types", i.e. Object[], Map and Collection because those could
430 * contain themselves.
430431 * <p>
431 * Primitive arrays are converted using their respective {@code Arrays.toString()} methods, while
432 * special handling is implemented for <i>container types</i>, i.e. {@code Object[]}, {@code Map} and {@code Collection},
433 * because those could contain themselves.
432 * dejaVu is used in case of those container types to prevent an endless recursion.
433 * </p>
434434 * <p>
435 * It should be noted that neither {@code AbstractMap.toString()} nor {@code AbstractCollection.toString()} implement such a behavior.
436 * They only check if the container is directly contained in itself, but not if a contained container contains the original one.
437 * Because of that, {@code Arrays.toString(Object[])} isn't safe either.
438 * Confusing? Just read the last paragraph again and check the respective {@code toString()} implementation.
435 * It should be noted that neither AbstractMap.toString() nor AbstractCollection.toString() implement such a
436 * behavior.
437 * They only check if the container is directly contained in itself, but not if a contained container contains the
438 * original one. Because of that, Arrays.toString(Object[]) isn't safe either.
439 * Confusing? Just read the last paragraph again and check the respective toString() implementation.
440 * </p>
439441 * <p>
440 * This means, in effect, that logging would produce a usable output even if an ordinary {@code System.out.println(o)}
441 * would produce a relatively hard-to-debug {@code StackOverflowError}.
442 *
443 * @param o the {@code Object} to convert into a {@code String}
444 * @param str the {@code StringBuilder} that {@code o} will be appended to
445 */
446 static void recursiveDeepToString(final Object o, final StringBuilder str) {
447 recursiveDeepToString(o, str, null);
448 }
449
450 /**
451 * This method performs a deep {@code toString()} of the given {@code Object}.
452 * <p>
453 * Primitive arrays are converted using their respective {@code Arrays.toString()} methods, while
454 * special handling is implemented for <i>container types</i>, i.e. {@code Object[]}, {@code Map} and {@code Collection},
455 * because those could contain themselves.
456 * <p>
457 * {@code dejaVu} is used in case of those container types to prevent an endless recursion.
458 * <p>
459 * It should be noted that neither {@code AbstractMap.toString()} nor {@code AbstractCollection.toString()} implement such a behavior.
460 * They only check if the container is directly contained in itself, but not if a contained container contains the original one.
461 * Because of that, {@code Arrays.toString(Object[])} isn't safe either.
462 * Confusing? Just read the last paragraph again and check the respective {@code toString()} implementation.
463 * <p>
464 * This means, in effect, that logging would produce a usable output even if an ordinary {@code System.out.println(o)}
465 * would produce a relatively hard-to-debug {@code StackOverflowError}.
466 *
467 * @param o the {@code Object} to convert into a {@code String}
468 * @param str the {@code StringBuilder} that {@code o} will be appended to
469 * @param dejaVu a set of container objects directly or transitively containing {@code o}
470 */
471 private static void recursiveDeepToString(final Object o, final StringBuilder str, final Set<Object> dejaVu) {
442 * This means, in effect, that logging would produce a usable output even if an ordinary System.out.println(o)
443 * would produce a relatively hard-to-debug StackOverflowError.
444 * </p>
445 *
446 * @param o the Object to convert into a String
447 * @param str the StringBuilder that o will be appended to
448 * @param dejaVu a list of container identities that were already used.
449 */
450 static void recursiveDeepToString(final Object o, final StringBuilder str, final Set<String> dejaVu) {
472451 if (appendSpecialTypes(o, str)) {
473452 return;
474453 }
488467 return false;
489468 }
490469 final Date date = (Date) o;
491 final SimpleDateFormat format = SIMPLE_DATE_FORMAT_REF.get();
470 final SimpleDateFormat format = getSimpleDateFormat();
492471 str.append(format.format(date));
493472 return true;
494473 }
495474
475 private static SimpleDateFormat getSimpleDateFormat() {
476 SimpleDateFormat result = threadLocalSimpleDateFormat.get();
477 if (result == null) {
478 result = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
479 threadLocalSimpleDateFormat.set(result);
480 }
481 return result;
482 }
483
496484 /**
497485 * Returns {@code true} if the specified object is an array, a Map or a Collection.
498486 */
500488 return o.getClass().isArray() || o instanceof Map || o instanceof Collection;
501489 }
502490
503 private static void appendPotentiallyRecursiveValue(
504 final Object o,
505 final StringBuilder str,
506 final Set<Object> dejaVu) {
491 private static void appendPotentiallyRecursiveValue(final Object o, final StringBuilder str,
492 final Set<String> dejaVu) {
507493 final Class<?> oClass = o.getClass();
508494 if (oClass.isArray()) {
509495 appendArray(o, str, dejaVu, oClass);
511497 appendMap(o, str, dejaVu);
512498 } else if (o instanceof Collection) {
513499 appendCollection(o, str, dejaVu);
514 } else {
515 throw new IllegalArgumentException("was expecting a container, found " + oClass);
516 }
517 }
518
519 private static void appendArray(
520 final Object o,
521 final StringBuilder str,
522 final Set<Object> dejaVu,
500 }
501 }
502
503 private static void appendArray(final Object o, final StringBuilder str, Set<String> dejaVu,
523504 final Class<?> oClass) {
524505 if (oClass == byte[].class) {
525506 str.append(Arrays.toString((byte[]) o));
538519 } else if (oClass == char[].class) {
539520 str.append(Arrays.toString((char[]) o));
540521 } else {
522 if (dejaVu == null) {
523 dejaVu = new HashSet<>();
524 }
541525 // special handling of container Object[]
542 final Set<Object> effectiveDejaVu = getOrCreateDejaVu(dejaVu);
543 final boolean seen = !effectiveDejaVu.add(o);
544 if (seen) {
545 final String id = identityToString(o);
526 final String id = identityToString(o);
527 if (dejaVu.contains(id)) {
546528 str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
547529 } else {
530 dejaVu.add(id);
548531 final Object[] oArray = (Object[]) o;
549532 str.append('[');
550533 boolean first = true;
554537 } else {
555538 str.append(", ");
556539 }
557 recursiveDeepToString(current, str, cloneDejaVu(effectiveDejaVu));
540 recursiveDeepToString(current, str, new HashSet<>(dejaVu));
558541 }
559542 str.append(']');
560543 }
561 }
562 }
563
564 /**
565 * Specialized handler for {@link Map}s.
566 */
567 private static void appendMap(
568 final Object o,
569 final StringBuilder str,
570 final Set<Object> dejaVu) {
571 final Set<Object> effectiveDejaVu = getOrCreateDejaVu(dejaVu);
572 final boolean seen = !effectiveDejaVu.add(o);
573 if (seen) {
574 final String id = identityToString(o);
544 //str.append(Arrays.deepToString((Object[]) o));
545 }
546 }
547
548 private static void appendMap(final Object o, final StringBuilder str, Set<String> dejaVu) {
549 // special handling of container Map
550 if (dejaVu == null) {
551 dejaVu = new HashSet<>();
552 }
553 final String id = identityToString(o);
554 if (dejaVu.contains(id)) {
575555 str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
576556 } else {
557 dejaVu.add(id);
577558 final Map<?, ?> oMap = (Map<?, ?>) o;
578559 str.append('{');
579560 boolean isFirst = true;
586567 }
587568 final Object key = current.getKey();
588569 final Object value = current.getValue();
589 recursiveDeepToString(key, str, cloneDejaVu(effectiveDejaVu));
570 recursiveDeepToString(key, str, new HashSet<>(dejaVu));
590571 str.append('=');
591 recursiveDeepToString(value, str, cloneDejaVu(effectiveDejaVu));
572 recursiveDeepToString(value, str, new HashSet<>(dejaVu));
592573 }
593574 str.append('}');
594575 }
595576 }
596577
597 /**
598 * Specialized handler for {@link Collection}s.
599 */
600 private static void appendCollection(
601 final Object o,
602 final StringBuilder str,
603 final Set<Object> dejaVu) {
604 final Set<Object> effectiveDejaVu = getOrCreateDejaVu(dejaVu);
605 final boolean seen = !effectiveDejaVu.add(o);
606 if (seen) {
607 final String id = identityToString(o);
578 private static void appendCollection(final Object o, final StringBuilder str, Set<String> dejaVu) {
579 // special handling of container Collection
580 if (dejaVu == null) {
581 dejaVu = new HashSet<>();
582 }
583 final String id = identityToString(o);
584 if (dejaVu.contains(id)) {
608585 str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX);
609586 } else {
587 dejaVu.add(id);
610588 final Collection<?> oCol = (Collection<?>) o;
611589 str.append('[');
612590 boolean isFirst = true;
616594 } else {
617595 str.append(", ");
618596 }
619 recursiveDeepToString(anOCol, str, cloneDejaVu(effectiveDejaVu));
597 recursiveDeepToString(anOCol, str, new HashSet<>(dejaVu));
620598 }
621599 str.append(']');
622600 }
623 }
624
625 private static Set<Object> getOrCreateDejaVu(Set<Object> dejaVu) {
626 return dejaVu == null
627 ? createDejaVu()
628 : dejaVu;
629 }
630
631 private static Set<Object> createDejaVu() {
632 return Collections.newSetFromMap(new IdentityHashMap<>());
633 }
634
635 private static Set<Object> cloneDejaVu(Set<Object> dejaVu) {
636 Set<Object> clonedDejaVu = createDejaVu();
637 clonedDejaVu.addAll(dejaVu);
638 return clonedDejaVu;
639601 }
640602
641603 private static void tryObjectToString(final Object o, final StringBuilder str) {
220220 public void formatTo(final StringBuilder buffer) {
221221 if (formattedMessage != null) {
222222 buffer.append(formattedMessage);
223 } else if (indices[0] < 0) {
224 ParameterFormatter.formatMessage(buffer, messagePattern, argArray, usedCount);
225223 } else {
226 ParameterFormatter.formatMessage2(buffer, messagePattern, argArray, usedCount, indices);
224 if (indices[0] < 0) {
225 ParameterFormatter.formatMessage(buffer, messagePattern, argArray, usedCount);
226 } else {
227 ParameterFormatter.formatMessage2(buffer, messagePattern, argArray, usedCount, indices);
228 }
227229 }
228230 }
229231
4545 * Constructs a message factory.
4646 */
4747 public ParameterizedMessageFactory() {
48 super();
4849 }
4950
5051 /**
7979 * Constructs a message factory with default flow strings.
8080 */
8181 public ParameterizedNoReferenceMessageFactory() {
82 super();
8283 }
8384
8485 /**
4545 * Constructs a message factory.
4646 */
4747 public ReusableMessageFactory() {
48 super();
4849 }
4950
5051 private static ReusableParameterizedMessage getParameterized() {
6767 result = params;
6868 if (emptyReplacement.length >= MAX_PARMS) {
6969 params = emptyReplacement;
70 } else if (argCount <= emptyReplacement.length) {
70 } else {
7171 // Bad replacement! Too small, may blow up future 10-arg messages.
72 // copy params into the specified replacement array and return that
73 System.arraycopy(params, 0, emptyReplacement, 0, argCount);
74 // Do not retain references to objects in the reusable params array.
75 for (int i = 0; i < argCount; i++) {
76 params[i] = null;
72 if (argCount <= emptyReplacement.length) {
73 // copy params into the specified replacement array and return that
74 System.arraycopy(params, 0, emptyReplacement, 0, argCount);
75 // Do not retain references to objects in the reusable params array.
76 for (int i = 0; i < argCount; i++) {
77 params[i] = null;
78 }
79 result = emptyReplacement;
80 } else {
81 // replacement array is too small for current content and future content: discard it
82 params = new Object[MAX_PARMS];
7783 }
78 result = emptyReplacement;
79 } else {
80 // replacement array is too small for current content and future content: discard it
81 params = new Object[MAX_PARMS];
8284 }
8385 } else {
8486 // The returned array will be reused by the caller in future swapParameter() calls.
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.apache.logging.log4j.util.Constants;
1918 import org.apache.logging.log4j.util.PerformanceSensitive;
2019
2120 /**
2524 @PerformanceSensitive("allocation")
2625 public class ReusableSimpleMessage implements ReusableMessage, CharSequence, ParameterVisitable, Clearable {
2726 private static final long serialVersionUID = -9199974506498249809L;
27 private static Object[] EMPTY_PARAMS = new Object[0];
2828 private CharSequence charSequence;
2929
3030 public void set(final String message) {
4747
4848 @Override
4949 public Object[] getParameters() {
50 return Constants.EMPTY_OBJECT_ARRAY;
50 return EMPTY_PARAMS;
5151 }
5252
5353 @Override
4444 * Constructs a message factory with default flow strings.
4545 */
4646 public StringFormatterMessageFactory() {
47 super();
4748 }
4849
4950 /**
3535 * Constructs a new instance.
3636 */
3737 public StringMapMessage() {
38 super();
3839 }
3940
4041 /**
372372 }
373373
374374 /**
375 * Formats the message according to the specified format.
375 * Formats the message according the the specified format.
376376 * @param formats An array of Strings that provide extra information about how to format the message.
377377 * StructuredDataMessage accepts only a format of "FULL" which will cause the event type to be
378378 * prepended and the event message to be appended. Specifying any other value will cause only the
4343 public void removeContext(final LoggerContext removeContext) {
4444 // do nothing
4545 }
46
47 @Override
48 public boolean isClassLoaderDependent() {
49 return false;
50 }
5146 }
1515 */
1616 package org.apache.logging.log4j.spi;
1717
18 import java.io.IOException;
19 import java.io.ObjectInputStream;
2018 import java.io.Serializable;
21 import java.lang.reflect.Field;
2219
2320 import org.apache.logging.log4j.Level;
24 import org.apache.logging.log4j.LogBuilder;
2521 import org.apache.logging.log4j.LoggingException;
2622 import org.apache.logging.log4j.Marker;
2723 import org.apache.logging.log4j.MarkerManager;
28 import org.apache.logging.log4j.internal.DefaultLogBuilder;
2924 import org.apache.logging.log4j.message.DefaultFlowMessageFactory;
3025 import org.apache.logging.log4j.message.EntryMessage;
3126 import org.apache.logging.log4j.message.FlowMessageFactory;
109104 protected final String name;
110105 private final MessageFactory2 messageFactory;
111106 private final FlowMessageFactory flowMessageFactory;
112 private static final ThreadLocal<int[]> recursionDepthHolder = new ThreadLocal<>(); // LOG4J2-1518, LOG4J2-2031
113 protected final transient ThreadLocal<DefaultLogBuilder> logBuilder;
107 private static ThreadLocal<int[]> recursionDepthHolder = new ThreadLocal<>(); // LOG4J2-1518, LOG4J2-2031
114108
115109 /**
116110 * Creates a new logger named after this class (or subclass).
119113 this.name = getClass().getName();
120114 this.messageFactory = createDefaultMessageFactory();
121115 this.flowMessageFactory = createDefaultFlowMessageFactory();
122 this.logBuilder = new LocalLogBuilder(this);
123116 }
124117
125118 /**
141134 this.name = name;
142135 this.messageFactory = messageFactory == null ? createDefaultMessageFactory() : narrow(messageFactory);
143136 this.flowMessageFactory = createDefaultFlowMessageFactory();
144 this.logBuilder = new LocalLogBuilder(this);
145137 }
146138
147139 /**
171163 }
172164
173165 @Override
174 public void catching(final Level level, final Throwable throwable) {
175 catching(FQCN, level, throwable);
166 public void catching(final Level level, final Throwable t) {
167 catching(FQCN, level, t);
176168 }
177169
178170 /**
180172 *
181173 * @param fqcn The fully qualified class name of the <b>caller</b>.
182174 * @param level The logging level.
183 * @param throwable The Throwable.
175 * @param t The Throwable.
184176 */
185 protected void catching(final String fqcn, final Level level, final Throwable throwable) {
177 protected void catching(final String fqcn, final Level level, final Throwable t) {
186178 if (isEnabled(level, CATCHING_MARKER, (Object) null, null)) {
187 logMessageSafely(fqcn, level, CATCHING_MARKER, catchingMsg(throwable), throwable);
188 }
189 }
190
191 @Override
192 public void catching(final Throwable throwable) {
179 logMessageSafely(fqcn, level, CATCHING_MARKER, catchingMsg(t), t);
180 }
181 }
182
183 @Override
184 public void catching(final Throwable t) {
193185 if (isEnabled(Level.ERROR, CATCHING_MARKER, (Object) null, null)) {
194 logMessageSafely(FQCN, Level.ERROR, CATCHING_MARKER, catchingMsg(throwable), throwable);
195 }
196 }
197
198 protected Message catchingMsg(final Throwable throwable) {
186 logMessageSafely(FQCN, Level.ERROR, CATCHING_MARKER, catchingMsg(t), t);
187 }
188 }
189
190 protected Message catchingMsg(final Throwable t) {
199191 return messageFactory.newMessage(CATCHING);
200192 }
201193
207199 : parameterizedMessageFactoryClass.getName();
208200 final String clsName = PropertiesUtil.getProperties().getStringProperty(property, fallback);
209201 return LoaderUtil.loadClass(clsName).asSubclass(MessageFactory.class);
210 } catch (final Throwable throwable) {
202 } catch (final Throwable t) {
211203 return parameterizedMessageFactoryClass;
212204 }
213205 }
217209 try {
218210 final String clsName = PropertiesUtil.getProperties().getStringProperty(property, defaultFlowMessageFactoryClass.getName());
219211 return LoaderUtil.loadClass(clsName).asSubclass(FlowMessageFactory.class);
220 } catch (final Throwable throwable) {
212 } catch (final Throwable t) {
221213 return defaultFlowMessageFactoryClass;
222214 }
223215 }
252244 }
253245
254246 @Override
255 public void debug(final Marker marker, final CharSequence message, final Throwable throwable) {
256 logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable);
257 }
258
259 @Override
260 public void debug(final Marker marker, final Message message) {
261 logIfEnabled(FQCN, Level.DEBUG, marker, message, message != null ? message.getThrowable() : null);
262 }
263
264 @Override
265 public void debug(final Marker marker, final Message message, final Throwable throwable) {
266 logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable);
247 public void debug(final Marker marker, final CharSequence message, final Throwable t) {
248 logIfEnabled(FQCN, Level.DEBUG, marker, message, t);
249 }
250
251 @Override
252 public void debug(final Marker marker, final Message msg) {
253 logIfEnabled(FQCN, Level.DEBUG, marker, msg, msg != null ? msg.getThrowable() : null);
254 }
255
256 @Override
257 public void debug(final Marker marker, final Message msg, final Throwable t) {
258 logIfEnabled(FQCN, Level.DEBUG, marker, msg, t);
267259 }
268260
269261 @Override
272264 }
273265
274266 @Override
275 public void debug(final Marker marker, final Object message, final Throwable throwable) {
276 logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable);
267 public void debug(final Marker marker, final Object message, final Throwable t) {
268 logIfEnabled(FQCN, Level.DEBUG, marker, message, t);
277269 }
278270
279271 @Override
287279 }
288280
289281 @Override
290 public void debug(final Marker marker, final String message, final Throwable throwable) {
291 logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable);
292 }
293
294 @Override
295 public void debug(final Message message) {
296 logIfEnabled(FQCN, Level.DEBUG, null, message, message != null ? message.getThrowable() : null);
297 }
298
299 @Override
300 public void debug(final Message message, final Throwable throwable) {
301 logIfEnabled(FQCN, Level.DEBUG, null, message, throwable);
282 public void debug(final Marker marker, final String message, final Throwable t) {
283 logIfEnabled(FQCN, Level.DEBUG, marker, message, t);
284 }
285
286 @Override
287 public void debug(final Message msg) {
288 logIfEnabled(FQCN, Level.DEBUG, null, msg, msg != null ? msg.getThrowable() : null);
289 }
290
291 @Override
292 public void debug(final Message msg, final Throwable t) {
293 logIfEnabled(FQCN, Level.DEBUG, null, msg, t);
302294 }
303295
304296 @Override
307299 }
308300
309301 @Override
310 public void debug(final CharSequence message, final Throwable throwable) {
311 logIfEnabled(FQCN, Level.DEBUG, null, message, throwable);
302 public void debug(final CharSequence message, final Throwable t) {
303 logIfEnabled(FQCN, Level.DEBUG, null, message, t);
312304 }
313305
314306 @Override
317309 }
318310
319311 @Override
320 public void debug(final Object message, final Throwable throwable) {
321 logIfEnabled(FQCN, Level.DEBUG, null, message, throwable);
312 public void debug(final Object message, final Throwable t) {
313 logIfEnabled(FQCN, Level.DEBUG, null, message, t);
322314 }
323315
324316 @Override
332324 }
333325
334326 @Override
335 public void debug(final String message, final Throwable throwable) {
336 logIfEnabled(FQCN, Level.DEBUG, null, message, throwable);
337 }
338
339 @Override
340 public void debug(final Supplier<?> messageSupplier) {
341 logIfEnabled(FQCN, Level.DEBUG, null, messageSupplier, (Throwable) null);
342 }
343
344 @Override
345 public void debug(final Supplier<?> messageSupplier, final Throwable throwable) {
346 logIfEnabled(FQCN, Level.DEBUG, null, messageSupplier, throwable);
347 }
348
349 @Override
350 public void debug(final Marker marker, final Supplier<?> messageSupplier) {
351 logIfEnabled(FQCN, Level.DEBUG, marker, messageSupplier, (Throwable) null);
327 public void debug(final String message, final Throwable t) {
328 logIfEnabled(FQCN, Level.DEBUG, null, message, t);
329 }
330
331 @Override
332 public void debug(final Supplier<?> msgSupplier) {
333 logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, (Throwable) null);
334 }
335
336 @Override
337 public void debug(final Supplier<?> msgSupplier, final Throwable t) {
338 logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, t);
339 }
340
341 @Override
342 public void debug(final Marker marker, final Supplier<?> msgSupplier) {
343 logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, (Throwable) null);
352344 }
353345
354346 @Override
357349 }
358350
359351 @Override
360 public void debug(final Marker marker, final Supplier<?> messageSupplier, final Throwable throwable) {
361 logIfEnabled(FQCN, Level.DEBUG, marker, messageSupplier, throwable);
352 public void debug(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {
353 logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, t);
362354 }
363355
364356 @Override
367359 }
368360
369361 @Override
370 public void debug(final Marker marker, final MessageSupplier messageSupplier) {
371 logIfEnabled(FQCN, Level.DEBUG, marker, messageSupplier, (Throwable) null);
372 }
373
374 @Override
375 public void debug(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) {
376 logIfEnabled(FQCN, Level.DEBUG, marker, messageSupplier, throwable);
377 }
378
379 @Override
380 public void debug(final MessageSupplier messageSupplier) {
381 logIfEnabled(FQCN, Level.DEBUG, null, messageSupplier, (Throwable) null);
382 }
383
384 @Override
385 public void debug(final MessageSupplier messageSupplier, final Throwable throwable) {
386 logIfEnabled(FQCN, Level.DEBUG, null, messageSupplier, throwable);
362 public void debug(final Marker marker, final MessageSupplier msgSupplier) {
363 logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, (Throwable) null);
364 }
365
366 @Override
367 public void debug(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) {
368 logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, t);
369 }
370
371 @Override
372 public void debug(final MessageSupplier msgSupplier) {
373 logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, (Throwable) null);
374 }
375
376 @Override
377 public void debug(final MessageSupplier msgSupplier, final Throwable t) {
378 logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, t);
387379 }
388380
389381 @Override
556548 * Logs entry to a method with location information.
557549 *
558550 * @param fqcn The fully qualified class name of the <b>caller</b>.
559 * @param messageSupplier The Supplier of the Message.
551 * @param msgSupplier The Supplier of the Message.
560552 */
561553 @Deprecated
562 protected EntryMessage enter(final String fqcn, final MessageSupplier messageSupplier) {
554 protected EntryMessage enter(final String fqcn, final MessageSupplier msgSupplier) {
563555 EntryMessage message = null;
564556 if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) {
565557 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, message = flowMessageFactory.newEntryMessage(
566 messageSupplier.get()), null);
558 msgSupplier.get()), null);
567559 }
568560 return message;
569561 }
660652 }
661653
662654 @Override
663 public void error(final Marker marker, final Message message) {
664 logIfEnabled(FQCN, Level.ERROR, marker, message, message != null ? message.getThrowable() : null);
665 }
666
667 @Override
668 public void error(final Marker marker, final Message message, final Throwable throwable) {
669 logIfEnabled(FQCN, Level.ERROR, marker, message, throwable);
655 public void error(final Marker marker, final Message msg) {
656 logIfEnabled(FQCN, Level.ERROR, marker, msg, msg != null ? msg.getThrowable() : null);
657 }
658
659 @Override
660 public void error(final Marker marker, final Message msg, final Throwable t) {
661 logIfEnabled(FQCN, Level.ERROR, marker, msg, t);
670662 }
671663
672664 @Override
675667 }
676668
677669 @Override
678 public void error(final Marker marker, final CharSequence message, final Throwable throwable) {
679 logIfEnabled(FQCN, Level.ERROR, marker, message, throwable);
670 public void error(final Marker marker, final CharSequence message, final Throwable t) {
671 logIfEnabled(FQCN, Level.ERROR, marker, message, t);
680672 }
681673
682674 @Override
685677 }
686678
687679 @Override
688 public void error(final Marker marker, final Object message, final Throwable throwable) {
689 logIfEnabled(FQCN, Level.ERROR, marker, message, throwable);
680 public void error(final Marker marker, final Object message, final Throwable t) {
681 logIfEnabled(FQCN, Level.ERROR, marker, message, t);
690682 }
691683
692684 @Override
700692 }
701693
702694 @Override
703 public void error(final Marker marker, final String message, final Throwable throwable) {
704 logIfEnabled(FQCN, Level.ERROR, marker, message, throwable);
705 }
706
707 @Override
708 public void error(final Message message) {
709 logIfEnabled(FQCN, Level.ERROR, null, message, message != null ? message.getThrowable() : null);
710 }
711
712 @Override
713 public void error(final Message message, final Throwable throwable) {
714 logIfEnabled(FQCN, Level.ERROR, null, message, throwable);
695 public void error(final Marker marker, final String message, final Throwable t) {
696 logIfEnabled(FQCN, Level.ERROR, marker, message, t);
697 }
698
699 @Override
700 public void error(final Message msg) {
701 logIfEnabled(FQCN, Level.ERROR, null, msg, msg != null ? msg.getThrowable() : null);
702 }
703
704 @Override
705 public void error(final Message msg, final Throwable t) {
706 logIfEnabled(FQCN, Level.ERROR, null, msg, t);
715707 }
716708
717709 @Override
720712 }
721713
722714 @Override
723 public void error(final CharSequence message, final Throwable throwable) {
724 logIfEnabled(FQCN, Level.ERROR, null, message, throwable);
715 public void error(final CharSequence message, final Throwable t) {
716 logIfEnabled(FQCN, Level.ERROR, null, message, t);
725717 }
726718
727719 @Override
730722 }
731723
732724 @Override
733 public void error(final Object message, final Throwable throwable) {
734 logIfEnabled(FQCN, Level.ERROR, null, message, throwable);
725 public void error(final Object message, final Throwable t) {
726 logIfEnabled(FQCN, Level.ERROR, null, message, t);
735727 }
736728
737729 @Override
745737 }
746738
747739 @Override
748 public void error(final String message, final Throwable throwable) {
749 logIfEnabled(FQCN, Level.ERROR, null, message, throwable);
750 }
751
752 @Override
753 public void error(final Supplier<?> messageSupplier) {
754 logIfEnabled(FQCN, Level.ERROR, null, messageSupplier, (Throwable) null);
755 }
756
757 @Override
758 public void error(final Supplier<?> messageSupplier, final Throwable throwable) {
759 logIfEnabled(FQCN, Level.ERROR, null, messageSupplier, throwable);
760 }
761
762 @Override
763 public void error(final Marker marker, final Supplier<?> messageSupplier) {
764 logIfEnabled(FQCN, Level.ERROR, marker, messageSupplier, (Throwable) null);
740 public void error(final String message, final Throwable t) {
741 logIfEnabled(FQCN, Level.ERROR, null, message, t);
742 }
743
744 @Override
745 public void error(final Supplier<?> msgSupplier) {
746 logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, (Throwable) null);
747 }
748
749 @Override
750 public void error(final Supplier<?> msgSupplier, final Throwable t) {
751 logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, t);
752 }
753
754 @Override
755 public void error(final Marker marker, final Supplier<?> msgSupplier) {
756 logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, (Throwable) null);
765757 }
766758
767759 @Override
770762 }
771763
772764 @Override
773 public void error(final Marker marker, final Supplier<?> messageSupplier, final Throwable throwable) {
774 logIfEnabled(FQCN, Level.ERROR, marker, messageSupplier, throwable);
765 public void error(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {
766 logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, t);
775767 }
776768
777769 @Override
780772 }
781773
782774 @Override
783 public void error(final Marker marker, final MessageSupplier messageSupplier) {
784 logIfEnabled(FQCN, Level.ERROR, marker, messageSupplier, (Throwable) null);
785 }
786
787 @Override
788 public void error(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) {
789 logIfEnabled(FQCN, Level.ERROR, marker, messageSupplier, throwable);
790 }
791
792 @Override
793 public void error(final MessageSupplier messageSupplier) {
794 logIfEnabled(FQCN, Level.ERROR, null, messageSupplier, (Throwable) null);
795 }
796
797 @Override
798 public void error(final MessageSupplier messageSupplier, final Throwable throwable) {
799 logIfEnabled(FQCN, Level.ERROR, null, messageSupplier, throwable);
775 public void error(final Marker marker, final MessageSupplier msgSupplier) {
776 logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, (Throwable) null);
777 }
778
779 @Override
780 public void error(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) {
781 logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, t);
782 }
783
784 @Override
785 public void error(final MessageSupplier msgSupplier) {
786 logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, (Throwable) null);
787 }
788
789 @Override
790 public void error(final MessageSupplier msgSupplier, final Throwable t) {
791 logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, t);
800792 }
801793
802794 @Override
973965 }
974966
975967 @Override
976 public void fatal(final Marker marker, final Message message) {
977 logIfEnabled(FQCN, Level.FATAL, marker, message, message != null ? message.getThrowable() : null);
978 }
979
980 @Override
981 public void fatal(final Marker marker, final Message message, final Throwable throwable) {
982 logIfEnabled(FQCN, Level.FATAL, marker, message, throwable);
968 public void fatal(final Marker marker, final Message msg) {
969 logIfEnabled(FQCN, Level.FATAL, marker, msg, msg != null ? msg.getThrowable() : null);
970 }
971
972 @Override
973 public void fatal(final Marker marker, final Message msg, final Throwable t) {
974 logIfEnabled(FQCN, Level.FATAL, marker, msg, t);
983975 }
984976
985977 @Override
988980 }
989981
990982 @Override
991 public void fatal(final Marker marker, final CharSequence message, final Throwable throwable) {
992 logIfEnabled(FQCN, Level.FATAL, marker, message, throwable);
983 public void fatal(final Marker marker, final CharSequence message, final Throwable t) {
984 logIfEnabled(FQCN, Level.FATAL, marker, message, t);
993985 }
994986
995987 @Override
998990 }
999991
1000992 @Override
1001 public void fatal(final Marker marker, final Object message, final Throwable throwable) {
1002 logIfEnabled(FQCN, Level.FATAL, marker, message, throwable);
993 public void fatal(final Marker marker, final Object message, final Throwable t) {
994 logIfEnabled(FQCN, Level.FATAL, marker, message, t);
1003995 }
1004996
1005997 @Override
10131005 }
10141006
10151007 @Override
1016 public void fatal(final Marker marker, final String message, final Throwable throwable) {
1017 logIfEnabled(FQCN, Level.FATAL, marker, message, throwable);
1018 }
1019
1020 @Override
1021 public void fatal(final Message message) {
1022 logIfEnabled(FQCN, Level.FATAL, null, message, message != null ? message.getThrowable() : null);
1023 }
1024
1025 @Override
1026 public void fatal(final Message message, final Throwable throwable) {
1027 logIfEnabled(FQCN, Level.FATAL, null, message, throwable);
1008 public void fatal(final Marker marker, final String message, final Throwable t) {
1009 logIfEnabled(FQCN, Level.FATAL, marker, message, t);
1010 }
1011
1012 @Override
1013 public void fatal(final Message msg) {
1014 logIfEnabled(FQCN, Level.FATAL, null, msg, msg != null ? msg.getThrowable() : null);
1015 }
1016
1017 @Override
1018 public void fatal(final Message msg, final Throwable t) {
1019 logIfEnabled(FQCN, Level.FATAL, null, msg, t);
10281020 }
10291021
10301022 @Override
10331025 }
10341026
10351027 @Override
1036 public void fatal(final CharSequence message, final Throwable throwable) {
1037 logIfEnabled(FQCN, Level.FATAL, null, message, throwable);
1028 public void fatal(final CharSequence message, final Throwable t) {
1029 logIfEnabled(FQCN, Level.FATAL, null, message, t);
10381030 }
10391031
10401032 @Override
10431035 }
10441036
10451037 @Override
1046 public void fatal(final Object message, final Throwable throwable) {
1047 logIfEnabled(FQCN, Level.FATAL, null, message, throwable);
1038 public void fatal(final Object message, final Throwable t) {
1039 logIfEnabled(FQCN, Level.FATAL, null, message, t);
10481040 }
10491041
10501042 @Override
10581050 }
10591051
10601052 @Override
1061 public void fatal(final String message, final Throwable throwable) {
1062 logIfEnabled(FQCN, Level.FATAL, null, message, throwable);
1063 }
1064
1065 @Override
1066 public void fatal(final Supplier<?> messageSupplier) {
1067 logIfEnabled(FQCN, Level.FATAL, null, messageSupplier, (Throwable) null);
1068 }
1069
1070 @Override
1071 public void fatal(final Supplier<?> messageSupplier, final Throwable throwable) {
1072 logIfEnabled(FQCN, Level.FATAL, null, messageSupplier, throwable);
1073 }
1074
1075 @Override
1076 public void fatal(final Marker marker, final Supplier<?> messageSupplier) {
1077 logIfEnabled(FQCN, Level.FATAL, marker, messageSupplier, (Throwable) null);
1053 public void fatal(final String message, final Throwable t) {
1054 logIfEnabled(FQCN, Level.FATAL, null, message, t);
1055 }
1056
1057 @Override
1058 public void fatal(final Supplier<?> msgSupplier) {
1059 logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, (Throwable) null);
1060 }
1061
1062 @Override
1063 public void fatal(final Supplier<?> msgSupplier, final Throwable t) {
1064 logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, t);
1065 }
1066
1067 @Override
1068 public void fatal(final Marker marker, final Supplier<?> msgSupplier) {
1069 logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, (Throwable) null);
10781070 }
10791071
10801072 @Override
10831075 }
10841076
10851077 @Override
1086 public void fatal(final Marker marker, final Supplier<?> messageSupplier, final Throwable throwable) {
1087 logIfEnabled(FQCN, Level.FATAL, marker, messageSupplier, throwable);
1078 public void fatal(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {
1079 logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, t);
10881080 }
10891081
10901082 @Override
10931085 }
10941086
10951087 @Override
1096 public void fatal(final Marker marker, final MessageSupplier messageSupplier) {
1097 logIfEnabled(FQCN, Level.FATAL, marker, messageSupplier, (Throwable) null);
1098 }
1099
1100 @Override
1101 public void fatal(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) {
1102 logIfEnabled(FQCN, Level.FATAL, marker, messageSupplier, throwable);
1103 }
1104
1105 @Override
1106 public void fatal(final MessageSupplier messageSupplier) {
1107 logIfEnabled(FQCN, Level.FATAL, null, messageSupplier, (Throwable) null);
1108 }
1109
1110 @Override
1111 public void fatal(final MessageSupplier messageSupplier, final Throwable throwable) {
1112 logIfEnabled(FQCN, Level.FATAL, null, messageSupplier, throwable);
1088 public void fatal(final Marker marker, final MessageSupplier msgSupplier) {
1089 logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, (Throwable) null);
1090 }
1091
1092 @Override
1093 public void fatal(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) {
1094 logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, t);
1095 }
1096
1097 @Override
1098 public void fatal(final MessageSupplier msgSupplier) {
1099 logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, (Throwable) null);
1100 }
1101
1102 @Override
1103 public void fatal(final MessageSupplier msgSupplier, final Throwable t) {
1104 logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, t);
11131105 }
11141106
11151107 @Override
12401232 }
12411233
12421234 @Override
1243 public void info(final Marker marker, final Message message) {
1244 logIfEnabled(FQCN, Level.INFO, marker, message, message != null ? message.getThrowable() : null);
1245 }
1246
1247 @Override
1248 public void info(final Marker marker, final Message message, final Throwable throwable) {
1249 logIfEnabled(FQCN, Level.INFO, marker, message, throwable);
1235 public void info(final Marker marker, final Message msg) {
1236 logIfEnabled(FQCN, Level.INFO, marker, msg, msg != null ? msg.getThrowable() : null);
1237 }
1238
1239 @Override
1240 public void info(final Marker marker, final Message msg, final Throwable t) {
1241 logIfEnabled(FQCN, Level.INFO, marker, msg, t);
12501242 }
12511243
12521244 @Override
12551247 }
12561248
12571249 @Override
1258 public void info(final Marker marker, final CharSequence message, final Throwable throwable) {
1259 logIfEnabled(FQCN, Level.INFO, marker, message, throwable);
1250 public void info(final Marker marker, final CharSequence message, final Throwable t) {
1251 logIfEnabled(FQCN, Level.INFO, marker, message, t);
12601252 }
12611253
12621254 @Override
12651257 }
12661258
12671259 @Override
1268 public void info(final Marker marker, final Object message, final Throwable throwable) {
1269 logIfEnabled(FQCN, Level.INFO, marker, message, throwable);
1260 public void info(final Marker marker, final Object message, final Throwable t) {
1261 logIfEnabled(FQCN, Level.INFO, marker, message, t);
12701262 }
12711263
12721264 @Override
12801272 }
12811273
12821274 @Override
1283 public void info(final Marker marker, final String message, final Throwable throwable) {
1284 logIfEnabled(FQCN, Level.INFO, marker, message, throwable);
1285 }
1286
1287 @Override
1288 public void info(final Message message) {
1289 logIfEnabled(FQCN, Level.INFO, null, message, message != null ? message.getThrowable() : null);
1290 }
1291
1292 @Override
1293 public void info(final Message message, final Throwable throwable) {
1294 logIfEnabled(FQCN, Level.INFO, null, message, throwable);
1275 public void info(final Marker marker, final String message, final Throwable t) {
1276 logIfEnabled(FQCN, Level.INFO, marker, message, t);
1277 }
1278
1279 @Override
1280 public void info(final Message msg) {
1281 logIfEnabled(FQCN, Level.INFO, null, msg, msg != null ? msg.getThrowable() : null);
1282 }
1283
1284 @Override
1285 public void info(final Message msg, final Throwable t) {
1286 logIfEnabled(FQCN, Level.INFO, null, msg, t);
12951287 }
12961288
12971289 @Override
13001292 }
13011293
13021294 @Override
1303 public void info(final CharSequence message, final Throwable throwable) {
1304 logIfEnabled(FQCN, Level.INFO, null, message, throwable);
1295 public void info(final CharSequence message, final Throwable t) {
1296 logIfEnabled(FQCN, Level.INFO, null, message, t);
13051297 }
13061298
13071299 @Override
13101302 }
13111303
13121304 @Override
1313 public void info(final Object message, final Throwable throwable) {
1314 logIfEnabled(FQCN, Level.INFO, null, message, throwable);
1305 public void info(final Object message, final Throwable t) {
1306 logIfEnabled(FQCN, Level.INFO, null, message, t);
13151307 }
13161308
13171309 @Override
13251317 }
13261318
13271319 @Override
1328 public void info(final String message, final Throwable throwable) {
1329 logIfEnabled(FQCN, Level.INFO, null, message, throwable);
1330 }
1331
1332 @Override
1333 public void info(final Supplier<?> messageSupplier) {
1334 logIfEnabled(FQCN, Level.INFO, null, messageSupplier, (Throwable) null);
1335 }
1336
1337 @Override
1338 public void info(final Supplier<?> messageSupplier, final Throwable throwable) {
1339 logIfEnabled(FQCN, Level.INFO, null, messageSupplier, throwable);
1340 }
1341
1342 @Override
1343 public void info(final Marker marker, final Supplier<?> messageSupplier) {
1344 logIfEnabled(FQCN, Level.INFO, marker, messageSupplier, (Throwable) null);
1320 public void info(final String message, final Throwable t) {
1321 logIfEnabled(FQCN, Level.INFO, null, message, t);
1322 }
1323
1324 @Override
1325 public void info(final Supplier<?> msgSupplier) {
1326 logIfEnabled(FQCN, Level.INFO, null, msgSupplier, (Throwable) null);
1327 }
1328
1329 @Override
1330 public void info(final Supplier<?> msgSupplier, final Throwable t) {
1331 logIfEnabled(FQCN, Level.INFO, null, msgSupplier, t);
1332 }
1333
1334 @Override
1335 public void info(final Marker marker, final Supplier<?> msgSupplier) {
1336 logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, (Throwable) null);
13451337 }
13461338
13471339 @Override
13501342 }
13511343
13521344 @Override
1353 public void info(final Marker marker, final Supplier<?> messageSupplier, final Throwable throwable) {
1354 logIfEnabled(FQCN, Level.INFO, marker, messageSupplier, throwable);
1345 public void info(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {
1346 logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, t);
13551347 }
13561348
13571349 @Override
13601352 }
13611353
13621354 @Override
1363 public void info(final Marker marker, final MessageSupplier messageSupplier) {
1364 logIfEnabled(FQCN, Level.INFO, marker, messageSupplier, (Throwable) null);
1365 }
1366
1367 @Override
1368 public void info(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) {
1369 logIfEnabled(FQCN, Level.INFO, marker, messageSupplier, throwable);
1370 }
1371
1372 @Override
1373 public void info(final MessageSupplier messageSupplier) {
1374 logIfEnabled(FQCN, Level.INFO, null, messageSupplier, (Throwable) null);
1375 }
1376
1377 @Override
1378 public void info(final MessageSupplier messageSupplier, final Throwable throwable) {
1379 logIfEnabled(FQCN, Level.INFO, null, messageSupplier, throwable);
1355 public void info(final Marker marker, final MessageSupplier msgSupplier) {
1356 logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, (Throwable) null);
1357 }
1358
1359 @Override
1360 public void info(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) {
1361 logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, t);
1362 }
1363
1364 @Override
1365 public void info(final MessageSupplier msgSupplier) {
1366 logIfEnabled(FQCN, Level.INFO, null, msgSupplier, (Throwable) null);
1367 }
1368
1369 @Override
1370 public void info(final MessageSupplier msgSupplier, final Throwable t) {
1371 logIfEnabled(FQCN, Level.INFO, null, msgSupplier, t);
13801372 }
13811373
13821374 @Override
15681560 }
15691561
15701562 @Override
1571 public void log(final Level level, final Marker marker, final Message message) {
1572 logIfEnabled(FQCN, level, marker, message, message != null ? message.getThrowable() : null);
1573 }
1574
1575 @Override
1576 public void log(final Level level, final Marker marker, final Message message, final Throwable throwable) {
1577 logIfEnabled(FQCN, level, marker, message, throwable);
1563 public void log(final Level level, final Marker marker, final Message msg) {
1564 logIfEnabled(FQCN, level, marker, msg, msg != null ? msg.getThrowable() : null);
1565 }
1566
1567 @Override
1568 public void log(final Level level, final Marker marker, final Message msg, final Throwable t) {
1569 logIfEnabled(FQCN, level, marker, msg, t);
15781570 }
15791571
15801572 @Override
15831575 }
15841576
15851577 @Override
1586 public void log(final Level level, final Marker marker, final CharSequence message, final Throwable throwable) {
1587 if (isEnabled(level, marker, message, throwable)) {
1588 logMessage(FQCN, level, marker, message, throwable);
1578 public void log(final Level level, final Marker marker, final CharSequence message, final Throwable t) {
1579 if (isEnabled(level, marker, message, t)) {
1580 logMessage(FQCN, level, marker, message, t);
15891581 }
15901582 }
15911583
15951587 }
15961588
15971589 @Override
1598 public void log(final Level level, final Marker marker, final Object message, final Throwable throwable) {
1599 if (isEnabled(level, marker, message, throwable)) {
1600 logMessage(FQCN, level, marker, message, throwable);
1590 public void log(final Level level, final Marker marker, final Object message, final Throwable t) {
1591 if (isEnabled(level, marker, message, t)) {
1592 logMessage(FQCN, level, marker, message, t);
16011593 }
16021594 }
16031595
16121604 }
16131605
16141606 @Override
1615 public void log(final Level level, final Marker marker, final String message, final Throwable throwable) {
1616 logIfEnabled(FQCN, level, marker, message, throwable);
1617 }
1618
1619 @Override
1620 public void log(final Level level, final Message message) {
1621 logIfEnabled(FQCN, level, null, message, message != null ? message.getThrowable() : null);
1622 }
1623
1624 @Override
1625 public void log(final Level level, final Message message, final Throwable throwable) {
1626 logIfEnabled(FQCN, level, null, message, throwable);
1607 public void log(final Level level, final Marker marker, final String message, final Throwable t) {
1608 logIfEnabled(FQCN, level, marker, message, t);
1609 }
1610
1611 @Override
1612 public void log(final Level level, final Message msg) {
1613 logIfEnabled(FQCN, level, null, msg, msg != null ? msg.getThrowable() : null);
1614 }
1615
1616 @Override
1617 public void log(final Level level, final Message msg, final Throwable t) {
1618 logIfEnabled(FQCN, level, null, msg, t);
16271619 }
16281620
16291621 @Override
16321624 }
16331625
16341626 @Override
1635 public void log(final Level level, final CharSequence message, final Throwable throwable) {
1636 logIfEnabled(FQCN, level, null, message, throwable);
1627 public void log(final Level level, final CharSequence message, final Throwable t) {
1628 logIfEnabled(FQCN, level, null, message, t);
16371629 }
16381630
16391631 @Override
16421634 }
16431635
16441636 @Override
1645 public void log(final Level level, final Object message, final Throwable throwable) {
1646 logIfEnabled(FQCN, level, null, message, throwable);
1637 public void log(final Level level, final Object message, final Throwable t) {
1638 logIfEnabled(FQCN, level, null, message, t);
16471639 }
16481640
16491641 @Override
16571649 }
16581650
16591651 @Override
1660 public void log(final Level level, final String message, final Throwable throwable) {
1661 logIfEnabled(FQCN, level, null, message, throwable);
1662 }
1663
1664 @Override
1665 public void log(final Level level, final Supplier<?> messageSupplier) {
1666 logIfEnabled(FQCN, level, null, messageSupplier, (Throwable) null);
1667 }
1668
1669 @Override
1670 public void log(final Level level, final Supplier<?> messageSupplier, final Throwable throwable) {
1671 logIfEnabled(FQCN, level, null, messageSupplier, throwable);
1672 }
1673
1674 @Override
1675 public void log(final Level level, final Marker marker, final Supplier<?> messageSupplier) {
1676 logIfEnabled(FQCN, level, marker, messageSupplier, (Throwable) null);
1652 public void log(final Level level, final String message, final Throwable t) {
1653 logIfEnabled(FQCN, level, null, message, t);
1654 }
1655
1656 @Override
1657 public void log(final Level level, final Supplier<?> msgSupplier) {
1658 logIfEnabled(FQCN, level, null, msgSupplier, (Throwable) null);
1659 }
1660
1661 @Override
1662 public void log(final Level level, final Supplier<?> msgSupplier, final Throwable t) {
1663 logIfEnabled(FQCN, level, null, msgSupplier, t);
1664 }
1665
1666 @Override
1667 public void log(final Level level, final Marker marker, final Supplier<?> msgSupplier) {
1668 logIfEnabled(FQCN, level, marker, msgSupplier, (Throwable) null);
16771669 }
16781670
16791671 @Override
16821674 }
16831675
16841676 @Override
1685 public void log(final Level level, final Marker marker, final Supplier<?> messageSupplier, final Throwable throwable) {
1686 logIfEnabled(FQCN, level, marker, messageSupplier, throwable);
1677 public void log(final Level level, final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {
1678 logIfEnabled(FQCN, level, marker, msgSupplier, t);
16871679 }
16881680
16891681 @Override
16921684 }
16931685
16941686 @Override
1695 public void log(final Level level, final Marker marker, final MessageSupplier messageSupplier) {
1696 logIfEnabled(FQCN, level, marker, messageSupplier, (Throwable) null);
1697 }
1698
1699 @Override
1700 public void log(final Level level, final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) {
1701 logIfEnabled(FQCN, level, marker, messageSupplier, throwable);
1702 }
1703
1704 @Override
1705 public void log(final Level level, final MessageSupplier messageSupplier) {
1706 logIfEnabled(FQCN, level, null, messageSupplier, (Throwable) null);
1707 }
1708
1709 @Override
1710 public void log(final Level level, final MessageSupplier messageSupplier, final Throwable throwable) {
1711 logIfEnabled(FQCN, level, null, messageSupplier, throwable);
1687 public void log(final Level level, final Marker marker, final MessageSupplier msgSupplier) {
1688 logIfEnabled(FQCN, level, marker, msgSupplier, (Throwable) null);
1689 }
1690
1691 @Override
1692 public void log(final Level level, final Marker marker, final MessageSupplier msgSupplier, final Throwable t) {
1693 logIfEnabled(FQCN, level, marker, msgSupplier, t);
1694 }
1695
1696 @Override
1697 public void log(final Level level, final MessageSupplier msgSupplier) {
1698 logIfEnabled(FQCN, level, null, msgSupplier, (Throwable) null);
1699 }
1700
1701 @Override
1702 public void log(final Level level, final MessageSupplier msgSupplier, final Throwable t) {
1703 logIfEnabled(FQCN, level, null, msgSupplier, t);
17121704 }
17131705
17141706 @Override
18291821 }
18301822
18311823 @Override
1832 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Message message,
1833 final Throwable throwable) {
1834 if (isEnabled(level, marker, message, throwable)) {
1835 logMessageSafely(fqcn, level, marker, message, throwable);
1824 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Message msg,
1825 final Throwable t) {
1826 if (isEnabled(level, marker, msg, t)) {
1827 logMessageSafely(fqcn, level, marker, msg, t);
18361828 }
18371829 }
18381830
18391831 @Override
18401832 public void logIfEnabled(final String fqcn, final Level level, final Marker marker,
1841 final MessageSupplier messageSupplier, final Throwable throwable) {
1842 if (isEnabled(level, marker, messageSupplier, throwable)) {
1843 logMessage(fqcn, level, marker, messageSupplier, throwable);
1833 final MessageSupplier msgSupplier, final Throwable t) {
1834 if (isEnabled(level, marker, msgSupplier, t)) {
1835 logMessage(fqcn, level, marker, msgSupplier, t);
18441836 }
18451837 }
18461838
18471839 @Override
18481840 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Object message,
1849 final Throwable throwable) {
1850 if (isEnabled(level, marker, message, throwable)) {
1851 logMessage(fqcn, level, marker, message, throwable);
1841 final Throwable t) {
1842 if (isEnabled(level, marker, message, t)) {
1843 logMessage(fqcn, level, marker, message, t);
18521844 }
18531845 }
18541846
18551847 @Override
18561848 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final CharSequence message,
1857 final Throwable throwable) {
1858 if (isEnabled(level, marker, message, throwable)) {
1859 logMessage(fqcn, level, marker, message, throwable);
1860 }
1861 }
1862
1863 @Override
1864 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Supplier<?> messageSupplier,
1865 final Throwable throwable) {
1866 if (isEnabled(level, marker, messageSupplier, throwable)) {
1867 logMessage(fqcn, level, marker, messageSupplier, throwable);
1849 final Throwable t) {
1850 if (isEnabled(level, marker, message, t)) {
1851 logMessage(fqcn, level, marker, message, t);
1852 }
1853 }
1854
1855 @Override
1856 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Supplier<?> msgSupplier,
1857 final Throwable t) {
1858 if (isEnabled(level, marker, msgSupplier, t)) {
1859 logMessage(fqcn, level, marker, msgSupplier, t);
18681860 }
18691861 }
18701862
19771969
19781970 @Override
19791971 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final String message,
1980 final Throwable throwable) {
1981 if (isEnabled(level, marker, message, throwable)) {
1982 logMessage(fqcn, level, marker, message, throwable);
1972 final Throwable t) {
1973 if (isEnabled(level, marker, message, t)) {
1974 logMessage(fqcn, level, marker, message, t);
19831975 }
19841976 }
19851977
19861978 protected void logMessage(final String fqcn, final Level level, final Marker marker, final CharSequence message,
1987 final Throwable throwable) {
1988 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), throwable);
1979 final Throwable t) {
1980 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t);
19891981 }
19901982
19911983 protected void logMessage(final String fqcn, final Level level, final Marker marker, final Object message,
1992 final Throwable throwable) {
1993 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), throwable);
1984 final Throwable t) {
1985 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t);
19941986 }
19951987
19961988 protected void logMessage(final String fqcn, final Level level, final Marker marker,
1997 final MessageSupplier messageSupplier, final Throwable throwable) {
1998 final Message message = LambdaUtil.get(messageSupplier);
1999 final Throwable effectiveThrowable = (throwable == null && message != null)
2000 ? message.getThrowable()
2001 : throwable;
2002 logMessageSafely(fqcn, level, marker, message, effectiveThrowable);
2003 }
2004
2005 protected void logMessage(final String fqcn, final Level level, final Marker marker, final Supplier<?> messageSupplier,
2006 final Throwable throwable) {
2007 final Message message = LambdaUtil.getMessage(messageSupplier, messageFactory);
2008 final Throwable effectiveThrowable = (throwable == null && message != null)
2009 ? message.getThrowable()
2010 : throwable;
2011 logMessageSafely(fqcn, level, marker, message, effectiveThrowable);
1989 final MessageSupplier msgSupplier, final Throwable t) {
1990 final Message message = LambdaUtil.get(msgSupplier);
1991 logMessageSafely(fqcn, level, marker, message, (t == null && message != null) ? message.getThrowable() : t);
1992 }
1993
1994 protected void logMessage(final String fqcn, final Level level, final Marker marker, final Supplier<?> msgSupplier,
1995 final Throwable t) {
1996 final Message message = LambdaUtil.getMessage(msgSupplier, messageFactory);
1997 logMessageSafely(fqcn, level, marker, message, (t == null && message != null) ? message.getThrowable() : t);
20121998 }
20131999
20142000 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
2015 final Throwable throwable) {
2016 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), throwable);
2001 final Throwable t) {
2002 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t);
20172003 }
20182004
20192005 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message) {
20972083 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20982084 }
20992085
2100 @Override
21012086 public void logMessage(final Level level, final Marker marker, final String fqcn, final StackTraceElement location,
21022087 final Message message, final Throwable throwable) {
21032088 try {
21042089 incrementRecursionDepth();
21052090 log(level, marker, fqcn, location, message, throwable);
2106 } catch (Throwable ex) {
2107 handleLogMessageException(ex, fqcn, message);
2091 } catch (Throwable t) {
2092 handleLogMessageException(t, fqcn, message);
21082093 } finally {
21092094 decrementRecursionDepth();
21102095 ReusableMessageFactory.release(message);
21192104 @Override
21202105 public void printf(final Level level, final Marker marker, final String format, final Object... params) {
21212106 if (isEnabled(level, marker, format, params)) {
2122 final Message message = new StringFormattedMessage(format, params);
2123 logMessageSafely(FQCN, level, marker, message, message.getThrowable());
2107 final Message msg = new StringFormattedMessage(format, params);
2108 logMessageSafely(FQCN, level, marker, msg, msg.getThrowable());
21242109 }
21252110 }
21262111
21272112 @Override
21282113 public void printf(final Level level, final String format, final Object... params) {
21292114 if (isEnabled(level, null, format, params)) {
2130 final Message message = new StringFormattedMessage(format, params);
2131 logMessageSafely(FQCN, level, null, message, message.getThrowable());
2115 final Message msg = new StringFormattedMessage(format, params);
2116 logMessageSafely(FQCN, level, null, msg, msg.getThrowable());
21322117 }
21332118 }
21342119
21352120 @PerformanceSensitive
21362121 // NOTE: This is a hot method. Current implementation compiles to 30 bytes of byte code.
21372122 // This is within the 35 byte MaxInlineSize threshold. Modify with care!
2138 private void logMessageSafely(final String fqcn, final Level level, final Marker marker, final Message message,
2123 private void logMessageSafely(final String fqcn, final Level level, final Marker marker, final Message msg,
21392124 final Throwable throwable) {
21402125 try {
2141 logMessageTrackRecursion(fqcn, level, marker, message, throwable);
2126 logMessageTrackRecursion(fqcn, level, marker, msg, throwable);
21422127 } finally {
21432128 // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString())
2144 ReusableMessageFactory.release(message);
2129 ReusableMessageFactory.release(msg);
21452130 }
21462131 }
21472132
21512136 private void logMessageTrackRecursion(final String fqcn,
21522137 final Level level,
21532138 final Marker marker,
2154 final Message message,
2139 final Message msg,
21552140 final Throwable throwable) {
21562141 try {
21572142 incrementRecursionDepth(); // LOG4J2-1518, LOG4J2-2031
2158 tryLogMessage(fqcn, getLocation(fqcn), level, marker, message, throwable);
2143 tryLogMessage(fqcn, getLocation(fqcn), level, marker, msg, throwable);
21592144 } finally {
21602145 decrementRecursionDepth();
21612146 }
21732158 private static void incrementRecursionDepth() {
21742159 getRecursionDepthHolder()[0]++;
21752160 }
2176
21772161 private static void decrementRecursionDepth() {
2178 int newDepth = --getRecursionDepthHolder()[0];
2179 if (newDepth < 0) {
2180 throw new IllegalStateException("Recursion depth became negative: " + newDepth);
2162 final int[] depth = getRecursionDepthHolder();
2163 depth[0]--;
2164 if (depth[0] < 0) {
2165 throw new IllegalStateException("Recursion depth became negative: " + depth[0]);
21812166 }
21822167 }
21832168
21982183 final StackTraceElement location,
21992184 final Level level,
22002185 final Marker marker,
2201 final Message message,
2186 final Message msg,
22022187 final Throwable throwable) {
22032188 try {
2204 log(level, marker, fqcn, location, message, throwable);
2189 log(level, marker, fqcn, location, msg, throwable);
22052190 } catch (final Throwable t) {
22062191 // LOG4J2-1990 Log4j2 suppresses all exceptions that occur once application called the logger
2207 handleLogMessageException(t, fqcn, message);
2192 handleLogMessageException(t, fqcn, msg);
22082193 }
22092194 }
22102195
22172202
22182203 // LOG4J2-1990 Log4j2 suppresses all exceptions that occur once application called the logger
22192204 // TODO Configuration setting to propagate exceptions back to the caller *if requested*
2220 private void handleLogMessageException(final Throwable throwable, final String fqcn, final Message message) {
2221 if (throwable instanceof LoggingException) {
2222 throw (LoggingException) throwable;
2223 }
2224 StatusLogger.getLogger().warn("{} caught {} logging {}: {}",
2225 fqcn,
2226 throwable.getClass().getName(),
2227 message.getClass().getSimpleName(),
2228 message.getFormat(),
2229 throwable);
2230 }
2231
2232 @Override
2233 public <T extends Throwable> T throwing(final T throwable) {
2234 return throwing(FQCN, Level.ERROR, throwable);
2235 }
2236
2237 @Override
2238 public <T extends Throwable> T throwing(final Level level, final T throwable) {
2239 return throwing(FQCN, level, throwable);
2205 private void handleLogMessageException(final Throwable exception, final String fqcn, final Message msg) {
2206 if (exception instanceof LoggingException) {
2207 throw (LoggingException) exception;
2208 }
2209 final String format = msg.getFormat();
2210 final int formatLength = format == null ? 4 : format.length();
2211 final StringBuilder sb = new StringBuilder(formatLength + 100);
2212 sb.append(fqcn);
2213 sb.append(" caught ");
2214 sb.append(exception.getClass().getName());
2215 sb.append(" logging ");
2216 sb.append(msg.getClass().getSimpleName());
2217 sb.append(": ");
2218 sb.append(format);
2219 StatusLogger.getLogger().warn(sb.toString(), exception);
2220 }
2221
2222 @Override
2223 public <T extends Throwable> T throwing(final T t) {
2224 return throwing(FQCN, Level.ERROR, t);
2225 }
2226
2227 @Override
2228 public <T extends Throwable> T throwing(final Level level, final T t) {
2229 return throwing(FQCN, level, t);
22402230 }
22412231
22422232 /**
22452235 * @param <T> the type of the Throwable.
22462236 * @param fqcn the fully qualified class name of this Logger implementation.
22472237 * @param level The logging Level.
2248 * @param throwable The Throwable.
2238 * @param t The Throwable.
22492239 * @return the Throwable.
22502240 */
2251 protected <T extends Throwable> T throwing(final String fqcn, final Level level, final T throwable) {
2241 protected <T extends Throwable> T throwing(final String fqcn, final Level level, final T t) {
22522242 if (isEnabled(level, THROWING_MARKER, (Object) null, null)) {
2253 logMessageSafely(fqcn, level, THROWING_MARKER, throwingMsg(throwable), throwable);
2254 }
2255 return throwable;
2256 }
2257
2258 protected Message throwingMsg(final Throwable throwable) {
2243 logMessageSafely(fqcn, level, THROWING_MARKER, throwingMsg(t), t);
2244 }
2245 return t;
2246 }
2247
2248 protected Message throwingMsg(final Throwable t) {
22592249 return messageFactory.newMessage(THROWING);
22602250 }
22612251
22622252 @Override
2263 public void trace(final Marker marker, final Message message) {
2264 logIfEnabled(FQCN, Level.TRACE, marker, message, message != null ? message.getThrowable() : null);
2265 }
2266
2267 @Override
2268 public void trace(final Marker marker, final Message message, final Throwable throwable) {
2269 logIfEnabled(FQCN, Level.TRACE, marker, message, throwable);
2253 public void trace(final Marker marker, final Message msg) {
2254 logIfEnabled(FQCN, Level.TRACE, marker, msg, msg != null ? msg.getThrowable() : null);
2255 }
2256
2257 @Override
2258 public void trace(final Marker marker, final Message msg, final Throwable t) {
2259 logIfEnabled(FQCN, Level.TRACE, marker, msg, t);
22702260 }
22712261
22722262 @Override
22752265 }
22762266
22772267 @Override
2278 public void trace(final Marker marker, final CharSequence message, final Throwable throwable) {
2279 logIfEnabled(FQCN, Level.TRACE, marker, message, throwable);
2268 public void trace(final Marker marker, final CharSequence message, final Throwable t) {
2269 logIfEnabled(FQCN, Level.TRACE, marker, message, t);
22802270 }
22812271
22822272 @Override
22852275 }
22862276
22872277 @Override
2288 public void trace(final Marker marker, final Object message, final Throwable throwable) {
2289 logIfEnabled(FQCN, Level.TRACE, marker, message, throwable);
2278 public void trace(final Marker marker, final Object message, final Throwable t) {
2279 logIfEnabled(FQCN, Level.TRACE, marker, message, t);
22902280 }
22912281
22922282 @Override
23002290 }
23012291
23022292 @Override
2303 public void trace(final Marker marker, final String message, final Throwable throwable) {
2304 logIfEnabled(FQCN, Level.TRACE, marker, message, throwable);
2305 }
2306
2307 @Override
2308 public void trace(final Message message) {
2309 logIfEnabled(FQCN, Level.TRACE, null, message, message != null ? message.getThrowable() : null);
2310 }
2311
2312 @Override
2313 public void trace(final Message message, final Throwable throwable) {
2314 logIfEnabled(FQCN, Level.TRACE, null, message, throwable);
2293 public void trace(final Marker marker, final String message, final Throwable t) {
2294 logIfEnabled(FQCN, Level.TRACE, marker, message, t);
2295 }
2296
2297 @Override
2298 public void trace(final Message msg) {
2299 logIfEnabled(FQCN, Level.TRACE, null, msg, msg != null ? msg.getThrowable() : null);
2300 }
2301
2302 @Override
2303 public void trace(final Message msg, final Throwable t) {
2304 logIfEnabled(FQCN, Level.TRACE, null, msg, t);
23152305 }
23162306
23172307 @Override
23202310 }
23212311
23222312 @Override
2323 public void trace(final CharSequence message, final Throwable throwable) {
2324 logIfEnabled(FQCN, Level.TRACE, null, message, throwable);
2313 public void trace(final CharSequence message, final Throwable t) {
2314 logIfEnabled(FQCN, Level.TRACE, null, message, t);
23252315 }
23262316
23272317 @Override
23302320 }
23312321
23322322 @Override
2333 public void trace(final Object message, final Throwable throwable) {
2334 logIfEnabled(FQCN, Level.TRACE, null, message, throwable);
2323 public void trace(final Object message, final Throwable t) {
2324 logIfEnabled(FQCN, Level.TRACE, null, message, t);
23352325 }
23362326
23372327 @Override
23452335 }
23462336
23472337 @Override
2348 public void trace(final String message, final Throwable throwable) {
2349 logIfEnabled(FQCN, Level.TRACE, null, message, throwable);
2350 }
2351
2352 @Override
2353 public void trace(final Supplier<?> messageSupplier) {
2354 logIfEnabled(FQCN, Level.TRACE, null, messageSupplier, (Throwable) null);
2355 }
2356
2357 @Override
2358 public void trace(final Supplier<?> messageSupplier, final Throwable throwable) {
2359 logIfEnabled(FQCN, Level.TRACE, null, messageSupplier, throwable);
2360 }
2361
2362 @Override
2363 public void trace(final Marker marker, final Supplier<?> messageSupplier) {
2364 logIfEnabled(FQCN, Level.TRACE, marker, messageSupplier, (Throwable) null);
2338 public void trace(final String message, final Throwable t) {
2339 logIfEnabled(FQCN, Level.TRACE, null, message, t);
2340 }
2341
2342 @Override
2343 public void trace(final Supplier<?> msgSupplier) {
2344 logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, (Throwable) null);
2345 }
2346
2347 @Override
2348 public void trace(final Supplier<?> msgSupplier, final Throwable t) {
2349 logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, t);
2350 }
2351
2352 @Override
2353 public void trace(final Marker marker, final Supplier<?> msgSupplier) {
2354 logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, (Throwable) null);
23652355 }
23662356
23672357 @Override
23702360 }
23712361
23722362 @Override
2373 public void trace(final Marker marker, final Supplier<?> messageSupplier, final Throwable throwable) {
2374 logIfEnabled(FQCN, Level.TRACE, marker, messageSupplier, throwable);
2363 public void trace(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {
2364 logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, t);
23752365 }
23762366
23772367 @Override
23802370 }
23812371
23822372 @Override
2383 public void trace(final Marker marker, final MessageSupplier messageSupplier) {
2384 logIfEnabled(FQCN, Level.TRACE, marker, messageSupplier, (Throwable) null);
2385 }
2386
2387 @Override
2388 public void trace(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) {
2389 logIfEnabled(FQCN, Level.TRACE, marker, messageSupplier, throwable);
2390 }
2391
2392 @Override
2393 public void trace(final MessageSupplier messageSupplier) {
2394 logIfEnabled(FQCN, Level.TRACE, null, messageSupplier, (Throwable) null);
2395 }
2396
2397 @Override
2398 public void trace(final MessageSupplier messageSupplier, final Throwable throwable) {
2399 logIfEnabled(FQCN, Level.TRACE, null, messageSupplier, throwable);
2373 public void trace(final Marker marker, final MessageSupplier msgSupplier) {
2374 logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, (Throwable) null);
2375 }
2376
2377 @Override
2378 public void trace(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) {
2379 logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, t);
2380 }
2381
2382 @Override
2383 public void trace(final MessageSupplier msgSupplier) {
2384 logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, (Throwable) null);
2385 }
2386
2387 @Override
2388 public void trace(final MessageSupplier msgSupplier, final Throwable t) {
2389 logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, t);
24002390 }
24012391
24022392 @Override
25812571 }
25822572
25832573 @Override
2584 public void warn(final Marker marker, final Message message) {
2585 logIfEnabled(FQCN, Level.WARN, marker, message, message != null ? message.getThrowable() : null);
2586 }
2587
2588 @Override
2589 public void warn(final Marker marker, final Message message, final Throwable throwable) {
2590 logIfEnabled(FQCN, Level.WARN, marker, message, throwable);
2574 public void warn(final Marker marker, final Message msg) {
2575 logIfEnabled(FQCN, Level.WARN, marker, msg, msg != null ? msg.getThrowable() : null);
2576 }
2577
2578 @Override
2579 public void warn(final Marker marker, final Message msg, final Throwable t) {
2580 logIfEnabled(FQCN, Level.WARN, marker, msg, t);
25912581 }
25922582
25932583 @Override
25962586 }
25972587
25982588 @Override
2599 public void warn(final Marker marker, final CharSequence message, final Throwable throwable) {
2600 logIfEnabled(FQCN, Level.WARN, marker, message, throwable);
2589 public void warn(final Marker marker, final CharSequence message, final Throwable t) {
2590 logIfEnabled(FQCN, Level.WARN, marker, message, t);
26012591 }
26022592
26032593 @Override
26062596 }
26072597
26082598 @Override
2609 public void warn(final Marker marker, final Object message, final Throwable throwable) {
2610 logIfEnabled(FQCN, Level.WARN, marker, message, throwable);
2599 public void warn(final Marker marker, final Object message, final Throwable t) {
2600 logIfEnabled(FQCN, Level.WARN, marker, message, t);
26112601 }
26122602
26132603 @Override
26212611 }
26222612
26232613 @Override
2624 public void warn(final Marker marker, final String message, final Throwable throwable) {
2625 logIfEnabled(FQCN, Level.WARN, marker, message, throwable);
2626 }
2627
2628 @Override
2629 public void warn(final Message message) {
2630 logIfEnabled(FQCN, Level.WARN, null, message, message != null ? message.getThrowable() : null);
2631 }
2632
2633 @Override
2634 public void warn(final Message message, final Throwable throwable) {
2635 logIfEnabled(FQCN, Level.WARN, null, message, throwable);
2614 public void warn(final Marker marker, final String message, final Throwable t) {
2615 logIfEnabled(FQCN, Level.WARN, marker, message, t);
2616 }
2617
2618 @Override
2619 public void warn(final Message msg) {
2620 logIfEnabled(FQCN, Level.WARN, null, msg, msg != null ? msg.getThrowable() : null);
2621 }
2622
2623 @Override
2624 public void warn(final Message msg, final Throwable t) {
2625 logIfEnabled(FQCN, Level.WARN, null, msg, t);
26362626 }
26372627
26382628 @Override
26412631 }
26422632
26432633 @Override
2644 public void warn(final CharSequence message, final Throwable throwable) {
2645 logIfEnabled(FQCN, Level.WARN, null, message, throwable);
2634 public void warn(final CharSequence message, final Throwable t) {
2635 logIfEnabled(FQCN, Level.WARN, null, message, t);
26462636 }
26472637
26482638 @Override
26512641 }
26522642
26532643 @Override
2654 public void warn(final Object message, final Throwable throwable) {
2655 logIfEnabled(FQCN, Level.WARN, null, message, throwable);
2644 public void warn(final Object message, final Throwable t) {
2645 logIfEnabled(FQCN, Level.WARN, null, message, t);
26562646 }
26572647
26582648 @Override
26662656 }
26672657
26682658 @Override
2669 public void warn(final String message, final Throwable throwable) {
2670 logIfEnabled(FQCN, Level.WARN, null, message, throwable);
2671 }
2672
2673 @Override
2674 public void warn(final Supplier<?> messageSupplier) {
2675 logIfEnabled(FQCN, Level.WARN, null, messageSupplier, (Throwable) null);
2676 }
2677
2678 @Override
2679 public void warn(final Supplier<?> messageSupplier, final Throwable throwable) {
2680 logIfEnabled(FQCN, Level.WARN, null, messageSupplier, throwable);
2681 }
2682
2683 @Override
2684 public void warn(final Marker marker, final Supplier<?> messageSupplier) {
2685 logIfEnabled(FQCN, Level.WARN, marker, messageSupplier, (Throwable) null);
2659 public void warn(final String message, final Throwable t) {
2660 logIfEnabled(FQCN, Level.WARN, null, message, t);
2661 }
2662
2663 @Override
2664 public void warn(final Supplier<?> msgSupplier) {
2665 logIfEnabled(FQCN, Level.WARN, null, msgSupplier, (Throwable) null);
2666 }
2667
2668 @Override
2669 public void warn(final Supplier<?> msgSupplier, final Throwable t) {
2670 logIfEnabled(FQCN, Level.WARN, null, msgSupplier, t);
2671 }
2672
2673 @Override
2674 public void warn(final Marker marker, final Supplier<?> msgSupplier) {
2675 logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, (Throwable) null);
26862676 }
26872677
26882678 @Override
26912681 }
26922682
26932683 @Override
2694 public void warn(final Marker marker, final Supplier<?> messageSupplier, final Throwable throwable) {
2695 logIfEnabled(FQCN, Level.WARN, marker, messageSupplier, throwable);
2684 public void warn(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {
2685 logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, t);
26962686 }
26972687
26982688 @Override
27012691 }
27022692
27032693 @Override
2704 public void warn(final Marker marker, final MessageSupplier messageSupplier) {
2705 logIfEnabled(FQCN, Level.WARN, marker, messageSupplier, (Throwable) null);
2706 }
2707
2708 @Override
2709 public void warn(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) {
2710 logIfEnabled(FQCN, Level.WARN, marker, messageSupplier, throwable);
2711 }
2712
2713 @Override
2714 public void warn(final MessageSupplier messageSupplier) {
2715 logIfEnabled(FQCN, Level.WARN, null, messageSupplier, (Throwable) null);
2716 }
2717
2718 @Override
2719 public void warn(final MessageSupplier messageSupplier, final Throwable throwable) {
2720 logIfEnabled(FQCN, Level.WARN, null, messageSupplier, throwable);
2694 public void warn(final Marker marker, final MessageSupplier msgSupplier) {
2695 logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, (Throwable) null);
2696 }
2697
2698 @Override
2699 public void warn(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) {
2700 logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, t);
2701 }
2702
2703 @Override
2704 public void warn(final MessageSupplier msgSupplier) {
2705 logIfEnabled(FQCN, Level.WARN, null, msgSupplier, (Throwable) null);
2706 }
2707
2708 @Override
2709 public void warn(final MessageSupplier msgSupplier, final Throwable t) {
2710 logIfEnabled(FQCN, Level.WARN, null, msgSupplier, t);
27212711 }
27222712
27232713 @Override
28382828 protected boolean requiresLocation() {
28392829 return false;
28402830 }
2841
2842 /**
2843 * Construct a trace log event.
2844 * @return a LogBuilder.
2845 * @since 2.13.0
2846 */
2847 @Override
2848 public LogBuilder atTrace() {
2849 return atLevel(Level.TRACE);
2850 }
2851 /**
2852 * Construct a debug log event.
2853 * @return a LogBuilder.
2854 * @since 2.13.0
2855 */
2856 @Override
2857 public LogBuilder atDebug() {
2858 return atLevel(Level.DEBUG);
2859 }
2860 /**
2861 * Construct an informational log event.
2862 * @return a LogBuilder.
2863 * @since 2.13.0
2864 */
2865 @Override
2866 public LogBuilder atInfo() {
2867 return atLevel(Level.INFO);
2868 }
2869 /**
2870 * Construct a warning log event.
2871 * @return a LogBuilder.
2872 * @since 2.13.0
2873 */
2874 @Override
2875 public LogBuilder atWarn() {
2876 return atLevel(Level.WARN);
2877 }
2878 /**
2879 * Construct an error log event.
2880 * @return a LogBuilder.
2881 * @since 2.13.0
2882 */
2883 @Override
2884 public LogBuilder atError() {
2885 return atLevel(Level.ERROR);
2886 }
2887 /**
2888 * Construct a fatal log event.
2889 * @return a LogBuilder.
2890 * @since 2.13.0
2891 */
2892 @Override
2893 public LogBuilder atFatal() {
2894 return atLevel(Level.FATAL);
2895 }
2896 /**
2897 * Construct a fatal log event.
2898 * @return a LogBuilder.
2899 * @since 2.13.0
2900 */
2901 @Override
2902 public LogBuilder always() {
2903 DefaultLogBuilder builder = logBuilder.get();
2904 if (builder.isInUse()) {
2905 return new DefaultLogBuilder(this);
2906 }
2907 return builder.reset(Level.OFF);
2908 }
2909 /**
2910 * Construct a log event.
2911 * @return a LogBuilder.
2912 * @since 2.13.0
2913 */
2914 @Override
2915 public LogBuilder atLevel(Level level) {
2916 if (isEnabled(level)) {
2917 return getLogBuilder(level).reset(level);
2918 } else {
2919 return LogBuilder.NOOP;
2920 }
2921 }
2922
2923 private DefaultLogBuilder getLogBuilder(Level level) {
2924 DefaultLogBuilder builder = logBuilder.get();
2925 return Constants.ENABLE_THREADLOCALS && !builder.isInUse() ? builder : new DefaultLogBuilder(this, level);
2926 }
2927
2928 private void readObject (final ObjectInputStream s) throws ClassNotFoundException, IOException {
2929 s.defaultReadObject( );
2930 try {
2931 Field f = this.getClass().getDeclaredField("logBuilder");
2932 f.setAccessible(true);
2933 f.set(this, new LocalLogBuilder(this));
2934 } catch (NoSuchFieldException | IllegalAccessException ex) {
2935 StatusLogger.getLogger().warn("Unable to initialize LogBuilder");
2936 }
2937 }
2938
2939 private class LocalLogBuilder extends ThreadLocal<DefaultLogBuilder> {
2940 private AbstractLogger logger;
2941 LocalLogBuilder(AbstractLogger logger) {
2942 this.logger = logger;
2943 }
2944
2945 @Override
2946 protected DefaultLogBuilder initialValue() {
2947 return new DefaultLogBuilder(logger);
2948 }
2949 }
29502831 }
1818 import java.util.HashSet;
1919 import java.util.Map;
2020 import java.util.Set;
21 import java.util.WeakHashMap;
2122 import java.util.concurrent.ConcurrentHashMap;
2223 import java.util.concurrent.ConcurrentMap;
2324 import java.util.concurrent.locks.ReadWriteLock;
1818 import java.util.Collections;
1919 import java.util.HashMap;
2020 import java.util.Map;
21 import java.util.Objects;
2221
2322 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2423 import org.apache.logging.log4j.util.SortedArrayStringMap;
213212 @Override
214213 public Map<String, String> getCopy() {
215214 final StringMap map = localMap.get();
216 return map == null ? new HashMap<>() : map.toMap();
215 return map == null ? new HashMap<String, String>() : map.toMap();
217216 }
218217
219218 /**
234233 @Override
235234 public boolean isEmpty() {
236235 final StringMap map = localMap.get();
237 return map == null || map.isEmpty();
236 return map == null || map.size() == 0;
238237 }
239238
240239 @Override
266265 final ThreadContextMap other = (ThreadContextMap) obj;
267266 final Map<String, String> map = this.getImmutableMapOrNull();
268267 final Map<String, String> otherMap = other.getImmutableMapOrNull();
269 return Objects.equals(map, otherMap);
268 if (map == null) {
269 if (otherMap != null) {
270 return false;
271 }
272 } else if (!map.equals(otherMap)) {
273 return false;
274 }
275 return true;
270276 }
271277 }
1818 import java.util.Collections;
1919 import java.util.HashMap;
2020 import java.util.Map;
21 import java.util.Objects;
2221
2322 import org.apache.logging.log4j.util.BiConsumer;
2423 import org.apache.logging.log4j.util.ReadOnlyStringMap;
8584 return;
8685 }
8786 Map<String, String> map = localMap.get();
88 map = map == null ? new HashMap<>(1) : new HashMap<>(map);
87 map = map == null ? new HashMap<String, String>(1) : new HashMap<>(map);
8988 map.put(key, value);
9089 localMap.set(Collections.unmodifiableMap(map));
9190 }
9594 return;
9695 }
9796 Map<String, String> map = localMap.get();
98 map = map == null ? new HashMap<>(m.size()) : new HashMap<>(map);
97 map = map == null ? new HashMap<String, String>(m.size()) : new HashMap<>(map);
9998 for (final Map.Entry<String, String> e : m.entrySet()) {
10099 map.put(e.getKey(), e.getValue());
101100 }
185184 @Override
186185 public Map<String, String> getCopy() {
187186 final Map<String, String> map = localMap.get();
188 return map == null ? new HashMap<>() : new HashMap<>(map);
187 return map == null ? new HashMap<String, String>() : new HashMap<>(map);
189188 }
190189
191190 @Override
196195 @Override
197196 public boolean isEmpty() {
198197 final Map<String, String> map = localMap.get();
199 return map == null || map.isEmpty();
198 return map == null || map.size() == 0;
200199 }
201200
202201 @Override
241240 final ThreadContextMap other = (ThreadContextMap) obj;
242241 final Map<String, String> map = this.localMap.get();
243242 final Map<String, String> otherMap = other.getImmutableMapOrNull();
244 return Objects.equals(map, otherMap);
243 if (map == null) {
244 if (otherMap != null) {
245 return false;
246 }
247 } else if (!map.equals(otherMap)) {
248 return false;
249 }
250 return true;
245251 }
246252 }
169169 @Override
170170 public String peek() {
171171 final MutableThreadContextStack values = STACK.get();
172 if (values == null || values.isEmpty()) {
172 if (values == null || values.size() == 0) {
173173 return Strings.EMPTY;
174174 }
175175 return values.peek();
181181 return Strings.EMPTY;
182182 }
183183 final MutableThreadContextStack values = STACK.get();
184 if (values == null || values.isEmpty()) {
184 if (values == null || values.size() == 0) {
185185 // Like version 1.2
186186 return Strings.EMPTY;
187187 }
206206 return false;
207207 }
208208 final MutableThreadContextStack values = STACK.get();
209 if (values == null || values.isEmpty()) {
209 if (values == null || values.size() == 0) {
210210 return false;
211211 }
212212 final MutableThreadContextStack copy = (MutableThreadContextStack) values.copy();
258258 public Object[] toArray() {
259259 final MutableThreadContextStack result = STACK.get();
260260 if (result == null) {
261 return Strings.EMPTY_ARRAY;
261 return new String[0];
262262 }
263263 return result.toArray(new Object[result.size()]);
264264 }
1818 import java.util.Collections;
1919 import java.util.HashMap;
2020 import java.util.Map;
21 import java.util.Objects;
2221
2322 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2423 import org.apache.logging.log4j.util.StringMap;
201200 @Override
202201 public Map<String, String> getCopy() {
203202 final StringMap map = localMap.get();
204 return map == null ? new HashMap<>() : map.toMap();
203 return map == null ? new HashMap<String, String>() : map.toMap();
205204 }
206205
207206 /**
226225 @Override
227226 public boolean isEmpty() {
228227 final StringMap map = localMap.get();
229 return map == null || map.isEmpty();
228 return map == null || map.size() == 0;
230229 }
231230
232231 @Override
258257 final ThreadContextMap other = (ThreadContextMap) obj;
259258 final Map<String, String> map = this.getImmutableMapOrNull();
260259 final Map<String, String> otherMap = other.getImmutableMapOrNull();
261 return Objects.equals(map, otherMap);
260 if (map == null) {
261 if (otherMap != null) {
262 return false;
263 }
264 } else if (!map.equals(otherMap)) {
265 return false;
266 }
267 return true;
262268 }
263269 }
2929 Object getExternalContext();
3030
3131 /**
32 * Retrieve an object by its name.
33 * @param key The object's key.
34 * @since 2.13.0
35 */
36 default Object getObject(String key) {
37 return null;
38 }
39
40 /**
41 * Store an object into the LoggerContext by name for later use.
42 * @param key The object's key.
43 * @param value The object.
44 * @return The previous object or null.
45 * @since 2.13.0
46 */
47 default Object putObject(String key, Object value) {
48 return null;
49 }
50
51 /**
52 * Store an object into the LoggerContext by name for later use if an object is not already stored with that key.
53 * @param key The object's key.
54 * @param value The object.
55 * @return The previous object or null.
56 * @since 2.13.0
57 */
58 default Object putObjectIfAbsent(String key, Object value) {
59 return null;
60 }
61
62 /**
63 * Remove an object if it is present.
64 * @param key The object's key.
65 * @return The object if it was present, null if it was not.
66 * @since 2.13.0
67 */
68 default Object removeObject(String key) {
69 return null;
70 }
71
72 /**
73 * Remove an object if it is present and the provided object is stored.
74 * @param key The object's key.
75 * @param value The object.
76 * @return The object if it was present, null if it was not.
77 * @since 2.13.0
78 */
79 default boolean removeObject(String key, Object value) {
80 return false;
81 }
82
83 /**
8432 * Returns an ExtendedLogger.
8533 * @param name The name of the Logger to return.
8634 * @return The logger with the specified name.
8735 */
8836 ExtendedLogger getLogger(String name);
89
90 /**
91 * Returns an ExtendedLogger using the fully qualified name of the Class as the Logger name.
92 * @param cls The Class whose name should be used as the Logger name.
93 * @return The logger.
94 * @since 2.14.0
95 */
96 default ExtendedLogger getLogger(Class<?> cls) {
97 final String canonicalName = cls.getCanonicalName();
98 return getLogger(canonicalName != null ? canonicalName : cls.getName());
99 }
10037
10138 /**
10239 * Returns an ExtendedLogger.
10643 * @return The logger with the specified name.
10744 */
10845 ExtendedLogger getLogger(String name, MessageFactory messageFactory);
109
110 /**
111 * Returns an ExtendedLogger using the fully qualified name of the Class as the Logger name.
112 * @param cls The Class whose name should be used as the Logger name.
113 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the
114 * logger but will log a warning if mismatched.
115 * @return The logger.
116 * @since 2.14.0
117 */
118 default ExtendedLogger getLogger(Class<?> cls, MessageFactory messageFactory) {
119 final String canonicalName = cls.getCanonicalName();
120 return getLogger(canonicalName != null ? canonicalName : cls.getName(), messageFactory);
121 }
12246
12347 /**
12448 * Detects if a Logger with the specified name exists.
2121 * Implemented by factories that create {@link LoggerContext} objects.
2222 */
2323 public interface LoggerContextFactory {
24
25 /**
26 * Shuts down the LoggerContext.
27 * @param fqcn The fully qualified class name of the caller.
28 * @param loader The ClassLoader to use or null.
29 * @param currentContext If true shuts down the current Context, if false shuts down the Context appropriate
30 * for the caller if a more appropriate Context can be determined.
31 * @param allContexts if true all LoggerContexts that can be located will be shutdown.
32 * @since 2.13.0
33 */
34 default void shutdown(String fqcn, ClassLoader loader, boolean currentContext, boolean allContexts) {
35 if (hasContext(fqcn, loader, currentContext)) {
36 LoggerContext ctx = getContext(fqcn, loader, null, currentContext);
37 if (ctx instanceof Terminable) {
38 ((Terminable) ctx).terminate();
39 }
40 }
41 }
42
43 /**
44 * Checks to see if a LoggerContext is installed. The default implementation returns false.
45 * @param fqcn The fully qualified class name of the caller.
46 * @param loader The ClassLoader to use or null.
47 * @param currentContext If true returns the current Context, if false returns the Context appropriate
48 * for the caller if a more appropriate Context can be determined.
49 * @return true if a LoggerContext has been installed, false otherwise.
50 * @since 2.13.0
51 */
52 default boolean hasContext(String fqcn, ClassLoader loader, boolean currentContext) {
53 return false;
54 }
5524
5625 /**
5726 * Creates a {@link LoggerContext}.
8655 * @param context The context to remove.
8756 */
8857 void removeContext(LoggerContext context);
89
90 /**
91 * Determines whether or not this factory and perhaps the underlying
92 * ContextSelector behavior depend on the callers classloader.
93 *
94 * This method should be overridden by implementations, however a default method is provided which always
95 * returns {@code true} to preserve the old behavior.
96 *
97 * @since 2.15.0
98 */
99 default boolean isClassLoaderDependent() {
100 return true;
101 }
10258 }
1919 import java.util.Collection;
2020 import java.util.Iterator;
2121 import java.util.List;
22 import java.util.Objects;
2322
2423 import org.apache.logging.log4j.ThreadContext.ContextStack;
2524 import org.apache.logging.log4j.util.StringBuilderFormattable;
211210
212211 @Override
213212 public int hashCode() {
214 return 31 + Objects.hashCode(list);
213 final int prime = 31;
214 int result = 1;
215 result = prime * result + ((this.list == null) ? 0 : this.list.hashCode());
216 return result;
215217 }
216218
217219 @Override
227229 }
228230 final ThreadContextStack other = (ThreadContextStack) obj;
229231 final List<String> otherAsList = other.asList();
230 return Objects.equals(this.list, otherAsList);
232 if (this.list == null) {
233 if (otherAsList != null) {
234 return false;
235 }
236 } else if (!this.list.equals(otherAsList)) {
237 return false;
238 }
239 return true;
231240 }
232241
233242 @Override
8080 void put(final String key, final String value);
8181
8282 /**
83 * Removes the context identified by the <code>key</code>
83 * Removes the the context identified by the <code>key</code>
8484 * parameter.
8585 * @param key The key to remove.
8686 */
268268 msgLock.unlock();
269269 }
270270 // LOG4J2-1813 if system property "log4j2.debug" is defined, all status logging is enabled
271 if (isDebugPropertyEnabled() || (listeners.size() <= 0)) {
271 if (isDebugPropertyEnabled()) {
272272 logger.logMessage(fqcn, level, marker, msg, t);
273273 } else {
274 for (final StatusListener listener : listeners) {
275 if (data.getLevel().isMoreSpecificThan(listener.getStatusLevel())) {
276 listener.log(data);
274 if (listeners.size() > 0) {
275 for (final StatusListener listener : listeners) {
276 if (data.getLevel().isMoreSpecificThan(listener.getStatusLevel())) {
277 listener.log(data);
278 }
277279 }
280 } else {
281 logger.logMessage(fqcn, level, marker, msg, t);
278282 }
279283 }
280284 }
1818 import java.lang.reflect.Method;
1919
2020 import org.apache.logging.log4j.LoggingException;
21 import org.apache.logging.log4j.status.StatusLogger;
2122
2223 /**
2324 * Base64 encodes Strings. This utility is only necessary because the mechanism to do this changed in Java 8 and
2727 * is present in the classpath.
2828 */
2929 public static final boolean IS_WEB_APP = PropertiesUtil.getProperties().getBooleanProperty(
30 "log4j2.is.webapp", isClassAvailable("javax.servlet.Servlet")
31 || isClassAvailable("jakarta.servlet.Servlet"));
30 "log4j2.is.webapp", isClassAvailable("javax.servlet.Servlet"));
3231
3332 /**
3433 * Kill switch for object pooling in ThreadLocals that enables much of the LOG4J2-1270 no-GC behaviour.
5655 /**
5756 * Name of the system property that will turn on TRACE level internal log4j2 status logging.
5857 * <p>
59 * If system property {@value} is either defined empty or its value equals to {@code true} (ignoring case), all internal log4j2 logging will be
58 * If system property {@value} is defined, regardless of the property value, all internal log4j2 logging will be
6059 * printed to the console. The presence of this system property overrides any value set in the configuration's
6160 * {@code <Configuration status="<level>" ...>} status attribute, as well as any value set for
6261 * system property {@code org.apache.logging.log4j.simplelog.StatusLogger.level}.
8382 }
8483
8584 /**
86 * The empty array.
87 */
88 public static final Object[] EMPTY_OBJECT_ARRAY = {};
89
90 /**
91 * The empty array.
92 */
93 public static final byte[] EMPTY_BYTE_ARRAY = {};
94
95 /**
9685 * Prevent class instantiation.
9786 */
9887 private Constants() {
2222 import java.io.ObjectStreamClass;
2323 import java.util.Arrays;
2424 import java.util.Collection;
25 import java.util.Collections;
2625 import java.util.HashSet;
27 import java.util.Set;
26 import java.util.List;
2827
2928 /**
30 * Extends {@link ObjectInputStream} to only allow some built-in Log4j classes and caller-specified classes to be
31 * deserialized.
29 * Extended ObjectInputStream that only allows certain classes to be deserialized.
3230 *
3331 * @since 2.8.2
3432 */
3533 public class FilteredObjectInputStream extends ObjectInputStream {
3634
37 private static final Set<String> REQUIRED_JAVA_CLASSES = new HashSet<>(Arrays.asList(
38 // @formatter:off
35 private static final List<String> REQUIRED_JAVA_CLASSES = Arrays.asList(
3936 "java.math.BigDecimal",
4037 "java.math.BigInteger",
4138 // for Message delegate
4239 "java.rmi.MarshalledObject",
4340 "[B"
44 // @formatter:on
45 ));
41 );
4642
47 private static final Set<String> REQUIRED_JAVA_PACKAGES = new HashSet<>(Arrays.asList(
48 // @formatter:off
43 private static final List<String> REQUIRED_JAVA_PACKAGES = Arrays.asList(
4944 "java.lang.",
50 "java.time.",
45 "java.time",
5146 "java.util.",
5247 "org.apache.logging.log4j.",
5348 "[Lorg.apache.logging.log4j."
54 // @formatter:on
55 ));
49 );
5650
57 private final Collection<String> allowedExtraClasses;
51 private final Collection<String> allowedClasses;
5852
5953 public FilteredObjectInputStream() throws IOException, SecurityException {
60 this.allowedExtraClasses = Collections.emptySet();
54 super();
55 this.allowedClasses = new HashSet<>();
6156 }
6257
63 public FilteredObjectInputStream(final InputStream inputStream) throws IOException {
64 super(inputStream);
65 this.allowedExtraClasses = Collections.emptySet();
58 public FilteredObjectInputStream(final InputStream in) throws IOException {
59 super(in);
60 this.allowedClasses = new HashSet<>();
6661 }
6762
68 public FilteredObjectInputStream(final Collection<String> allowedExtraClasses)
69 throws IOException, SecurityException {
70 this.allowedExtraClasses = allowedExtraClasses;
63 public FilteredObjectInputStream(final Collection<String> allowedClasses) throws IOException, SecurityException {
64 super();
65 this.allowedClasses = allowedClasses;
7166 }
7267
73 public FilteredObjectInputStream(final InputStream inputStream, final Collection<String> allowedExtraClasses)
74 throws IOException {
75 super(inputStream);
76 this.allowedExtraClasses = allowedExtraClasses;
68 public FilteredObjectInputStream(final InputStream in, final Collection<String> allowedClasses) throws IOException {
69 super(in);
70 this.allowedClasses = allowedClasses;
7771 }
7872
7973 public Collection<String> getAllowedClasses() {
80 return allowedExtraClasses;
74 return allowedClasses;
8175 }
8276
8377 @Override
8478 protected Class<?> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
8579 final String name = desc.getName();
86 if (!(isAllowedByDefault(name) || allowedExtraClasses.contains(name))) {
80 if (!(isAllowedByDefault(name) || allowedClasses.contains(name))) {
8781 throw new InvalidObjectException("Class is not allowed for deserialization: " + name);
8882 }
8983 return super.resolveClass(desc);
2020 import java.net.URL;
2121 import java.security.AccessController;
2222 import java.security.PrivilegedAction;
23 import java.util.ArrayList;
2324 import java.util.Collection;
2425 import java.util.Enumeration;
2526 import java.util.LinkedHashSet;
27 import java.util.List;
2628 import java.util.Objects;
2729
2830 /**
103105 }
104106
105107 public static ClassLoader[] getClassLoaders() {
106 final Collection<ClassLoader> classLoaders = new LinkedHashSet<>();
108 final List<ClassLoader> classLoaders = new ArrayList<>();
107109 final ClassLoader tcl = getThreadContextClassLoader();
108 if (tcl != null) {
109 classLoaders.add(tcl);
110 }
111 accumulateClassLoaders(LoaderUtil.class.getClassLoader(), classLoaders);
112 accumulateClassLoaders(tcl == null ? null : tcl.getParent(), classLoaders);
110 classLoaders.add(tcl);
111 // Some implementations may use null to represent the bootstrap class loader.
112 final ClassLoader current = LoaderUtil.class.getClassLoader();
113 if (current != null && current != tcl) {
114 classLoaders.add(current);
115 final ClassLoader parent = current.getParent();
116 while (parent != null && !classLoaders.contains(parent)) {
117 classLoaders.add(parent);
118 }
119 }
120 ClassLoader parent = tcl == null ? null : tcl.getParent();
121 while (parent != null && !classLoaders.contains(parent)) {
122 classLoaders.add(parent);
123 parent = parent.getParent();
124 }
113125 final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
114 if (systemClassLoader != null) {
126 if (!classLoaders.contains(systemClassLoader)) {
115127 classLoaders.add(systemClassLoader);
116128 }
117129 return classLoaders.toArray(new ClassLoader[classLoaders.size()]);
118 }
119
120 /**
121 * Adds the provided loader to the loaders collection, and traverses up the tree until either a null
122 * value or a classloader which has already been added is encountered.
123 */
124 private static void accumulateClassLoaders(ClassLoader loader, Collection<ClassLoader> loaders) {
125 // Some implementations may use null to represent the bootstrap class loader.
126 if (loader != null && loaders.add(loader)) {
127 accumulateClassLoaders(loader.getParent(), loaders);
128 }
129130 }
130131
131132 /**
161162 return Class.forName(className);
162163 }
163164 try {
164 ClassLoader tccl = getThreadContextClassLoader();
165 if (tccl != null) {
166 return tccl.loadClass(className);
167 }
165 return getThreadContextClassLoader().loadClass(className);
168166 } catch (final Throwable ignored) {
169 }
170 return Class.forName(className);
167 return Class.forName(className);
168 }
171169 }
172170
173171 /**
1818 import java.io.IOException;
1919 import java.io.InputStream;
2020 import java.nio.charset.Charset;
21 import java.time.Duration;
22 import java.time.temporal.ChronoUnit;
23 import java.time.temporal.TemporalUnit;
2421 import java.util.ArrayList;
2522 import java.util.Collections;
2623 import java.util.List;
157154 }
158155
159156 /**
160 * Retrieves a property that may be prefixed by more than one string.
161 * @param prefixes The array of prefixes.
162 * @param key The key to locate.
163 * @param supplier The method to call to derive the default value. If the value is null, null will be returned
164 * if no property is found.
165 * @return The value or null if it is not found.
166 * @since 2.13.0
167 */
168 public Boolean getBooleanProperty(final String[] prefixes, String key, Supplier<Boolean> supplier) {
169 for (String prefix : prefixes) {
170 if (hasProperty(prefix + key)) {
171 return getBooleanProperty(prefix + key);
172 }
173 }
174 return supplier != null ? supplier.get() : null;
175 }
176
177 /**
178157 * Gets the named property as a Charset value.
179158 *
180159 * @param name the name of the property to look up
225204 try {
226205 return Double.parseDouble(prop);
227206 } catch (final Exception ignored) {
207 return defaultValue;
228208 }
229209 }
230210 return defaultValue;
244224 try {
245225 return Integer.parseInt(prop);
246226 } catch (final Exception ignored) {
247 // ignore
227 return defaultValue;
248228 }
249229 }
250230 return defaultValue;
251 }
252
253 /**
254 * Retrieves a property that may be prefixed by more than one string.
255 * @param prefixes The array of prefixes.
256 * @param key The key to locate.
257 * @param supplier The method to call to derive the default value. If the value is null, null will be returned
258 * if no property is found.
259 * @return The value or null if it is not found.
260 * @since 2.13.0
261 */
262 public Integer getIntegerProperty(final String[] prefixes, String key, Supplier<Integer> supplier) {
263 for (String prefix : prefixes) {
264 if (hasProperty(prefix + key)) {
265 return getIntegerProperty(prefix + key, 0);
266 }
267 }
268 return supplier != null ? supplier.get() : null;
269231 }
270232
271233 /**
281243 try {
282244 return Long.parseLong(prop);
283245 } catch (final Exception ignored) {
246 return defaultValue;
284247 }
285248 }
286249 return defaultValue;
287 }
288
289 /**
290 * Retrieves a property that may be prefixed by more than one string.
291 * @param prefixes The array of prefixes.
292 * @param key The key to locate.
293 * @param supplier The method to call to derive the default value. If the value is null, null will be returned
294 * if no property is found.
295 * @return The value or null if it is not found.
296 * @since 2.13.0
297 */
298 public Long getLongProperty(final String[] prefixes, String key, Supplier<Long> supplier) {
299 for (String prefix : prefixes) {
300 if (hasProperty(prefix + key)) {
301 return getLongProperty(prefix + key, 0);
302 }
303 }
304 return supplier != null ? supplier.get() : null;
305 }
306
307 /**
308 * Retrieves a Duration where the String is of the format nnn[unit] where nnn represents an integer value
309 * and unit represents a time unit.
310 * @param name The property name.
311 * @param defaultValue The default value.
312 * @return The value of the String as a Duration or the default value, which may be null.
313 * @since 2.13.0
314 */
315 public Duration getDurationProperty(final String name, Duration defaultValue) {
316 final String prop = getStringProperty(name);
317 if (prop != null) {
318 return TimeUnit.getDuration(prop);
319 }
320 return defaultValue;
321 }
322
323 /**
324 * Retrieves a property that may be prefixed by more than one string.
325 * @param prefixes The array of prefixes.
326 * @param key The key to locate.
327 * @param supplier The method to call to derive the default value. If the value is null, null will be returned
328 * if no property is found.
329 * @return The value or null if it is not found.
330 * @since 2.13.0
331 */
332 public Duration getDurationProperty(final String[] prefixes, String key, Supplier<Duration> supplier) {
333 for (String prefix : prefixes) {
334 if (hasProperty(prefix + key)) {
335 return getDurationProperty(prefix + key, null);
336 }
337 }
338 return supplier != null ? supplier.get() : null;
339 }
340
341 /**
342 * Retrieves a property that may be prefixed by more than one string.
343 * @param prefixes The array of prefixes.
344 * @param key The key to locate.
345 * @param supplier The method to call to derive the default value. If the value is null, null will be returned
346 * if no property is found.
347 * @return The value or null if it is not found.
348 * @since 2.13.0
349 */
350 public String getStringProperty(final String[] prefixes, String key, Supplier<String> supplier) {
351 for (String prefix : prefixes) {
352 String result = getStringProperty(prefix + key);
353 if (result != null) {
354 return result;
355 }
356 }
357 return supplier != null ? supplier.get() : null;
358250 }
359251
360252 /**
426318 private Environment(final PropertySource propertySource) {
427319 PropertyFilePropertySource sysProps = new PropertyFilePropertySource(LOG4J_SYSTEM_PROPERTIES_FILE_NAME);
428320 try {
429 sysProps.forEach((key, value) -> {
430 if (System.getProperty(key) == null) {
431 System.setProperty(key, value);
321 sysProps.forEach(new BiConsumer<String, String>() {
322 @Override
323 public void accept(String key, String value) {
324 if (System.getProperty(key) == null) {
325 System.setProperty(key, value);
326 }
432327 }
433328 });
434329 } catch (SecurityException ex) {
455350 normalized.clear();
456351 tokenized.clear();
457352 for (final PropertySource source : sources) {
458 source.forEach((key, value) -> {
459 if (key != null && value != null) {
460 literal.put(key, value);
461 final List<CharSequence> tokens = PropertySource.Util.tokenize(key);
462 if (tokens.isEmpty()) {
463 normalized.put(source.getNormalForm(Collections.singleton(key)), value);
464 } else {
465 normalized.put(source.getNormalForm(tokens), value);
466 tokenized.put(tokens, value);
353 source.forEach(new BiConsumer<String, String>() {
354 @Override
355 public void accept(final String key, final String value) {
356 if (key != null && value != null) {
357 literal.put(key, value);
358 final List<CharSequence> tokens = PropertySource.Util.tokenize(key);
359 if (tokens.isEmpty()) {
360 normalized.put(source.getNormalForm(Collections.singleton(key)), value);
361 } else {
362 normalized.put(source.getNormalForm(tokens), value);
363 tokenized.put(tokens, value);
364 }
467365 }
468366 }
469367 });
487385 }
488386 if (hasSystemProperty(key)) {
489387 return System.getProperty(key);
490 }
491 for (final PropertySource source : sources) {
492 if (source.containsProperty(key)) {
493 return source.getProperty(key);
494 }
495388 }
496389 return tokenized.get(PropertySource.Util.tokenize(key));
497390 }
569462 return getStringProperty("os.name", "").startsWith("Windows");
570463 }
571464
572 private enum TimeUnit {
573 NANOS("ns,nano,nanos,nanosecond,nanoseconds", ChronoUnit.NANOS),
574 MICROS("us,micro,micros,microsecond,microseconds", ChronoUnit.MICROS),
575 MILLIS("ms,milli,millis,millsecond,milliseconds", ChronoUnit.MILLIS),
576 SECONDS("s,second,seconds", ChronoUnit.SECONDS),
577 MINUTES("m,minute,minutes", ChronoUnit.MINUTES),
578 HOURS("h,hour,hours", ChronoUnit.HOURS),
579 DAYS("d,day,days", ChronoUnit.DAYS);
580
581 private final String[] descriptions;
582 private final ChronoUnit timeUnit;
583
584 TimeUnit(String descriptions, ChronoUnit timeUnit) {
585 this.descriptions = descriptions.split(",");
586 this.timeUnit = timeUnit;
587 }
588
589 ChronoUnit getTimeUnit() {
590 return this.timeUnit;
591 }
592
593 static Duration getDuration(String time) {
594 String value = time.trim();
595 TemporalUnit temporalUnit = ChronoUnit.MILLIS;
596 long timeVal = 0;
597 for (TimeUnit timeUnit : values()) {
598 for (String suffix : timeUnit.descriptions) {
599 if (value.endsWith(suffix)) {
600 temporalUnit = timeUnit.timeUnit;
601 timeVal = Long.parseLong(value.substring(0, value.length() - suffix.length()));
602 }
603 }
604 }
605 return Duration.of(timeVal, temporalUnit);
606 }
607 }
608465 }
4444 *
4545 * @param action action to perform on each key/value pair
4646 */
47 default void forEach(BiConsumer<String, String> action) {
48 }
47 void forEach(BiConsumer<String, String> action);
4948
5049 /**
5150 * Converts a list of property name tokens into a normal form. For example, a list of tokens such as
5453 * @param tokens list of property name tokens
5554 * @return a normalized property name using the given tokens
5655 */
57 default CharSequence getNormalForm(Iterable<? extends CharSequence> tokens) {
58 return null;
59 }
60
61 /**
62 * For PropertySources that cannot iterate over all the potential properties this provides a direct lookup.
63 * @param key The key to search for.
64 * @return The value or null;
65 * @since 2.13.0
66 */
67 default String getProperty(String key) {
68 return null;
69 }
70
71
72 /**
73 * For PropertySources that cannot iterate over all the potential properties this provides a direct lookup.
74 * @param key The key to search for.
75 * @return The value or null;
76 * @since 2.13.0
77 */
78 default boolean containsProperty(String key) {
79 return false;
80 }
56 CharSequence getNormalForm(Iterable<? extends CharSequence> tokens);
8157
8258 /**
8359 * Comparator for ordering PropertySource instances by priority.
6666 private static final long serialVersionUID = -5748905872274478116L;
6767 private static final int HASHVAL = 31;
6868
69 private static final TriConsumer<String, Object, StringMap> PUT_ALL = (key, value, contextData) -> contextData.putValue(key, value);
69 private static final TriConsumer<String, Object, StringMap> PUT_ALL = new TriConsumer<String, Object, StringMap>() {
70 @Override
71 public void accept(final String key, final Object value, final StringMap contextData) {
72 contextData.putValue(key, value);
73 }
74 };
7075
7176 /**
7277 * An empty array instance to share when the table is not inflated.
1717
1818 import java.lang.reflect.Method;
1919 import java.util.Stack;
20 import java.util.function.Predicate;
2120
2221 /**
2322 * <em>Consider this class private.</em> Provides various methods to determine the caller class. <h3>Background</h3>
9695 // TODO: return Object.class instead of null (though it will have a null ClassLoader)
9796 // (MS) I believe this would work without any modifications elsewhere, but I could be wrong
9897
99 @PerformanceSensitive
100 public Class<?> getCallerClass(final Class<?> sentinelClass, final Predicate<Class<?>> callerPredicate) {
101 if (sentinelClass == null) {
102 throw new IllegalArgumentException("sentinelClass cannot be null");
103 }
104 if (callerPredicate == null) {
105 throw new IllegalArgumentException("callerPredicate cannot be null");
106 }
107 boolean foundSentinel = false;
108 Class<?> clazz;
109 for (int i = 2; null != (clazz = getCallerClass(i)); i++) {
110 if (sentinelClass.equals(clazz)) {
111 foundSentinel = true;
112 } else if (foundSentinel && callerPredicate.test(clazz)) {
113 return clazz;
114 }
115 }
116 return null;
117 }
118
11998 // migrated from ReflectiveCallerClassUtility
12099 @PerformanceSensitive
121100 public Class<?> getCallerClass(final int depth) {
122101 if (depth < 0) {
123102 throw new IndexOutOfBoundsException(Integer.toString(depth));
124 }
125 if (GET_CALLER_CLASS == null) {
126 return null;
127103 }
128104 // note that we need to add 1 to the depth value to compensate for this method, but not for the Method.invoke
129105 // since Reflection.getCallerClass ignores the call to Method.invoke()
1717
1818 import java.util.NoSuchElementException;
1919 import java.util.Stack;
20 import java.util.function.Predicate;
2120
2221 import org.apache.logging.log4j.status.StatusLogger;
2322
2625 */
2726 public final class StackLocatorUtil {
2827 private static StackLocator stackLocator = null;
29 private static volatile boolean errorLogged;
28 private static volatile boolean errorLogged = false;
3029
3130 static {
3231 stackLocator = StackLocator.getInstance();
4746 public static StackTraceElement getStackTraceElement(final int depth) {
4847 return stackLocator.getStackTraceElement(depth + 1);
4948 }
50
51 /**
52 * Equivalent to {@link #getCallerClass(String, String)} with an empty {@code pkg}.
53 */
5449 // migrated from ClassLoaderContextSelector
5550 @PerformanceSensitive
5651 public static Class<?> getCallerClass(final String fqcn) {
5752 return getCallerClass(fqcn, Strings.EMPTY);
5853 }
5954
60 /**
61 * Search for a calling class.
62 *
63 * @param fqcn Root class name whose caller to search for.
64 * @param pkg Package name prefix that must be matched after the {@code fqcn} has been found.
65 * @return The caller class that was matched, or null if one could not be located.
66 */
55 // migrated from Log4jLoggerFactory
6756 @PerformanceSensitive
6857 public static Class<?> getCallerClass(final String fqcn, final String pkg) {
6958 return stackLocator.getCallerClass(fqcn, pkg);
70 }
71
72 /**
73 * Search for a calling class.
74 *
75 * @param sentinelClass Sentinel class at which to begin searching
76 * @param callerPredicate Predicate checked after the sentinelClass is found
77 * @return the first matching class after <code>sentinelClass</code> is found.
78 */
79 @PerformanceSensitive
80 public static Class<?> getCallerClass(final Class<?> sentinelClass, final Predicate<Class<?>> callerPredicate) {
81 return stackLocator.getCallerClass(sentinelClass, callerPredicate);
8259 }
8360
8461 // added for use in LoggerAdapter implementations mainly
2626 */
2727 public final class Strings {
2828
29 private static final ThreadLocal<StringBuilder> tempStr = ThreadLocal.withInitial(StringBuilder::new);
30
3129 /**
3230 * The empty string.
3331 */
3432 public static final String EMPTY = "";
35
36 /**
37 * The empty array.
38 */
39 public static final String[] EMPTY_ARRAY = {};
4033
4134 /**
4235 * OS-dependent line separator, defaults to {@code "\n"} if the system property {@code ""line.separator"} cannot be
5649 }
5750
5851 /**
59 * Checks if a String is blank. A blank string is one that is either
60 * {@code null}, empty, or all characters are {@link Character#isWhitespace(char)}.
52 * Checks if a String is blank. A blank string is one that is {@code null}, empty, or when trimmed using
53 * {@link String#trim()} is empty.
6154 *
6255 * @param s the String to check, may be {@code null}
63 * @return {@code true} if the String is {@code null}, empty, or or all characters are {@link Character#isWhitespace(char)}
56 * @return {@code true} if the String is {@code null}, empty, or trims to empty.
6457 */
6558 public static boolean isBlank(final String s) {
66 if (s == null || s.isEmpty()) {
67 return true;
68 }
69 for (int i = 0; i < s.length(); i++) {
70 char c = s.charAt(i);
71 if (!Character.isWhitespace(c)) {
72 return false;
73 }
74 }
75 return true;
59 return s == null || s.trim().isEmpty();
7660 }
7761
7862 /**
288272 return str.toUpperCase(Locale.ROOT);
289273 }
290274
291 /**
292 * Concatenates 2 Strings without allocation.
293 * @param str1 the first string.
294 * @param str2 the second string.
295 * @return the concatenated String.
296 */
297 public static String concat(String str1, String str2) {
298 if (isEmpty(str1)) {
299 return str2;
300 } else if (isEmpty(str2)) {
301 return str1;
302 }
303 StringBuilder sb = tempStr.get();
304 try {
305 return sb.append(str1).append(str2).toString();
306 } finally {
307 sb.setLength(0);
308 }
309 }
310
311 /**
312 * Creates a new string repeating given {@code str} {@code count} times.
313 * @param str input string
314 * @param count the repetition count
315 * @return the new string
316 * @throws IllegalArgumentException if either {@code str} is null or {@code count} is negative
317 */
318 public static String repeat(final String str, final int count) {
319 Objects.requireNonNull(str, "str");
320 if (count < 0) {
321 throw new IllegalArgumentException("count");
322 }
323 StringBuilder sb = tempStr.get();
324 try {
325 for (int index = 0; index < count; index++) {
326 sb.append(str);
327 }
328 return sb.toString();
329 } finally {
330 sb.setLength(0);
331 }
332 }
333
334275 }
2121 /**
2222 * Primarily used in unit tests, but can be used to track elapsed time for a request or portion of any other operation
2323 * so long as all the timer methods are called on the same thread in which it was started. Calling start on
24 * multiple threads will cause the times to be aggregated.
24 * multiple threads will cause the the times to be aggregated.
2525 */
2626 public class Timer implements Serializable, StringBuilderFormattable
2727 {
1616 package org.apache.logging.log4j;
1717
1818 import static org.hamcrest.CoreMatchers.containsString;
19 import static org.hamcrest.MatcherAssert.assertThat;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertNull;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24 import static org.junit.jupiter.api.Assertions.fail;
25
26 import java.util.List;
27
28 import org.apache.logging.log4j.junit.StatusLoggerLevel;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertNull;
22 import static org.junit.Assert.assertThat;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25
26 import org.apache.logging.log4j.junit.StatusLoggerRule;
2927 import org.apache.logging.log4j.message.Message;
3028 import org.apache.logging.log4j.message.ObjectMessage;
3129 import org.apache.logging.log4j.message.ParameterizedMessage;
3533 import org.apache.logging.log4j.spi.MessageFactory2Adapter;
3634 import org.apache.logging.log4j.status.StatusData;
3735 import org.apache.logging.log4j.status.StatusLogger;
38 import org.apache.logging.log4j.util.Constants;
3936 import org.apache.logging.log4j.util.MessageSupplier;
4037 import org.apache.logging.log4j.util.Supplier;
41 import org.junit.jupiter.api.Test;
42 import org.junit.jupiter.api.parallel.ResourceLock;
43
44 @StatusLoggerLevel("WARN")
45 @ResourceLock("log4j2.MarkerManager")
38 import org.junit.Rule;
39 import org.junit.Test;
40
41 import java.util.List;
42
43 /**
44 *
45 */
4646 public class AbstractLoggerTest {
4747
4848 private static final StringBuilder CHAR_SEQ = new StringBuilder("CharSeq");
5050 // TODO add proper tests for ReusableMessage
5151
5252 @SuppressWarnings("ThrowableInstanceNeverThrown")
53 private static final Throwable t = new UnsupportedOperationException("Test");
54
55 private static final Class<AbstractLogger> obj = AbstractLogger.class;
56 private static final String pattern = "{}, {}";
57 private static final String p1 = "Long Beach";
58
59 private static final String p2 = "California";
60 private static final Message charSeq = new SimpleMessage(CHAR_SEQ);
61 private static final Message simple = new SimpleMessage("Hello");
62 private static final Message object = new ObjectMessage(obj);
63
64 private static final Message param = new ParameterizedMessage(pattern, p1, p2);
53 private static Throwable t = new UnsupportedOperationException("Test");
54
55 private static Class<AbstractLogger> obj = AbstractLogger.class;
56 private static String pattern = "{}, {}";
57 private static String p1 = "Long Beach";
58
59 private static String p2 = "California";
60 private static Message charSeq = new SimpleMessage(CHAR_SEQ);
61 private static Message simple = new SimpleMessage("Hello");
62 private static Message object = new ObjectMessage(obj);
63
64 private static Message param = new ParameterizedMessage(pattern, p1, p2);
6565
6666 private static final Marker MARKER = MarkerManager.getMarker("TEST");
6767 private static final String MARKER_NAME = "TEST";
68
69 @Rule
70 public StatusLoggerRule status = new StatusLoggerRule(Level.WARN);
6871
6972 private static final LogEvent[] EVENTS = new LogEvent[] {
7073 new LogEvent(null, simple, null),
144147 logger.setCurrentEvent(EVENTS[18]);
145148 logger.debug(MARKER, CHAR_SEQ, t);
146149
147 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
148 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
150 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
151 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
149152 }
150153
151154 @Test
199202 logger.setCurrentEvent(EVENTS[18]);
200203 logger.error(MARKER, CHAR_SEQ, t);
201204
202 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
203 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
205 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
206 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
204207 }
205208
206209 @Test
254257 logger.setCurrentEvent(EVENTS[18]);
255258 logger.fatal(MARKER, CHAR_SEQ, t);
256259
257 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
258 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
260 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
261 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
259262 }
260263
261264 @Test
309312 logger.setCurrentEvent(EVENTS[18]);
310313 logger.info(MARKER, CHAR_SEQ, t);
311314
312 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
313 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
315 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
316 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
314317 }
315318
316319 @Test
364367 logger.setCurrentEvent(EVENTS[18]);
365368 logger.log(Level.DEBUG, MARKER, CHAR_SEQ, t);
366369
367 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
368 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
370 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
371 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
369372 }
370373
371374 @Test
419422 logger.setCurrentEvent(EVENTS[18]);
420423 logger.log(Level.ERROR, MARKER, CHAR_SEQ, t);
421424
422 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
423 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
425 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
426 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
424427 }
425428
426429 @Test
474477 logger.setCurrentEvent(EVENTS[18]);
475478 logger.log(Level.FATAL, MARKER, CHAR_SEQ, t);
476479
477 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
478 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
480 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
481 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
479482 }
480483
481484 @Test
529532 logger.setCurrentEvent(EVENTS[18]);
530533 logger.log(Level.INFO, MARKER, CHAR_SEQ, t);
531534
532 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
533 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
535 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
536 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
534537 }
535538
536539 @Test
584587 logger.setCurrentEvent(EVENTS[18]);
585588 logger.log(Level.TRACE, MARKER, CHAR_SEQ, t);
586589
587 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
588 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
590 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
591 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
589592 }
590593
591594 @Test
639642 logger.setCurrentEvent(EVENTS[18]);
640643 logger.log(Level.WARN, MARKER, CHAR_SEQ, t);
641644
642 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
643 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
645 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
646 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
644647 }
645648
646649 @Test
694697 logger.setCurrentEvent(EVENTS[18]);
695698 logger.trace(MARKER, CHAR_SEQ, t);
696699
697 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
698 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
700 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
701 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
699702 }
700703
701704 @Test
749752 logger.setCurrentEvent(EVENTS[18]);
750753 logger.warn(MARKER, CHAR_SEQ, t);
751754
752 assertEquals(4, logger.getCharSeqCount(), "log(CharSeq) invocations");
753 assertEquals(5, logger.getObjectCount(), "log(Object) invocations");
755 assertEquals("log(CharSeq) invocations", 4, logger.getCharSeqCount());
756 assertEquals("log(Object) invocations", 5, logger.getObjectCount());
754757 }
755758
756759 @Test
801804 public void testMessageSupplierWithThrowable() {
802805 final ThrowableExpectingLogger logger = new ThrowableExpectingLogger(true);
803806 final ThrowableMessage message = new ThrowableMessage(t);
804 final MessageSupplier supplier = () -> message;
807 final MessageSupplier supplier = new MessageSupplier() {
808 @Override
809 public Message get() {
810 return message;
811 }
812 };
805813
806814 logger.debug(supplier);
807815 logger.error(supplier);
824832 public void testMessageSupplierWithoutThrowable() {
825833 final ThrowableExpectingLogger logger = new ThrowableExpectingLogger(false);
826834 final ThrowableMessage message = new ThrowableMessage(null);
827 final MessageSupplier supplier = () -> message;
835 final MessageSupplier supplier = new MessageSupplier() {
836 @Override
837 public Message get() {
838 return message;
839 }
840 };
828841
829842 logger.debug(supplier);
830843 logger.error(supplier);
847860 public void testSupplierWithThrowable() {
848861 final ThrowableExpectingLogger logger = new ThrowableExpectingLogger(true);
849862 final ThrowableMessage message = new ThrowableMessage(t);
850 final Supplier<Message> supplier = () -> message;
863 final Supplier<Message> supplier = new Supplier<Message>() {
864 @Override
865 public Message get() {
866 return message;
867 }
868 };
851869
852870 logger.debug(supplier);
853871 logger.error(supplier);
870888 public void testSupplierWithoutThrowable() {
871889 final ThrowableExpectingLogger logger = new ThrowableExpectingLogger(false);
872890 final ThrowableMessage message = new ThrowableMessage(null);
873 final Supplier<Message> supplier = () -> message;
891 final Supplier<Message> supplier = new Supplier<Message>() {
892 @Override
893 public Message get() {
894 return message;
895 }
896 };
874897
875898 logger.debug(supplier);
876899 logger.error(supplier);
890913 }
891914
892915 @Test
893 @ResourceLock("log4j2.StatusLogger")
894916 public void testMessageThrows() {
895917 final ThrowableExpectingLogger logger = new ThrowableExpectingLogger(false);
896 logger.error(new TestMessage(() -> {
897 throw new IllegalStateException("Oops!");
918 logger.error(new TestMessage(new TestMessage.FormattedMessageSupplier() {
919 @Override
920 public String getFormattedMessage() {
921 throw new IllegalStateException("Oops!");
922 }
898923 }, "Message Format"));
899924 final List<StatusData> statusDatalist = StatusLogger.getLogger().getStatusData();
900925 final StatusData mostRecent = statusDatalist.get(statusDatalist.size() - 1);
905930 }
906931
907932 @Test
908 @ResourceLock("log4j2.StatusLogger")
909933 public void testMessageThrowsAndNullFormat() {
910934 final ThrowableExpectingLogger logger = new ThrowableExpectingLogger(false);
911 logger.error(new TestMessage(() -> {
912 throw new IllegalStateException("Oops!");
935 logger.error(new TestMessage(new TestMessage.FormattedMessageSupplier() {
936 @Override
937 public String getFormattedMessage() {
938 throw new IllegalStateException("Oops!");
939 }
913940 }, null /* format */));
914941 final List<StatusData> statusDatalist = StatusLogger.getLogger().getStatusData();
915942 final StatusData mostRecent = statusDatalist.get(statusDatalist.size() - 1);
939966
940967 @Override
941968 public Object[] getParameters() {
942 return Constants.EMPTY_OBJECT_ARRAY;
969 return new Object[0];
943970 }
944971
945972 @Override
9871014
9881015 @Override
9891016 public boolean isEnabled(final Level level, final Marker marker, final Message data, final Throwable t) {
990 assertEquals(level, currentLevel, "Incorrect Level. Expected " + currentLevel + ", actual " + level);
1017 assertTrue("Incorrect Level. Expected " + currentLevel + ", actual " + level, level.equals(currentLevel));
9911018 if (marker == null) {
9921019 if (currentEvent.markerName != null) {
9931020 fail("Incorrect marker. Expected " + currentEvent.markerName + ", actual is null");
9941021 }
995 } else if (currentEvent.markerName == null) {
996 fail("Incorrect marker. Expected null. Actual is " + marker.getName());
9971022 } else {
998 assertEquals(currentEvent.markerName, marker.getName(),
999 "Incorrect marker. Expected " + currentEvent.markerName + ", actual " + marker.getName());
1023 if (currentEvent.markerName == null) {
1024 fail("Incorrect marker. Expected null. Actual is " + marker.getName());
1025 } else {
1026 assertTrue("Incorrect marker. Expected " + currentEvent.markerName + ", actual " +
1027 marker.getName(), currentEvent.markerName.equals(marker.getName()));
1028 }
10001029 }
10011030 if (data == null) {
10021031 if (currentEvent.data != null) {
10031032 fail("Incorrect message. Expected " + currentEvent.data + ", actual is null");
10041033 }
1005 } else if (currentEvent.data == null) {
1006 fail("Incorrect message. Expected null. Actual is " + data.getFormattedMessage());
10071034 } else {
1008 assertTrue(data.getClass().isAssignableFrom(currentEvent.data.getClass()),
1009 "Incorrect message type. Expected " + currentEvent.data + ", actual " + data);
1010 assertEquals(currentEvent.data.getFormattedMessage(), data.getFormattedMessage(),
1011 "Incorrect message. Expected " + currentEvent.data.getFormattedMessage() + ", actual "
1012 + data.getFormattedMessage());
1035 if (currentEvent.data == null) {
1036 fail("Incorrect message. Expected null. Actual is " + data.getFormattedMessage());
1037 } else {
1038 assertTrue("Incorrect message type. Expected " + currentEvent.data + ", actual " + data,
1039 data.getClass().isAssignableFrom(currentEvent.data.getClass()));
1040 assertTrue("Incorrect message. Expected " + currentEvent.data.getFormattedMessage() + ", actual " +
1041 data.getFormattedMessage(),
1042 currentEvent.data.getFormattedMessage().equals(data.getFormattedMessage()));
1043 }
10131044 }
10141045 if (t == null) {
10151046 if (currentEvent.t != null) {
10161047 fail("Incorrect Throwable. Expected " + currentEvent.t + ", actual is null");
10171048 }
1018 } else if (currentEvent.t == null) {
1019 fail("Incorrect Throwable. Expected null. Actual is " + t);
10201049 } else {
1021 assertEquals(currentEvent.t, t, "Incorrect Throwable. Expected " + currentEvent.t + ", actual " + t);
1050 if (currentEvent.t == null) {
1051 fail("Incorrect Throwable. Expected null. Actual is " + t);
1052 } else {
1053 assertTrue("Incorrect Throwable. Expected " + currentEvent.t + ", actual " + t,
1054 currentEvent.t.equals(t));
1055 }
10221056 }
10231057 return true;
10241058 }
11201154 }
11211155
11221156 @Override
1123 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message data,
1124 final Throwable t) {
1125 assertEquals(level, currentLevel, "Incorrect Level. Expected " + currentLevel + ", actual " + level);
1157 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message data, final Throwable t) {
1158 assertTrue("Incorrect Level. Expected " + currentLevel + ", actual " + level, level.equals(currentLevel));
11261159 if (marker == null) {
11271160 if (currentEvent.markerName != null) {
11281161 fail("Incorrect marker. Expected " + currentEvent.markerName + ", actual is null");
11291162 }
1130 } else if (currentEvent.markerName == null) {
1131 fail("Incorrect marker. Expected null. Actual is " + marker.getName());
11321163 } else {
1133 assertEquals(currentEvent.markerName, marker.getName(),
1134 "Incorrect marker. Expected " + currentEvent.markerName + ", actual " + marker.getName());
1164 if (currentEvent.markerName == null) {
1165 fail("Incorrect marker. Expected null. Actual is " + marker.getName());
1166 } else {
1167 assertTrue("Incorrect marker. Expected " + currentEvent.markerName + ", actual " +
1168 marker.getName(), currentEvent.markerName.equals(marker.getName()));
1169 }
11351170 }
11361171 if (data == null) {
11371172 if (currentEvent.data != null) {
11381173 fail("Incorrect message. Expected " + currentEvent.data + ", actual is null");
11391174 }
1140 } else if (currentEvent.data == null) {
1141 fail("Incorrect message. Expected null. Actual is " + data.getFormattedMessage());
11421175 } else {
1143 assertTrue(data.getClass().isAssignableFrom(currentEvent.data.getClass()),
1144 "Incorrect message type. Expected " + currentEvent.data + ", actual " + data);
1145 assertEquals(currentEvent.data.getFormattedMessage(), data.getFormattedMessage(),
1146 "Incorrect message. Expected " + currentEvent.data.getFormattedMessage() + ", actual "
1147 + data.getFormattedMessage());
1176 if (currentEvent.data == null) {
1177 fail("Incorrect message. Expected null. Actual is " + data.getFormattedMessage());
1178 } else {
1179 assertTrue("Incorrect message type. Expected " + currentEvent.data + ", actual " + data,
1180 data.getClass().isAssignableFrom(currentEvent.data.getClass()));
1181 assertTrue("Incorrect message. Expected " + currentEvent.data.getFormattedMessage() + ", actual " +
1182 data.getFormattedMessage(),
1183 currentEvent.data.getFormattedMessage().equals(data.getFormattedMessage()));
1184 }
11481185 }
11491186 if (t == null) {
11501187 if (currentEvent.t != null) {
11511188 fail("Incorrect Throwable. Expected " + currentEvent.t + ", actual is null");
11521189 }
1153 } else if (currentEvent.t == null) {
1154 fail("Incorrect Throwable. Expected null. Actual is " + t);
11551190 } else {
1156 assertEquals(currentEvent.t, t, "Incorrect Throwable. Expected " + currentEvent.t + ", actual " + t);
1191 if (currentEvent.t == null) {
1192 fail("Incorrect Throwable. Expected null. Actual is " + t);
1193 } else {
1194 assertTrue("Incorrect Throwable. Expected " + currentEvent.t + ", actual " + t,
1195 currentEvent.t.equals(t));
1196 }
11571197 }
11581198 }
11591199 }
12621302 @Override
12631303 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message message, final Throwable t) {
12641304 if(expectingThrowables) {
1265 assertNotNull(t, "Expected a Throwable but received null!");
1305 assertNotNull("Expected a Throwable but received null!", t);
12661306 } else {
1267 assertNull(t, "Expected null but received a Throwable! "+t);
1307 assertNull("Expected null but received a Throwable! "+t, t);
12681308 }
12691309 if (message != null) {
12701310 message.getFormattedMessage();
12781318 }
12791319
12801320 private static class ThrowableMessage implements Message {
1321 /**
1322 *
1323 */
12811324 private static final long serialVersionUID = 1L;
12821325 private final Throwable throwable;
12831326
12971340
12981341 @Override
12991342 public Object[] getParameters() {
1300 return Constants.EMPTY_OBJECT_ARRAY;
1343 return new Object[0];
13011344 }
13021345
13031346 @Override
3333 private final Serializable serializable;
3434
3535 public AbstractSerializationTest(final Serializable serializable) {
36 super();
3637 this.serializable = serializable;
3738 }
3839
1515 */
1616 package org.apache.logging.log4j;
1717
18 import org.junit.jupiter.api.AfterEach;
19 import org.junit.jupiter.api.BeforeEach;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.parallel.ResourceAccessMode;
22 import org.junit.jupiter.api.parallel.ResourceLock;
23 import org.junit.jupiter.api.parallel.Resources;
18 import org.apache.logging.log4j.junit.ThreadContextRule;
19 import org.junit.Rule;
20 import org.junit.Test;
2421
2522 import java.util.HashMap;
2623 import java.util.List;
2724 import java.util.Map;
2825
29 import static org.junit.jupiter.api.Assertions.*;
26 import static org.hamcrest.CoreMatchers.is;
27 import static org.junit.Assert.assertThat;
3028
3129 /**
3230 * Tests {@link CloseableThreadContext}.
3331 *
3432 * @since 2.6
3533 */
36 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
3734 public class CloseableThreadContextTest {
3835
3936 private final String key = "key";
4037 private final String value = "value";
4138
42 @BeforeEach
43 @AfterEach
44 void clearThreadContext() {
45 ThreadContext.clearAll();
46 }
47
48 @Test
49 public void shouldAddAnEntryToTheMap() {
50 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
51 assertNotNull(ignored);
52 assertEquals(value, ThreadContext.get(key));
53 }
54 }
55
56 @Test
57 public void shouldAddTwoEntriesToTheMap() {
39 @Rule
40 public final ThreadContextRule threadContextRule = new ThreadContextRule();
41
42 @Test
43 public void shouldAddAnEntryToTheMap() throws Exception {
44 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
45 assertThat(ThreadContext.get(key), is(value));
46 }
47 }
48
49 @Test
50 public void shouldAddTwoEntriesToTheMap() throws Exception {
5851 final String key2 = "key2";
5952 final String value2 = "value2";
6053 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value).put(key2, value2)) {
61 assertNotNull(ignored);
62 assertEquals(value, ThreadContext.get(key));
63 assertEquals(value2, ThreadContext.get(key2));
64 }
65 }
66
67 @Test
68 public void shouldNestEntries() {
54 assertThat(ThreadContext.get(key), is(value));
55 assertThat(ThreadContext.get(key2), is(value2));
56 }
57 }
58
59 @Test
60 public void shouldNestEntries() throws Exception {
6961 final String oldValue = "oldValue";
7062 final String innerValue = "innerValue";
7163 ThreadContext.put(key, oldValue);
7264 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
73 assertNotNull(ignored);
74 assertEquals(value, ThreadContext.get(key));
65 assertThat(ThreadContext.get(key), is(value));
7566 try (final CloseableThreadContext.Instance ignored2 = CloseableThreadContext.put(key, innerValue)) {
76 assertNotNull(ignored2);
77 assertEquals(innerValue, ThreadContext.get(key));
67 assertThat(ThreadContext.get(key), is(innerValue));
7868 }
79 assertEquals(value, ThreadContext.get(key));
80 }
81 assertEquals(oldValue, ThreadContext.get(key));
82 }
83
84 @Test
85 public void shouldPreserveOldEntriesFromTheMapWhenAutoClosed() {
86 final String oldValue = "oldValue";
87 ThreadContext.put(key, oldValue);
88 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
89 assertNotNull(ignored);
90 assertEquals(value, ThreadContext.get(key));
91 }
92 assertEquals(oldValue, ThreadContext.get(key));
93 }
94
95 @Test
96 public void ifTheSameKeyIsAddedTwiceTheOriginalShouldBeUsed() {
69 assertThat(ThreadContext.get(key), is(value));
70 }
71 assertThat(ThreadContext.get(key), is(oldValue));
72 }
73
74 @Test
75 public void shouldPreserveOldEntriesFromTheMapWhenAutoClosed() throws Exception {
76 final String oldValue = "oldValue";
77 ThreadContext.put(key, oldValue);
78 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
79 assertThat(ThreadContext.get(key), is(value));
80 }
81 assertThat(ThreadContext.get(key), is(oldValue));
82 }
83
84 @Test
85 public void ifTheSameKeyIsAddedTwiceTheOriginalShouldBeUsed() throws Exception {
9786 final String oldValue = "oldValue";
9887 final String secondValue = "innerValue";
9988 ThreadContext.put(key, oldValue);
10089 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value).put(key, secondValue)) {
101 assertNotNull(ignored);
102 assertEquals(secondValue, ThreadContext.get(key));
103 }
104 assertEquals(oldValue, ThreadContext.get(key));
105 }
106
107 @Test
108 public void shouldPushAndPopAnEntryToTheStack() {
90 assertThat(ThreadContext.get(key), is(secondValue));
91 }
92 assertThat(ThreadContext.get(key), is(oldValue));
93 }
94
95 @Test
96 public void shouldPushAndPopAnEntryToTheStack() throws Exception {
10997 final String message = "message";
11098 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.push(message)) {
111 assertNotNull(ignored);
112 assertEquals(message, ThreadContext.peek());
113 }
114 assertEquals("", ThreadContext.peek());
115 }
116
117 @Test
118 public void shouldPushAndPopTwoEntriesToTheStack() {
99 assertThat(ThreadContext.peek(), is(message));
100 }
101 assertThat(ThreadContext.peek(), is(""));
102 }
103
104 @Test
105 public void shouldPushAndPopTwoEntriesToTheStack() throws Exception {
119106 final String message1 = "message1";
120107 final String message2 = "message2";
121108 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.push(message1).push(message2)) {
122 assertNotNull(ignored);
123 assertEquals(message2, ThreadContext.peek());
124 }
125 assertEquals("", ThreadContext.peek());
126 }
127
128 @Test
129 public void shouldPushAndPopAParameterizedEntryToTheStack() {
109 assertThat(ThreadContext.peek(), is(message2));
110 }
111 assertThat(ThreadContext.peek(), is(""));
112 }
113
114 @Test
115 public void shouldPushAndPopAParameterizedEntryToTheStack() throws Exception {
130116 final String parameterizedMessage = "message {}";
131117 final String parameterizedMessageParameter = "param";
132118 final String formattedMessage = parameterizedMessage.replace("{}", parameterizedMessageParameter);
133119 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.push(parameterizedMessage,
134120 parameterizedMessageParameter)) {
135 assertNotNull(ignored);
136 assertEquals(formattedMessage, ThreadContext.peek());
137 }
138 assertEquals("", ThreadContext.peek());
139 }
140
141 @Test
142 public void shouldRemoveAnEntryFromTheMapWhenAutoClosed() {
143 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
144 assertNotNull(ignored);
145 assertEquals(value, ThreadContext.get(key));
146 }
147 assertFalse(ThreadContext.containsKey(key));
148 }
149
150 @Test
151 public void shouldAddEntriesToBothStackAndMap() {
121 assertThat(ThreadContext.peek(), is(formattedMessage));
122 }
123 assertThat(ThreadContext.peek(), is(""));
124 }
125
126 @Test
127 public void shouldRemoveAnEntryFromTheMapWhenAutoClosed() throws Exception {
128 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
129 assertThat(ThreadContext.get(key), is(value));
130 }
131 assertThat(ThreadContext.containsKey(key), is(false));
132 }
133
134 @Test
135 public void shouldAddEntriesToBothStackAndMap() throws Exception {
152136 final String stackValue = "something";
153137 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value).push(stackValue)) {
154 assertNotNull(ignored);
155 assertEquals(value, ThreadContext.get(key));
156 assertEquals(stackValue, ThreadContext.peek());
157 }
158 assertFalse(ThreadContext.containsKey(key));
159 assertEquals("", ThreadContext.peek());
160 }
161
162 @Test
163 public void canReuseCloseableThreadContext() {
138 assertThat(ThreadContext.get(key), is(value));
139 assertThat(ThreadContext.peek(), is(stackValue));
140 }
141 assertThat(ThreadContext.containsKey(key), is(false));
142 assertThat(ThreadContext.peek(), is(""));
143 }
144
145 @Test
146 public void canReuseCloseableThreadContext() throws Exception {
164147 final String stackValue = "something";
165148 // Create a ctc and close it
166149 final CloseableThreadContext.Instance ctc = CloseableThreadContext.push(stackValue).put(key, value);
167 assertNotNull(ctc);
168 assertEquals(value, ThreadContext.get(key));
169 assertEquals(stackValue, ThreadContext.peek());
170 ctc.close();
171
172 assertFalse(ThreadContext.containsKey(key));
173 assertEquals("", ThreadContext.peek());
150 assertThat(ThreadContext.get(key), is(value));
151 assertThat(ThreadContext.peek(), is(stackValue));
152 ctc.close();
153
154 assertThat(ThreadContext.containsKey(key), is(false));
155 assertThat(ThreadContext.peek(), is(""));
174156
175157 final String anotherKey = "key2";
176158 final String anotherValue = "value2";
177159 final String anotherStackValue = "something else";
178160 // Use it again
179161 ctc.push(anotherStackValue).put(anotherKey, anotherValue);
180 assertEquals(anotherValue, ThreadContext.get(anotherKey));
181 assertEquals(anotherStackValue, ThreadContext.peek());
182 ctc.close();
183
184 assertFalse(ThreadContext.containsKey(anotherKey));
185 assertEquals("", ThreadContext.peek());
186 }
187
188 @Test
189 public void closeIsIdempotent() {
162 assertThat(ThreadContext.get(anotherKey), is(anotherValue));
163 assertThat(ThreadContext.peek(), is(anotherStackValue));
164 ctc.close();
165
166 assertThat(ThreadContext.containsKey(anotherKey), is(false));
167 assertThat(ThreadContext.peek(), is(""));
168 }
169
170 @Test
171 public void closeIsIdempotent() throws Exception {
190172
191173 final String originalMapValue = "map to keep";
192174 final String originalStackValue = "stack to keep";
196178 final String newMapValue = "temp map value";
197179 final String newStackValue = "temp stack to keep";
198180 final CloseableThreadContext.Instance ctc = CloseableThreadContext.push(newStackValue).put(key, newMapValue);
199 assertNotNull(ctc);
200
201 ctc.close();
202 assertEquals(originalMapValue, ThreadContext.get(key));
203 assertEquals(originalStackValue, ThreadContext.peek());
204
205 ctc.close();
206 assertEquals(originalMapValue, ThreadContext.get(key));
207 assertEquals(originalStackValue, ThreadContext.peek());
208 }
209
210 @Test
211 public void putAllWillPutAllValues() {
181
182 ctc.close();
183 assertThat(ThreadContext.get(key), is(originalMapValue));
184 assertThat(ThreadContext.peek(), is(originalStackValue));
185
186 ctc.close();
187 assertThat(ThreadContext.get(key), is(originalMapValue));
188 assertThat(ThreadContext.peek(), is(originalStackValue));
189 }
190
191 @Test
192 public void putAllWillPutAllValues() throws Exception {
212193
213194 final String oldValue = "oldValue";
214195 ThreadContext.put(key, oldValue);
217198 valuesToPut.put(key, value);
218199
219200 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.putAll(valuesToPut)) {
220 assertNotNull(ignored);
221 assertEquals(value, ThreadContext.get(key));
222 }
223 assertEquals(oldValue, ThreadContext.get(key));
224
225 }
226
227 @Test
228 public void pushAllWillPushAllValues() {
201 assertThat(ThreadContext.get(key), is(value));
202 }
203 assertThat(ThreadContext.get(key), is(oldValue));
204
205 }
206
207 @Test
208 public void pushAllWillPushAllValues() throws Exception {
229209
230210 ThreadContext.push(key);
231211 final List<String> messages = ThreadContext.getImmutableStack().asList();
232212 ThreadContext.pop();
233213
234214 try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.pushAll(messages)) {
235 assertNotNull(ignored);
236 assertEquals(key, ThreadContext.peek());
237 }
238 assertEquals("", ThreadContext.peek());
215 assertThat(ThreadContext.peek(), is(key));
216 }
217 assertThat(ThreadContext.peek(), is(""));
239218
240219 }
241220
1515 */
1616 package org.apache.logging.log4j;
1717
18 import org.apache.logging.log4j.message.StructuredDataMessage;
19 import org.junit.jupiter.api.BeforeEach;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.parallel.ResourceLock;
22
2318 import java.util.List;
2419 import java.util.Locale;
2520
26 import static org.assertj.core.api.Assertions.assertThat;
21 import org.apache.logging.log4j.message.StructuredDataMessage;
22 import org.junit.Before;
23 import org.junit.Test;
2724
28 @ResourceLock("log4j2.TestLogger")
25 import static org.hamcrest.CoreMatchers.*;
26
27 import static org.junit.Assert.*;
28
29 /**
30 *
31 */
2932 public class EventLoggerTest {
3033
3134 TestLogger logger = (TestLogger) LogManager.getLogger("EventLogger");
3235 List<String> results = logger.getEntries();
3336
34 @BeforeEach
37 @Before
3538 public void setup() {
3639 results.clear();
3740 }
4043 public void structuredData() {
4144 ThreadContext.put("loginId", "JohnDoe");
4245 ThreadContext.put("ipAddress", "192.168.0.120");
43 ThreadContext.put("locale", Locale.US.getDisplayName(Locale.US));
46 ThreadContext.put("locale", Locale.US.getDisplayName());
4447 final StructuredDataMessage msg = new StructuredDataMessage("Transfer@18060", "Transfer Complete", "Audit");
4548 msg.put("ToAccount", "123456");
4649 msg.put("FromAccount", "123457");
4750 msg.put("Amount", "200.00");
4851 EventLogger.logEvent(msg);
4952 ThreadContext.clearMap();
50 assertThat(results).hasSize(1);
53 assertEquals(1, results.size());
5154 final String expected = "EVENT OFF Audit [Transfer@18060 Amount=\"200.00\" FromAccount=\"123457\" ToAccount=\"123456\"] Transfer Complete";
52 assertThat(results.get(0)).startsWith(expected);
55 assertThat("Incorrect structured data", results.get(0), startsWith(expected));
5356 }
5457
5558 }
1616
1717 package org.apache.logging.log4j;
1818
19 import java.util.ArrayList;
20 import java.util.List;
21
1922 import org.apache.logging.log4j.message.Message;
2023 import org.apache.logging.log4j.message.ReusableMessage;
2124 import org.apache.logging.log4j.message.SimpleMessage;
2225 import org.apache.logging.log4j.spi.AbstractLogger;
2326 import org.apache.logging.log4j.util.Supplier;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import static org.junit.jupiter.api.Assertions.*;
27 import org.junit.Before;
28 import org.junit.Test;
29
30 import static org.junit.Assert.*;
3131
3232 /**
3333 * Tests the AbstractLogger implementation of the Logger2 interface.
211211 final Supplier[] supplierArray1 = new Supplier[] {supplier};
212212 final Supplier[] supplierArray2 = new Supplier[] {supplier, supplier2};
213213
214 @BeforeEach
214 @Before
215215 public void beforeEachTest() {
216216 logger2.list.clear();
217217 supplier.invoked = false;
1515 */
1616 package org.apache.logging.log4j;
1717
18 import org.junit.jupiter.api.Test;
19
20 import static org.junit.jupiter.api.Assertions.*;
21
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22
23 import org.junit.Test;
24
25 /**
26 *
27 */
2228 public class LevelTest {
2329
2430 @Test
1515 */
1616 package org.apache.logging.log4j;
1717
18 import org.apache.logging.log4j.message.ParameterizedMessageFactory;
19 import org.apache.logging.log4j.spi.LoggerContext;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.parallel.ResourceAccessMode;
22 import org.junit.jupiter.api.parallel.ResourceLock;
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
2320
2421 import java.io.Closeable;
2522 import java.io.IOException;
2623
27 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import org.apache.logging.log4j.message.ParameterizedMessageFactory;
25 import org.apache.logging.log4j.spi.LoggerContext;
26 import org.junit.Assert;
27 import org.junit.Test;
2928
30 @ResourceLock(value = "log4j2.LoggerContextFactory", mode = ResourceAccessMode.READ)
29 /**
30 *
31 */
3132 public class LogManagerTest {
3233
33 @SuppressWarnings("InnerClassMayBeStatic")
3434 class Inner {
3535 final Logger LOGGER = LogManager.getLogger();
3636 }
3737
38 @SuppressWarnings("InnerClassMayBeStatic")
3938 class InnerByClass {
4039 final Logger LOGGER = LogManager.getLogger(InnerByClass.class);
4140 }
5150 @Test
5251 public void testGetLogger() {
5352 Logger logger = LogManager.getLogger();
54 assertNotNull(logger, "No Logger returned");
55 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
53 assertNotNull("No Logger returned", logger);
54 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
5655 logger = LogManager.getLogger(ParameterizedMessageFactory.INSTANCE);
57 assertNotNull(logger, "No Logger returned");
58 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
56 assertNotNull("No Logger returned", logger);
57 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
5958 logger = LogManager.getLogger((Class<?>) null);
60 assertNotNull(logger, "No Logger returned");
61 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
59 assertNotNull("No Logger returned", logger);
60 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
6261 logger = LogManager.getLogger((Class<?>) null, ParameterizedMessageFactory.INSTANCE);
63 assertNotNull(logger, "No Logger returned");
64 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
62 assertNotNull("No Logger returned", logger);
63 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
6564 logger = LogManager.getLogger((String) null);
66 assertNotNull(logger, "No Logger returned");
67 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
65 assertNotNull("No Logger returned", logger);
66 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
6867 logger = LogManager.getLogger((String) null, ParameterizedMessageFactory.INSTANCE);
69 assertNotNull(logger, "No Logger returned");
70 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
68 assertNotNull("No Logger returned", logger);
69 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
7170 logger = LogManager.getLogger((Object) null);
72 assertNotNull(logger, "No Logger returned");
73 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
71 assertNotNull("No Logger returned", logger);
72 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
7473 logger = LogManager.getLogger((Object) null, ParameterizedMessageFactory.INSTANCE);
75 assertNotNull(logger, "No Logger returned");
76 assertEquals(LogManagerTest.class.getName(), logger.getName(), "Incorrect Logger name: " + logger.getName());
74 assertNotNull("No Logger returned", logger);
75 assertTrue("Incorrect Logger name: " + logger.getName(),LogManagerTest.class.getName().equals(logger.getName()));
7776 }
7877
7978 @Test
8079 public void testGetLoggerForAnonymousInnerClass1() throws IOException {
8180 final Closeable closeable = new Closeable() {
8281
83 final Logger LOGGER = LogManager.getLogger();
82 Logger LOGGER = LogManager.getLogger();
8483
8584 @Override
8685 public void close() throws IOException {
87 assertEquals("org.apache.logging.log4j.LogManagerTest$1", LOGGER.getName());
86 Assert.assertEquals("org.apache.logging.log4j.LogManagerTest$1", LOGGER.getName());
8887 }
8988 };
9089 closeable.close();
9493 public void testGetLoggerForAnonymousInnerClass2() throws IOException {
9594 final Closeable closeable = new Closeable() {
9695
97 final Logger LOGGER = LogManager.getLogger(getClass());
96 Logger LOGGER = LogManager.getLogger(getClass());
9897
9998 @Override
10099 public void close() throws IOException {
101 assertEquals("org.apache.logging.log4j.LogManagerTest$2", LOGGER.getName());
100 Assert.assertEquals("org.apache.logging.log4j.LogManagerTest$2", LOGGER.getName());
102101 }
103102 };
104103 closeable.close();
106105
107106 @Test
108107 public void testGetLoggerForInner() {
109 assertEquals("org.apache.logging.log4j.LogManagerTest.Inner", new Inner().LOGGER.getName());
108 Assert.assertEquals("org.apache.logging.log4j.LogManagerTest.Inner", new Inner().LOGGER.getName());
110109 }
111110
112111 @Test
113112 public void testGetLoggerForInnerByClass() {
114 assertEquals("org.apache.logging.log4j.LogManagerTest.InnerByClass", new InnerByClass().LOGGER.getName());
113 Assert.assertEquals("org.apache.logging.log4j.LogManagerTest.InnerByClass", new InnerByClass().LOGGER.getName());
115114 }
116115
117116 @Test
118117 public void testGetLoggerForStaticInner() {
119 assertEquals("org.apache.logging.log4j.LogManagerTest.StaticInner", StaticInner.LOGGER.getName());
118 Assert.assertEquals("org.apache.logging.log4j.LogManagerTest.StaticInner", StaticInner.LOGGER.getName());
120119 }
121120
122121 @Test
123122 public void testGetLoggerForStaticInnerByClass() {
124 assertEquals("org.apache.logging.log4j.LogManagerTest.StaticInnerByClass", StaticInnerByClass.LOGGER.getName());
123 Assert.assertEquals("org.apache.logging.log4j.LogManagerTest.StaticInnerByClass", StaticInnerByClass.LOGGER.getName());
125124 }
126125
127126 @Test
1515 */
1616 package org.apache.logging.log4j;
1717
18 import static org.hamcrest.CoreMatchers.containsString;
19 import static org.hamcrest.CoreMatchers.not;
20 import static org.hamcrest.CoreMatchers.startsWith;
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertThat;
23
24 import java.util.List;
25 import java.util.Locale;
26
1827 import org.apache.logging.log4j.message.FormattedMessage;
1928 import org.apache.logging.log4j.message.JsonMessage;
2029 import org.apache.logging.log4j.message.LocalizedMessage;
2635 import org.apache.logging.log4j.message.StringFormattedMessage;
2736 import org.apache.logging.log4j.message.ThreadDumpMessage;
2837 import org.apache.logging.log4j.util.Supplier;
29 import org.junit.jupiter.api.AfterEach;
30 import org.junit.jupiter.api.BeforeEach;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.parallel.ResourceLock;
33 import org.junit.jupiter.api.parallel.Resources;
34
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.Properties;
38
39 import static org.assertj.core.api.Assertions.assertThat;
38 import org.junit.After;
39 import org.junit.Before;
40 import org.junit.Test;
4041
4142 /**
4243 * Tests Logger APIs with {@link Supplier}.
4344 */
44 @ResourceLock(Resources.LOCALE)
45 @ResourceLock("log4j2.TestLogger")
4645 public class LoggerSupplierTest {
4746
4847 private final TestLogger logger = (TestLogger) LogManager.getLogger("LoggerTest");
5352
5453 @Test
5554 public void flowTracing_SupplierOfFormattedMessage() {
56 logger.traceEntry(() -> new FormattedMessage("int foo={}", 1234567890));
57 assertThat(results).hasSize(1);
58 String entry = results.get(0);
59 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
60 .contains("(int foo=1234567890)")
61 .doesNotContain("FormattedMessage");
55 logger.traceEntry(new Supplier<FormattedMessage>() {
56 @Override
57 public FormattedMessage get() {
58 return new FormattedMessage("int foo={}", 1234567890);
59 }
60 });
61 assertEquals(1, results.size());
62 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
63 assertThat("Missing entry data", results.get(0), containsString("(int foo=1234567890)"));
64 assertThat("Bad toString()", results.get(0), not(containsString("FormattedMessage")));
6265 }
6366
6467 @Test
6568 public void flowTracing_SupplierOfJsonMessage() {
66 Properties props = new Properties();
67 props.setProperty("foo", "bar");
68 logger.traceEntry(() -> new JsonMessage(props));
69 assertThat(results).hasSize(1);
70 String entry = results.get(0);
71 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
72 .contains("\"foo\":\"bar\"")
73 .doesNotContain("JsonMessage");
69 logger.traceEntry(new Supplier<JsonMessage>() {
70 @Override
71 public JsonMessage get() {
72 return new JsonMessage(System.getProperties());
73 }
74 });
75 assertEquals(1, results.size());
76 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
77 assertThat("Missing entry data", results.get(0), containsString("\"java.runtime.name\":"));
78 assertThat("Bad toString()", results.get(0), not(containsString("JsonMessage")));
7479 }
7580
7681 @Test
7782 public void flowTracing_SupplierOfLocalizedMessage() {
78 logger.traceEntry(() -> new LocalizedMessage("int foo={}", 1234567890));
79 assertThat(results).hasSize(1);
80 String entry = results.get(0);
81 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
82 .contains("(int foo=1234567890)")
83 .doesNotContain("LocalizedMessage");
83 logger.traceEntry(new Supplier<LocalizedMessage>() {
84 @Override
85 public LocalizedMessage get() {
86 return new LocalizedMessage("int foo={}", 1234567890);
87 }
88 });
89 assertEquals(1, results.size());
90 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
91 assertThat("Missing entry data", results.get(0), containsString("(int foo=1234567890)"));
92 assertThat("Bad toString()", results.get(0), not(containsString("LocalizedMessage")));
8493 }
8594
8695 @Test
8796 public void flowTracing_SupplierOfLong() {
88 logger.traceEntry(() -> 1234567890L);
89 assertThat(results).hasSize(1);
90 String entry = results.get(0);
91 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
92 .contains("(1234567890)")
93 .doesNotContain("SimpleMessage");
97 logger.traceEntry(new Supplier<Long>() {
98 @Override
99 public Long get() {
100 return Long.valueOf(1234567890);
101 }
102 });
103 assertEquals(1, results.size());
104 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
105 assertThat("Missing entry data", results.get(0), containsString("(1234567890)"));
106 assertThat("Bad toString()", results.get(0), not(containsString("SimpleMessage")));
94107 }
95108
96109 @Test
97110 public void flowTracing_SupplierOfMessageFormatMessage() {
98 logger.traceEntry(() -> new MessageFormatMessage("int foo={0}", 1234567890));
99 assertThat(results).hasSize(1);
100 String entry = results.get(0);
101 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
102 .contains("(int foo=1,234,567,890)")
103 .doesNotContain("MessageFormatMessage");
111 logger.traceEntry(new Supplier<MessageFormatMessage>() {
112 @Override
113 public MessageFormatMessage get() {
114 return new MessageFormatMessage("int foo={0}", 1234567890);
115 }
116 });
117 assertEquals(1, results.size());
118 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
119 assertThat("Missing entry data", results.get(0), containsString("(int foo=1,234,567,890)"));
120 assertThat("Bad toString()", results.get(0), not(containsString("MessageFormatMessage")));
104121 }
105122
106123 @Test
107124 public void flowTracing_SupplierOfObjectArrayMessage() {
108 logger.traceEntry(() -> new ObjectArrayMessage(1234567890));
109 assertThat(results).hasSize(1);
110 String entry = results.get(0);
111 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
112 .contains("([1234567890])")
113 .doesNotContain("ObjectArrayMessage");
125 logger.traceEntry(new Supplier<ObjectArrayMessage>() {
126 @Override
127 public ObjectArrayMessage get() {
128 return new ObjectArrayMessage(1234567890);
129 }
130 });
131 assertEquals(1, results.size());
132 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
133 assertThat("Missing Enter data", results.get(0), containsString("([1234567890])"));
134 assertThat("Bad toString()", results.get(0), not(containsString("ObjectArrayMessage")));
114135 }
115136
116137 @Test
117138 public void flowTracing_SupplierOfObjectMessage() {
118 logger.traceEntry(() -> new ObjectMessage(1234567890));
119 assertThat(results).hasSize(1);
120 String entry = results.get(0);
121 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
122 .contains("(1234567890)")
123 .doesNotContain("ObjectMessage");
139 logger.traceEntry(new Supplier<ObjectMessage>() {
140 @Override
141 public ObjectMessage get() {
142 return new ObjectMessage(1234567890);
143 }
144 });
145 assertEquals(1, results.size());
146 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
147 assertThat("Missing entry data", results.get(0), containsString("(1234567890)"));
148 assertThat("Bad toString()", results.get(0), not(containsString("ObjectMessage")));
124149 }
125150
126151 @Test
127152 public void flowTracing_SupplierOfParameterizedMessage() {
128 logger.traceEntry(() -> new ParameterizedMessage("int foo={}", 1234567890));
129 assertThat(results).hasSize(1);
130 String entry = results.get(0);
131 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
132 .contains("(int foo=1234567890)")
133 .doesNotContain("ParameterizedMessage");
153 logger.traceEntry(new Supplier<ParameterizedMessage>() {
154 @Override
155 public ParameterizedMessage get() {
156 return new ParameterizedMessage("int foo={}", 1234567890);
157 }
158 });
159 assertEquals(1, results.size());
160 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
161 assertThat("Missing entry data", results.get(0), containsString("(int foo=1234567890)"));
162 assertThat("Bad toString()", results.get(0), not(containsString("ParameterizedMessage")));
134163 }
135164
136165 @Test
137166 public void flowTracing_SupplierOfSimpleMessage() {
138 logger.traceEntry(() -> new SimpleMessage("1234567890"));
139 assertThat(results).hasSize(1);
140 String entry = results.get(0);
141 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
142 .contains("(1234567890)")
143 .doesNotContain("SimpleMessage");
167 logger.traceEntry(new Supplier<SimpleMessage>() {
168 @Override
169 public SimpleMessage get() {
170 return new SimpleMessage("1234567890");
171 }
172 });
173 assertEquals(1, results.size());
174 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
175 assertThat("Missing entry data", results.get(0), containsString("(1234567890)"));
176 assertThat("Bad toString()", results.get(0), not(containsString("SimpleMessage")));
144177 }
145178
146179 @Test
147180 public void flowTracing_SupplierOfString() {
148 logger.traceEntry(() -> "1234567890");
149 assertThat(results).hasSize(1);
150 String entry = results.get(0);
151 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
152 .contains("(1234567890)")
153 .doesNotContain("SimpleMessage");
181 logger.traceEntry(new Supplier<String>() {
182 @Override
183 public String get() {
184 return "1234567890";
185 }
186 });
187 assertEquals(1, results.size());
188 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
189 assertThat("Missing entry data", results.get(0), containsString("(1234567890)"));
190 assertThat("Bad toString()", results.get(0), not(containsString("SimpleMessage")));
154191 }
155192
156193 @Test
157194 public void flowTracing_SupplierOfStringFormattedMessage() {
158 logger.traceEntry(() -> new StringFormattedMessage("int foo=%,d", 1234567890));
159 assertThat(results).hasSize(1);
160 String entry = results.get(0);
161 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter")
162 .contains("(int foo=1,234,567,890)")
163 .doesNotContain("StringFormattedMessage");
195 logger.traceEntry(new Supplier<StringFormattedMessage>() {
196 @Override
197 public StringFormattedMessage get() {
198 return new StringFormattedMessage("int foo=%,d", 1234567890);
199 }
200 });
201 assertEquals(1, results.size());
202 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
203 assertThat("Missing entry data", results.get(0), containsString("(int foo=1,234,567,890)"));
204 assertThat("Bad toString()", results.get(0), not(containsString("StringFormattedMessage")));
164205 }
165206
166207 @Test
167208 public void flowTracing_SupplierOfThreadDumpMessage() {
168 logger.traceEntry(() -> new ThreadDumpMessage("Title of ..."));
169 assertThat(results).hasSize(1);
170 String entry = results.get(0);
171 assertThat(entry).startsWith("ENTER[ FLOW ] TRACE Enter").contains("RUNNABLE", "Title of ...", getClass().getName());
209 logger.traceEntry(new Supplier<ThreadDumpMessage>() {
210 @Override
211 public ThreadDumpMessage get() {
212 return new ThreadDumpMessage("Title of ...");
213 }
214 });
215 assertEquals(1, results.size());
216 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
217 assertThat("Missing entry data", results.get(0), containsString("RUNNABLE"));
218 assertThat("Missing entry data", results.get(0), containsString("Title of ..."));
219 assertThat("Missing entry data", results.get(0), containsString(getClass().getName()));
172220 }
173221
174 @BeforeEach
222 @Before
175223 public void setup() {
176224 results.clear();
177225 defaultLocale = Locale.getDefault(Locale.Category.FORMAT);
178226 Locale.setDefault(Locale.Category.FORMAT, java.util.Locale.US);
179227 }
180228
181 @AfterEach
229 @After
182230 public void tearDown() {
183231 Locale.setDefault(Locale.Category.FORMAT, defaultLocale);
184232 }
1515 */
1616 package org.apache.logging.log4j;
1717
18 import java.util.Date;
19 import java.util.List;
20 import java.util.Locale;
21
1822 import org.apache.logging.log4j.message.EntryMessage;
1923 import org.apache.logging.log4j.message.JsonMessage;
2024 import org.apache.logging.log4j.message.Message;
2125 import org.apache.logging.log4j.message.MessageFactory;
2226 import org.apache.logging.log4j.message.ObjectMessage;
2327 import org.apache.logging.log4j.message.ParameterizedMessageFactory;
24 import org.apache.logging.log4j.message.SimpleMessage;
2528 import org.apache.logging.log4j.message.SimpleMessageFactory;
2629 import org.apache.logging.log4j.message.StringFormatterMessageFactory;
2730 import org.apache.logging.log4j.message.StructuredDataMessage;
2831 import org.apache.logging.log4j.spi.MessageFactory2Adapter;
2932 import org.apache.logging.log4j.util.Strings;
3033 import org.apache.logging.log4j.util.Supplier;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
33 import org.junit.jupiter.api.parallel.ResourceLock;
34 import java.util.Date;
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.Properties;
38
39 import static org.hamcrest.CoreMatchers.*;
40 import static org.hamcrest.MatcherAssert.assertThat;
41 import static org.junit.jupiter.api.Assertions.*;
42
43 @ResourceLock("log4j2.MarkerManager")
44 @ResourceLock("log4j2.TestLogger")
34 import org.junit.Before;
35 import org.junit.Test;
36
37 import static org.hamcrest.CoreMatchers.containsString;
38 import static org.hamcrest.CoreMatchers.endsWith;
39 import static org.hamcrest.CoreMatchers.equalTo;
40 import static org.hamcrest.CoreMatchers.startsWith;
41 import static org.junit.Assert.*;
42 /**
43 *
44 */
4545 public class LoggerTest {
4646
4747 private static class TestParameterizedMessageFactory {
5757 private final List<String> results = logger.getEntries();
5858
5959 @Test
60 public void builder() {
61 logger.atDebug().withLocation().log("Hello");
62 logger.atError().withMarker(marker).log("Hello {}", "John");
63 logger.atWarn().withThrowable(new Throwable("This is a test")).log((Message) new SimpleMessage("Log4j rocks!"));
64 assertEquals(3, results.size());
65 assertThat("Incorrect message 1", results.get(0),
66 equalTo(" DEBUG org.apache.logging.log4j.LoggerTest.builder(LoggerTest.java:62) Hello"));
67 assertThat("Incorrect message 2", results.get(1), equalTo("test ERROR Hello John"));
68 assertThat("Incorrect message 3", results.get(2),
69 startsWith(" WARN Log4j rocks! java.lang.Throwable: This is a test"));
70 assertThat("Throwable incorrect in message 3", results.get(2),
71 containsString("at org.apache.logging.log4j.LoggerTest.builder(LoggerTest.java:64)"));
72 }
73
74 @Test
7560 public void basicFlow() {
7661 logger.entry();
7762 logger.exit();
8368
8469 @Test
8570 public void flowTracingMessage() {
86 Properties props = new Properties();
87 props.setProperty("foo", "bar");
88 logger.traceEntry(new JsonMessage(props));
71 logger.traceEntry(new JsonMessage(System.getProperties()));
8972 final Response response = new Response(-1, "Generic error");
9073 logger.traceExit(new JsonMessage(response), response);
9174 assertEquals(2, results.size());
9275 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
93 assertThat("Missing entry data", results.get(0), containsString("\"foo\":\"bar\""));
76 assertThat("Missing entry data", results.get(0), containsString("\"java.runtime.name\":"));
9477 assertThat("incorrect Exit", results.get(1), startsWith("EXIT[ FLOW ] TRACE Exit"));
9578 assertThat("Missing exit data", results.get(1), containsString("\"message\":\"Generic error\""));
9679 }
159142
160143 @Test
161144 public void flowTracingString_SupplierOfObjectMessages() {
162 final EntryMessage msg = logger.traceEntry("doFoo(a={}, b={})", (Supplier<Message>) () -> new ObjectMessage(1), (Supplier<Message>) () -> new ObjectMessage(2));
145 final EntryMessage msg = logger.traceEntry("doFoo(a={}, b={})", new Supplier<Message>() {
146 @Override
147 public Message get() {
148 return new ObjectMessage(1);
149 }
150 }, new Supplier<Message>() {
151 @Override
152 public Message get() {
153 return new ObjectMessage(2);
154 }
155 });
163156 logger.traceExit(msg, 3);
164157 assertEquals(2, results.size());
165158 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
170163
171164 @Test
172165 public void flowTracingString_SupplierOfStrings() {
173 final EntryMessage msg = logger.traceEntry("doFoo(a={}, b={})", (Supplier<String>) () -> "1", (Supplier<String>) () -> "2");
166 final EntryMessage msg = logger.traceEntry("doFoo(a={}, b={})", new Supplier<String>() {
167 @Override
168 public String get() {
169 return "1";
170 }
171 }, new Supplier<String>() {
172 @Override
173 public String get() {
174 return "2";
175 }
176 });
174177 logger.traceExit(msg, 3);
175178 assertEquals(2, results.size());
176179 assertThat("Incorrect Entry", results.get(0), startsWith("ENTER[ FLOW ] TRACE Enter"));
195198 public void debug() {
196199 logger.debug("Debug message");
197200 assertEquals(1, results.size());
198 assertTrue(results.get(0).startsWith(" DEBUG Debug message"), "Incorrect message");
201 assertTrue("Incorrect message", results.get(0).startsWith(" DEBUG Debug message"));
199202 }
200203
201204 @Test
202205 public void debugObject() {
203206 logger.debug(new Date());
204207 assertEquals(1, results.size());
205 assertTrue(results.get(0).length() > 7, "Invalid length");
208 assertTrue("Invalid length", results.get(0).length() > 7);
206209 }
207210
208211 @Test
209212 public void debugWithParms() {
210213 logger.debug("Hello, {}", "World");
211214 assertEquals(1, results.size());
212 assertTrue(results.get(0).startsWith(" DEBUG Hello, World"), "Incorrect substitution");
215 assertTrue("Incorrect substitution", results.get(0).startsWith(" DEBUG Hello, World"));
213216 }
214217
215218 @Test
216219 public void debugWithParmsAndThrowable() {
217220 logger.debug("Hello, {}", "World", new RuntimeException("Test Exception"));
218221 assertEquals(1, results.size());
219 assertTrue(
220 results.get(0).startsWith(" DEBUG Hello, World java.lang.RuntimeException: Test Exception"),
221 "Unexpected results: " + results.get(0));
222 assertTrue("Unexpected results: " + results.get(0),
223 results.get(0).startsWith(" DEBUG Hello, World java.lang.RuntimeException: Test Exception"));
222224 }
223225
224226 @Test
440442
441443 @Test
442444 public void isAllEnabled() {
443 assertTrue(logger.isEnabled(Level.ALL), "Incorrect level");
445 assertTrue("Incorrect level", logger.isEnabled(Level.ALL));
444446 }
445447
446448 @Test
447449 public void isDebugEnabled() {
448 assertTrue(logger.isDebugEnabled(), "Incorrect level");
449 assertTrue(logger.isEnabled(Level.DEBUG), "Incorrect level");
450 assertTrue("Incorrect level", logger.isDebugEnabled());
451 assertTrue("Incorrect level", logger.isEnabled(Level.DEBUG));
450452 }
451453
452454 @Test
453455 public void isErrorEnabled() {
454 assertTrue(logger.isErrorEnabled(), "Incorrect level");
455 assertTrue(logger.isEnabled(Level.ERROR), "Incorrect level");
456 assertTrue("Incorrect level", logger.isErrorEnabled());
457 assertTrue("Incorrect level", logger.isEnabled(Level.ERROR));
456458 }
457459
458460 @Test
459461 public void isFatalEnabled() {
460 assertTrue(logger.isFatalEnabled(), "Incorrect level");
461 assertTrue(logger.isEnabled(Level.FATAL), "Incorrect level");
462 assertTrue("Incorrect level", logger.isFatalEnabled());
463 assertTrue("Incorrect level", logger.isEnabled(Level.FATAL));
462464 }
463465
464466 @Test
465467 public void isInfoEnabled() {
466 assertTrue(logger.isInfoEnabled(), "Incorrect level");
467 assertTrue(logger.isEnabled(Level.INFO), "Incorrect level");
468 assertTrue("Incorrect level", logger.isInfoEnabled());
469 assertTrue("Incorrect level", logger.isEnabled(Level.INFO));
468470 }
469471
470472 @Test
471473 public void isOffEnabled() {
472 assertTrue(logger.isEnabled(Level.OFF), "Incorrect level");
474 assertTrue("Incorrect level", logger.isEnabled(Level.OFF));
473475 }
474476
475477 @Test
476478 public void isTraceEnabled() {
477 assertTrue(logger.isTraceEnabled(), "Incorrect level");
478 assertTrue(logger.isEnabled(Level.TRACE), "Incorrect level");
479 assertTrue("Incorrect level", logger.isTraceEnabled());
480 assertTrue("Incorrect level", logger.isEnabled(Level.TRACE));
479481 }
480482
481483 @Test
482484 public void isWarnEnabled() {
483 assertTrue(logger.isWarnEnabled(), "Incorrect level");
484 assertTrue(logger.isEnabled(Level.WARN), "Incorrect level");
485 assertTrue("Incorrect level", logger.isWarnEnabled());
486 assertTrue("Incorrect level", logger.isEnabled(Level.WARN));
485487 }
486488
487489 @Test
488490 public void isAllEnabledWithMarker() {
489 assertTrue(logger.isEnabled(Level.ALL, marker), "Incorrect level");
491 assertTrue("Incorrect level", logger.isEnabled(Level.ALL, marker));
490492 }
491493
492494 @Test
493495 public void isDebugEnabledWithMarker() {
494 assertTrue(logger.isDebugEnabled(marker), "Incorrect level");
495 assertTrue(logger.isEnabled(Level.DEBUG, marker), "Incorrect level");
496 assertTrue("Incorrect level", logger.isDebugEnabled(marker));
497 assertTrue("Incorrect level", logger.isEnabled(Level.DEBUG, marker));
496498 }
497499
498500 @Test
499501 public void isErrorEnabledWithMarker() {
500 assertTrue(logger.isErrorEnabled(marker), "Incorrect level");
501 assertTrue(logger.isEnabled(Level.ERROR, marker), "Incorrect level");
502 assertTrue("Incorrect level", logger.isErrorEnabled(marker));
503 assertTrue("Incorrect level", logger.isEnabled(Level.ERROR, marker));
502504 }
503505
504506 @Test
505507 public void isFatalEnabledWithMarker() {
506 assertTrue(logger.isFatalEnabled(marker), "Incorrect level");
507 assertTrue(logger.isEnabled(Level.FATAL, marker), "Incorrect level");
508 assertTrue("Incorrect level", logger.isFatalEnabled(marker));
509 assertTrue("Incorrect level", logger.isEnabled(Level.FATAL, marker));
508510 }
509511
510512 @Test
511513 public void isInfoEnabledWithMarker() {
512 assertTrue(logger.isInfoEnabled(marker), "Incorrect level");
513 assertTrue(logger.isEnabled(Level.INFO, marker), "Incorrect level");
514 assertTrue("Incorrect level", logger.isInfoEnabled(marker));
515 assertTrue("Incorrect level", logger.isEnabled(Level.INFO, marker));
514516 }
515517
516518 @Test
517519 public void isOffEnabledWithMarker() {
518 assertTrue(logger.isEnabled(Level.OFF, marker), "Incorrect level");
520 assertTrue("Incorrect level", logger.isEnabled(Level.OFF, marker));
519521 }
520522
521523 @Test
522524 public void isTraceEnabledWithMarker() {
523 assertTrue(logger.isTraceEnabled(marker), "Incorrect level");
524 assertTrue(logger.isEnabled(Level.TRACE, marker), "Incorrect level");
525 assertTrue("Incorrect level", logger.isTraceEnabled(marker));
526 assertTrue("Incorrect level", logger.isEnabled(Level.TRACE, marker));
525527 }
526528
527529 @Test
528530 public void isWarnEnabledWithMarker() {
529 assertTrue(logger.isWarnEnabled(marker), "Incorrect level");
530 assertTrue(logger.isEnabled(Level.WARN, marker), "Incorrect level");
531 assertTrue("Incorrect level", logger.isWarnEnabled(marker));
532 assertTrue("Incorrect level", logger.isEnabled(Level.WARN, marker));
531533 }
532534
533535 @Test
534536 public void mdc() {
535537
536 ThreadContext.put("TestYear", Integer.toString(2010));
538 ThreadContext.put("TestYear", Integer.valueOf(2010).toString());
537539 logger.debug("Debug message");
538540 final String testYear = ThreadContext.get("TestYear");
539 assertNotNull(testYear, "Test Year is null");
540 assertEquals("2010", testYear, "Incorrect test year: " + testYear);
541 assertNotNull("Test Year is null", testYear);
542 assertEquals("Incorrect test year: " + testYear, "2010", testYear);
541543 ThreadContext.clearMap();
542544 logger.debug("Debug message");
543545 assertEquals(2, results.size());
544546 System.out.println("Log line 1: " + results.get(0));
545547 System.out.println("log line 2: " + results.get(1));
546 assertTrue(
547 results.get(0).startsWith(" DEBUG Debug message {TestYear=2010}"), "Incorrect MDC: " + results.get(0));
548 assertTrue(
549 results.get(1).startsWith(" DEBUG Debug message"), "MDC not cleared?: " + results.get(1));
548 assertTrue("Incorrect MDC: " + results.get(0),
549 results.get(0).startsWith(" DEBUG Debug message {TestYear=2010}"));
550 assertTrue("MDC not cleared?: " + results.get(1),
551 results.get(1).startsWith(" DEBUG Debug message"));
550552 }
551553
552554 @Test
558560 assertThat("Incorrect message", results.get(1), startsWith("Test DEBUG Debug message 2"));
559561 }
560562
561 @BeforeEach
563 @Before
562564 public void setup() {
563565 results.clear();
564566 }
588590 }
589591
590592
591 private static class Response {
593 private class Response {
592594 int status;
593595 String message;
594596
1515 */
1616 package org.apache.logging.log4j;
1717
18 import org.junit.jupiter.api.BeforeEach;
19 import org.junit.jupiter.api.Test;
20 import org.junit.jupiter.api.parallel.ResourceLock;
18 import org.junit.Before;
19 import org.junit.Test;
2120
22 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2322
24 @ResourceLock("log4j2.MarkerManager")
23 /**
24 *
25 */
2526 public class MarkerTest {
2627
27 @BeforeEach
28 @Before
2829 public void setUp() {
2930 MarkerManager.clear();
3031 }
5758
5859 @Test
5960 public void testMarker() {
60 // root (level 1)
6161 final Marker parent = MarkerManager.getMarker("PARENT");
62 // level 2
6362 final Marker test1 = MarkerManager.getMarker("TEST1").setParents(parent);
6463 final Marker test2 = MarkerManager.getMarker("TEST2").addParents(parent);
65 assertTrue(test1.isInstanceOf(parent), "TEST1 is not an instance of PARENT");
66 assertTrue(test2.isInstanceOf(parent), "TEST2 is not an instance of PARENT");
67 assertFalse(parent.isInstanceOf(test1));
68 assertFalse(parent.isInstanceOf(test2));
69 // level 3
70 final Marker test3 = MarkerManager.getMarker("TEST3").addParents(test2);
71 assertTrue(test3.isInstanceOf(test2));
72 assertTrue(test3.isInstanceOf("TEST2"));
73 assertTrue(test3.isInstanceOf("PARENT"));
74 assertTrue(test2.isInstanceOf("PARENT"));
75 assertFalse(parent.isInstanceOf(test3));
76 assertFalse(parent.isInstanceOf(test3));
77 }
78
79 @Test
80 public void testMarkerSharedIntermediaryMarker() {
81 final Marker parent1 = MarkerManager.getMarker("PARENT1");
82 final Marker parent2 = MarkerManager.getMarker("PARENT2");
83 final Marker test1 = MarkerManager.getMarker("TEST1").setParents(parent1, parent2);
84 assertTrue(test1.isInstanceOf(parent1));
85 // Leaf
86 final Marker leaf = MarkerManager.getMarker("LEAF").setParents(test1);
87 assertTrue(leaf.isInstanceOf("TEST1"));
88 assertTrue(leaf.isInstanceOf("PARENT1"));
89 assertTrue(leaf.isInstanceOf("PARENT2"));
64 assertTrue("TEST1 is not an instance of PARENT", test1.isInstanceOf(parent));
65 assertTrue("TEST2 is not an instance of PARENT", test2.isInstanceOf(parent));
9066 }
9167
9268 @Test
9571 final Marker parent2 = MarkerManager.getMarker("PARENT2");
9672 final Marker test1 = MarkerManager.getMarker("TEST1").setParents(parent1, parent2);
9773 final Marker test2 = MarkerManager.getMarker("TEST2").addParents(parent1, parent2);
98 assertTrue(test1.isInstanceOf(parent1), "TEST1 is not an instance of PARENT1");
99 assertTrue(test1.isInstanceOf("PARENT1"), "TEST1 is not an instance of PARENT1");
100 assertTrue(test1.isInstanceOf(parent2), "TEST1 is not an instance of PARENT2");
101 assertTrue(test1.isInstanceOf("PARENT2"), "TEST1 is not an instance of PARENT2");
102 assertTrue(test2.isInstanceOf(parent1), "TEST2 is not an instance of PARENT1");
103 assertTrue(test2.isInstanceOf("PARENT1"), "TEST2 is not an instance of PARENT1");
104 assertTrue(test2.isInstanceOf(parent2), "TEST2 is not an instance of PARENT2");
105 assertTrue(test2.isInstanceOf("PARENT2"), "TEST2 is not an instance of PARENT2");
74 assertTrue("TEST1 is not an instance of PARENT1", test1.isInstanceOf(parent1));
75 assertTrue("TEST1 is not an instance of PARENT2", test1.isInstanceOf(parent2));
76 assertTrue("TEST2 is not an instance of PARENT1", test2.isInstanceOf(parent1));
77 assertTrue("TEST2 is not an instance of PARENT2", test2.isInstanceOf(parent2));
10678 }
10779
10880 @Test
11183 final Marker existing = MarkerManager.getMarker("EXISTING");
11284 final Marker test1 = MarkerManager.getMarker("TEST1").setParents(existing);
11385 test1.addParents(parent);
114 assertTrue(test1.isInstanceOf(parent), "TEST1 is not an instance of PARENT");
115 assertTrue(test1.isInstanceOf("PARENT"), "TEST1 is not an instance of PARENT");
116 assertTrue(test1.isInstanceOf(existing), "TEST1 is not an instance of EXISTING");
117 assertTrue(test1.isInstanceOf("EXISTING"), "TEST1 is not an instance of EXISTING");
86 assertTrue("TEST1 is not an instance of PARENT", test1.isInstanceOf(parent));
87 assertTrue("TEST1 is not an instance of EXISTING", test1.isInstanceOf(existing));
11888 }
11989
12090
12696 test1.addParents(parent);
12797 final Marker[] parents = test1.getParents();
12898 test1.addParents(existing);
129 assertEquals(parents.length, test1.getParents().length, "duplicate add allowed");
99 assertTrue("duplicate add allowed", parents.length == test1.getParents().length);
130100 test1.addParents(existing, MarkerManager.getMarker("EXTRA"));
131 assertEquals(parents.length + 1, test1.getParents().length, "incorrect add");
132 assertTrue(test1.isInstanceOf(parent), "TEST1 is not an instance of PARENT");
133 assertTrue(test1.isInstanceOf("PARENT"), "TEST1 is not an instance of PARENT");
134 assertTrue(test1.isInstanceOf(existing), "TEST1 is not an instance of EXISTING");
135 assertTrue(test1.isInstanceOf("EXISTING"), "TEST1 is not an instance of EXISTING");
101 assertTrue("incorrect add", parents.length + 1 == test1.getParents().length);
102 assertTrue("TEST1 is not an instance of PARENT", test1.isInstanceOf(parent));
103 assertTrue("TEST1 is not an instance of EXISTING", test1.isInstanceOf(existing));
136104 }
137105 }
1515 */
1616 package org.apache.logging.log4j;
1717
18 import org.junit.jupiter.api.AfterAll;
19 import org.junit.jupiter.api.BeforeAll;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.parallel.ResourceLock;
22 import org.junit.jupiter.api.parallel.Resources;
18 import org.junit.AfterClass;
19 import org.junit.BeforeClass;
20 import org.junit.Test;
2321
24 import static org.junit.jupiter.api.Assertions.assertNull;
22 import static org.junit.Assert.*;
2523
2624 /**
2725 * Tests {@link ThreadContext}.
2826 */
29 @ResourceLock(Resources.SYSTEM_PROPERTIES)
3027 public class NoopThreadContextTest {
3128
3229 private static final String TRUE = "true";
3330 private static final String PROPERY_KEY_ALL = "disableThreadContext";
3431 private static final String PROPERY_KEY_MAP = "disableThreadContextMap";
3532
36 @BeforeAll
33 @BeforeClass
3734 public static void before() {
3835 System.setProperty(PROPERY_KEY_ALL, TRUE);
3936 System.setProperty(PROPERY_KEY_MAP, TRUE);
4037 ThreadContext.init();
4138 }
4239
43 @AfterAll
40 @AfterClass
4441 public static void after() {
4542 System.clearProperty(PROPERY_KEY_ALL);
4643 System.clearProperty(PROPERY_KEY_MAP);
5148 public void testNoop() {
5249 ThreadContext.put("Test", "Test");
5350 final String value = ThreadContext.get("Test");
54 assertNull(value, "value was saved");
51 assertNull("value was saved", value);
5552 }
5653
5754
3333 private static final long serialVersionUID = 1L;
3434
3535 public TestLogger() {
36 super();
3637 }
3738
3839 public TestLogger(final String name, final MessageFactory messageFactory) {
5051 }
5152
5253 @Override
53 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message msg,
54 final Throwable throwable) {
55 log(level, marker, fqcn, (StackTraceElement) null, msg, throwable);
56 }
57
58 @Override
59 protected void log(final Level level, final Marker marker, final String fqcn, final StackTraceElement location,
60 final Message message, final Throwable throwable) {
54 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) {
6155 final StringBuilder sb = new StringBuilder();
6256 if (marker != null) {
6357 sb.append(marker);
6559 sb.append(' ');
6660 sb.append(level.toString());
6761 sb.append(' ');
68 if (location != null) {
69 sb.append(location.toString());
70 sb.append(' ');
71 }
72 sb.append(message.getFormattedMessage());
62 sb.append(msg.getFormattedMessage());
7363 final Map<String, String> mdc = ThreadContext.getImmutableContext();
7464 if (mdc.size() > 0) {
7565 sb.append(' ');
7666 sb.append(mdc.toString());
7767 sb.append(' ');
7868 }
79 final Object[] params = message.getParameters();
69 final Object[] params = msg.getParameters();
8070 Throwable t;
8171 if (throwable == null && params != null && params.length > 0 && params[params.length - 1] instanceof Throwable) {
8272 t = (Throwable) params[params.length - 1];
4242 @Override
4343 public void removeContext(final LoggerContext context) {
4444 }
45
46 @Override
47 public boolean isClassLoaderDependent() {
48 return false;
49 }
5045 }
1515 */
1616 package org.apache.logging.log4j;
1717
18 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertTrue;
22
23 import org.apache.logging.log4j.junit.ThreadContextRule;
1924 import org.apache.logging.log4j.spi.DefaultThreadContextMap;
20 import org.junit.jupiter.api.AfterAll;
21 import org.junit.jupiter.api.BeforeAll;
22 import org.junit.jupiter.api.Tag;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.api.parallel.ResourceLock;
25 import org.junit.jupiter.api.parallel.Resources;
26
27 import static org.junit.jupiter.api.Assertions.*;
25 import org.junit.AfterClass;
26 import org.junit.BeforeClass;
27 import org.junit.Rule;
28 import org.junit.Test;
2829
2930 /**
3031 * Tests {@link ThreadContext}.
3132 */
32 @UsingAnyThreadContext
33 @ResourceLock(Resources.SYSTEM_PROPERTIES)
3433 public class ThreadContextInheritanceTest {
3534
36 @BeforeAll
35 @Rule
36 public ThreadContextRule threadContextRule = new ThreadContextRule();
37
38 @BeforeClass
3739 public static void setupClass() {
3840 System.setProperty(DefaultThreadContextMap.INHERITABLE_MAP, "true");
3941 ThreadContext.init();
4042 }
4143
42 @AfterAll
44 @AfterClass
4345 public static void tearDownClass() {
4446 System.clearProperty(DefaultThreadContextMap.INHERITABLE_MAP);
4547 ThreadContext.init();
4850 @Test
4951 public void testPush() {
5052 ThreadContext.push("Hello");
51 ThreadContext.push("{} is {}", ThreadContextInheritanceTest.class.getSimpleName(), "running");
52 assertEquals(
53 ThreadContext.pop(), "ThreadContextInheritanceTest is running", "Incorrect parameterized stack value");
54 assertEquals(ThreadContext.pop(), "Hello", "Incorrect simple stack value");
53 ThreadContext.push("{} is {}", ThreadContextInheritanceTest.class.getSimpleName(),
54 "running");
55 assertEquals("Incorrect parameterized stack value",
56 ThreadContext.pop(), "ThreadContextInheritanceTest is running");
57 assertEquals("Incorrect simple stack value", ThreadContext.pop(),
58 "Hello");
5559 }
5660
5761 @Test
6670 thread.start();
6771 thread.join();
6872 String str = sb.toString();
69 assertEquals("Hello", str, "Unexpected ThreadContext value. Expected Hello. Actual " + str);
73 assertTrue("Unexpected ThreadContext value. Expected Hello. Actual "
74 + str, "Hello".equals(str));
7075 sb = new StringBuilder();
7176 thread = new TestThread(sb);
7277 thread.start();
7378 thread.join();
7479 str = sb.toString();
75 assertEquals("Hello", str, "Unexpected ThreadContext value. Expected Hello. Actual " + str);
80 assertTrue("Unexpected ThreadContext value. Expected Hello. Actual "
81 + str, "Hello".equals(str));
7682 } finally {
7783 System.clearProperty(DefaultThreadContextMap.INHERITABLE_MAP);
7884 }
7985 }
8086
8187 @Test
82 @Tag("performance")
83 public void perfTest() {
88 public void perfTest() throws Exception {
8489 ThreadContextUtilityClass.perfTest();
8590 }
8691
99104 ThreadContextUtilityClass.testGetImmutableContextReturnsEmptyMapIfEmpty();
100105 }
101106
102 @Test
107 @Test(expected = UnsupportedOperationException.class)
103108 public void testGetImmutableContextReturnsImmutableMapIfNonEmpty() {
104109 ThreadContextUtilityClass.testGetImmutableContextReturnsImmutableMapIfNonEmpty();
105110 }
106111
107 @Test
112 @Test(expected = UnsupportedOperationException.class)
108113 public void testGetImmutableContextReturnsImmutableMapIfEmpty() {
109114 ThreadContextUtilityClass.testGetImmutableContextReturnsImmutableMapIfEmpty();
110115 }
142147 assertFalse(ThreadContext.containsKey("testKey"));
143148 }
144149
145 private static class TestThread extends Thread {
150 private class TestThread extends Thread {
146151
147152 private final StringBuilder sb;
148153
1919 import java.util.HashMap;
2020 import java.util.Map;
2121
22 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
23 import org.junit.jupiter.api.Tag;
24 import org.junit.jupiter.api.Test;
22 import org.apache.logging.log4j.junit.ThreadContextRule;
23 import org.junit.Rule;
24 import org.junit.Test;
2525
26 import static org.junit.jupiter.api.Assertions.*;
26 import static org.junit.Assert.*;
2727
28 @UsingAnyThreadContext
28 /**
29 *
30 */
2931 public class ThreadContextTest {
3032 public static void reinitThreadContext() {
3133 ThreadContext.init();
3234 }
3335
36 @Rule
37 public ThreadContextRule threadContextRule = new ThreadContextRule();
38
3439 @Test
3540 public void testPush() {
3641 ThreadContext.push("Hello");
37 ThreadContext.push("{} is {}", ThreadContextTest.class.getSimpleName(), "running");
38 assertEquals(ThreadContext.pop(), "ThreadContextTest is running", "Incorrect parameterized stack value");
39 assertEquals(ThreadContext.pop(), "Hello", "Incorrect simple stack value");
42 ThreadContext.push("{} is {}", ThreadContextTest.class.getSimpleName(),
43 "running");
44 assertEquals("Incorrect parameterized stack value",
45 ThreadContext.pop(), "ThreadContextTest is running");
46 assertEquals("Incorrect simple stack value", ThreadContext.pop(),
47 "Hello");
4048 }
4149
4250 @Test
4755 thread.start();
4856 thread.join();
4957 String str = sb.toString();
50 assertEquals("null", str, "Unexpected ThreadContext value. Expected null. Actual " + str);
58 assertTrue("Unexpected ThreadContext value. Expected null. Actual "
59 + str, "null".equals(str));
5160 sb = new StringBuilder();
5261 thread = new TestThread(sb);
5362 thread.start();
5463 thread.join();
5564 str = sb.toString();
56 assertEquals("null", str, "Unexpected ThreadContext value. Expected null. Actual " + str);
65 assertTrue("Unexpected ThreadContext value. Expected null. Actual "
66 + str, "null".equals(str));
5767 }
5868
5969 @Test
60 @Tag("performance")
61 public void perfTest() {
70 public void perfTest() throws Exception {
6271 ThreadContextUtilityClass.perfTest();
6372 }
6473
7786 ThreadContextUtilityClass.testGetImmutableContextReturnsEmptyMapIfEmpty();
7887 }
7988
80 @Test
89 @Test(expected = UnsupportedOperationException.class)
8190 public void testGetImmutableContextReturnsImmutableMapIfNonEmpty() {
8291 ThreadContextUtilityClass.testGetImmutableContextReturnsImmutableMapIfNonEmpty();
8392 }
8493
85 @Test
94 @Test(expected = UnsupportedOperationException.class)
8695 public void testGetImmutableContextReturnsImmutableMapIfEmpty() {
8796 ThreadContextUtilityClass.testGetImmutableContextReturnsImmutableMapIfEmpty();
8897 }
95104 @Test
96105 public void testPut() {
97106 ThreadContextUtilityClass.testPut();
98 }
99
100 @Test
101 public void testPutIfNotNull() {
102 ThreadContext.clearMap();
103 assertNull(ThreadContext.get("testKey"));
104 ThreadContext.put("testKey", "testValue");
105 assertEquals("testValue", ThreadContext.get("testKey"));
106 assertEquals("testValue", ThreadContext.get("testKey"), "Incorrect value in test key");
107 ThreadContext.putIfNull("testKey", "new Value");
108 assertEquals("testValue", ThreadContext.get("testKey"), "Incorrect value in test key");
109 ThreadContext.clearMap();
110107 }
111108
112109 @Test
161158 assertFalse(ThreadContext.containsKey("testKey"));
162159 }
163160
164 private static class TestThread extends Thread {
161 private class TestThread extends Thread {
165162
166163 private final StringBuilder sb;
167164
1515 */
1616 package org.apache.logging.log4j;
1717
18 import java.util.Map;
19
1820 import org.apache.logging.log4j.util.Timer;
1921
20 import java.util.Map;
22 import static org.junit.Assert.*;
2123
22 import static org.junit.jupiter.api.Assertions.*;
24
2325
2426 public class ThreadContextUtilityClass {
2527
26 public static void perfTest() {
28 public static void perfTest() throws Exception {
2729 ThreadContext.clearMap();
2830 final Timer complete = new Timer("ThreadContextTest");
2931 complete.start();
8991 ThreadContext.clearMap();
9092 ThreadContext.put("key", "val");
9193 final Map<String, String> immutable = ThreadContext.getImmutableContext();
92 assertThrows(UnsupportedOperationException.class, () -> immutable.put("otherkey", "otherval"));
94 immutable.put("otherkey", "otherval");
9395 }
9496
9597 public static void testGetImmutableContextReturnsImmutableMapIfEmpty() {
9698 ThreadContext.clearMap();
9799 final Map<String, String> immutable = ThreadContext.getImmutableContext();
98 assertThrows(UnsupportedOperationException.class, () -> immutable.put("otherkey", "otherval"));
100 immutable.put("otherkey", "otherval");
99101 }
100102
101103 public static void testGetImmutableStackReturnsEmptyStackIfEmpty() {
2525 import org.apache.logging.log4j.message.ReusableParameterizedMessageTest;
2626 import org.apache.logging.log4j.message.SimpleMessage;
2727 import org.apache.logging.log4j.spi.AbstractLogger;
28 import org.junit.jupiter.api.Test;
29
30 import static org.junit.jupiter.api.Assertions.*;
31
28 import org.junit.Test;
29
30 import static org.junit.Assert.*;
31
32 /**
33 *
34 */
3235 public class TraceLoggingTest extends AbstractLogger {
3336 static final StringBuilder CHAR_SEQ = new StringBuilder("CharSeq");
3437 private int charSeqCount;
216219 }
217220
218221 @Override
219 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message data,
220 final Throwable t) {
221 assertEquals(level, currentLevel, "Incorrect Level. Expected " + currentLevel + ", actual " + level);
222 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message data, final Throwable t) {
223 assertTrue("Incorrect Level. Expected " + currentLevel + ", actual " + level, level.equals(currentLevel));
222224 if (marker == null) {
223225 if (currentEvent.markerName != null) {
224226 fail("Incorrect marker. Expected " + currentEvent.markerName + ", actual is null");
225227 }
226 } else if (currentEvent.markerName == null) {
227 fail("Incorrect marker. Expected null. Actual is " + marker.getName());
228228 } else {
229 assertEquals(currentEvent.markerName, marker.getName(),
230 "Incorrect marker. Expected " + currentEvent.markerName + ", actual " + marker.getName());
229 if (currentEvent.markerName == null) {
230 fail("Incorrect marker. Expected null. Actual is " + marker.getName());
231 } else {
232 assertTrue("Incorrect marker. Expected " + currentEvent.markerName + ", actual " +
233 marker.getName(), currentEvent.markerName.equals(marker.getName()));
234 }
231235 }
232236 if (data == null) {
233237 if (currentEvent.data != null) {
234238 fail("Incorrect message. Expected " + currentEvent.data + ", actual is null");
235239 }
236 } else if (currentEvent.data == null) {
237 fail("Incorrect message. Expected null. Actual is " + data.getFormattedMessage());
238240 } else {
239 assertTrue(data.getClass().isAssignableFrom(currentEvent.data.getClass()),
240 "Incorrect message type. Expected " + currentEvent.data + ", actual " + data);
241 assertEquals(currentEvent.data.getFormattedMessage(), data.getFormattedMessage(),
242 "Incorrect message. Expected " + currentEvent.data.getFormattedMessage() + ", actual "
243 + data.getFormattedMessage());
241 if (currentEvent.data == null) {
242 fail("Incorrect message. Expected null. Actual is " + data.getFormattedMessage());
243 } else {
244 assertTrue("Incorrect message type. Expected " + currentEvent.data + ", actual " + data,
245 data.getClass().isAssignableFrom(currentEvent.data.getClass()));
246 assertTrue("Incorrect message. Expected " + currentEvent.data.getFormattedMessage() + ", actual " +
247 data.getFormattedMessage(),
248 currentEvent.data.getFormattedMessage().equals(data.getFormattedMessage()));
249 }
244250 }
245251 if (t == null) {
246252 if (currentEvent.t != null) {
247253 fail("Incorrect Throwable. Expected " + currentEvent.t + ", actual is null");
248254 }
249 } else if (currentEvent.t == null) {
250 fail("Incorrect Throwable. Expected null. Actual is " + t);
251255 } else {
252 assertEquals(currentEvent.t, t, "Incorrect Throwable. Expected " + currentEvent.t + ", actual " + t);
256 if (currentEvent.t == null) {
257 fail("Incorrect Throwable. Expected null. Actual is " + t);
258 } else {
259 assertTrue("Incorrect Throwable. Expected " + currentEvent.t + ", actual " + t,
260 currentEvent.t.equals(t));
261 }
253262 }
254263 }
255264
+0
-90
log4j-api/src/test/java/org/apache/logging/log4j/junit/AbstractFileCleaner.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.AfterEachCallback;
20 import org.junit.jupiter.api.extension.BeforeEachCallback;
21 import org.junit.jupiter.api.extension.ExtensionContext;
22
23 import java.io.IOException;
24 import java.io.InterruptedIOException;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.util.Collection;
28 import java.util.Map;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.TimeUnit;
31 import java.util.stream.Collectors;
32
33 import static org.junit.jupiter.api.Assertions.fail;
34
35 abstract class AbstractFileCleaner implements BeforeEachCallback, AfterEachCallback {
36
37 private static final int MAX_TRIES = Integer.getInteger("log4j2.junit.fileCleanerMaxTries", 10);
38
39 private static final int SLEEP_PERIOD_MILLIS = Integer.getInteger("log4j2.junit.fileCleanerSleepPeriodMillis", 200);
40
41 @Override
42 public void beforeEach(final ExtensionContext context) throws Exception {
43 clean(context);
44 }
45
46 @Override
47 public void afterEach(final ExtensionContext context) throws Exception {
48 clean(context);
49 }
50
51 private void clean(final ExtensionContext context) {
52 final Collection<Path> paths = getPathsForTest(context);
53 if (paths.isEmpty()) {
54 return;
55 }
56 final Map<Path, IOException> failures = new ConcurrentHashMap<>();
57 for (final Path path : paths) {
58 if (Files.exists(path)) {
59 for (int i = 0; i < MAX_TRIES; i++) {
60 try {
61 if (delete(path)) {
62 failures.remove(path);
63 break;
64 }
65 } catch (final IOException e) {
66 failures.put(path, e);
67 }
68 try {
69 TimeUnit.MILLISECONDS.sleep(SLEEP_PERIOD_MILLIS);
70 } catch (final InterruptedException ignored) {
71 failures.put(path, new InterruptedIOException());
72 Thread.currentThread().interrupt();
73 break;
74 }
75 }
76 }
77 }
78 if (!failures.isEmpty()) {
79 final String message = failures.entrySet().stream()
80 .map(e -> e.getKey() + " failed with " + e.getValue())
81 .collect(Collectors.joining(", "));
82 fail(message);
83 }
84 }
85
86 abstract Collection<Path> getPathsForTest(final ExtensionContext context);
87
88 abstract boolean delete(final Path path) throws IOException;
89 }
+0
-46
log4j-api/src/test/java/org/apache/logging/log4j/junit/CleanUpDirectories.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtendWith;
20
21 import java.lang.annotation.Documented;
22 import java.lang.annotation.ElementType;
23 import java.lang.annotation.Inherited;
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.lang.annotation.Target;
27
28 /**
29 * JUnit extension to automatically clean up a list of directories and their contents before and after test execution.
30 * This will automatically retry deletion up to 10 times per file while pausing for 200ms each time.
31 * These can be overridden with system properties {@code log4j2.junit.fileCleanerMaxTries} and
32 * {@code log4j2.junit.fileCleanerSleepPeriodMillis}.
33 *
34 * @see DirectoryCleaner
35 * @see CleanUpFiles
36 * @since 2.14.0
37 */
38 @Retention(RetentionPolicy.RUNTIME)
39 @Target({ElementType.TYPE, ElementType.METHOD})
40 @Documented
41 @Inherited
42 @ExtendWith(DirectoryCleaner.class)
43 public @interface CleanUpDirectories {
44 String[] value();
45 }
+0
-46
log4j-api/src/test/java/org/apache/logging/log4j/junit/CleanUpFiles.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtendWith;
20
21 import java.lang.annotation.Documented;
22 import java.lang.annotation.ElementType;
23 import java.lang.annotation.Inherited;
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.lang.annotation.Target;
27
28 /**
29 * JUnit extension to automatically clean up a list of files before and after test execution.
30 * This will automatically retry deletion up to 10 times per file while pausing for 200ms each time.
31 * These can be overridden with system properties {@code log4j2.junit.fileCleanerMaxTries} and
32 * {@code log4j2.junit.fileCleanerSleepPeriodMillis}.
33 *
34 * @see FileCleaner
35 * @see CleanUpDirectories
36 * @since 2.14.0
37 */
38 @Retention(RetentionPolicy.RUNTIME)
39 @Target({ElementType.TYPE, ElementType.METHOD})
40 @Documented
41 @Inherited
42 @ExtendWith(FileCleaner.class)
43 public @interface CleanUpFiles {
44 String[] value();
45 }
+0
-70
log4j-api/src/test/java/org/apache/logging/log4j/junit/DirectoryCleaner.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtensionContext;
20
21 import java.io.IOException;
22 import java.nio.file.FileVisitResult;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.nio.file.Paths;
26 import java.nio.file.SimpleFileVisitor;
27 import java.nio.file.attribute.BasicFileAttributes;
28 import java.util.Collection;
29 import java.util.HashSet;
30
31 class DirectoryCleaner extends AbstractFileCleaner {
32 @Override
33 Collection<Path> getPathsForTest(final ExtensionContext context) {
34 final Collection<Path> paths = new HashSet<>();
35 final CleanUpDirectories testClassAnnotation = context.getRequiredTestClass().getAnnotation(CleanUpDirectories.class);
36 if (testClassAnnotation != null) {
37 for (final String path : testClassAnnotation.value()) {
38 paths.add(Paths.get(path));
39 }
40 }
41 final CleanUpDirectories testMethodAnnotation = context.getRequiredTestMethod().getAnnotation(CleanUpDirectories.class);
42 if (testMethodAnnotation != null) {
43 for (final String path : testMethodAnnotation.value()) {
44 paths.add(Paths.get(path));
45 }
46 }
47 return paths;
48 }
49
50 @Override
51 boolean delete(final Path path) throws IOException {
52 if (Files.exists(path) && Files.isDirectory(path)) {
53 Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
54 @Override
55 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
56 Files.deleteIfExists(file);
57 return FileVisitResult.CONTINUE;
58 }
59
60 @Override
61 public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
62 Files.deleteIfExists(dir);
63 return FileVisitResult.CONTINUE;
64 }
65 });
66 }
67 return true;
68 }
69 }
+0
-52
log4j-api/src/test/java/org/apache/logging/log4j/junit/FileCleaner.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtensionContext;
20
21 import java.io.IOException;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.nio.file.Paths;
25 import java.util.Collection;
26 import java.util.HashSet;
27
28 class FileCleaner extends AbstractFileCleaner {
29 @Override
30 Collection<Path> getPathsForTest(final ExtensionContext context) {
31 final Collection<Path> paths = new HashSet<>();
32 final CleanUpFiles testClassAnnotation = context.getRequiredTestClass().getAnnotation(CleanUpFiles.class);
33 if (testClassAnnotation != null) {
34 for (final String path : testClassAnnotation.value()) {
35 paths.add(Paths.get(path));
36 }
37 }
38 final CleanUpFiles testMethodAnnotation = context.getRequiredTestMethod().getAnnotation(CleanUpFiles.class);
39 if (testMethodAnnotation != null) {
40 for (final String path : testMethodAnnotation.value()) {
41 paths.add(Paths.get(path));
42 }
43 }
44 return paths;
45 }
46
47 @Override
48 boolean delete(final Path path) throws IOException {
49 return Files.deleteIfExists(path);
50 }
51 }
2222 /**
2323 * Sets the {@link LogManager}'s {@link LoggerContextFactory} to the given instance before the test and restores it to
2424 * the original value after the test.
25 *
26 * @deprecated Use {@link LoggerContextFactoryExtension} with JUnit 5
2725 */
28 @Deprecated
2926 public class LogManagerLoggerContextFactoryRule extends ExternalResource {
3027
3128 private final LoggerContextFactory loggerContextFactory;
3330 private LoggerContextFactory restoreLoggerContextFactory;
3431
3532 public LogManagerLoggerContextFactoryRule(final LoggerContextFactory loggerContextFactory) {
33 super();
3634 this.loggerContextFactory = loggerContextFactory;
3735 }
3836
+0
-54
log4j-api/src/test/java/org/apache/logging/log4j/junit/LoggerContextFactoryExtension.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.spi.LoggerContextFactory;
21 import org.junit.jupiter.api.extension.AfterAllCallback;
22 import org.junit.jupiter.api.extension.BeforeAllCallback;
23 import org.junit.jupiter.api.extension.ExtensionContext;
24
25 /**
26 * JUnit 5 extension that sets a particular {@link LoggerContextFactory} for the entire run of tests in a class.
27 *
28 * @since 2.14.0
29 */
30 public class LoggerContextFactoryExtension implements BeforeAllCallback, AfterAllCallback {
31
32 private static final String KEY = "previousFactory";
33 private final LoggerContextFactory loggerContextFactory;
34
35 public LoggerContextFactoryExtension(LoggerContextFactory loggerContextFactory) {
36 this.loggerContextFactory = loggerContextFactory;
37 }
38
39 @Override
40 public void beforeAll(ExtensionContext context) throws Exception {
41 getStore(context).put(KEY, LogManager.getFactory());
42 LogManager.setFactory(loggerContextFactory);
43 }
44
45 @Override
46 public void afterAll(ExtensionContext context) throws Exception {
47 LogManager.setFactory(getStore(context).get(KEY, LoggerContextFactory.class));
48 }
49
50 private ExtensionContext.Store getStore(ExtensionContext context) {
51 return context.getStore(ExtensionContext.Namespace.create(getClass(), context.getRequiredTestClass()));
52 }
53 }
5858 * the {@link SecurityManager} to use while running a test.
5959 */
6060 public SecurityManagerTestRule(final SecurityManager securityManager) {
61 super();
6162 this.securityManager = securityManager;
6263 }
6364
+0
-44
log4j-api/src/test/java/org/apache/logging/log4j/junit/StatusLoggerLevel.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtendWith;
20 import org.junit.jupiter.api.parallel.ResourceLock;
21
22 import java.lang.annotation.Documented;
23 import java.lang.annotation.ElementType;
24 import java.lang.annotation.Inherited;
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.lang.annotation.Target;
28
29 /**
30 * JUnit 5 test extension that sets a specific StatusLogger logging level for each test.
31 *
32 * @since 2.14.0
33 */
34 @Retention(RetentionPolicy.RUNTIME)
35 @Target(ElementType.TYPE)
36 @Documented
37 @Inherited
38 @ExtendWith(StatusLoggerLevelExtension.class)
39 @ResourceLock("log4j2.StatusLogger")
40 public @interface StatusLoggerLevel {
41 /** Name of {@link org.apache.logging.log4j.Level} to use for status logger. */
42 String value();
43 }
+0
-50
log4j-api/src/test/java/org/apache/logging/log4j/junit/StatusLoggerLevelExtension.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.status.StatusLogger;
21 import org.junit.jupiter.api.extension.AfterEachCallback;
22 import org.junit.jupiter.api.extension.BeforeEachCallback;
23 import org.junit.jupiter.api.extension.ExtensionContext;
24
25 class StatusLoggerLevelExtension implements BeforeEachCallback, AfterEachCallback {
26
27 private static final String KEY = "previousLevel";
28
29 @Override
30 public void beforeEach(ExtensionContext context) throws Exception {
31 final StatusLoggerLevel annotation = context.getRequiredTestClass().getAnnotation(StatusLoggerLevel.class);
32 if (annotation == null) {
33 return;
34 }
35 final StatusLogger logger = StatusLogger.getLogger();
36 getStore(context).put(KEY, logger.getLevel());
37 logger.setLevel(Level.valueOf(annotation.value()));
38 }
39
40 @Override
41 public void afterEach(ExtensionContext context) throws Exception {
42 StatusLogger.getLogger().setLevel(getStore(context).get(KEY, Level.class));
43 }
44
45 private ExtensionContext.Store getStore(ExtensionContext context) {
46 return context.getStore(ExtensionContext.Namespace
47 .create(getClass(), context.getRequiredTestInstance()));
48 }
49 }
2424 * Log4j configuration file.
2525 *
2626 * @since 2.8
27 * @deprecated Use {@link StatusLoggerLevel} with JUnit 5
2827 */
29 @Deprecated
3028 public class StatusLoggerRule extends ExternalResource {
3129
3230 private final StatusLogger statusLogger = StatusLogger.getLogger();
+0
-57
log4j-api/src/test/java/org/apache/logging/log4j/junit/ThreadContextExtension.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.ThreadContext;
20 import org.apache.logging.log4j.ThreadContextHolder;
21 import org.junit.jupiter.api.extension.AfterEachCallback;
22 import org.junit.jupiter.api.extension.BeforeEachCallback;
23 import org.junit.jupiter.api.extension.ExtensionContext;
24
25 class ThreadContextExtension implements BeforeEachCallback, AfterEachCallback {
26 @Override
27 public void beforeEach(ExtensionContext context) throws Exception {
28 final Class<?> testClass = context.getRequiredTestClass();
29 final ThreadContextHolder holder;
30 if (testClass.isAnnotationPresent(UsingAnyThreadContext.class)) {
31 holder = new ThreadContextHolder(true, true);
32 ThreadContext.clearAll();
33 } else if (testClass.isAnnotationPresent(UsingThreadContextMap.class)) {
34 holder = new ThreadContextHolder(true, false);
35 ThreadContext.clearMap();
36 } else if (testClass.isAnnotationPresent(UsingThreadContextStack.class)) {
37 holder = new ThreadContextHolder(false, true);
38 ThreadContext.clearStack();
39 } else {
40 return;
41 }
42 getStore(context).put(ThreadContextHolder.class, holder);
43 }
44
45 @Override
46 public void afterEach(ExtensionContext context) throws Exception {
47 final ThreadContextHolder holder = getStore(context).get(ThreadContextHolder.class, ThreadContextHolder.class);
48 if (holder != null) {
49 holder.restore();
50 }
51 }
52
53 private ExtensionContext.Store getStore(ExtensionContext context) {
54 return context.getStore(ExtensionContext.Namespace.create(getClass(), context.getRequiredTestInstance()));
55 }
56 }
2424 * &#64;Rule
2525 * public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
2626 * </pre>
27 *
28 * @deprecated use {@link UsingThreadContextMap} with JUnit 5
2927 */
30 @Deprecated
3128 public class ThreadContextMapRule extends ThreadContextRule {
3229
3330 /**
2828 * &#64;Rule
2929 * public final ThreadContextRule threadContextRule = new ThreadContextRule();
3030 * </pre>
31 *
32 * @deprecated use {@link UsingAnyThreadContext} with JUnit 5
3331 */
34 @Deprecated
3532 public class ThreadContextRule extends ExternalResource {
3633
3734 private final boolean restoreMap;
5451 * Whether to restore the thread context stack.
5552 */
5653 public ThreadContextRule(final boolean restoreMap, final boolean restoreStack) {
54 super();
5755 this.restoreMap = restoreMap;
5856 this.restoreStack = restoreStack;
5957 }
2424 * &#64;Rule
2525 * public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
2626 * </pre>
27 * @deprecated use {@link UsingThreadContextStack} with JUnit 5
2827 */
29 @Deprecated
3028 public class ThreadContextStackRule extends ThreadContextRule {
3129
3230 /**
+0
-45
log4j-api/src/test/java/org/apache/logging/log4j/junit/UsingAnyThreadContext.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtendWith;
20 import org.junit.jupiter.api.parallel.ResourceAccessMode;
21 import org.junit.jupiter.api.parallel.ResourceLock;
22 import org.junit.jupiter.api.parallel.Resources;
23
24 import java.lang.annotation.Documented;
25 import java.lang.annotation.ElementType;
26 import java.lang.annotation.Inherited;
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.lang.annotation.Target;
30
31 /**
32 * Marks a test class as using {@link org.apache.logging.log4j.ThreadContext} APIs. This will automatically clear and restore
33 * both the thread context map and stack for each test invocation.
34 *
35 * @since 2.14.0
36 */
37 @Retention(RetentionPolicy.RUNTIME)
38 @Target(ElementType.TYPE)
39 @Documented
40 @Inherited
41 @ExtendWith(ThreadContextExtension.class)
42 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
43 public @interface UsingAnyThreadContext {
44 }
+0
-45
log4j-api/src/test/java/org/apache/logging/log4j/junit/UsingThreadContextMap.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtendWith;
20 import org.junit.jupiter.api.parallel.ResourceAccessMode;
21 import org.junit.jupiter.api.parallel.ResourceLock;
22 import org.junit.jupiter.api.parallel.Resources;
23
24 import java.lang.annotation.Documented;
25 import java.lang.annotation.ElementType;
26 import java.lang.annotation.Inherited;
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.lang.annotation.Target;
30
31 /**
32 * Marks a test class as using {@link org.apache.logging.log4j.spi.ThreadContextMap} APIs. This will automatically clear and
33 * restore the thread context map (MDC) for each test invocation.
34 *
35 * @since 2.14.0
36 */
37 @Retention(RetentionPolicy.RUNTIME)
38 @Target(ElementType.TYPE)
39 @Documented
40 @Inherited
41 @ExtendWith(ThreadContextExtension.class)
42 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
43 public @interface UsingThreadContextMap {
44 }
+0
-45
log4j-api/src/test/java/org/apache/logging/log4j/junit/UsingThreadContextStack.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
17 package org.apache.logging.log4j.junit;
18
19 import org.junit.jupiter.api.extension.ExtendWith;
20 import org.junit.jupiter.api.parallel.ResourceAccessMode;
21 import org.junit.jupiter.api.parallel.ResourceLock;
22 import org.junit.jupiter.api.parallel.Resources;
23
24 import java.lang.annotation.Documented;
25 import java.lang.annotation.ElementType;
26 import java.lang.annotation.Inherited;
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.lang.annotation.Target;
30
31 /**
32 * Marks a test class as using {@link org.apache.logging.log4j.spi.ThreadContextStack} APIs. This will automatically clear and
33 * restore the thread context stack (NDC) for each test invocation.
34 *
35 * @since 2.14.0
36 */
37 @Retention(RetentionPolicy.RUNTIME)
38 @Target(ElementType.TYPE)
39 @Documented
40 @Inherited
41 @ExtendWith(ThreadContextExtension.class)
42 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
43 public @interface UsingThreadContextStack {
44 }
2424
2525 import org.apache.logging.log4j.junit.Mutable;
2626 import org.apache.logging.log4j.util.Constants;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.parallel.ResourceAccessMode;
29 import org.junit.jupiter.api.parallel.ResourceLock;
30 import org.junit.jupiter.api.parallel.Resources;
27 import org.junit.Assert;
28 import org.junit.Test;
3129
32 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
33 import static org.junit.jupiter.api.Assertions.assertEquals;
30 import static org.junit.Assert.assertEquals;
3431
35 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
32 /**
33 *
34 */
3635 public class FormattedMessageTest {
3736
3837 private static final String SPACE = Constants.JAVA_MAJOR_VERSION < 9 ? " " : "\u00a0";
141140 // modify parameter before calling msg.getFormattedMessage
142141 param.set("XYZ");
143142 final String actual = msg.getFormattedMessage();
144 assertEquals("Test message XYZ", actual, "Expected most recent param value");
143 assertEquals("Expected most recent param value", "Test message XYZ", actual);
145144 }
146145
147146 @Test
154153 msg.getFormattedMessage(); // freeze the formatted message
155154 param.set("XYZ");
156155 final String actual = msg.getFormattedMessage();
157 assertEquals("Test message abc", actual, "Should use initial param value");
156 assertEquals("Should use initial param value", "Test message abc", actual);
158157 }
159158
160159 @Test
167166 final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
168167 final ObjectInputStream in = new ObjectInputStream(bais);
169168 final FormattedMessage actual = (FormattedMessage) in.readObject();
170 assertEquals(expected, actual);
171 assertEquals(expected.getFormat(), actual.getFormat());
172 assertEquals(expected.getFormattedMessage(), actual.getFormattedMessage());
173 assertArrayEquals(expected.getParameters(), actual.getParameters());
169 Assert.assertEquals(expected, actual);
170 Assert.assertEquals(expected.getFormat(), actual.getFormat());
171 Assert.assertEquals(expected.getFormattedMessage(), actual.getFormattedMessage());
172 Assert.assertArrayEquals(expected.getParameters(), actual.getParameters());
174173 }
175174 }
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.junit.jupiter.api.Test;
19
2018 import java.util.Locale;
2119 import java.util.ResourceBundle;
2220
23 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import org.junit.Assert;
22 import org.junit.Test;
2423
2524 /**
2625 * Tests {@link LocalizedMessageFactory}.
3231 final LocalizedMessageFactory localizedMessageFactory = new LocalizedMessageFactory(
3332 ResourceBundle.getBundle("MF", Locale.US));
3433 final Message message = localizedMessageFactory.newMessage("hello_world");
35 assertEquals("Hello world.", message.getFormattedMessage());
34 Assert.assertEquals("Hello world.", message.getFormattedMessage());
3635 }
3736 }
2020
2121 import org.apache.commons.lang3.SerializationUtils;
2222 import org.apache.logging.log4j.junit.Mutable;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.api.parallel.ResourceAccessMode;
25 import org.junit.jupiter.api.parallel.ResourceLock;
26 import org.junit.jupiter.api.parallel.Resources;
23 import org.junit.Test;
2724
28 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2926
3027 /**
3128 * Tests LocalizedMessage.
3229 */
33 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
3430 public class LocalizedMessageTest {
3531
3632 private <T extends Serializable> T roundtrip(final T msg) {
7470 // modify parameter before calling msg.getFormattedMessage
7571 param.set("XYZ");
7672 final String actual = msg.getFormattedMessage();
77 assertEquals("Test message XYZ", actual, "Expected most recent param value");
73 assertEquals("Expected most recent param value", "Test message XYZ", actual);
7874 }
7975
8076 @Test
8783 msg.getFormattedMessage();
8884 param.set("XYZ");
8985 final String actual = msg.getFormattedMessage();
90 assertEquals("Test message abc", actual, "Should use initial param value");
86 assertEquals("Should use initial param value", "Test message abc", actual);
9187 }
9288 }
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import com.google.common.base.Strings;
1918 import org.apache.logging.log4j.util.StringBuilderFormattable;
20 import org.junit.jupiter.api.Test;
21
22 import java.math.BigDecimal;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.LinkedHashMap;
26 import java.util.LinkedList;
27 import java.util.List;
28
29 import static org.junit.jupiter.api.Assertions.*;
19 import org.junit.Test;
20
21 import static org.junit.Assert.*;
3022
3123 /**
3224 *
8678 msg.put("message", testMsg);
8779 msg.put("project", "Log4j");
8880 final String result = msg.getFormattedMessage(new String[]{"JSON"});
89 final String expected = "{'message':'Test message {}','project':'Log4j'}".replace('\'', '"');
81 final String expected = "{\"message\":\"Test message {}\", \"project\":\"Log4j\"}";
9082 assertEquals(expected, result);
9183 }
9284
109101 final String expected =
110102 "{\"one\\ntwo\":\"hello\\tworld\\r\\nhh\\bere is it\\f\"}";
111103 assertEquals(expected, result);
112 }
113
114 @Test
115 public void testJsonFormatterNestedObjectSupport() {
116 final String actualJson = new ObjectMapMessage()
117 .with("key1", "val1")
118 .with("key2", Collections.singletonMap("key2.1", "val2.1"))
119 .with("key3", Arrays.asList(
120 3,
121 (byte) 127,
122 4.5D,
123 4.6F,
124 Arrays.asList(true, false),
125 new BigDecimal(30),
126 Collections.singletonMap("key3.3", "val3.3")))
127 .with("key4", new LinkedHashMap<String, Object>() {{
128 put("chars", new char[]{'a', 'b', 'c'});
129 put("booleans", new boolean[]{true, false});
130 put("bytes", new byte[]{1, 2});
131 put("shorts", new short[]{3, 4});
132 put("ints", new int[]{256, 257});
133 put("longs", new long[]{2147483648L, 2147483649L});
134 put("floats", new float[]{1.0F, 1.1F});
135 put("doubles", new double[]{2.0D, 2.1D});
136 put("objects", new Object[]{"foo", "bar"});
137 }})
138 .getFormattedMessage(new String[]{"JSON"});
139 final String expectedJson = ("{" +
140 "'key1':'val1'," +
141 "'key2':{'key2.1':'val2.1'}," +
142 "'key3':[3,127,4.5,4.6,[true,false],30,{'key3.3':'val3.3'}]," +
143 "'key4':{" +
144 "'chars':['a','b','c']," +
145 "'booleans':[true,false]," +
146 "'bytes':[1,2]," +
147 "'shorts':[3,4]," +
148 "'ints':[256,257]," +
149 "'longs':[2147483648,2147483649]," +
150 "'floats':[1.0,1.1]," +
151 "'doubles':[2.0,2.1]," +
152 "'objects':['foo','bar']" +
153 "}}").replace('\'', '"');
154 assertEquals(expectedJson, actualJson);
155 }
156
157 @Test
158 public void testJsonFormatterInfiniteRecursionPrevention() {
159 final List<Object> recursiveValue = Arrays.asList(1, null);
160 // noinspection CollectionAddedToSelf
161 recursiveValue.set(1, recursiveValue);
162 assertThrows(IllegalArgumentException.class, () -> new ObjectMapMessage()
163 .with("key", recursiveValue)
164 .getFormattedMessage(new String[]{"JSON"}));
165 }
166
167 @Test
168 public void testJsonFormatterMaxDepthViolation() {
169 assertThrows(IllegalArgumentException.class, () -> testJsonFormatterMaxDepth(MapMessageJsonFormatter.MAX_DEPTH - 1));
170 }
171
172 @Test
173 public void testJsonFormatterMaxDepthConformance() {
174 int depth = MapMessageJsonFormatter.MAX_DEPTH - 2;
175 String expectedJson = String
176 .format("{'key':%s1%s}",
177 Strings.repeat("[", depth),
178 Strings.repeat("]", depth))
179 .replace('\'', '"');
180 String actualJson = testJsonFormatterMaxDepth(depth);
181 assertEquals(expectedJson, actualJson);
182 }
183
184 public static String testJsonFormatterMaxDepth(int depth) {
185 List<Object> list = new LinkedList<>();
186 list.add(1);
187 while (--depth > 0) {
188 list = new LinkedList<>(Collections.singletonList(list));
189 }
190 return new ObjectMapMessage()
191 .with("key", list)
192 .getFormattedMessage(new String[]{"JSON"});
193104 }
194105
195106 @Test
239150
240151 @Test
241152 public void testJSONFormatNonStringValue() {
242 final ObjectMapMessage msg = new ObjectMapMessage().with("key", 1L);
243 final String result = msg.getFormattedMessage(new String[]{"JSON"});
244 final String expected = "{'key':1}".replace('\'', '"');
153 final ObjectMapMessage msg = new ObjectMapMessage()
154 .with("key", 1L);
155 final String result = msg.getFormattedMessage(new String[]{"JSON"});
156 final String expected = "{\"key\":\"1\"}";
245157 assertEquals(expected, result);
246158 }
247159
2020 import java.util.Collection;
2121
2222 import org.apache.logging.log4j.AbstractSerializationTest;
23 import org.junit.jupiter.api.parallel.ResourceAccessMode;
24 import org.junit.jupiter.api.parallel.ResourceLock;
25 import org.junit.jupiter.api.parallel.Resources;
2623 import org.junit.runners.Parameterized;
2724
28 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
2925 public class MessageFormatMessageSerializationTest extends AbstractSerializationTest {
3026
3127 @Parameterized.Parameters
1818
1919 import org.apache.logging.log4j.junit.Mutable;
2020 import org.apache.logging.log4j.util.Constants;
21 import org.junit.jupiter.api.Test;
22 import org.junit.jupiter.api.parallel.ResourceAccessMode;
23 import org.junit.jupiter.api.parallel.ResourceLock;
24 import org.junit.jupiter.api.parallel.Resources;
21 import org.junit.Test;
22
23 import static org.junit.Assert.*;
2524
2625 import java.util.Locale;
2726
28 import static org.junit.jupiter.api.Assertions.*;
29
30 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
27 /**
28 *
29 */
3130 public class MessageFormatMessageTest {
3231
3332 private static final String SPACE = Constants.JAVA_MAJOR_VERSION < 9 ? " " : "\u00a0";
8483 final String expected = "Test message Apache";
8584 assertEquals(expected, result);
8685 final Throwable t = msg.getThrowable();
87 assertNotNull(t, "No Throwable");
86 assertNotNull("No Throwable", t);
8887 }
8988
9089 @Test
9695 // modify parameter before calling msg.getFormattedMessage
9796 param.set("XYZ");
9897 final String actual = msg.getFormattedMessage();
99 assertEquals("Test message XYZ", actual, "Expected most recent param value");
98 assertEquals("Expected most recent param value", "Test message XYZ", actual);
10099 }
101100
102101 @Test
109108 msg.getFormattedMessage();
110109 param.set("XYZ");
111110 final String actual = msg.getFormattedMessage();
112 assertEquals("Test message abc", actual, "Should use initial param value");
111 assertEquals("Should use initial param value", "Test message abc", actual);
113112 }
114113 }
1616 package org.apache.logging.log4j.message;
1717
1818 import org.apache.logging.log4j.util.Timer;
19 import org.junit.jupiter.api.AfterAll;
20 import org.junit.jupiter.api.Tag;
21 import org.junit.jupiter.api.Test;
22 import org.junit.jupiter.api.parallel.ResourceAccessMode;
23 import org.junit.jupiter.api.parallel.ResourceLock;
24 import org.junit.jupiter.api.parallel.Resources;
19 import org.junit.AfterClass;
20 import org.junit.Test;
2521
2622 /**
2723 *
2824 */
29 @Tag("performance")
30 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
3125 public class MessageFormatsPerfTest {
3226
3327 private static final int LOOP_CNT = 500;
3731 private static long msgFormatTime = 0;
3832 private static long formattedTime = 0;
3933
40 @AfterAll
34 @AfterClass
4135 public static void after() {
4236 if (stringTime > paramTime) {
4337 System.out.println(String.format("Parameterized is %1$.2f times faster than StringFormat.",
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.junit.jupiter.api.Test;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertNull;
18 import org.junit.Assert;
19 import org.junit.Test;
2220
2321 /**
2422 * @since 2.4
3028
3129 @Test
3230 public void testGetParameters() {
33 assertArrayEquals(ARRAY, OBJECT_ARRAY_MESSAGE.getParameters());
31 Assert.assertArrayEquals(ARRAY, OBJECT_ARRAY_MESSAGE.getParameters());
3432 }
3533
3634 @Test
3735 public void testGetThrowable() {
38 assertNull(OBJECT_ARRAY_MESSAGE.getThrowable());
36 Assert.assertEquals(null, OBJECT_ARRAY_MESSAGE.getThrowable());
3937 }
4038
4139 }
2020
2121 import org.apache.logging.log4j.junit.Mutable;
2222 import org.apache.logging.log4j.junit.SerialUtil;
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
2727 /**
2828 * Tests {@link ObjectMessage}.
5252 // modify parameter before calling msg.getFormattedMessage
5353 param.set("XYZ");
5454 final String actual = msg.getFormattedMessage();
55 assertEquals("XYZ", actual, "Expected most recent param value");
55 assertEquals("Expected most recent param value", "XYZ", actual);
5656 }
5757
5858 @Test
6464 msg.getFormattedMessage();
6565 param.set("XYZ");
6666 final String actual = msg.getFormattedMessage();
67 assertEquals("abc", actual, "Should use initial param value");
67 assertEquals("Should use initial param value", "abc", actual);
6868 }
6969
7070 @Test
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.junit.jupiter.api.Test;
18 import java.util.ArrayList;
19 import java.util.List;
20 import org.junit.Test;
1921
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23
24 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.Assert.*;
2523
2624 /**
27 * Tests {@link ParameterFormatter}.
25 * Tests ParameterFormatter.
2826 */
2927 public class ParameterFormatterTest {
3028
3129 @Test
32 public void testCountArgumentPlaceholders() {
30 public void testCountArgumentPlaceholders() throws Exception {
3331 assertEquals(0, ParameterFormatter.countArgumentPlaceholders(""));
3432 assertEquals(0, ParameterFormatter.countArgumentPlaceholders("aaa"));
3533 assertEquals(0, ParameterFormatter.countArgumentPlaceholders("\\{}"));
169167 }
170168
171169 @Test
172 public void testDeepToString() {
170 public void testDeepToString() throws Exception {
173171 final List<Object> list = new ArrayList<>();
174172 list.add(1);
175 // noinspection CollectionAddedToSelf
176173 list.add(list);
177174 list.add(2);
178175 final String actual = ParameterFormatter.deepToString(list);
181178 }
182179
183180 @Test
184 public void testDeepToStringUsingNonRecursiveButConsequentObjects() {
185 final List<Object> list = new ArrayList<>();
186 final Object item = Collections.singletonList(0);
187 list.add(1);
188 list.add(item);
189 list.add(2);
190 list.add(item);
191 list.add(3);
192 final String actual = ParameterFormatter.deepToString(list);
193 final String expected = "[1, [0], 2, [0], 3]";
194 assertEquals(expected, actual);
195 }
196
197 @Test
198 public void testIdentityToString() {
181 public void testIdentityToString() throws Exception {
199182 final List<Object> list = new ArrayList<>();
200183 list.add(1);
201 // noinspection CollectionAddedToSelf
202184 list.add(list);
203185 list.add(2);
204186 final String actual = ParameterFormatter.identityToString(list);
205187 final String expected = list.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(list));
206188 assertEquals(expected, actual);
207189 }
208
209 }
190 }
1616 package org.apache.logging.log4j.message;
1717
1818 import org.apache.logging.log4j.junit.Mutable;
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 *
134134 // modify parameter before calling msg.getFormattedMessage
135135 param.set("XYZ");
136136 final String actual = msg.getFormattedMessage();
137 assertEquals("Test message XYZ", actual, "Should use current param value");
137 assertEquals("Should use current param value", "Test message XYZ", actual);
138138
139139 // modify parameter after calling msg.getFormattedMessage
140140 param.set("000");
141141 final String after = msg.getFormattedMessage();
142 assertEquals("Test message XYZ", after, "Should not change after rendered once");
142 assertEquals("Should not change after rendered once", "Test message XYZ", after);
143143 }
144144 }
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
21
22 import java.util.concurrent.atomic.AtomicReference;
20 import static org.junit.Assert.*;
2321
2422 /**
2523 * Tests the ReusableMessageFactory class.
5452 private void assertReusableParameterizeMessage(final Message message, final String txt, final Object[] params) {
5553 assertTrue(message instanceof ReusableParameterizedMessage);
5654 final ReusableParameterizedMessage msg = (ReusableParameterizedMessage) message;
57 assertTrue(msg.reserved, "reserved");
55 assertTrue("reserved", msg.reserved);
5856
5957 assertEquals(txt, msg.getFormat());
60 assertEquals(msg.getParameterCount(), params.length, "count");
58 assertEquals("count", msg.getParameterCount(), params.length);
6159 final Object[] messageParams = msg.getParameters();
6260 for (int i = 0; i < params.length; i++) {
6361 assertEquals(messageParams[i], params[i]);
9088 @Test
9189 public void testCreateEventReturnsThreadLocalInstance() throws Exception {
9290 final ReusableMessageFactory factory = new ReusableMessageFactory();
93 final AtomicReference<Message> message1 = new AtomicReference<>();
94 final AtomicReference<Message> message2 = new AtomicReference<>();
91 final Message[] message1 = new Message[1];
92 final Message[] message2 = new Message[1];
9593 final Thread t1 = new Thread("THREAD 1") {
9694 @Override
9795 public void run() {
98 message1.set(factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4));
96 message1[0] = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4);
9997 }
10098 };
10199 final Thread t2 = new Thread("Thread 2") {
102100 @Override
103101 public void run() {
104 message2.set(factory.newMessage("other, A={} B={} C={} D={}", 1, 2, 3, 4));
102 message2[0] = factory.newMessage("other, A={} B={} C={} D={}", 1, 2, 3, 4);
105103 }
106104 };
107105 t1.start();
108106 t2.start();
109107 t1.join();
110108 t2.join();
111 assertNotNull(message1.get());
112 assertNotNull(message2.get());
113 assertNotSame(message1.get(), message2.get());
114 assertReusableParameterizeMessage(message1.get(), "text, p0={} p1={} p2={} p3={}", new Object[]{
109 assertNotNull(message1[0]);
110 assertNotNull(message2[0]);
111 assertNotSame(message1[0], message2[0]);
112 assertReusableParameterizeMessage(message1[0], "text, p0={} p1={} p2={} p3={}", new Object[]{
115113 new Integer(1), //
116114 new Integer(2), //
117115 new Integer(3), //
118116 new Integer(4), //
119117 });
120118
121 assertReusableParameterizeMessage(message2.get(), "other, A={} B={} C={} D={}", new Object[]{
119 assertReusableParameterizeMessage(message2[0], "other, A={} B={} C={} D={}", new Object[]{
122120 new Integer(1), //
123121 new Integer(2), //
124122 new Integer(3), //
125123 new Integer(4), //
126124 });
127 ReusableMessageFactory.release(message1.get());
128 ReusableMessageFactory.release(message2.get());
125 ReusableMessageFactory.release(message1[0]);
126 ReusableMessageFactory.release(message2[0]);
129127 }
130128
131129 }
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 /**
2323 * Tests ReusableObjectMessage.
1616 package org.apache.logging.log4j.message;
1717
1818 import org.apache.logging.log4j.junit.Mutable;
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
2121 import java.util.LinkedList;
2222 import java.util.List;
2323
24 import static org.junit.jupiter.api.Assertions.*;
24 import static org.junit.Assert.*;
2525
2626 /**
2727 * Tests ReusableParameterizedMessage.
126126 // modify parameter before calling msg.getFormattedMessage
127127 param.set("XYZ");
128128 final String actual = msg.getFormattedMessage();
129 assertEquals("Test message XYZ", actual, "Should use current param value");
129 assertEquals("Should use current param value", "Test message XYZ", actual);
130130
131131 // modify parameter after calling msg.getFormattedMessage
132132 param.set("000");
133133 final String after = msg.getFormattedMessage();
134 assertEquals("Test message 000", after, "Renders again");
134 assertEquals("Renders again", "Test message 000", after);
135135 }
136136
137137 @Test
157157 expected.add("msg");
158158 expected.add(EXCEPTION1);
159159 final List<Object> actual = new LinkedList<>();
160 msg.forEachParameter((parameter, parameterIndex, state) -> actual.add(parameter), null);
160 msg.forEachParameter(new ParameterConsumer<Void>() {
161 @Override
162 public void accept(final Object parameter, final int parameterIndex, final Void state) {
163 actual.add(parameter);
164 }
165 }, null);
161166 assertEquals(expected, actual);
162167 }
163168 }
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertNull;
18 import org.junit.Test;
2119
22 import org.apache.logging.log4j.util.Constants;
23 import org.junit.jupiter.api.Test;
20 import static org.junit.Assert.*;
2421
2522 /**
2623 * Tests ReusableSimpleMessage.
6865
6966 @Test
7067 public void testGetParameters_InitiallyReturnsEmptyArray() throws Exception {
71 assertArrayEquals(Constants.EMPTY_OBJECT_ARRAY, new ReusableSimpleMessage().getParameters());
68 assertArrayEquals(new Object[0], new ReusableSimpleMessage().getParameters());
7269 }
7370
7471 @Test
7572 public void testGetParameters_ReturnsEmptyArrayAfterMessageSet() throws Exception {
7673 final ReusableSimpleMessage msg = new ReusableSimpleMessage();
7774 msg.set("abc");
78 assertArrayEquals(Constants.EMPTY_OBJECT_ARRAY, msg.getParameters());
75 assertArrayEquals(new Object[0], msg.getParameters());
7976 msg.set("def");
80 assertArrayEquals(Constants.EMPTY_OBJECT_ARRAY, msg.getParameters());
77 assertArrayEquals(new Object[0], msg.getParameters());
8178 }
8279
8380 @Test
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 /**
2323 * Tests the SimpleMessage class.
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20
1821 import java.io.ByteArrayInputStream;
1922 import java.io.ByteArrayOutputStream;
2023 import java.io.IOException;
2326 import java.util.Locale;
2427
2528 import org.apache.logging.log4j.junit.Mutable;
26 import org.junit.jupiter.api.Test;
27 import org.junit.jupiter.api.parallel.ResourceAccessMode;
28 import org.junit.jupiter.api.parallel.ResourceLock;
29 import org.junit.jupiter.api.parallel.Resources;
29 import org.junit.Assert;
30 import org.junit.Test;
3031
31 import static org.junit.jupiter.api.Assertions.*;
32
33 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
32 /**
33 *
34 */
3435 public class StringFormattedMessageTest {
3536
3637 private static final int LOOP_CNT = 500;
8485 final String expected = "Test message Apache";
8586 assertEquals(expected, result);
8687 final Throwable t = msg.getThrowable();
87 assertNotNull(t, "No Throwable");
88 assertNotNull("No Throwable", t);
8889 }
8990
9091 @Test
9697 // modify parameter before calling msg.getFormattedMessage
9798 param.set("XYZ");
9899 final String actual = msg.getFormattedMessage();
99 assertEquals("Test message XYZ", actual, "Should use initial param value");
100 assertEquals("Should use initial param value", "Test message XYZ", actual);
100101 }
101102
102103 @Test
109110 msg.getFormattedMessage();
110111 param.set("XYZ");
111112 final String actual = msg.getFormattedMessage();
112 assertEquals("Test message abc", actual, "Should use initial param value");
113 assertEquals("Should use initial param value", "Test message abc", actual);
113114 }
114115
115116 @Test
122123 final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
123124 final ObjectInputStream in = new ObjectInputStream(bais);
124125 final StringFormattedMessage actual = (StringFormattedMessage) in.readObject();
125 assertEquals(expected, actual);
126 assertEquals(expected.getFormat(), actual.getFormat());
127 assertEquals(expected.getFormattedMessage(), actual.getFormattedMessage());
128 assertArrayEquals(expected.getParameters(), actual.getParameters());
126 Assert.assertEquals(expected, actual);
127 Assert.assertEquals(expected.getFormat(), actual.getFormat());
128 Assert.assertEquals(expected.getFormattedMessage(), actual.getFormattedMessage());
129 Assert.assertArrayEquals(expected.getParameters(), actual.getParameters());
129130 }
130131 }
1515 */
1616 package org.apache.logging.log4j.message;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 /**
2323 *
8181 assertEquals(expected, result);
8282 }
8383
84 @Test
84 @Test(expected = IllegalArgumentException.class)
8585 public void testMsgWithKeyTooLong() {
8686 final String testMsg = "Test message {}";
8787 final StructuredDataMessage msg = new StructuredDataMessage("MsgId@12345", testMsg, "Alert");
88 assertThrows(IllegalArgumentException.class, () ->
89 msg.put("This is a very long key that will violate the key length validation", "Testing"));
88 msg.put("This is a very long key that will violate the key length validation", "Testing");
9089 }
9190
9291 @Test
1616 package org.apache.logging.log4j.message;
1717
1818 import java.util.concurrent.CountDownLatch;
19 import java.util.concurrent.atomic.AtomicReference;
2019 import java.util.concurrent.locks.ReentrantLock;
2120
22 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2322
24 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2524
25 /**
26 *
27 */
2628 public class ThreadDumpMessageTest {
2729
2830 @Test
3133
3234 final String message = msg.getFormattedMessage();
3335 //System.out.print(message);
34 assertTrue(message.contains("Testing"), "No header");
35 assertTrue(message.contains("RUNNABLE"), "No RUNNABLE");
36 assertTrue(message.contains("ThreadDumpMessage"), "No ThreadDumpMessage");
36 assertTrue("No header", message.contains("Testing"));
37 assertTrue("No RUNNABLE", message.contains("RUNNABLE"));
38 assertTrue("No ThreadDumpMessage", message.contains("ThreadDumpMessage"));
3739 }
3840
3941
5759
5860 final String message = msg.getFormattedMessage();
5961 //System.out.print(message);
60 assertTrue(message.contains("Testing"), "No header");
61 assertTrue(message.contains("RUNNABLE"), "No RUNNABLE");
62 assertTrue(message.contains("ThreadDumpMessage"), "No ThreadDumpMessage");
62 assertTrue("No header", message.contains("Testing"));
63 assertTrue("No RUNNABLE", message.contains("RUNNABLE"));
64 assertTrue("No ThreadDumpMessage", message.contains("ThreadDumpMessage"));
6365 //assertTrue("No Locks", message.contains("waiting on"));
6466 //assertTrue("No syncronizers", message.contains("locked syncrhonizers"));
6567 }
7779 public void testUseConstructorThread() throws InterruptedException { // LOG4J2-763
7880 final ThreadDumpMessage msg = new ThreadDumpMessage("Test");
7981
80 final AtomicReference<String> actual = new AtomicReference<>();
82 final String[] actual = new String[1];
8183 final Thread other = new Thread("OtherThread") {
8284 @Override
8385 public void run() {
84 actual.set(msg.getFormattedMessage());
86 actual[0] = msg.getFormattedMessage();
8587 }
8688 };
8789 other.start();
8890 other.join();
8991
90 assertFalse(actual.get().contains("OtherThread"), "No mention of other thread in msg");
92 assertTrue("No mention of other thread in msg", !actual[0].contains("OtherThread"));
9193 }
9294
9395 @Test
9597
9698 final ThreadDumpMessage message = new ThreadDumpMessage("");
9799 final String initial = message.getFormattedMessage();
98 assertFalse(initial.contains("ThreadWithCountDownLatch"), "no ThreadWithCountDownLatch thread yet");
100 assertFalse("no ThreadWithCountDownLatch thread yet", initial.contains("ThreadWithCountDownLatch"));
99101
100102 final CountDownLatch started = new CountDownLatch(1);
101103 final CountDownLatch keepAlive = new CountDownLatch(1);
105107
106108 final StringBuilder result = new StringBuilder();
107109 message.formatTo(result);
108 assertFalse(
109 result.toString().contains("ThreadWithCountDownLatch"), "no ThreadWithCountDownLatch captured");
110 assertFalse("no ThreadWithCountDownLatch captured",
111 result.toString().contains("ThreadWithCountDownLatch"));
110112 assertEquals(initial, result.toString());
111113 keepAlive.countDown(); // allow thread to die
112114 }
113115
114 private static class Thread1 extends Thread {
116 private class Thread1 extends Thread {
115117 private final ReentrantLock lock;
116118
117119 public Thread1(final ReentrantLock lock) {
125127 }
126128 }
127129
128 private static class Thread2 extends Thread {
130 private class Thread2 extends Thread {
129131 private final Object obj;
130132
131133 public Thread2(final Object obj) {
139141 }
140142 }
141143
142 private static class ThreadWithCountDownLatch extends Thread {
144 private class ThreadWithCountDownLatch extends Thread {
143145 private final CountDownLatch started;
144146 private final CountDownLatch keepAlive;
145147 volatile boolean finished;
1717
1818 import org.apache.logging.log4j.LogManager;
1919 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.junit.LoggerContextFactoryExtension;
21 import org.apache.logging.log4j.util.Constants;
22 import org.junit.jupiter.api.Tag;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.api.extension.RegisterExtension;
25 import org.junit.jupiter.api.parallel.ResourceLock;
20 import org.apache.logging.log4j.junit.LogManagerLoggerContextFactoryRule;
21 import org.junit.ClassRule;
22 import org.junit.Test;
2623
27 @Tag("smoke")
28 @ResourceLock("log4j2.LoggerContextFactory")
2924 public class SimpleLoggerTest {
3025
31 @RegisterExtension
32 public static final LoggerContextFactoryExtension EXTENSION =
33 new LoggerContextFactoryExtension(new SimpleLoggerContextFactory());
26 @ClassRule
27 public static final LogManagerLoggerContextFactoryRule rule = new LogManagerLoggerContextFactoryRule(
28 new SimpleLoggerContextFactory());
3429
3530 private final Logger logger = LogManager.getLogger("TestError");
3631
4641
4742 @Test
4843 public void testEmptyObjectArray() {
49 logger.error(Constants.EMPTY_OBJECT_ARRAY);
44 logger.error(new Object[0]);
5045 }
5146
5247 /**
5449 */
5550 @Test
5651 public void testMessageWithEmptyObjectArray() {
57 logger.error("Logging with an empty Object[] {} {}", Constants.EMPTY_BYTE_ARRAY);
52 logger.error("Logging with an empty Object[] {} {}", new Object[0]);
5853 }
5954
6055 /**
1515 */
1616 package org.apache.logging.log4j.spi;
1717
18 import org.apache.logging.log4j.junit.UsingThreadContextMap;
19 import org.junit.jupiter.api.Test;
20 import org.junit.jupiter.api.parallel.ResourceLock;
21 import org.junit.jupiter.api.parallel.Resources;
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertTrue;
2222
2323 import java.util.HashMap;
2424 import java.util.Map;
2525
26 import static org.junit.jupiter.api.Assertions.*;
26 import org.junit.Test;
2727
2828 /**
2929 * Tests the {@code DefaultThreadContextMap} class.
3030 */
31 @UsingThreadContextMap
3231 public class DefaultThreadContextMapTest {
3332
3433 @Test
171170 assertNull(map.getImmutableMapOrNull());
172171 }
173172
174 @Test
173 @Test(expected = UnsupportedOperationException.class)
175174 public void testGetImmutableMapReturnsImmutableMapIfNonEmpty() {
176175 final DefaultThreadContextMap map = new DefaultThreadContextMap(true);
177176 map.put("key1", "value1");
181180 assertEquals("value1", immutable.get("key1")); // copy has values too
182181
183182 // immutable
184 assertThrows(UnsupportedOperationException.class, () -> immutable.put("key", "value"));
183 immutable.put("key", "value"); // error
185184 }
186185
187186 @Test
214213 }
215214
216215 @Test
217 @ResourceLock(Resources.SYSTEM_PROPERTIES)
218216 public void testThreadLocalNotInheritableByDefault() {
219217 System.clearProperty(DefaultThreadContextMap.INHERITABLE_MAP);
220218 final ThreadLocal<Map<String, String>> threadLocal = DefaultThreadContextMap.createThreadLocalMap(true);
222220 }
223221
224222 @Test
225 @ResourceLock(Resources.SYSTEM_PROPERTIES)
226223 public void testThreadLocalInheritableIfConfigured() {
227224 System.setProperty(DefaultThreadContextMap.INHERITABLE_MAP, "true");
228225 ThreadContextMapFactory.init();
1616 package org.apache.logging.log4j.spi;
1717
1818 import java.util.Arrays;
19 import java.util.Collections;
2019 import java.util.Iterator;
2120
2221 import org.apache.logging.log4j.ThreadContext.ContextStack;
23 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
28
29 @UsingAnyThreadContext
22 import org.junit.Before;
23 import org.junit.Test;
24
25 import static org.junit.Assert.*;
26
3027 public class DefaultThreadContextStackTest {
3128
32 @BeforeEach
29 @Before
3330 public void before() {
3431 // clear the thread-local map
3532 new DefaultThreadContextMap(true).clear();
4744
4845 @Test
4946 public void testEqualsVsMutable() {
50 final ThreadContextStack stack1 = createStack();
51 final ThreadContextStack stack2 = MutableThreadContextStackTest.createStack();
47 final DefaultThreadContextStack stack1 = createStack();
48 final MutableThreadContextStack stack2 = MutableThreadContextStackTest.createStack();
5249 assertEquals(stack1, stack1);
5350 assertEquals(stack2, stack2);
5451 assertEquals(stack1, stack2);
6663 public void testImmutableOrNullReturnsNullIfUseStackIsFalse() {
6764 final DefaultThreadContextStack stack = new DefaultThreadContextStack(false);
6865 stack.clear();
69 assertNull(stack.getImmutableStackOrNull());
66 assertEquals(null, stack.getImmutableStackOrNull());
7067 }
7168
7269 @Test
7471 final DefaultThreadContextStack stack = new DefaultThreadContextStack(true);
7572 stack.clear();
7673 assertTrue(stack.isEmpty());
77 assertNull(stack.getImmutableStackOrNull());
74 assertEquals(null, stack.getImmutableStackOrNull());
7875 }
7976
8077 @Test
8178 public void testImmutableOrNullReturnsCopyOfContents() {
8279 final DefaultThreadContextStack stack = createStack();
83 assertFalse(stack.isEmpty());
80 assertTrue(!stack.isEmpty());
8481 final ContextStack actual = stack.getImmutableStackOrNull();
8582 assertNotNull(actual);
8683 assertEquals(stack, actual);
8784 }
8885
89 @Test
86 @Test(expected = UnsupportedOperationException.class)
9087 public void testModifyingImmutableOrNullThrowsException() {
9188 final DefaultThreadContextStack stack = createStack();
9289 final int originalSize = stack.size();
9491 final ContextStack actual = stack.getImmutableStackOrNull();
9592 assertEquals(originalSize, actual.size());
9693
97 assertThrows(UnsupportedOperationException.class, () -> actual.pop());
94 actual.pop();
9895 }
9996
10097 @Test
279276
280277 stack.remove("msg3");
281278 assertEquals(1, stack.size());
282 assertTrue(stack.containsAll(Collections.singletonList("msg2")));
279 assertTrue(stack.containsAll(Arrays.asList("msg2")));
283280 assertEquals("msg2", stack.peek());
284281 }
285282
2020 import org.apache.logging.log4j.TestLoggerContext;
2121 import org.apache.logging.log4j.TestLoggerContextFactory;
2222 import org.apache.logging.log4j.simple.SimpleLoggerContext;
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
2525 import java.util.HashSet;
2626 import java.util.Map;
2828 import java.util.concurrent.ConcurrentHashMap;
2929 import java.util.concurrent.CountDownLatch;
3030
31 import static org.junit.jupiter.api.Assertions.*;
31 import static org.junit.Assert.assertEquals;
32 import static org.junit.Assert.assertSame;
3233
3334 /**
3435 * Created by Pavel.Sivolobtchik@uxpsystems.com on 2016-10-19.
3536 */
3637 public class LoggerAdapterTest {
3738
38 private static class RunnableThreadTest implements Runnable {
39 private class RunnableThreadTest implements Runnable {
3940 private final AbstractLoggerAdapter<Logger> adapter;
4041 private final LoggerContext context;
4142 private final CountDownLatch doneSignal;
136137 LoggerContext lc = adapter.getContext(Integer.toString(i));
137138 lc.getLogger(Integer.toString(i));
138139 }
139 assertEquals(5, adapter.registry.size(), "Expected 5 LoggerContexts");
140 assertEquals("Expected 5 LoggerContexts", 5, adapter.registry.size());
140141 Set<LoggerContext> contexts = new HashSet<>(adapter.registry.keySet());
141142 for (LoggerContext context : contexts) {
142143 ((TestLoggerContext2) context).shutdown();
143144 }
144 assertEquals(0, adapter.registry.size(), "Expected 0 LoggerContexts");
145 assertEquals("Expected 0 LoggerContexts", 0, adapter.registry.size());
145146 }
146147
147148
178179 //maps for the same context should be the same instance
179180 final Map<String, Logger> resultMap1 = instances[i].getResultMap();
180181 final Map<String, Logger> resultMap2 = instances[i + 1].getResultMap();
181 assertSame(resultMap1, resultMap2, "not the same map for instances" + i + " and " + (i + 1) + ":");
182 assertSame("not the same map for instances" + i + " and " + (i + 1) + ":", resultMap1, resultMap2);
182183 assertEquals(2, resultMap1.size());
183184 }
184185 }
1515 */
1616 package org.apache.logging.log4j.spi;
1717
18 import org.junit.jupiter.api.Test;
19
2018 import java.util.ArrayList;
2119 import java.util.Arrays;
2220 import java.util.Iterator;
2321 import java.util.List;
2422
25 import static org.junit.jupiter.api.Assertions.*;
23 import org.junit.Test;
24
25 import static org.junit.Assert.*;
2626
2727 public class MutableThreadContextStackTest {
2828
2929 @Test
3030 public void testEmptyIfConstructedWithEmptyList() {
31 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<>());
31 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<String>());
3232 assertTrue(stack.isEmpty());
3333 }
3434
4242
4343 @Test
4444 public void testPushAndAddIncreaseStack() {
45 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<>());
45 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<String>());
4646 stack.clear();
4747 assertTrue(stack.isEmpty());
4848 stack.push("msg1");
5353
5454 @Test
5555 public void testPeekReturnsLastAddedItem() {
56 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<>());
56 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<String>());
5757 stack.clear();
5858 assertTrue(stack.isEmpty());
5959 stack.push("msg1");
8686
8787 @Test
8888 public void testAsList() {
89 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<>());
89 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<String>());
9090 stack.clear();
9191 assertTrue(stack.isEmpty());
9292 stack.push("msg1");
164164 * @return
165165 */
166166 static MutableThreadContextStack createStack() {
167 final MutableThreadContextStack stack1 = new MutableThreadContextStack(new ArrayList<>());
167 final MutableThreadContextStack stack1 = new MutableThreadContextStack(new ArrayList<String>());
168168 stack1.clear();
169169 assertTrue(stack1.isEmpty());
170170 stack1.push("msg1");
227227
228228 stack.remove("msg3");
229229 assertEquals(1, stack.size());
230 assertTrue(stack.contains("msg2"));
230 assertTrue(stack.containsAll(Arrays.asList("msg2")));
231231 assertEquals("msg2", stack.peek());
232232 }
233233
275275
276276 @Test
277277 public void testToStringShowsListContents() {
278 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<>());
278 final MutableThreadContextStack stack = new MutableThreadContextStack(new ArrayList<String>());
279279 assertEquals("[]", stack.toString());
280280
281281 stack.push("msg1");
301301 assertTrue(stack.isFrozen());
302302 }
303303
304 @Test
304 @Test(expected = UnsupportedOperationException.class)
305305 public void testAddAllOnFrozenStackThrowsException() {
306306 final MutableThreadContextStack stack = new MutableThreadContextStack();
307307 stack.freeze();
308 assertThrows(UnsupportedOperationException.class, () -> stack.addAll(Arrays.asList("a", "b", "c")));
309 }
310
311 @Test
308 stack.addAll(Arrays.asList("a", "b", "c"));
309 }
310
311 @Test(expected = UnsupportedOperationException.class)
312312 public void testAddOnFrozenStackThrowsException() {
313313 final MutableThreadContextStack stack = new MutableThreadContextStack();
314314 stack.freeze();
315 assertThrows(UnsupportedOperationException.class, () -> stack.add("a"));
316 }
317
318 @Test
315 stack.add("a");
316 }
317
318 @Test(expected = UnsupportedOperationException.class)
319319 public void testClearOnFrozenStackThrowsException() {
320320 final MutableThreadContextStack stack = new MutableThreadContextStack();
321321 stack.freeze();
322 assertThrows(UnsupportedOperationException.class, stack::clear);
323 }
324
325 @Test
322 stack.clear();
323 }
324
325 @Test(expected = UnsupportedOperationException.class)
326326 public void testPopOnFrozenStackThrowsException() {
327327 final MutableThreadContextStack stack = new MutableThreadContextStack();
328328 stack.freeze();
329 assertThrows(UnsupportedOperationException.class, stack::pop);
330 }
331
332 @Test
329 stack.pop();
330 }
331
332 @Test(expected = UnsupportedOperationException.class)
333333 public void testPushOnFrozenStackThrowsException() {
334334 final MutableThreadContextStack stack = new MutableThreadContextStack();
335335 stack.freeze();
336 assertThrows(UnsupportedOperationException.class, () -> stack.push("a"));
337 }
338
339 @Test
336 stack.push("a");
337 }
338
339 @Test(expected = UnsupportedOperationException.class)
340340 public void testRemoveOnFrozenStackThrowsException() {
341341 final MutableThreadContextStack stack = new MutableThreadContextStack();
342342 stack.freeze();
343 assertThrows(UnsupportedOperationException.class, () -> stack.remove("a"));
344 }
345
346 @Test
343 stack.remove("a");
344 }
345
346 @Test(expected = UnsupportedOperationException.class)
347347 public void testRemoveAllOnFrozenStackThrowsException() {
348348 final MutableThreadContextStack stack = new MutableThreadContextStack();
349349 stack.freeze();
350 assertThrows(UnsupportedOperationException.class, () -> stack.removeAll(Arrays.asList("a", "b")));
351 }
352
353 @Test
350 stack.removeAll(Arrays.asList("a", "b"));
351 }
352
353 @Test(expected = UnsupportedOperationException.class)
354354 public void testRetainAllOnFrozenStackThrowsException() {
355355 final MutableThreadContextStack stack = new MutableThreadContextStack();
356356 stack.freeze();
357 assertThrows(UnsupportedOperationException.class, () -> stack.retainAll(Arrays.asList("a", "b")));
358 }
359
360 @Test
357 stack.retainAll(Arrays.asList("a", "b"));
358 }
359
360 @Test(expected = UnsupportedOperationException.class)
361361 public void testTrimOnFrozenStackThrowsException() {
362362 final MutableThreadContextStack stack = new MutableThreadContextStack();
363363 stack.freeze();
364 assertThrows(UnsupportedOperationException.class, () -> stack.trim(3));
364 stack.trim(3);
365365 }
366366 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.api.Test;
19 import org.junit.jupiter.params.ParameterizedTest;
20 import org.junit.jupiter.params.provider.ValueSource;
18 import org.junit.Test;
2119
22 import java.util.stream.IntStream;
20 import static org.junit.Assert.assertEquals;
2321
24 import static org.junit.jupiter.api.Assertions.*;
25
22 /**
23 *
24 */
2625 public class CharsTest {
27 @ParameterizedTest
28 @ValueSource(ints = {-1, 16, 400, -1, 16, 400})
29 public void invalidDigitReturnsNullCharacter(int invalidDigit) {
30 assertAll(
31 () -> assertEquals('\0', Chars.getUpperCaseHex(invalidDigit)),
32 () -> assertEquals('\0', Chars.getLowerCaseHex(invalidDigit))
33 );
26 @Test
27 public void invalidDigitReturnsNullCharacter() throws Exception {
28 assertEquals('\0', Chars.getUpperCaseHex(-1));
29 assertEquals('\0', Chars.getUpperCaseHex(16));
30 assertEquals('\0', Chars.getUpperCaseHex(400));
31 assertEquals('\0', Chars.getLowerCaseHex(-1));
32 assertEquals('\0', Chars.getLowerCaseHex(16));
33 assertEquals('\0', Chars.getLowerCaseHex(400));
3434 }
3535
3636 @Test
37 public void validDigitReturnsProperCharacter() {
37 public void validDigitReturnsProperCharacter() throws Exception {
3838 final char[] expectedLower = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
3939 final char[] expectedUpper = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
40 assertAll(IntStream.range(0, 16).mapToObj(i -> () -> assertAll(
41 () -> assertEquals(expectedLower[i], Chars.getLowerCaseHex(i), String.format("Expected %x", i)),
42 () -> assertEquals(expectedUpper[i], Chars.getUpperCaseHex(i), String.format("Expected %X", i))
43 )));
40 for (int i = 0; i < 16; i++) {
41 assertEquals(String.format("Expected %x", i), expectedLower[i], Chars.getLowerCaseHex(i));
42 assertEquals(String.format("Expected %X", i), expectedUpper[i], Chars.getUpperCaseHex(i));
43 }
4444 }
4545 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 public class ConstantsTest {
2323
2121 import org.apache.logging.log4j.junit.SecurityManagerTestRule;
2222 import org.junit.Rule;
2323 import org.junit.Test;
24 import org.junit.jupiter.api.parallel.ResourceLock;
2524
2625 /**
2726 * Tests https://issues.apache.org/jira/browse/LOG4J2-2274.
3534 * @see SecurityManager
3635 * @see System#setSecurityManager(SecurityManager)
3736 */
38 @ResourceLock("java.lang.SecurityManager")
3937 public class EnvironmentPropertySourceSecurityManagerIT {
4038
4139 @Rule
4543 * Always throws a SecurityException for any environment variables permission
4644 * check.
4745 */
48 private static class TestSecurityManager extends SecurityManager {
46 private class TestSecurityManager extends SecurityManager {
4947 @Override
5048 public void checkPermission(final Permission permission) {
5149 if ("getenv.*".equals(permission.getName())) {
1919 import java.util.Collections;
2020 import java.util.List;
2121
22 import org.junit.jupiter.params.ParameterizedTest;
23 import org.junit.jupiter.params.provider.MethodSource;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.Parameterized;
2425
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26 import static org.junit.Assert.assertEquals;
2627
28 /**
29 *
30 */
31 @RunWith(Parameterized.class)
2732 public class EnvironmentPropertySourceTest {
2833
2934 private final PropertySource source = new EnvironmentPropertySource();
35 private final CharSequence expected;
36 private final List<? extends CharSequence> tokens;
3037
38 public EnvironmentPropertySourceTest(final CharSequence expected, final List<? extends CharSequence> tokens) {
39 this.expected = expected;
40 this.tokens = tokens;
41 }
42
43 @Parameterized.Parameters(name = "{0}")
3144 public static Object[][] data() {
3245 return new Object[][]{
3346 {"LOG4J_CONFIGURATION_FILE", Arrays.asList("configuration", "file")},
3750 };
3851 }
3952
40 @ParameterizedTest
41 @MethodSource("data")
42 public void testNormalFormFollowsEnvironmentVariableConventions(CharSequence expected, List<? extends CharSequence> tokens) {
53 @Test
54 public void testNormalFormFollowsEnvironmentVariableConventions() throws Exception {
4355 assertEquals(expected, source.getNormalForm(tokens));
4456 }
4557 }
1818
1919 import org.apache.logging.log4j.message.Message;
2020 import org.apache.logging.log4j.message.SimpleMessage;
21 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2222
23 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2424
2525 /**
2626 * Tests the LambdaUtil class.
3030 @Test
3131 public void testGetSupplierResultOfSupplier() {
3232 final String expected = "result";
33 final Object actual = LambdaUtil.get((Supplier<String>) () -> expected);
33 final Object actual = LambdaUtil.get(new Supplier<String>() {
34 @Override
35 public String get() {
36 return expected;
37 }
38 });
3439 assertSame(expected, actual);
3540 }
3641
3742 @Test
3843 public void testGetMessageSupplierResultOfSupplier() {
3944 final Message expected = new SimpleMessage("hi");
40 final Message actual = LambdaUtil.get(() -> expected);
45 final Message actual = LambdaUtil.get(new MessageSupplier() {
46 @Override
47 public Message get() {
48 return expected;
49 }
50 });
4151 assertSame(expected, actual);
4252 }
4353
5363 assertNull(actual);
5464 }
5565
56 @Test
66 @Test(expected = RuntimeException.class)
5767 public void testGetSupplierExceptionIfSupplierThrowsException() {
58 assertThrows(RuntimeException.class, () -> LambdaUtil.get((Supplier<String>) () -> {
59 throw new RuntimeException();
60 }));
68 LambdaUtil.get(new Supplier<String>() {
69 @Override
70 public String get() {
71 throw new RuntimeException();
72 }
73 });
6174 }
6275
63 @Test
76 @Test(expected = RuntimeException.class)
6477 public void testGetMessageSupplierExceptionIfSupplierThrowsException() {
65 assertThrows(RuntimeException.class, () -> LambdaUtil.get(() -> {
66 throw new RuntimeException();
67 }));
78 LambdaUtil.get(new MessageSupplier() {
79 @Override
80 public Message get() {
81 throw new RuntimeException();
82 }
83 });
6884 }
6985
7086 @Test
7187 public void testGetAllReturnsResultOfSuppliers() {
7288 final String expected1 = "result1";
73 final Supplier<String> function1 = () -> expected1;
89 final Supplier<String> function1 = new Supplier<String>() {
90 @Override
91 public String get() {
92 return expected1;
93 }
94 };
7495 final String expected2 = "result2";
75 final Supplier<String> function2 = () -> expected2;
96 final Supplier<String> function2 = new Supplier<String>() {
97 @Override
98 public String get() {
99 return expected2;
100 }
101 };
76102
77103 final Supplier<?>[] functions = { function1, function2 };
78104 final Object[] actual = LambdaUtil.getAll(functions);
97123 }
98124 }
99125
100 @Test
126 @Test(expected = RuntimeException.class)
101127 public void testGetAllThrowsExceptionIfAnyOfTheSuppliersThrowsException() {
102 final Supplier<String> function1 = () -> "abc";
103 final Supplier<String> function2 = () -> {
104 throw new RuntimeException();
128 final Supplier<String> function1 = new Supplier<String>() {
129 @Override
130 public String get() {
131 return "abc";
132 }
133 };
134 final Supplier<String> function2 = new Supplier<String>() {
135 @Override
136 public String get() {
137 throw new RuntimeException();
138 }
105139 };
106140
107141 final Supplier<?>[] functions = { function1, function2 };
108 assertThrows(RuntimeException.class, () -> LambdaUtil.getAll(functions));
142 LambdaUtil.getAll(functions);
109143 }
110144 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.params.ParameterizedTest;
19 import org.junit.jupiter.params.provider.MethodSource;
20
2118 import java.util.List;
2219
23 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 import org.junit.runners.Parameterized;
2423
24 import static org.junit.Assert.*;
25
26 @RunWith(Parameterized.class)
2527 public class LegacyPropertiesCompatibilityTest {
2628
29 private final CharSequence newName;
30 private final CharSequence oldName;
31
32 public LegacyPropertiesCompatibilityTest(final CharSequence newName, final CharSequence oldName) {
33 this.newName = newName;
34 this.oldName = oldName;
35 }
36
37 @Parameterized.Parameters(name = "New: {0}; Old: {1}")
2738 public static Object[][] data() {
2839 return new Object[][]{
2940 {"log4j2.configurationFile", "log4j.configurationFile"},
30 {"log4j2.mergeStrategy", "log4j.mergeStrategy"},
41 {"log4j2.mergeFactory", "log4j.mergeFactory"},
3142 {"log4j2.contextSelector", "Log4jContextSelector"},
3243 {"log4j2.logEventFactory", "Log4jLogEventFactory"},
3344 {"log4j2.configurationFactory", "log4j.configurationFactory"},
8293 };
8394 }
8495
85 @ParameterizedTest
86 @MethodSource("data")
87 public void compareNewWithOldName(final String newName, final String oldName) {
96 @Test
97 public void compareNewWithOldName() throws Exception {
8898 final List<CharSequence> newTokens = PropertySource.Util.tokenize(newName);
8999 final List<CharSequence> oldTokens = PropertySource.Util.tokenize(oldName);
90100 assertEquals(oldTokens, newTokens);
1616
1717 package org.apache.logging.log4j.util;
1818
19 import org.junit.jupiter.api.Test;
20
2119 import java.nio.charset.Charset;
2220 import java.util.Enumeration;
2321 import java.util.ResourceBundle;
2422
25 import static org.junit.jupiter.api.Assertions.assertFalse;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
23 import org.junit.Assert;
24 import org.junit.Test;
2725
2826 public class Log4jCharsetsPropertiesTest {
2927
3230 */
3331 @Test
3432 public void testLoadAll() {
35 ResourceBundle resourceBundle = PropertiesUtil.getCharsetsResourceBundle();
36 Enumeration<String> keys = resourceBundle.getKeys();
33 final ResourceBundle resourceBundle = PropertiesUtil.getCharsetsResourceBundle();
34 final Enumeration<String> keys = resourceBundle.getKeys();
3735 while (keys.hasMoreElements()) {
38 String key = keys.nextElement();
39 assertFalse(
40 Charset.isSupported(key), String.format("The Charset %s is available and should not be mapped", key));
41 String value = resourceBundle.getString(key);
42 assertTrue(
43 Charset.isSupported(value),
44 String.format("The Charset %s is is not available and is mapped from %s", value, key));
36 final String key = keys.nextElement();
37 Assert.assertFalse(String.format("The Charset %s is available and should not be mapped", key),
38 Charset.isSupported(key));
39 final String value = resourceBundle.getString(key);
40 Assert.assertTrue(String.format("The Charset %s is is not available and is mapped from %s", value, key),
41 Charset.isSupported(value));
4542 }
4643 }
4744 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 public class ProcessIdUtilTest {
2323
2424 @Test
25 public void processIdTest() {
26 String processId = ProcessIdUtil.getProcessId();
27 assertNotEquals(processId, ProcessIdUtil.DEFAULT_PROCESSID, "ProcessId is default");
25 public void processIdTest() throws Exception {
26 final String processId = ProcessIdUtil.getProcessId();
27 assertFalse("ProcessId is default", processId.equals(ProcessIdUtil.DEFAULT_PROCESSID));
2828 }
2929 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.params.ParameterizedTest;
19 import org.junit.jupiter.params.provider.MethodSource;
20
2118 import java.util.Arrays;
2219 import java.util.Collections;
2320 import java.util.List;
2421 import java.util.Properties;
2522
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.junit.runners.Parameterized;
26
2627 import static org.junit.Assert.assertEquals;
2728
29 @RunWith(Parameterized.class)
2830 public class PropertiesPropertySourceTest {
2931
3032 private final PropertySource source = new PropertiesPropertySource(new Properties());
33 private final CharSequence expected;
34 private final List<? extends CharSequence> tokens;
3135
36 public PropertiesPropertySourceTest(final String expected, final List<CharSequence> tokens) {
37 this.expected = expected;
38 this.tokens = tokens;
39 }
40
41 @Parameterized.Parameters(name = "{0}")
3242 public static Object[][] data() {
3343 return new Object[][]{
3444 {"log4j2.configurationFile", Arrays.asList("configuration", "file")},
3848 };
3949 }
4050
41 @ParameterizedTest
42 @MethodSource("data")
43 public void testNormalFormFollowsCamelCaseConventions(final String expected, final List<CharSequence> tokens) {
51 @Test
52 public void testNormalFormFollowsCamelCaseConventions() throws Exception {
4453 assertEquals(expected, source.getNormalForm(tokens));
4554 }
4655 }
1616
1717 package org.apache.logging.log4j.util;
1818
19 import org.junit.jupiter.api.BeforeEach;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.parallel.ResourceAccessMode;
22 import org.junit.jupiter.api.parallel.ResourceLock;
23 import org.junit.jupiter.api.parallel.Resources;
24
2519 import java.nio.charset.Charset;
2620 import java.nio.charset.StandardCharsets;
2721 import java.util.Map;
2822 import java.util.Properties;
2923
30 import static org.junit.jupiter.api.Assertions.*;
24 import org.junit.Before;
25 import org.junit.Test;
3126
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertNull;
30
31 /**
32 *
33 */
3234 public class PropertiesUtilTest {
3335
3436 private final Properties properties = new Properties();
3537
36 @BeforeEach
38 @Before
3739 public void setUp() throws Exception {
3840 properties.load(ClassLoader.getSystemResourceAsStream("PropertiesUtilTest.properties"));
3941 }
4042
4143 @Test
42 public void testExtractSubset() {
44 public void testExtractSubset() throws Exception {
4345 assertHasAllProperties(PropertiesUtil.extractSubset(properties, "a"));
4446 assertHasAllProperties(PropertiesUtil.extractSubset(properties, "b."));
4547 assertHasAllProperties(PropertiesUtil.extractSubset(properties, "c.1"));
4850 }
4951
5052 @Test
51 public void testPartitionOnCommonPrefix() {
53 public void testPartitionOnCommonPrefix() throws Exception {
5254 final Map<String, Properties> parts = PropertiesUtil.partitionOnCommonPrefixes(properties);
5355 assertEquals(4, parts.size());
5456 assertHasAllProperties(parts.get("a"));
6668
6769
6870 @Test
69 public void testGetCharsetProperty() {
71 public void testGetCharsetProperty() throws Exception {
7072 final Properties p = new Properties();
7173 p.setProperty("e.1", StandardCharsets.US_ASCII.name());
7274 p.setProperty("e.2", "wrong-charset-name");
7880 }
7981
8082 @Test
81 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
8283 public void testGetMappedProperty_sun_stdout_encoding() {
8384 final PropertiesUtil pu = new PropertiesUtil(System.getProperties());
84 Charset expected = System.console() == null ? Charset.defaultCharset() : StandardCharsets.UTF_8;
85 final Charset expected = System.console() == null ? Charset.defaultCharset() : StandardCharsets.UTF_8;
8586 assertEquals(expected, pu.getCharsetProperty("sun.stdout.encoding"));
8687 }
8788
8889 @Test
89 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
9090 public void testGetMappedProperty_sun_stderr_encoding() {
9191 final PropertiesUtil pu = new PropertiesUtil(System.getProperties());
92 Charset expected = System.console() == null ? Charset.defaultCharset() : StandardCharsets.UTF_8;
92 final Charset expected = System.console() == null ? Charset.defaultCharset() : StandardCharsets.UTF_8;
9393 assertEquals(expected, pu.getCharsetProperty("sun.err.encoding"));
9494 }
9595
9696 @Test
97 @ResourceLock(Resources.SYSTEM_PROPERTIES)
9897 public void testNonStringSystemProperties() {
99 Object key1 = "1";
100 Object key2 = new Object();
98 final Object key1 = "1";
99 final Object key2 = new Object();
101100 System.getProperties().put(key1, new Object());
102101 System.getProperties().put(key2, "value-2");
103102 try {
110109 }
111110
112111 @Test
113 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
114112 public void testPublish() {
115113 final Properties props = new Properties();
116114 final PropertiesUtil util = new PropertiesUtil(props);
117115 String value = System.getProperty("Application");
118 assertNotNull(value, "System property was not published");
116 assertNotNull("System property was not published", value);
119117 assertEquals("Log4j", value);
120118 }
121119 }
2323 import java.util.PropertyPermission;
2424
2525 import org.apache.logging.log4j.junit.SecurityManagerTestRule;
26 import org.junit.Assert;
2627 import org.junit.BeforeClass;
2728 import org.junit.Rule;
2829 import org.junit.Test;
29 import org.junit.jupiter.api.parallel.ResourceLock;
30
31 import static org.junit.Assert.assertNull;
32 import static org.junit.Assert.assertTrue;
3330
3431 /**
3532 * Test related to https://issues.apache.org/jira/browse/LOG4J2-2274.
4441 * @see System#setSecurityManager(SecurityManager)
4542 * @see PropertyPermission
4643 */
47 @ResourceLock("java.lang.SecurityManager")
4844 public class PropertyFilePropertySourceSecurityManagerIT {
4945
50 @BeforeClass
51 public static void beforeClass() {
52 assertTrue(TEST_FIXTURE_PATH, Files.exists(Paths.get(TEST_FIXTURE_PATH)));
53 }
54
55 @Rule
56 public final SecurityManagerTestRule rule = new SecurityManagerTestRule(new TestSecurityManager());
46 @BeforeClass
47 public static void beforeClass() {
48 Assert.assertTrue(TEST_FIXTURE_PATH, Files.exists(Paths.get(TEST_FIXTURE_PATH)));
49 }
50
51 @Rule
52 public final SecurityManagerTestRule rule = new SecurityManagerTestRule(new TestSecurityManager());
5753
58 private static final String TEST_FIXTURE_PATH = "src/test/resources/PropertiesUtilTest.properties";
54 private static final String TEST_FIXTURE_PATH = "src/test/resources/PropertiesUtilTest.properties";
5955
60 /**
61 * Always throws a SecurityException for any environment variables permission
62 * check.
63 */
64 private static class TestSecurityManager extends SecurityManager {
56 /**
57 * Always throws a SecurityException for any environment variables permission
58 * check.
59 */
60 private class TestSecurityManager extends SecurityManager {
6561
66 @Override
67 public void checkPermission(final Permission permission) {
68 if (permission instanceof FilePermission && permission.getName().endsWith(TEST_FIXTURE_PATH)) {
69 throw new SecurityException();
70 }
71 }
72 }
62 @Override
63 public void checkPermission(final Permission permission) {
64 if (permission instanceof FilePermission && permission.getName().endsWith(TEST_FIXTURE_PATH)) {
65 throw new SecurityException();
66 }
67 }
68 }
7369
74 /**
75 * Makes sure we do not blow up with exception below due to a security manager
76 * rejecting environment variable access in
77 * {@link SystemPropertiesPropertySource}.
78 *
79 * <pre>
80 * </pre>
81 */
82 @Test
83 public void test() {
84 final PropertiesUtil propertiesUtil = new PropertiesUtil(TEST_FIXTURE_PATH);
85 assertNull(propertiesUtil.getStringProperty("a.1"));
86 }
70 /**
71 * Makes sure we do not blow up with exception below due to a security manager
72 * rejecting environment variable access in
73 * {@link SystemPropertiesPropertySource}.
74 *
75 * <pre>
76 * </pre>
77 */
78 @Test
79 public void test() {
80 final PropertiesUtil propertiesUtil = new PropertiesUtil(TEST_FIXTURE_PATH);
81 Assert.assertEquals(null, propertiesUtil.getStringProperty("a.1"));
82 }
8783 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.params.ParameterizedTest;
19 import org.junit.jupiter.params.provider.MethodSource;
20
2118 import java.util.Arrays;
2219 import java.util.Collections;
2320 import java.util.List;
2421
25 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.Parameterized;
2625
26 import static org.junit.Assert.assertEquals;
27
28 @RunWith(Parameterized.class)
2729 public class PropertySourceCamelCaseTest {
2830
31 private final CharSequence expected;
32 private final List<String> tokens;
33
34 public PropertySourceCamelCaseTest(final CharSequence expected, final List<String> tokens) {
35 this.expected = expected;
36 this.tokens = tokens;
37 }
38
39 @Parameterized.Parameters(name = "{0}")
2940 public static Object[][] data() {
3041 return new Object[][]{
3142 {"", Collections.singletonList("")},
3546 };
3647 }
3748
38 @ParameterizedTest
39 @MethodSource("data")
40 public void testJoinAsCamelCase(final CharSequence expected, final List<String> tokens) {
49 @Test
50 public void testJoinAsCamelCase() throws Exception {
4151 assertEquals(expected, PropertySource.Util.joinAsCamelCase(tokens));
4252 }
4353 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.params.ParameterizedTest;
19 import org.junit.jupiter.params.provider.MethodSource;
20
2118 import java.util.Arrays;
2219 import java.util.Collections;
2320 import java.util.List;
2421
25 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.Parameterized;
2625
26 import static org.junit.Assert.assertEquals;
27
28 @RunWith(Parameterized.class)
2729 public class PropertySourceTokenizerTest {
2830
31 private final CharSequence value;
32 private final List<CharSequence> expectedTokens;
33
34 public PropertySourceTokenizerTest(final CharSequence value, final List<CharSequence> expectedTokens) {
35 this.value = value;
36 this.expectedTokens = expectedTokens;
37 }
38
39 @Parameterized.Parameters(name = "{0}")
2940 public static Object[][] data() {
3041 return new Object[][]{
3142 {"log4j.simple", Collections.singletonList("simple")},
4657 };
4758 }
4859
49 @ParameterizedTest
50 @MethodSource("data")
51 public void testTokenize(final CharSequence value, final List<CharSequence> expectedTokens) {
52 List<CharSequence> tokens = PropertySource.Util.tokenize(value);
60 @Test
61 public void testTokenize() throws Exception {
62 final List<CharSequence> tokens = PropertySource.Util.tokenize(value);
5363 assertEquals(expectedTokens, tokens);
5464 }
55 }
65 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.TestLoggerContext;
20 import org.apache.logging.log4j.spi.LoggerContext;
21 import org.junit.jupiter.api.Test;
22
2318 import java.io.File;
2419 import java.net.URL;
2520 import java.net.URLClassLoader;
2621
27 import static org.junit.jupiter.api.Assertions.assertTrue;
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.TestLoggerContext;
24 import org.apache.logging.log4j.spi.LoggerContext;
25 import org.junit.Test;
26
27 import static org.junit.Assert.assertTrue;
2828
2929 public class ProviderUtilTest {
3030
3636 worker.setContextClassLoader(classLoader);
3737 worker.start();
3838 worker.join();
39 assertTrue(worker.context instanceof TestLoggerContext, "Incorrect LoggerContext");
39 assertTrue("Incorrect LoggerContext", worker.context instanceof TestLoggerContext);
4040 }
4141
42 private static class Worker extends Thread {
42 private class Worker extends Thread {
4343 LoggerContext context = null;
4444
4545 @Override
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.api.Test;
19
2018 import java.io.BufferedReader;
2119 import java.io.ByteArrayInputStream;
2220 import java.io.ByteArrayOutputStream;
3028 import java.net.URL;
3129 import java.net.URLDecoder;
3230 import java.nio.charset.Charset;
33 import java.util.Arrays;
3431 import java.util.ConcurrentModificationException;
3532 import java.util.HashMap;
3633 import java.util.Map;
3734
38 import static org.junit.jupiter.api.Assertions.*;
35 import org.junit.Test;
36
37 import static org.junit.Assert.*;
3938
4039 /**
4140 * Tests the SortedArrayStringMap class.
4241 */
4342 public class SortedArrayStringMapTest {
4443
45 @Test
46 public void testConstructorDisallowsNegativeCapacity() {
47 assertThrows(IllegalArgumentException.class, () -> new SortedArrayStringMap(-1));
48 }
49
50 @Test
51 public void testConstructorAllowsZeroCapacity() {
52 SortedArrayStringMap sortedArrayStringMap = new SortedArrayStringMap(0);
44 @Test(expected = IllegalArgumentException.class)
45 public void testConstructorDisallowsNegativeCapacity() throws Exception {
46 new SortedArrayStringMap(-1);
47 }
48
49 public void testConstructorAllowsZeroCapacity() throws Exception {
50 final SortedArrayStringMap sortedArrayStringMap = new SortedArrayStringMap(0);
5351 assertEquals(0, sortedArrayStringMap.size());
5452 }
5553
5654 @Test
57 public void testConstructorIgnoresNull() {
55 public void testConstructorIgnoresNull() throws Exception {
5856 assertEquals(0, new SortedArrayStringMap((SortedArrayStringMap) null).size());
5957 }
6058
175173 }
176174
177175 @Test
178 public void testPutAll() {
176 public void testPutAll() throws Exception {
179177 final SortedArrayStringMap original = new SortedArrayStringMap();
180178 original.putValue("a", "avalue");
181179 original.putValue("B", "Bvalue");
196194 }
197195
198196 @Test
199 public void testPutAll_overwritesSameKeys2() {
197 public void testPutAll_overwritesSameKeys2() throws Exception {
200198 final SortedArrayStringMap original = new SortedArrayStringMap();
201199 original.putValue("a", "aORIG");
202200 original.putValue("b", "bORIG");
211209 other.putValue("c", "cc");
212210 original.putAll(other);
213211
214 assertEquals(7, original.size(), "size after put other");
212 assertEquals("size after put other", 7, original.size());
215213 assertEquals("aa", original.getValue("a"));
216214 assertEquals("bORIG", original.getValue("b"));
217215 assertEquals("cc", original.getValue("c"));
222220 }
223221
224222 @Test
225 public void testPutAll_nullKeyInLargeOriginal() {
223 public void testPutAll_nullKeyInLargeOriginal() throws Exception {
226224 final SortedArrayStringMap original = new SortedArrayStringMap();
227225 original.putValue(null, "nullORIG");
228226 original.putValue("a", "aORIG");
236234 other.putValue("a", "aa");
237235 original.putAll(other);
238236
239 assertEquals(7, original.size(), "size after put other");
237 assertEquals("size after put other", 7, original.size());
240238 assertEquals("aa", original.getValue("a"));
241239 assertEquals("bORIG", original.getValue("b"));
242240 assertEquals("cORIG", original.getValue("c"));
247245 }
248246
249247 @Test
250 public void testPutAll_nullKeyInSmallOriginal() {
248 public void testPutAll_nullKeyInSmallOriginal() throws Exception {
251249 final SortedArrayStringMap original = new SortedArrayStringMap();
252250 original.putValue(null, "nullORIG");
253251 original.putValue("a", "aORIG");
260258 other.putValue("a", "aa");
261259 original.putAll(other);
262260
263 assertEquals(6, original.size(), "size after put other");
261 assertEquals("size after put other", 6, original.size());
264262 assertEquals("aa", original.getValue("a"));
265263 assertEquals("bORIG", original.getValue("b"));
266264 assertEquals("11", original.getValue("1"));
270268 }
271269
272270 @Test
273 public void testPutAll_nullKeyInSmallAdditional() {
271 public void testPutAll_nullKeyInSmallAdditional() throws Exception {
274272 final SortedArrayStringMap original = new SortedArrayStringMap();
275273 original.putValue("a", "aORIG");
276274 original.putValue("b", "bORIG");
284282 other.putValue("a", "aa");
285283 original.putAll(other);
286284
287 assertEquals(7, original.size(), "size after put other");
285 assertEquals("size after put other", 7, original.size());
288286 assertEquals("aa", original.getValue("a"));
289287 assertEquals("bORIG", original.getValue("b"));
290288 assertEquals("cORIG", original.getValue("c"));
295293 }
296294
297295 @Test
298 public void testPutAll_nullKeyInLargeAdditional() {
296 public void testPutAll_nullKeyInLargeAdditional() throws Exception {
299297 final SortedArrayStringMap original = new SortedArrayStringMap();
300298 original.putValue("a", "aORIG");
301299 original.putValue("b", "bORIG");
308306 other.putValue("a", "aa");
309307 original.putAll(other);
310308
311 assertEquals(6, original.size(), "size after put other");
309 assertEquals("size after put other", 6, original.size());
312310 assertEquals("aa", original.getValue("a"));
313311 assertEquals("bORIG", original.getValue("b"));
314312 assertEquals("11", original.getValue("1"));
318316 }
319317
320318 @Test
321 public void testPutAll_nullKeyInBoth_LargeOriginal() {
319 public void testPutAll_nullKeyInBoth_LargeOriginal() throws Exception {
322320 final SortedArrayStringMap original = new SortedArrayStringMap();
323321 original.putValue(null, "nullORIG");
324322 original.putValue("a", "aORIG");
333331 other.putValue("a", "aa");
334332 original.putAll(other);
335333
336 assertEquals(7, original.size(), "size after put other");
334 assertEquals("size after put other", 7, original.size());
337335 assertEquals("aa", original.getValue("a"));
338336 assertEquals("bORIG", original.getValue("b"));
339337 assertEquals("cORIG", original.getValue("c"));
344342 }
345343
346344 @Test
347 public void testPutAll_nullKeyInBoth_SmallOriginal() {
345 public void testPutAll_nullKeyInBoth_SmallOriginal() throws Exception {
348346 final SortedArrayStringMap original = new SortedArrayStringMap();
349347 original.putValue(null, "nullORIG");
350348 original.putValue("a", "aORIG");
358356 other.putValue("a", "aa");
359357 original.putAll(other);
360358
361 assertEquals(6, original.size(), "size after put other");
359 assertEquals("size after put other", 6, original.size());
362360 assertEquals("aa", original.getValue("a"));
363361 assertEquals("bORIG", original.getValue("b"));
364362 assertEquals("11", original.getValue("1"));
368366 }
369367
370368 @Test
371 public void testPutAll_overwritesSameKeys1() {
369 public void testPutAll_overwritesSameKeys1() throws Exception {
372370 final SortedArrayStringMap original = new SortedArrayStringMap();
373371 original.putValue("a", "aORIG");
374372 original.putValue("b", "bORIG");
381379 other.putValue("c", "cc");
382380 original.putAll(other);
383381
384 assertEquals(5, original.size(), "size after put other");
382 assertEquals("size after put other", 5, original.size());
385383 assertEquals("aa", original.getValue("a"));
386384 assertEquals("bORIG", original.getValue("b"));
387385 assertEquals("cc", original.getValue("c"));
418416 }
419417
420418 @Test
421 public void testToMap() {
419 public void testToMap() throws Exception {
422420 final SortedArrayStringMap original = new SortedArrayStringMap();
423421 original.putValue("a", "avalue");
424422 original.putValue("B", "Bvalue");
431429
432430 assertEquals(expected, original.toMap());
433431
434 assertDoesNotThrow(() -> original.toMap().put("abc", "xyz"), "Expected map to be mutable");
432 try {
433 original.toMap().put("abc", "xyz");
434 } catch (final UnsupportedOperationException ex) {
435 fail("Expected map to be mutable, but " + ex);
436 }
435437 }
436438
437439 @Test
440442 original.putValue("a", "aaa");
441443 original.putValue("b", "bbb");
442444 original.putValue("c", "ccc");
443 assertEquals(3, original.size(), "size");
445 assertEquals("size", 3, original.size());
444446
445447 // add empty context data
446448 original.putAll(new SortedArrayStringMap());
447 assertEquals(3, original.size(), "size after put empty");
449 assertEquals("size after put empty", 3, original.size());
448450 assertEquals("aaa", original.getValue("a"));
449451 assertEquals("bbb", original.getValue("b"));
450452 assertEquals("ccc", original.getValue("c"));
455457 other.putValue("3", "333");
456458 original.putAll(other);
457459
458 assertEquals(6, original.size(), "size after put other");
460 assertEquals("size after put other", 6, original.size());
459461 assertEquals("aaa", original.getValue("a"));
460462 assertEquals("bbb", original.getValue("b"));
461463 assertEquals("ccc", original.getValue("c"));
471473 original.putValue("b", "bbb");
472474 original.putValue("c", "ccc");
473475 original.putValue("d", "ddd");
474 assertEquals(4, original.size(), "size");
476 assertEquals("size", 4, original.size());
475477
476478 // add empty context data
477479 original.putAll(new SortedArrayStringMap());
478 assertEquals(4, original.size(), "size after put empty");
480 assertEquals("size after put empty", 4, original.size());
479481 assertEquals("aaa", original.getValue("a"));
480482 assertEquals("bbb", original.getValue("b"));
481483 assertEquals("ccc", original.getValue("c"));
488490 other.putValue("4", "444");
489491 original.putAll(other);
490492
491 assertEquals(8, original.size(), "size after put other");
493 assertEquals("size after put other", 8, original.size());
492494 assertEquals("aaa", original.getValue("a"));
493495 assertEquals("bbb", original.getValue("b"));
494496 assertEquals("ccc", original.getValue("c"));
507509 original.putValue("b", "bbb");
508510 original.putValue("c", "ccc");
509511 original.putValue("d", "ddd");
510 assertEquals(5, original.size(), "size");
512 assertEquals("size", 5, original.size());
511513
512514 final SortedArrayStringMap other = new SortedArrayStringMap();
513515 for (int i = 0 ; i < 500; i++) {
516518 other.putValue(null, "otherVal");
517519 original.putAll(other);
518520
519 assertEquals(505, original.size(), "size after put other");
521 assertEquals("size after put other", 505, original.size());
520522 assertEquals("otherVal", original.getValue(null));
521523 assertEquals("aaa", original.getValue("a"));
522524 assertEquals("bbb", original.getValue("b"));
533535 original.putValue("a", "aaa");
534536 original.putValue("b", "bbb");
535537 original.putValue("c", "ccc");
536 assertEquals(3, original.size(), "size");
538 assertEquals("size", 3, original.size());
537539
538540 // putAll with self
539541 original.putAll(original);
540 assertEquals(3, original.size(), "size after put empty");
542 assertEquals("size after put empty", 3, original.size());
541543 assertEquals("aaa", original.getValue("a"));
542544 assertEquals("bbb", original.getValue("b"));
543545 assertEquals("ccc", original.getValue("c"));
544546 }
545547
546 @Test
548 @Test(expected = ConcurrentModificationException.class)
547549 public void testConcurrentModificationBiConsumerPut() {
548550 final SortedArrayStringMap original = new SortedArrayStringMap();
549551 original.putValue("a", "aaa");
550 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.putValue("c", "other")));
551 }
552
553 @Test
552 original.forEach(new BiConsumer<String, Object>() {
553 @Override
554 public void accept(final String s, final Object o) {
555 original.putValue("c", "other");
556 }
557 });
558 }
559
560 @Test(expected = ConcurrentModificationException.class)
554561 public void testConcurrentModificationBiConsumerPutValue() {
555562 final SortedArrayStringMap original = new SortedArrayStringMap();
556563 original.putValue("a", "aaa");
557 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.putValue("c", "other")));
558 }
559
560 @Test
564 original.forEach(new BiConsumer<String, Object>() {
565 @Override
566 public void accept(final String s, final Object o) {
567 original.putValue("c", "other");
568 }
569 });
570 }
571
572 @Test(expected = ConcurrentModificationException.class)
561573 public void testConcurrentModificationBiConsumerRemove() {
562574 final SortedArrayStringMap original = new SortedArrayStringMap();
563575 original.putValue("a", "aaa");
564 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.remove("a")));
565 }
566
567 @Test
576 original.forEach(new BiConsumer<String, Object>() {
577 @Override
578 public void accept(final String s, final Object o) {
579 original.remove("a");
580 }
581 });
582 }
583
584 @Test(expected = ConcurrentModificationException.class)
568585 public void testConcurrentModificationBiConsumerClear() {
569586 final SortedArrayStringMap original = new SortedArrayStringMap();
570587 original.putValue("a", "aaa");
571 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.clear()));
572 }
573
574 @Test
588 original.forEach(new BiConsumer<String, Object>() {
589 @Override
590 public void accept(final String s, final Object o) {
591 original.clear();
592 }
593 });
594 }
595
596 @Test(expected = ConcurrentModificationException.class)
575597 public void testConcurrentModificationTriConsumerPut() {
576598 final SortedArrayStringMap original = new SortedArrayStringMap();
577599 original.putValue("a", "aaa");
578 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.putValue("c", "other"), null));
579 }
580
581 @Test
600 original.forEach(new TriConsumer<String, Object, Object>() {
601 @Override
602 public void accept(final String s, final Object o, final Object o2) {
603 original.putValue("c", "other");
604 }
605 }, null);
606 }
607
608 @Test(expected = ConcurrentModificationException.class)
582609 public void testConcurrentModificationTriConsumerPutValue() {
583610 final SortedArrayStringMap original = new SortedArrayStringMap();
584611 original.putValue("a", "aaa");
585 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.putValue("c", "other"), null));
586 }
587
588 @Test
612 original.forEach(new TriConsumer<String, Object, Object>() {
613 @Override
614 public void accept(final String s, final Object o, final Object o2) {
615 original.putValue("c", "other");
616 }
617 }, null);
618 }
619
620 @Test(expected = ConcurrentModificationException.class)
589621 public void testConcurrentModificationTriConsumerRemove() {
590622 final SortedArrayStringMap original = new SortedArrayStringMap();
591623 original.putValue("a", "aaa");
592 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.remove("a"), null));
593 }
594
595 @Test
624 original.forEach(new TriConsumer<String, Object, Object>() {
625 @Override
626 public void accept(final String s, final Object o, final Object o2) {
627 original.remove("a");
628 }
629 }, null);
630 }
631
632 @Test(expected = ConcurrentModificationException.class)
596633 public void testConcurrentModificationTriConsumerClear() {
597634 final SortedArrayStringMap original = new SortedArrayStringMap();
598635 original.putValue("a", "aaa");
599 assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.clear(), null));
636 original.forEach(new TriConsumer<String, Object, Object>() {
637 @Override
638 public void accept(final String s, final Object o, final Object o2) {
639 original.clear();
640 }
641 }, null);
600642 }
601643
602644 @Test
607649 @Test
608650 public void testIsFrozenAfterCallingFreeze() {
609651 final SortedArrayStringMap original = new SortedArrayStringMap();
610 assertFalse(original.isFrozen(), "before freeze");
652 assertFalse("before freeze", original.isFrozen());
611653 original.freeze();
612 assertTrue(original.isFrozen(), "after freeze");
613 }
614
615 @Test
654 assertTrue("after freeze", original.isFrozen());
655 }
656
657 @Test(expected = UnsupportedOperationException.class)
616658 public void testFreezeProhibitsPutValue() {
617659 final SortedArrayStringMap original = new SortedArrayStringMap();
618660 original.freeze();
619 assertThrows(UnsupportedOperationException.class, () -> original.putValue("a", "aaa"));
620 }
621
622 @Test
661 original.putValue("a", "aaa");
662 }
663
664 @Test(expected = UnsupportedOperationException.class)
623665 public void testFreezeProhibitsRemove() {
624666 final SortedArrayStringMap original = new SortedArrayStringMap();
625667 original.putValue("b", "bbb");
626668 original.freeze();
627 assertThrows(UnsupportedOperationException.class, () -> original.remove("b")); // existing key: modifies the collection
669 original.remove("b"); // existing key: modifies the collection
628670 }
629671
630672 @Test
632674 final SortedArrayStringMap original = new SortedArrayStringMap();
633675 original.putValue("b", "bbb");
634676 original.freeze();
635 assertDoesNotThrow(() -> original.remove("a"));
677 original.remove("a"); // no actual modification
636678 }
637679
638680 @Test
639681 public void testFreezeAllowsRemoveIfEmpty() {
640682 final SortedArrayStringMap original = new SortedArrayStringMap();
641683 original.freeze();
642 assertDoesNotThrow(() -> original.remove("a"));
643 }
644
645 @Test
684 original.remove("a"); // no exception
685 }
686
687 @Test(expected = UnsupportedOperationException.class)
646688 public void testFreezeProhibitsClear() {
647689 final SortedArrayStringMap original = new SortedArrayStringMap();
648690 original.putValue("a", "aaa");
649691 original.freeze();
650 assertThrows(UnsupportedOperationException.class, original::clear);
692 original.clear();
651693 }
652694
653695 @Test
654696 public void testFreezeAllowsClearIfEmpty() {
655697 final SortedArrayStringMap original = new SortedArrayStringMap();
656698 original.freeze();
657 assertDoesNotThrow(original::clear);
658 }
659
660 @Test
661 public void testPutInsertsInAlphabeticOrder() {
699 original.clear();
700 }
701
702 @Test
703 public void testPutInsertsInAlphabeticOrder() throws Exception {
662704 final SortedArrayStringMap original = new SortedArrayStringMap();
663705 original.putValue("a", "avalue");
664706 original.putValue("B", "Bvalue");
683725 }
684726
685727 @Test
686 public void testPutValueInsertsInAlphabeticOrder() {
728 public void testPutValueInsertsInAlphabeticOrder() throws Exception {
687729 final SortedArrayStringMap original = new SortedArrayStringMap();
688730 original.putValue("a", "avalue");
689731 original.putValue("B", "Bvalue");
751793 expected.put("3", "3value");
752794 expected.put("c", "cvalue");
753795 expected.put("d", "dvalue");
754 assertEquals(expected, original.toMap(), "initial");
796 assertEquals("initial", expected, original.toMap());
755797
756798 original.putValue(null, "nullvalue");
757799 expected.put(null, "nullvalue");
758800 assertEquals(6, original.size());
759 assertEquals(expected, original.toMap(), "with null key");
801 assertEquals("with null key", expected, original.toMap());
760802
761803 original.putValue(null, "otherNullvalue");
762804 expected.put(null, "otherNullvalue");
763805 assertEquals(6, original.size());
764 assertEquals(expected, original.toMap(), "with null key value2");
806 assertEquals("with null key value2", expected, original.toMap());
765807
766808 original.putValue(null, "nullvalue");
767809 expected.put(null, "nullvalue");
768810 assertEquals(6, original.size());
769 assertEquals(expected, original.toMap(), "with null key value1 again");
811 assertEquals("with null key value1 again", expected, original.toMap());
770812
771813 original.putValue(null, "abc");
772814 expected.put(null, "abc");
773815 assertEquals(6, original.size());
774 assertEquals(expected, original.toMap(), "with null key value3");
816 assertEquals("with null key value3", expected, original.toMap());
775817 }
776818
777819 @Test
783825
784826 original.remove("a");
785827 assertEquals(0, original.size());
786 assertNull(original.getValue("a"), "no a val");
828 assertNull("no a val", original.getValue("a"));
787829
788830 original.remove("B");
789831 assertEquals(0, original.size());
790 assertNull(original.getValue("B"), "no B val");
832 assertNull("no B val", original.getValue("B"));
791833 }
792834
793835 @Test
807849 final Field f = SortedArrayStringMap.class.getDeclaredField("values");
808850 f.setAccessible(true);
809851 final Object[] values = (Object[]) f.get(original);
810 assertAll(Arrays.stream(values).map(value -> () -> assertNull(value)));
811 }
812
813 @Test
814 public void testRemoveWhenFull() {
852 for (int i = 0; i < values.length; i++) {
853 assertNull(values[i]);
854 }
855 }
856
857 @Test
858 public void testRemoveWhenFull() throws Exception {
815859 final SortedArrayStringMap original = new SortedArrayStringMap();
816860 original.putValue("a", "avalue");
817861 original.putValue("b", "bvalue");
829873
830874 original.putValue("a", null);
831875 assertEquals(1, original.size());
832 assertNull(original.getValue("a"), "no a val");
876 assertNull("no a val", original.getValue("a"));
833877
834878 original.putValue("B", null);
835879 assertEquals(2, original.size());
836 assertNull(original.getValue("B"), "no B val");
837 }
838
839 @Test
840 public void testGet() {
880 assertNull("no B val", original.getValue("B"));
881 }
882
883 @Test
884 public void testGet() throws Exception {
841885 final SortedArrayStringMap original = new SortedArrayStringMap();
842886 original.putValue("a", "avalue");
843887 original.putValue("B", "Bvalue");
855899 }
856900
857901 @Test
858 public void testGetValue_GetValueAt() {
902 public void testGetValue_GetValueAt() throws Exception {
859903 final SortedArrayStringMap original = new SortedArrayStringMap();
860904 original.putValue("a", "avalue");
861905 original.putValue("B", "Bvalue");
896940 final Field f = SortedArrayStringMap.class.getDeclaredField("values");
897941 f.setAccessible(true);
898942 final Object[] values = (Object[]) f.get(original);
899 assertAll(Arrays.stream(values).map(value -> () -> assertNull(value)));
900 }
901
902 @Test
903 public void testIndexOfKey() {
943 for (int i = 0; i < values.length; i++) {
944 assertNull(values[i]);
945 }
946 }
947
948 @Test
949 public void testIndexOfKey() throws Exception {
904950 final SortedArrayStringMap original = new SortedArrayStringMap();
905951 original.putValue("a", "avalue");
906952 assertEquals(0, original.indexOfKey("a"));
937983 }
938984
939985 @Test
940 public void testContainsKey() {
941 final SortedArrayStringMap original = new SortedArrayStringMap();
942 assertFalse(original.containsKey("a"), "a");
943 assertFalse(original.containsKey("B"), "B");
944 assertFalse(original.containsKey("3"), "3");
945 assertFalse(original.containsKey("A"), "A");
946
947 original.putValue("a", "avalue");
948 assertTrue(original.containsKey("a"), "a");
949 assertFalse(original.containsKey("B"), "B");
950 assertFalse(original.containsKey("3"), "3");
951 assertFalse(original.containsKey("A"), "A");
952
953 original.putValue("B", "Bvalue");
954 assertTrue(original.containsKey("a"), "a");
955 assertTrue(original.containsKey("B"), "B");
956 assertFalse(original.containsKey("3"), "3");
957 assertFalse(original.containsKey("A"), "A");
958
959 original.putValue("3", "3value");
960 assertTrue(original.containsKey("a"), "a");
961 assertTrue(original.containsKey("B"), "B");
962 assertTrue(original.containsKey("3"), "3");
963 assertFalse(original.containsKey("A"), "A");
986 public void testContainsKey() throws Exception {
987 final SortedArrayStringMap original = new SortedArrayStringMap();
988 assertFalse("a", original.containsKey("a"));
989 assertFalse("B", original.containsKey("B"));
990 assertFalse("3", original.containsKey("3"));
991 assertFalse("A", original.containsKey("A"));
992
993 original.putValue("a", "avalue");
994 assertTrue("a", original.containsKey("a"));
995 assertFalse("B", original.containsKey("B"));
996 assertFalse("3", original.containsKey("3"));
997 assertFalse("A", original.containsKey("A"));
998
999 original.putValue("B", "Bvalue");
1000 assertTrue("a", original.containsKey("a"));
1001 assertTrue("B", original.containsKey("B"));
1002 assertFalse("3", original.containsKey("3"));
1003 assertFalse("A", original.containsKey("A"));
1004
1005 original.putValue("3", "3value");
1006 assertTrue("a", original.containsKey("a"));
1007 assertTrue("B", original.containsKey("B"));
1008 assertTrue("3", original.containsKey("3"));
1009 assertFalse("A", original.containsKey("A"));
9641010
9651011 original.putValue("A", "AAA");
966 assertTrue(original.containsKey("a"), "a");
967 assertTrue(original.containsKey("B"), "B");
968 assertTrue(original.containsKey("3"), "3");
969 assertTrue(original.containsKey("A"), "A");
970 }
971
972 @Test
973 public void testGetValueAt() {
1012 assertTrue("a", original.containsKey("a"));
1013 assertTrue("B", original.containsKey("B"));
1014 assertTrue("3", original.containsKey("3"));
1015 assertTrue("A", original.containsKey("A"));
1016 }
1017
1018 @Test
1019 public void testGetValueAt() throws Exception {
9741020 final SortedArrayStringMap original = new SortedArrayStringMap();
9751021 original.putValue("a", "avalue");
9761022 assertEquals("a", original.getKeyAt(0));
9921038 }
9931039
9941040 @Test
995 public void testSizeAndIsEmpty() {
1041 public void testSizeAndIsEmpty() throws Exception {
9961042 final SortedArrayStringMap original = new SortedArrayStringMap();
9971043 assertEquals(0, original.size());
998 assertTrue(original.isEmpty(), "initial");
1044 assertTrue("initial", original.isEmpty());
9991045
10001046 original.putValue("a", "avalue");
10011047 assertEquals(1, original.size());
1002 assertFalse(original.isEmpty(), "size=" + original.size());
1048 assertFalse("size=" + original.size(), original.isEmpty());
10031049
10041050 original.putValue("B", "Bvalue");
10051051 assertEquals(2, original.size());
1006 assertFalse(original.isEmpty(), "size=" + original.size());
1052 assertFalse("size=" + original.size(), original.isEmpty());
10071053
10081054 original.putValue("3", "3value");
10091055 assertEquals(3, original.size());
1010 assertFalse(original.isEmpty(), "size=" + original.size());
1056 assertFalse("size=" + original.size(), original.isEmpty());
10111057
10121058 original.remove("B");
10131059 assertEquals(2, original.size());
1014 assertFalse(original.isEmpty(), "size=" + original.size());
1060 assertFalse("size=" + original.size(), original.isEmpty());
10151061
10161062 original.remove("3");
10171063 assertEquals(1, original.size());
1018 assertFalse(original.isEmpty(), "size=" + original.size());
1064 assertFalse("size=" + original.size(), original.isEmpty());
10191065
10201066 original.remove("a");
10211067 assertEquals(0, original.size());
1022 assertTrue(original.isEmpty(), "size=" + original.size());
1023 }
1024
1025 @Test
1026 public void testForEachBiConsumer() {
1068 assertTrue("size=" + original.size(), original.isEmpty());
1069 }
1070
1071 @Test
1072 public void testForEachBiConsumer() throws Exception {
10271073 final SortedArrayStringMap original = new SortedArrayStringMap();
10281074 original.putValue("a", "avalue");
10291075 original.putValue("B", "Bvalue");
10331079 int count = 0;
10341080 @Override
10351081 public void accept(final String key, final String value) {
1036 assertEquals(key, original.getKeyAt(count), "key");
1037 assertEquals(value, original.getValueAt(count), "val");
1082 assertEquals("key", key, original.getKeyAt(count));
1083 assertEquals("val", value, original.getValueAt(count));
10381084 count++;
1039 assertTrue(count <= original.size(), "count should not exceed size but was " + count);
1085 assertTrue("count should not exceed size but was " + count, count <= original.size());
10401086 }
10411087 });
10421088 }
10451091 SortedArrayStringMap data;
10461092 int count;
10471093 }
1048 static TriConsumer<String, String, State> COUNTER = (key, value, state) -> {
1049 assertEquals(key, state.data.getKeyAt(state.count), "key");
1050 assertEquals(value, state.data.getValueAt(state.count), "val");
1051 state.count++;
1052 assertTrue(
1053 state.count <= state.data.size(), "count should not exceed size but was " + state.count);
1094 static TriConsumer<String, String, State> COUNTER = new TriConsumer<String, String, State>() {
1095 @Override
1096 public void accept(final String key, final String value, final State state) {
1097 assertEquals("key", key, state.data.getKeyAt(state.count));
1098 assertEquals("val", value, state.data.getValueAt(state.count));
1099 state.count++;
1100 assertTrue("count should not exceed size but was " + state.count,
1101 state.count <= state.data.size());
1102 }
10541103 };
10551104
10561105 @Test
1057 public void testForEachTriConsumer() {
1106 public void testForEachTriConsumer() throws Exception {
10581107 final SortedArrayStringMap original = new SortedArrayStringMap();
10591108 original.putValue("a", "avalue");
10601109 original.putValue("B", "Bvalue");
10651114 original.forEach(COUNTER, state);
10661115 assertEquals(state.count, original.size());
10671116 }
1068 }
1117 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 /**
2323 * Tests the StringBuilders class.
2424 */
2525 public class StringBuildersTest {
2626 @Test
27 public void trimToMaxSize() {
27 public void trimToMaxSize() throws Exception {
2828 final StringBuilder sb = new StringBuilder();
2929 final char[] value = new char[4 * 1024];
3030 sb.append(value);
3131
32 assertTrue(sb.length() > Constants.MAX_REUSABLE_MESSAGE_SIZE, "needs trimming");
32 assertTrue("needs trimming", sb.length() > Constants.MAX_REUSABLE_MESSAGE_SIZE);
3333 StringBuilders.trimToMaxSize(sb, Constants.MAX_REUSABLE_MESSAGE_SIZE);
34 assertTrue(sb.length() <= Constants.MAX_REUSABLE_MESSAGE_SIZE, "trimmed OK");
34 assertTrue("trimmed OK", sb.length() <= Constants.MAX_REUSABLE_MESSAGE_SIZE);
3535 }
3636
3737 @Test
38 public void trimToMaxSizeWithLargeCapacity() {
38 public void trimToMaxSizeWithLargeCapacity() throws Exception {
3939 final StringBuilder sb = new StringBuilder();
4040 final char[] value = new char[4 * 1024];
4141 sb.append(value);
4242 sb.setLength(0);
4343
44 assertTrue(sb.capacity() > Constants.MAX_REUSABLE_MESSAGE_SIZE, "needs trimming");
44 assertTrue("needs trimming", sb.capacity() > Constants.MAX_REUSABLE_MESSAGE_SIZE);
4545 StringBuilders.trimToMaxSize(sb, Constants.MAX_REUSABLE_MESSAGE_SIZE);
46 assertTrue(sb.capacity() <= Constants.MAX_REUSABLE_MESSAGE_SIZE, "trimmed OK");
46 assertTrue("trimmed OK", sb.capacity() <= Constants.MAX_REUSABLE_MESSAGE_SIZE);
4747 }
4848
4949 @Test
1616
1717 package org.apache.logging.log4j.util;
1818
19 import org.junit.jupiter.api.Test;
20
2119 import java.util.Arrays;
22 import java.util.Collections;
2320 import java.util.Iterator;
2421
25 import static org.junit.jupiter.api.Assertions.*;
22 import org.junit.Assert;
23 import org.junit.Test;
2624
2725 public class StringsTest {
28
29 @Test
30 public void testIsEmpty() {
31 assertTrue(Strings.isEmpty(null));
32 assertTrue(Strings.isEmpty(""));
33 assertFalse(Strings.isEmpty(" "));
34 assertFalse(Strings.isEmpty("a"));
35 }
36
37 @Test
38 public void testIsBlank() {
39 assertTrue(Strings.isBlank(null));
40 assertTrue(Strings.isBlank(""));
41 assertTrue(Strings.isBlank(" "));
42 assertTrue(Strings.isBlank("\n"));
43 assertTrue(Strings.isBlank("\r"));
44 assertTrue(Strings.isBlank("\t"));
45 assertFalse(Strings.isEmpty("a"));
46 }
4726
4827 /**
4928 * A sanity test to make sure a typo does not mess up {@link Strings#EMPTY}.
5029 */
5130 @Test
5231 public void testEMPTY() {
53 assertEquals("", Strings.EMPTY);
54 assertEquals(0, Strings.EMPTY.length());
55 }
56
57 @Test
58 public void testConcat() {
59 assertEquals("ab", Strings.concat("a", "b"));
60 assertEquals("a", Strings.concat("a", ""));
61 assertEquals("a", Strings.concat("a", null));
62 assertEquals("b", Strings.concat("", "b"));
63 assertEquals("b", Strings.concat(null, "b"));
32 Assert.assertEquals("", Strings.EMPTY);
33 Assert.assertEquals(0, Strings.EMPTY.length());
6434 }
6535
6636 @Test
6737 public void testJoin() {
68 assertNull(Strings.join((Iterable<?>) null, '.'));
69 assertNull(Strings.join((Iterator<?>) null, '.'));
70 assertEquals("", Strings.join((Collections.emptyList()), '.'));
38 Assert.assertEquals(null, Strings.join((Iterable<?>) null, '.'));
39 Assert.assertEquals(null, Strings.join((Iterator<?>) null, '.'));
40 Assert.assertEquals("", Strings.join((Arrays.asList()), '.'));
7141
72 assertEquals("a", Strings.join(Collections.singletonList("a"), '.'));
73 assertEquals("a.b", Strings.join(Arrays.asList("a", "b"), '.'));
74 assertEquals("a.b.c", Strings.join(Arrays.asList("a", "b", "c"), '.'));
42 Assert.assertEquals("a", Strings.join(Arrays.asList("a"), '.'));
43 Assert.assertEquals("a.b", Strings.join(Arrays.asList("a", "b"), '.'));
44 Assert.assertEquals("a.b.c", Strings.join(Arrays.asList("a", "b", "c"), '.'));
7545
76 assertEquals("", Strings.join(Collections.singletonList((String) null), ':'));
77 assertEquals(":", Strings.join(Arrays.asList(null, null), ':'));
78 assertEquals("a:", Strings.join(Arrays.asList("a", null), ':'));
79 assertEquals(":b", Strings.join(Arrays.asList(null, "b"), ':'));
46 Assert.assertEquals("", Strings.join(Arrays.asList((String) null), ':'));
47 Assert.assertEquals(":", Strings.join(Arrays.asList(null, null), ':'));
48 Assert.assertEquals("a:", Strings.join(Arrays.asList("a", null), ':'));
49 Assert.assertEquals(":b", Strings.join(Arrays.asList(null, "b"), ':'));
8050 }
8151
8252 @Test
8353 public void testQuote() {
84 assertEquals("'Q'", Strings.quote("Q"));
54 Assert.assertEquals("'Q'", Strings.quote("Q"));
8555 }
8656
8757 }
2020 import java.util.PropertyPermission;
2121
2222 import org.apache.logging.log4j.junit.SecurityManagerTestRule;
23 import org.junit.Assert;
2324 import org.junit.Rule;
2425 import org.junit.Test;
25 import org.junit.jupiter.api.parallel.ResourceLock;
26
27 import static org.junit.Assert.assertNull;
2826
2927 /**
3028 * Test related to https://issues.apache.org/jira/browse/LOG4J2-2274.
3937 * @see System#setSecurityManager(SecurityManager)
4038 * @see PropertyPermission
4139 */
42 @ResourceLock("java.lang.SecurityManager")
4340 public class SystemPropertiesPropertySourceSecurityManagerIT {
4441
4542 @Rule
4946 * Always throws a SecurityException for any environment variables permission
5047 * check.
5148 */
52 private static class TestSecurityManager extends SecurityManager {
49 private class TestSecurityManager extends SecurityManager {
5350 @Override
5451 public void checkPermission(final Permission permission) {
5552 if (permission instanceof PropertyPermission) {
8380 @Test
8481 public void test() {
8582 final PropertiesUtil propertiesUtil = new PropertiesUtil("src/test/resources/PropertiesUtilTest.properties");
86 assertNull(propertiesUtil.getStringProperty("a.1"));
83 Assert.assertEquals(null, propertiesUtil.getStringProperty("a.1"));
8784 }
8885 }
0 package org.apache.logging.log4j.util;
1
2 import java.util.Properties;
3 import java.util.concurrent.ExecutionException;
4 import java.util.concurrent.ExecutorService;
5 import java.util.concurrent.Executors;
6 import java.util.concurrent.Future;
7
8 import org.junit.Test;
9
010 /*
111 * Licensed to the Apache Software Foundation (ASF) under one or more
212 * contributor license agreements. See the NOTICE file distributed with
1424 * limitations under the license.
1525 */
1626
17 package org.apache.logging.log4j.util;
18
19 import org.junit.jupiter.api.Tag;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.parallel.ResourceLock;
22 import org.junit.jupiter.api.parallel.Resources;
23
24 import java.util.Properties;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.Future;
29
3027 /**
3128 * Tests https://issues.apache.org/jira/browse/LOG4J2-2276.
3229 */
33 @Tag("concurrency")
34 @ResourceLock(Resources.SYSTEM_PROPERTIES)
3530 public class SystemPropertiesPropertySourceTest {
3631
37 private static final int ITERATIONS = 10000;
32 private static final int ITERATIONS = 10000;
3833
39 /**
40 * Tests avoiding a ConcurrentModificationException. For example:
41 *
42 * <pre>
43 * java.util.ConcurrentModificationException
44 * at java.util.Hashtable$Enumerator.next(Hashtable.java:1167)
45 * at org.apache.logging.log4j.util.SystemPropertiesPropertySource.forEach(SystemPropertiesPropertySource.java:38)
46 * at org.apache.logging.log4j.util.SystemPropertiesPropertySourceTest.testMultiThreadedAccess(SystemPropertiesPropertySourceTest.java:47)
47 * </pre>
48 * @throws InterruptedException
49 * @throws ExecutionException
50 */
51 @Test
52 public void testMultiThreadedAccess() throws InterruptedException, ExecutionException {
53 ExecutorService threadPool = Executors.newSingleThreadExecutor();
54 try {
55 Future<?> future = threadPool.submit(() -> {
56 final Properties properties = System.getProperties();
57 for (int i = 0; i < ITERATIONS; i++) {
58 properties.setProperty("FOO_" + i, "BAR");
59 }
60 });
61 for (int i = 0; i < ITERATIONS; i++) {
62 new SystemPropertiesPropertySource().forEach((key, value) -> {
63 // nothing
64 });
65 }
66 future.get();
67 } finally {
68 threadPool.shutdown();
69 }
70 }
34 /**
35 * Tests avoiding a ConcurrentModificationException. For example:
36 *
37 * <pre>
38 * java.util.ConcurrentModificationException
39 * at java.util.Hashtable$Enumerator.next(Hashtable.java:1167)
40 * at org.apache.logging.log4j.util.SystemPropertiesPropertySource.forEach(SystemPropertiesPropertySource.java:38)
41 * at org.apache.logging.log4j.util.SystemPropertiesPropertySourceTest.testMultiThreadedAccess(SystemPropertiesPropertySourceTest.java:47)
42 * </pre>
43 */
44 @Test
45 public void testMultiThreadedAccess() throws InterruptedException, ExecutionException {
46 final ExecutorService threadPool = Executors.newSingleThreadExecutor();
47 try {
48 final Future<?> future = threadPool.submit(new Runnable() {
49
50 @Override
51 public void run() {
52 final Properties properties = System.getProperties();
53 for (int i = 0; i < ITERATIONS; i++) {
54 properties.setProperty("FOO_" + i, "BAR");
55 }
56 }
57 });
58 for (int i = 0; i < ITERATIONS; i++)
59 new SystemPropertiesPropertySource().forEach(new BiConsumer<String, String>() {
60 @Override
61 public void accept(final String key, final String value) {
62 // nothing
63 }
64 });
65 future.get();
66 } finally {
67 threadPool.shutdown();
68 }
69 }
7170
7271 }
1616
1717 package org.apache.logging.log4j.util;
1818
19 import org.junit.jupiter.api.BeforeAll;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.parallel.ResourceLock;
22 import org.junit.jupiter.api.parallel.Resources;
19 import org.junit.BeforeClass;
20 import org.junit.Test;
2321
24 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2523
2624 /**
2725 * Tests the Unbox class.
2826 */
29 @ResourceLock(Resources.SYSTEM_PROPERTIES)
3027 public class Unbox1Test {
31 @BeforeAll
28 @BeforeClass
3229 public static void beforeClass() {
3330 System.clearProperty("log4j.unbox.ringbuffer.size");
3431 }
3532
3633 @Test
37 public void testBoxClaimsItHas32Slots() {
34 public void testBoxClaimsItHas32Slots() throws Exception {
3835 assertEquals(32, Unbox.getRingbufferSize());
3936 }
4037
4138 @Test
42 public void testBoxHas32Slots() {
39 public void testBoxHas32Slots() throws Exception {
4340 final int MAX = 32;
4441 final StringBuilder[] probe = new StringBuilder[MAX * 3];
4542 for (int i = 0; i <= probe.length - 8; ) {
5350 probe[i++] = Unbox.box(Short.MAX_VALUE);
5451 }
5552 for (int i = 0; i < probe.length - MAX; i++) {
56 assertSame(probe[i], probe[i + MAX], "probe[" + i +"], probe[" + (i + MAX) +"]");
53 assertSame("probe[" + i +"], probe[" + (i + MAX) +"]", probe[i], probe[i + MAX]);
5754 for (int j = 1; j < MAX - 1; j++) {
58 assertNotSame(probe[i], probe[i + j], "probe[" + i +"], probe[" + (i + j) +"]");
55 assertNotSame("probe[" + i +"], probe[" + (i + j) +"]", probe[i], probe[i + j]);
5956 }
6057 }
6158 }
6259
6360 @Test
64 public void testBoxBoolean() {
61 public void testBoxBoolean() throws Exception {
6562 assertEquals("true", Unbox.box(true).toString());
6663 assertEquals("false", Unbox.box(false).toString());
6764 }
6865
6966 @Test
70 public void testBoxByte() {
67 public void testBoxByte() throws Exception {
7168 assertEquals("0", Unbox.box((byte) 0).toString());
7269 assertEquals("1", Unbox.box((byte) 1).toString());
7370 assertEquals("127", Unbox.box((byte) 127).toString());
7673 }
7774
7875 @Test
79 public void testBoxChar() {
76 public void testBoxChar() throws Exception {
8077 assertEquals("a", Unbox.box('a').toString());
8178 assertEquals("b", Unbox.box('b').toString());
8279 assertEquals("字", Unbox.box('字').toString());
8380 }
8481
8582 @Test
86 public void testBoxDouble() {
83 public void testBoxDouble() throws Exception {
8784 assertEquals("3.14", Unbox.box(3.14).toString());
88 assertEquals(Double.toString(Double.MAX_VALUE), Unbox.box(Double.MAX_VALUE).toString());
89 assertEquals(Double.toString(Double.MIN_VALUE), Unbox.box(Double.MIN_VALUE).toString());
85 assertEquals(new Double(Double.MAX_VALUE).toString(), Unbox.box(Double.MAX_VALUE).toString());
86 assertEquals(new Double(Double.MIN_VALUE).toString(), Unbox.box(Double.MIN_VALUE).toString());
9087 }
9188
9289 @Test
93 public void testBoxFloat() {
90 public void testBoxFloat() throws Exception {
9491 assertEquals("3.14", Unbox.box(3.14F).toString());
95 assertEquals(Float.toString(Float.MAX_VALUE), Unbox.box(Float.MAX_VALUE).toString());
96 assertEquals(Float.toString(Float.MIN_VALUE), Unbox.box(Float.MIN_VALUE).toString());
92 assertEquals(new Float(Float.MAX_VALUE).toString(), Unbox.box(Float.MAX_VALUE).toString());
93 assertEquals(new Float(Float.MIN_VALUE).toString(), Unbox.box(Float.MIN_VALUE).toString());
9794 }
9895
9996 @Test
100 public void testBoxInt() {
97 public void testBoxInt() throws Exception {
10198 assertEquals("0", Unbox.box(0).toString());
10299 assertEquals("1", Unbox.box(1).toString());
103100 assertEquals("127", Unbox.box(127).toString());
104101 assertEquals("-1", Unbox.box(-1).toString());
105102 assertEquals("-128", Unbox.box(-128).toString());
106 assertEquals(Integer.toString(Integer.MAX_VALUE), Unbox.box(Integer.MAX_VALUE).toString());
107 assertEquals(Integer.toString(Integer.MIN_VALUE), Unbox.box(Integer.MIN_VALUE).toString());
103 assertEquals(new Integer(Integer.MAX_VALUE).toString(), Unbox.box(Integer.MAX_VALUE).toString());
104 assertEquals(new Integer(Integer.MIN_VALUE).toString(), Unbox.box(Integer.MIN_VALUE).toString());
108105 }
109106
110107 @Test
111 public void testBoxLong() {
108 public void testBoxLong() throws Exception {
112109 assertEquals("0", Unbox.box(0L).toString());
113110 assertEquals("1", Unbox.box(1L).toString());
114111 assertEquals("127", Unbox.box(127L).toString());
115112 assertEquals("-1", Unbox.box(-1L).toString());
116113 assertEquals("-128", Unbox.box(-128L).toString());
117 assertEquals(Long.toString(Long.MAX_VALUE), Unbox.box(Long.MAX_VALUE).toString());
118 assertEquals(Long.toString(Long.MIN_VALUE), Unbox.box(Long.MIN_VALUE).toString());
114 assertEquals(new Long(Long.MAX_VALUE).toString(), Unbox.box(Long.MAX_VALUE).toString());
115 assertEquals(new Long(Long.MIN_VALUE).toString(), Unbox.box(Long.MIN_VALUE).toString());
119116 }
120117
121118 @Test
122 public void testBoxShort() {
119 public void testBoxShort() throws Exception {
123120 assertEquals("0", Unbox.box((short) 0).toString());
124121 assertEquals("1", Unbox.box((short) 1).toString());
125122 assertEquals("127", Unbox.box((short) 127).toString());
126123 assertEquals("-1", Unbox.box((short) -1).toString());
127124 assertEquals("-128", Unbox.box((short) -128).toString());
128 assertEquals(Short.toString(Short.MAX_VALUE), Unbox.box(Short.MAX_VALUE).toString());
129 assertEquals(Short.toString(Short.MIN_VALUE), Unbox.box(Short.MIN_VALUE).toString());
125 assertEquals(new Short(Short.MAX_VALUE).toString(), Unbox.box(Short.MAX_VALUE).toString());
126 assertEquals(new Short(Short.MIN_VALUE).toString(), Unbox.box(Short.MIN_VALUE).toString());
130127 }
131128
132129 @Test
133130 public void testBoxIsThreadLocal() throws Exception {
134131 final StringBuilder[] probe = new StringBuilder[16 * 3];
135132 populate(0, probe);
136 final Thread t1 = new Thread(() -> populate(16, probe));
133 final Thread t1 = new Thread() {
134 @Override
135 public void run() {
136 populate(16, probe);
137 }
138 };
137139 t1.start();
138140 t1.join();
139 final Thread t2 = new Thread(() -> populate(16, probe));
141 final Thread t2 = new Thread() {
142 @Override
143 public void run() {
144 populate(16, probe);
145 }
146 };
140147 t2.start();
141148 t2.join();
142149 for (int i = 0; i < probe.length - 16; i++) {
143150 for (int j = 1; j < 16; j++) {
144 assertNotSame(
145 probe[i], probe[i + j], "probe[" + i +"]=" + probe[i] + ", probe[" + (i + j) +"]=" + probe[i + j]);
151 assertNotSame("probe[" + i +"]=" + probe[i] + ", probe[" + (i + j) +"]=" + probe[i + j],
152 probe[i], probe[i + j]);
146153 }
147154 }
148155 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import org.junit.jupiter.api.AfterAll;
19 import org.junit.jupiter.api.BeforeAll;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
22 import org.junit.jupiter.api.parallel.ResourceLock;
23 import org.junit.jupiter.api.parallel.Resources;
24
2518 import java.lang.reflect.Field;
2619 import java.lang.reflect.Modifier;
2720
28 import static org.junit.jupiter.api.Assertions.*;
21 import org.junit.AfterClass;
22 import org.junit.BeforeClass;
23 import org.junit.Ignore;
24 import org.junit.Test;
25
26 import static org.junit.Assert.*;
2927
3028 /**
3129 * Tests that the Unbox ring buffer size is configurable.
3230 * Must be run in a separate process as the other UnboxTest or the last-run test will fail.
33 * Run this test on its own via {@code mvn --projects log4j-api test -Dtest=Unbox2ConfigurableTest} which will automatically
34 * enable the test, too.
3531 */
36 @EnabledIfSystemProperty(named = "test", matches = ".*Unbox2ConfigurableTest.*")
37 @ResourceLock(Resources.SYSTEM_PROPERTIES)
3832 public class Unbox2ConfigurableTest {
39 @BeforeAll
33 @Ignore
34 @BeforeClass
4035 public static void beforeClass() {
4136 System.setProperty("log4j.unbox.ringbuffer.size", "65");
4237 }
4338
44 @AfterAll
39 @Ignore
40 @AfterClass
4541 public static void afterClass() throws Exception {
4642 System.clearProperty("log4j.unbox.ringbuffer.size");
4743
6258 threadLocalField.set(null, new ThreadLocal<>());
6359 }
6460
61 @Ignore
6562 @Test
66 public void testBoxConfiguredTo128Slots() {
63 public void testBoxConfiguredTo128Slots() throws Exception {
6764 // next power of 2 that is 65 or more
6865 assertEquals(128, Unbox.getRingbufferSize());
6966 }
7067
68 @Ignore
7169 @Test
72 public void testBoxSuccessfullyConfiguredTo128Slots() {
70 public void testBoxSuccessfullyConfiguredTo128Slots() throws Exception {
7371 final int MAX = 128;
7472 final StringBuilder[] probe = new StringBuilder[MAX * 3];
7573 for (int i = 0; i <= probe.length - 8; ) {
8381 probe[i++] = Unbox.box(Short.MAX_VALUE);
8482 }
8583 for (int i = 0; i < probe.length - MAX; i++) {
86 assertSame(probe[i], probe[i + MAX], "probe[" + i +"], probe[" + (i + MAX) +"]");
84 assertSame("probe[" + i +"], probe[" + (i + MAX) +"]", probe[i], probe[i + MAX]);
8785 for (int j = 1; j < MAX - 1; j++) {
88 assertNotSame(probe[i], probe[i + j], "probe[" + i +"], probe[" + (i + j) +"]");
86 assertNotSame("probe[" + i +"], probe[" + (i + j) +"]", probe[i], probe[i + j]);
8987 }
9088 }
9189 }
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-api-java9</artifactId>
3333 </properties>
3434 <dependencies>
3535 <dependency>
36 <groupId>org.junit.jupiter</groupId>
37 <artifactId>junit-jupiter-engine</artifactId>
36 <groupId>junit</groupId>
37 <artifactId>junit</artifactId>
38 <scope>test</scope>
3839 </dependency>
3940 <dependency>
4041 <groupId>org.apache.maven</groupId>
4748 <plugin>
4849 <groupId>org.apache.maven.plugins</groupId>
4950 <artifactId>maven-toolchains-plugin</artifactId>
50 <version>3.0.0</version>
51 <version>1.1</version>
5152 <executions>
5253 <execution>
5354 <goals>
143144 <skip>true</skip>
144145 </configuration>
145146 </plugin>
146 <plugin>
147 <groupId>org.apache.maven.plugins</groupId>
148 <artifactId>maven-site-plugin</artifactId>
149 <version>${site.plugin.version}</version>
150 <configuration>
151 <skip>true</skip>
152 <skipDeploy>true</skipDeploy>
153 </configuration>
154 </plugin>
155147 </plugins>
156148 </build>
157149 </project>
3333
3434 private final static StackLocator INSTANCE = new StackLocator();
3535
36 private final static ThreadLocal<String> FQCN = new ThreadLocal<>();
37 private final static FqcnCallerLocator LOCATOR = new FqcnCallerLocator();
38
3639 public static StackLocator getInstance() {
3740 return INSTANCE;
3841 }
4043 private StackLocator() {
4144 }
4245
43 public Class<?> getCallerClass(final Class<?> sentinelClass, final Predicate<Class<?>> callerPredicate) {
44 if (sentinelClass == null) {
45 throw new IllegalArgumentException("sentinelClass cannot be null");
46 }
47 if (callerPredicate == null) {
48 throw new IllegalArgumentException("callerPredicate cannot be null");
49 }
50 return walker.walk(s -> s
51 .map(StackWalker.StackFrame::getDeclaringClass)
52 // Skip until the sentinel class is found
53 .dropWhile(clazz -> !sentinelClass.equals(clazz))
54 // Skip until the predicate evaluates to true, also ignoring recurrences of the sentinel
55 .dropWhile(clazz -> sentinelClass.equals(clazz) || !callerPredicate.test(clazz))
56 .findFirst().orElse(null));
57 }
58
5946 public Class<?> getCallerClass(final String fqcn) {
6047 return getCallerClass(fqcn, "");
6148 }
6249
6350 public Class<?> getCallerClass(final String fqcn, final String pkg) {
64 return walker.walk(s -> s
65 .dropWhile(f -> !f.getClassName().equals(fqcn))
66 .dropWhile(f -> f.getClassName().equals(fqcn))
67 .dropWhile(f -> !f.getClassName().startsWith(pkg))
68 .findFirst())
69 .map(StackWalker.StackFrame::getDeclaringClass)
70 .orElse(null);
51 return walker.walk(s -> s.dropWhile(f -> !f.getClassName().equals(fqcn)).
52 dropWhile(f -> f.getClassName().equals(fqcn)).dropWhile(f -> !f.getClassName().startsWith(pkg)).
53 findFirst()).map(StackWalker.StackFrame::getDeclaringClass).orElse(null);
7154 }
7255
7356 public Class<?> getCallerClass(final Class<?> anchor) {
7760 }
7861
7962 public Class<?> getCallerClass(final int depth) {
63 ;
8064 return walker.walk(s -> s.skip(depth).findFirst()).map(StackWalker.StackFrame::getDeclaringClass).orElse(null);
8165 }
8266
9276 }
9377
9478 public StackTraceElement calcLocation(final String fqcnOfLogger) {
95 return stackWalker.walk(
96 s -> s.dropWhile(f -> !f.getClassName().equals(fqcnOfLogger)) // drop the top frames until we reach the logger
97 .dropWhile(f -> f.getClassName().equals(fqcnOfLogger)) // drop the logger frames
98 .findFirst()).map(StackWalker.StackFrame::toStackTraceElement).orElse(null);
79 FQCN.set(fqcnOfLogger);
80 StackTraceElement element = walker.walk(LOCATOR).toStackTraceElement();
81 FQCN.set(null);
82 return element;
9983 }
10084
10185 public StackTraceElement getStackTraceElement(final int depth) {
102 return stackWalker.walk(s -> s.skip(depth).findFirst())
103 .map(StackWalker.StackFrame::toStackTraceElement).orElse(null);
86 return stackWalker.walk(s -> s.skip(depth).findFirst()).get().toStackTraceElement();
87 }
88
89 static final class FqcnCallerLocator implements Function<Stream<StackWalker.StackFrame>, StackWalker.StackFrame> {
90
91 @Override
92 public StackWalker.StackFrame apply(Stream<StackWalker.StackFrame> stackFrameStream) {
93 String fqcn = FQCN.get();
94 boolean foundFqcn = false;
95 Object[] frames = stackFrameStream.toArray();
96 for (int i = 0; i < frames.length ; ++i) {
97 final String className = ((StackWalker.StackFrame) frames[i]).getClassName();
98 if (!foundFqcn) {
99 // Skip frames until we find the FQCN
100 foundFqcn = className.equals(fqcn);
101 } else if (!className.equals(fqcn)) {
102 // The frame is no longer equal to the FQCN so it is the one we want.
103 return (StackWalker.StackFrame) frames[i];
104 } // Otherwise it is equal to the FQCN so we need to skip it.
105 }
106 // Should never happen
107 return null;
108 }
104109 }
105110 }
+0
-22
log4j-api-java9/src/test/java/module-info.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 open module org.apache.logging.log4j.java9test {
17 exports org.apache.logging.log4j.util.java9;
18 requires org.apache.logging.log4j;
19 requires transitive org.junit.jupiter.engine;
20 requires transitive org.junit.jupiter.api;
21 }
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.util;
17
18 import org.junit.Test;
19 import static org.junit.Assert.assertFalse;
20
21 public class ProcessIdUtilTest {
22
23 @Test
24 public void processIdTest() throws Exception {
25 String processId = ProcessIdUtil.getProcessId();
26 assertFalse("ProcessId is default", processId.equals(ProcessIdUtil.DEFAULT_PROCESSID));
27 }
28 }
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.util;
17
18 import org.junit.BeforeClass;
19 import org.junit.Test;
20 import org.junit.runner.RunWith;
21 import org.junit.runners.BlockJUnit4ClassRunner;
22 import org.junit.runners.ParentRunner;
23
24 import java.util.Stack;
25
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertSame;
29
30 @RunWith(BlockJUnit4ClassRunner.class)
31 public class StackLocatorTest {
32
33 private static StackLocator stackLocator;
34
35 @BeforeClass
36 public static void setupClass() {
37
38 stackLocator = StackLocator.getInstance();
39 }
40
41 @Test
42 public void testGetCallerClass() throws Exception {
43 final Class<?> expected = StackLocatorTest.class;
44 final Class<?> actual = stackLocator.getCallerClass(1);
45 assertSame(expected, actual);
46 }
47
48 @Test
49 public void testGetCallerClassNameViaStackTrace() throws Exception {
50 final Class<?> expected = StackLocatorTest.class;
51 final Class<?> actual = Class.forName(new Throwable().getStackTrace()[0].getClassName());
52 assertSame(expected, actual);
53 }
54
55 @Test
56 public void testGetCurrentStackTrace() throws Exception {
57 final Stack<Class<?>> classes = stackLocator.getCurrentStackTrace();
58 final Stack<Class<?>> reversed = new Stack<>();
59 reversed.ensureCapacity(classes.size());
60 while (!classes.empty()) {
61 reversed.push(classes.pop());
62 }
63 while (reversed.peek() != StackLocator.class) {
64 reversed.pop();
65 }
66 reversed.pop(); // ReflectionUtil
67 assertSame(StackLocatorTest.class, reversed.pop());
68 }
69
70 @Test
71 public void testGetCallerClassViaName() throws Exception {
72 final Class<?> expected = BlockJUnit4ClassRunner.class;
73 final Class<?> actual = stackLocator.getCallerClass("org.junit.runners.ParentRunner");
74 // if this test fails in the future, it's probably because of a JUnit upgrade; check the new stack trace and
75 // update this test accordingly
76 assertSame(expected, actual);
77 }
78
79 @Test
80 public void testGetCallerClassViaAnchorClass() throws Exception {
81 final Class<?> expected = BlockJUnit4ClassRunner.class;
82 final Class<?> actual = stackLocator.getCallerClass(ParentRunner.class);
83 // if this test fails in the future, it's probably because of a JUnit upgrade; check the new stack trace and
84 // update this test accordingly
85 assertSame(expected, actual);
86 }
87
88 @Test
89 public void testLocateClass() {
90 ClassLocator locator = new ClassLocator();
91 Class<?> clazz = locator.locateClass();
92 assertNotNull("Could not locate class", clazz);
93 assertEquals("Incorrect class", this.getClass(), clazz);
94 }
95
96 private final class Foo {
97
98 private StackTraceElement foo() {
99 return new Bar().bar();
100 }
101
102 }
103
104 private final class Bar {
105
106 private StackTraceElement bar() {
107 return baz();
108 }
109
110 private StackTraceElement baz() {
111 return quux();
112 }
113
114 }
115
116 private StackTraceElement quux() {
117 return stackLocator.calcLocation("org.apache.logging.log4j.util.StackLocatorTest$Bar");
118 }
119
120 @Test
121 public void testCalcLocation() {
122 /*
123 * We are setting up a stack trace that looks like:
124 * - org.apache.logging.log4j.util.StackLocatorTest#quux(line:118)
125 * - org.apache.logging.log4j.util.StackLocatorTest$Bar#baz(line:112)
126 * - org.apache.logging.log4j.util.StackLocatorTest$Bar#bar(line:108)
127 * - org.apache.logging.log4j.util.StackLocatorTest$Foo(line:100)
128 *
129 * We are pretending that org.apache.logging.log4j.util.StackLocatorTest$Bar is the logging class, and
130 * org.apache.logging.log4j.util.StackLocatorTest$Foo is where the log line emanated.
131 */
132 final StackTraceElement element = new Foo().foo();
133 assertEquals("org.apache.logging.log4j.util.StackLocatorTest$Foo", element.getClassName());
134 assertEquals(100, element.getLineNumber());
135 }
136
137 class ClassLocator {
138
139 public Class<?> locateClass() {
140 return stackLocator.getCallerClass(ClassLocator.class);
141 }
142 }
143
144 }
+0
-31
log4j-api-java9/src/test/java/org/apache/logging/log4j/util/java9/ProcessIdUtilTest.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.logging.log4j.util.java9;
17
18 import org.apache.logging.log4j.util.ProcessIdUtil;
19 import org.junit.jupiter.api.Test;
20
21 import static org.junit.jupiter.api.Assertions.assertNotEquals;
22
23 public class ProcessIdUtilTest {
24
25 @Test
26 public void processIdTest() {
27 String processId = ProcessIdUtil.getProcessId();
28 assertNotEquals(processId, ProcessIdUtil.DEFAULT_PROCESSID, "ProcessId is default");
29 }
30 }
+0
-150
log4j-api-java9/src/test/java/org/apache/logging/log4j/util/java9/StackLocatorTest.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.logging.log4j.util.java9;
17
18 import org.apache.logging.log4j.util.StackLocator;
19 import org.junit.jupiter.api.Test;
20
21 import java.util.Stack;
22
23 import static org.junit.jupiter.api.Assertions.*;
24
25 public class StackLocatorTest {
26
27 @Test
28 public void testGetCallerClass() {
29 final Class<?> expected = StackLocatorTest.class;
30 final StackLocator stackLocator = StackLocator.getInstance();
31 final Class<?> actual = stackLocator.getCallerClass(1);
32 assertSame(expected, actual);
33 }
34
35 @Test
36 public void testGetCallerClassNameViaStackTrace() throws Exception {
37 final Class<?> expected = StackLocatorTest.class;
38 final Class<?> actual = Class.forName(new Throwable().getStackTrace()[0].getClassName());
39 assertSame(expected, actual);
40 }
41
42 @Test
43 public void testGetCurrentStackTrace() {
44 final StackLocator stackLocator = StackLocator.getInstance();
45 final Stack<Class<?>> classes = stackLocator.getCurrentStackTrace();
46 final Stack<Class<?>> reversed = new Stack<>();
47 reversed.ensureCapacity(classes.size());
48 while (!classes.empty()) {
49 reversed.push(classes.pop());
50 }
51 while (reversed.peek() != StackLocator.class) {
52 reversed.pop();
53 }
54 reversed.pop(); // ReflectionUtil
55 assertSame(StackLocatorTest.class, reversed.pop());
56 }
57
58 @Test
59 public void testGetCallerClassViaName() {
60 Inner.assertCallerClassViaName();
61 }
62
63 @Test
64 public void testGetCallerClassViaAnchorClass() {
65 Inner.assertCallerClassViaAnchorClass();
66 }
67
68 private static class Inner {
69 private static void assertCallerClassViaName() {
70 final Class<?> expected = StackLocatorTest.class;
71 final StackLocator stackLocator = StackLocator.getInstance();
72 final Class<?> actual = stackLocator.getCallerClass(Inner.class.getName());
73 assertSame(expected, actual);
74 }
75
76 private static void assertCallerClassViaAnchorClass() {
77 final Class<?> expected = StackLocatorTest.class;
78 final StackLocator stackLocator = StackLocator.getInstance();
79 final Class<?> actual = stackLocator.getCallerClass(Inner.class);
80 assertSame(expected, actual);
81 }
82 }
83
84 @Test
85 public void testLocateClass() {
86 ClassLocator locator = new ClassLocator();
87 Class<?> clazz = locator.locateClass();
88 assertNotNull(clazz, "Could not locate class");
89 assertEquals(this.getClass(), clazz, "Incorrect class");
90 }
91
92 private final class Foo {
93
94 private StackTraceElement foo() {
95 return new Bar().bar(); // <--- testCalcLocation() line
96 }
97
98 }
99
100 private final class Bar {
101
102 private StackTraceElement bar() {
103 return baz();
104 }
105
106 private StackTraceElement baz() {
107 return quux();
108 }
109
110 }
111
112 private StackTraceElement quux() {
113 final StackLocator stackLocator = StackLocator.getInstance();
114 return stackLocator.calcLocation("org.apache.logging.log4j.util.java9.StackLocatorTest$Bar");
115 }
116
117 @Test
118 public void testCalcLocation() {
119 /*
120 * We are setting up a stack trace that looks like:
121 * - org.apache.logging.log4j.util.test.StackLocatorTest#quux(line:118)
122 * - org.apache.logging.log4j.util.test.StackLocatorTest$Bar#baz(line:112)
123 * - org.apache.logging.log4j.util.test.StackLocatorTest$Bar#bar(line:108)
124 * - org.apache.logging.log4j.util.test.StackLocatorTest$Foo(line:100)
125 *
126 * We are pretending that org.apache.logging.log4j.util.test.StackLocatorTest$Bar is the logging class, and
127 * org.apache.logging.log4j.util.test.StackLocatorTest$Foo is where the log line emanated.
128 */
129 final StackTraceElement element = new Foo().foo();
130 assertEquals("org.apache.logging.log4j.util.java9.StackLocatorTest$Foo", element.getClassName());
131 assertEquals(96, element.getLineNumber());
132 }
133
134 @Test
135 public void testCalcLocationWhenNotInTheStack() {
136 final StackLocator stackLocator = StackLocator.getInstance();
137 final StackTraceElement stackTraceElement = stackLocator.calcLocation("java.util.Logger");
138 assertNull(stackTraceElement);
139 }
140
141 static class ClassLocator {
142
143 public Class<?> locateClass() {
144 final StackLocator stackLocator = StackLocator.getInstance();
145 return stackLocator.getCallerClass(ClassLocator.class);
146 }
147 }
148
149 }
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
3535 <tomcat.version>8.5.20</tomcat.version>
3636 <jetty.version>8.2.0.v20160908</jetty.version> <!-- Jetty 9 requires Java 8 -->
3737 <module.name>org.apache.logging.log4j.appserver</module.name>
38 <maven.doap.skip>true</maven.doap.skip>
3938 </properties>
4039
4140 <dependencies>
8887 <scope>test</scope>
8988 </dependency>
9089 <dependency>
91 <groupId>org.junit.vintage</groupId>
92 <artifactId>junit-vintage-engine</artifactId>
93 </dependency>
94 <dependency>
95 <groupId>org.junit.jupiter</groupId>
96 <artifactId>junit-jupiter-engine</artifactId>
90 <groupId>junit</groupId>
91 <artifactId>junit</artifactId>
92 <scope>test</scope>
9793 </dependency>
9894 <dependency>
9995 <groupId>org.springframework</groupId>
180176 </reportSets>
181177 </plugin>
182178 <plugin>
183 <groupId>com.github.spotbugs</groupId>
184 <artifactId>spotbugs-maven-plugin</artifactId>
179 <groupId>org.codehaus.mojo</groupId>
180 <artifactId>findbugs-maven-plugin</artifactId>
181 <version>${findbugs.plugin.version}</version>
182 <configuration>
183 <fork>true</fork>
184 <jvmArgs>-Duser.language=en</jvmArgs>
185 <threshold>Normal</threshold>
186 <effort>Default</effort>
187 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
188 </configuration>
185189 </plugin>
186190 <plugin>
187191 <groupId>org.apache.maven.plugins</groupId>
7171 }
7272
7373 public Log4j2Logger(final String name) {
74 super();
7475 this.name = name;
7576 this.logger = PrivateManager.getLogger(name);
7677 }
1818 <parent>
1919 <groupId>org.apache.logging</groupId>
2020 <artifactId>logging-parent</artifactId>
21 <version>3</version>
21 <version>1</version>
2222 </parent>
2323 <modelVersion>4.0.0</modelVersion>
2424 <name>Apache Log4j BOM</name>
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.12.3</version>
2929 <packaging>pom</packaging>
3030 <dependencyManagement>
3131 <dependencies>
3939 <dependency>
4040 <groupId>org.apache.logging.log4j</groupId>
4141 <artifactId>log4j-core</artifactId>
42 <version>${project.version}</version>
43 </dependency>
44 <!-- JSON template layout -->
45 <dependency>
46 <groupId>org.apache.logging.log4j</groupId>
47 <artifactId>log4j-layout-template-json</artifactId>
4842 <version>${project.version}</version>
4943 </dependency>
5044 <!-- Legacy Log4j 1.2 API -->
113107 <artifactId>log4j-couchdb</artifactId>
114108 <version>${project.version}</version>
115109 </dependency>
116 <!-- MongoDB 4 Appender Plugin -->
110 <!-- MongoDB 2 Appender Plugin -->
117111 <dependency>
118112 <groupId>org.apache.logging.log4j</groupId>
119 <artifactId>log4j-mongodb4</artifactId>
113 <artifactId>log4j-mongodb2</artifactId>
120114 <version>${project.version}</version>
121115 </dependency>
122116 <!-- MongoDB 3 Appender Plugin -->
149143 <artifactId>log4j-jul</artifactId>
150144 <version>${project.version}</version>
151145 </dependency>
152 <!-- Java System Platform Loggerr -->
153 <dependency>
154 <groupId>org.apache.logging.log4j</groupId>
155 <artifactId>log4j-jpl</artifactId>
156 <version>${project.version}</version>
157 </dependency>
158 <!-- Liquibase adapter -->
146 <!-- java.util.logging adapter -->
159147 <dependency>
160148 <groupId>org.apache.logging.log4j</groupId>
161149 <artifactId>log4j-liquibase</artifactId>
165153 <dependency>
166154 <groupId>org.apache.logging.log4j</groupId>
167155 <artifactId>log4j-docker</artifactId>
168 <version>${project.version}</version>
169 </dependency>
170 <!-- Kubernetes support -->
171 <dependency>
172 <groupId>org.apache.logging.log4j</groupId>
173 <artifactId>log4j-kubernetes</artifactId>
174 <version>${project.version}</version>
175 </dependency>
176 <!-- Spring Boot support -->
177 <dependency>
178 <groupId>org.apache.logging.log4j</groupId>
179 <artifactId>log4j-spring-boot</artifactId>
180156 <version>${project.version}</version>
181157 </dependency>
182158 <!-- Spring Cloud Config Client -->
216192 </build>
217193
218194 <scm>
219 <tag>log4j-2.17.0-rc1</tag>
195 <tag>log4j-2.12.3-rc1</tag>
220196 </scm>
221197 </project>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
3333 <docLabel>Cassandra Documentation</docLabel>
3434 <projectDir>/log4j-cassandra</projectDir>
3535 <module.name>org.apache.logging.log4j.cassandra</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
3736 </properties>
3837
3938 <dependencies>
4746 </dependency>
4847 <!-- Test Dependencies -->
4948 <dependency>
50 <groupId>org.junit.vintage</groupId>
51 <artifactId>junit-vintage-engine</artifactId>
52 </dependency>
53 <dependency>
54 <groupId>org.junit.jupiter</groupId>
55 <artifactId>junit-jupiter-engine</artifactId>
49 <groupId>junit</groupId>
50 <artifactId>junit</artifactId>
5651 </dependency>
5752 <dependency>
5853 <groupId>org.mockito</groupId>
161156 </reportSets>
162157 </plugin>
163158 <plugin>
164 <groupId>com.github.spotbugs</groupId>
165 <artifactId>spotbugs-maven-plugin</artifactId>
159 <groupId>org.codehaus.mojo</groupId>
160 <artifactId>findbugs-maven-plugin</artifactId>
161 <version>${findbugs.plugin.version}</version>
162 <configuration>
163 <fork>true</fork>
164 <jvmArgs>-Duser.language=en</jvmArgs>
165 <threshold>Normal</threshold>
166 <effort>Default</effort>
167 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
168 </configuration>
166169 </plugin>
167170 <plugin>
168171 <groupId>org.apache.maven.plugins</groupId>
2929 import org.apache.logging.log4j.categories.Appenders;
3030 import org.apache.logging.log4j.junit.LoggerContextRule;
3131 import org.junit.ClassRule;
32 import org.junit.Ignore;
3332 import org.junit.Test;
3433 import org.junit.experimental.categories.Category;
3534 import org.junit.rules.RuleChain;
4039 * Integration test for CassandraAppender.
4140 */
4241 @Category(Appenders.Cassandra.class)
43 @Ignore("Does not work on aarch64")
4442 public class CassandraAppenderIT {
4543
4644 private static final String DDL = "CREATE TABLE logs (" +
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-core</artifactId>
3030 <log4jParentDir>${basedir}/..</log4jParentDir>
3131 <docLabel>Core Documentation</docLabel>
3232 <projectDir>/core</projectDir>
33 <maven.doap.skip>true</maven.doap.skip>
3433 <!--<revapi.skip>true</revapi.skip>-->
3534 </properties>
3635 <dependencies>
5554 <dependency>
5655 <groupId>com.conversantmedia</groupId>
5756 <artifactId>disruptor</artifactId>
57 <classifier>jdk7</classifier>
5858 <optional>true</optional>
5959 </dependency>
6060 <!-- Alternative implementation of BlockingQueue using JCTools for AsyncAppender -->
8787 <artifactId>jackson-dataformat-xml</artifactId>
8888 <optional>true</optional>
8989 </dependency>
90 <!-- POM for jackson-dataformat-xml depends on woodstox-core -->
90 <!-- POM for jackson-dataformat-xml 2.9.2 depends on woodstox-core 5.0.3 -->
9191 <dependency>
9292 <groupId>com.fasterxml.woodstox</groupId>
9393 <artifactId>woodstox-core</artifactId>
94 <version>${woodstox.version}</version>
94 <version>5.0.3</version>
9595 <optional>true</optional>
9696 </dependency>
9797 <!-- Required for console color support in Windows -->
135135 <dependency>
136136 <groupId>org.apache.commons</groupId>
137137 <artifactId>commons-csv</artifactId>
138 <optional>true</optional>
139 </dependency>
140 <!-- Kafka needs slf4j -->
141 <dependency>
142 <groupId>org.slf4j</groupId>
143 <artifactId>slf4j-api</artifactId>
144138 <optional>true</optional>
145139 </dependency>
146140
163157 <dependency>
164158 <groupId>org.jmdns</groupId>
165159 <artifactId>jmdns</artifactId>
166 <version>3.5.7</version>
160 <version>3.5.3</version>
167161 <scope>test</scope>
168162 </dependency>
169163 <!-- Log4j 1.2 tests -->
176170 <!-- SLF4J tests -->
177171 <dependency>
178172 <groupId>org.slf4j</groupId>
173 <artifactId>slf4j-api</artifactId>
174 <scope>test</scope>
175 </dependency>
176 <dependency>
177 <groupId>org.slf4j</groupId>
179178 <artifactId>slf4j-ext</artifactId>
180179 <scope>test</scope>
181180 </dependency>
182181 <!-- JUnit, naturally -->
183182 <dependency>
184 <groupId>org.junit.vintage</groupId>
185 <artifactId>junit-vintage-engine</artifactId>
186 </dependency>
187 <dependency>
188 <groupId>org.junit.jupiter</groupId>
189 <artifactId>junit-jupiter-engine</artifactId>
190 </dependency>
191 <dependency>
192 <groupId>org.junit.jupiter</groupId>
193 <artifactId>junit-jupiter-params</artifactId>
183 <groupId>junit</groupId>
184 <artifactId>junit</artifactId>
185 <scope>test</scope>
194186 </dependency>
195187 <dependency>
196188 <groupId>org.hamcrest</groupId>
197 <artifactId>hamcrest</artifactId>
189 <artifactId>hamcrest-all</artifactId>
198190 <scope>test</scope>
199191 </dependency>
200192 <!-- Mocking framework for use with JUnit -->
201193 <dependency>
202194 <groupId>org.mockito</groupId>
203195 <artifactId>mockito-core</artifactId>
204 </dependency>
205 <dependency>
206 <groupId>org.mockito</groupId>
207 <artifactId>mockito-junit-jupiter</artifactId>
196 <scope>test</scope>
208197 </dependency>
209198 <!-- Embedded JDBC drivers for database appender tests -->
210199 <dependency>
334323 <dependency>
335324 <groupId>org.hdrhistogram</groupId>
336325 <artifactId>HdrHistogram</artifactId>
337 <scope>test</scope>
338 </dependency>
339 <dependency>
340 <groupId>org.awaitility</groupId>
341 <artifactId>awaitility</artifactId>
342 <scope>test</scope>
343 </dependency>
344 <dependency>
345 <groupId>org.zapodot</groupId>
346 <artifactId>embedded-ldap-junit</artifactId>
347326 <scope>test</scope>
348327 </dependency>
349328 </dependencies>
597576 </reportSets>
598577 </plugin>
599578 <plugin>
600 <groupId>com.github.spotbugs</groupId>
601 <artifactId>spotbugs-maven-plugin</artifactId>
579 <groupId>org.codehaus.mojo</groupId>
580 <artifactId>findbugs-maven-plugin</artifactId>
581 <version>${findbugs.plugin.version}</version>
582 <configuration>
583 <fork>true</fork>
584 <jvmArgs>-Duser.language=en</jvmArgs>
585 <threshold>Normal</threshold>
586 <effort>Default</effort>
587 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
588 </configuration>
602589 </plugin>
603590 <plugin>
604591 <groupId>org.apache.maven.plugins</groupId>
108108 "justification": "LOG4J2-2491 - Allow all appenders to optionally carry a property array"
109109 },
110110 {
111 "code": "java.method.parameterTypeChanged",
112 "old": "parameter java.nio.file.FileVisitResult java.nio.file.SimpleFileVisitor<T>::visitFileFailed(===T===, java.io.IOException) throws java.io.IOException @ org.apache.logging.log4j.core.appender.rolling.action.DeletingVisitor",
113 "new": "parameter java.nio.file.FileVisitResult org.apache.logging.log4j.core.appender.rolling.action.DeletingVisitor::visitFileFailed(===java.nio.file.Path===, java.io.IOException) throws java.io.IOException",
114 "justification": "Class overrides a type with generics, in practice there is no change."
115 },
116 {
117 "code": "java.method.parameterTypeChanged",
118 "old": "parameter java.nio.file.FileVisitResult java.nio.file.SimpleFileVisitor<T>::visitFileFailed(===T===, java.io.IOException) throws java.io.IOException @ org.apache.logging.log4j.core.appender.rolling.action.SortingVisitor",
119 "new": "parameter java.nio.file.FileVisitResult org.apache.logging.log4j.core.appender.rolling.action.SortingVisitor::visitFileFailed(===java.nio.file.Path===, java.io.IOException) throws java.io.IOException",
120 "justification": "Class overrides a type with generics, in practice there is no change."
121 },
122 {
123111 "code": "java.annotation.removed",
124112 "old": "method org.apache.logging.log4j.core.appender.SmtpAppender org.apache.logging.log4j.core.appender.SmtpAppender::createAppender(org.apache.logging.log4j.core.config.Configuration, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>, org.apache.logging.log4j.core.Filter, java.lang.String)",
125113 "new": "method org.apache.logging.log4j.core.appender.SmtpAppender org.apache.logging.log4j.core.appender.SmtpAppender::createAppender(org.apache.logging.log4j.core.config.Configuration, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, org.apache.logging.log4j.core.Layout<? extends java.io.Serializable>, org.apache.logging.log4j.core.Filter, java.lang.String)",
145133 "new": "parameter org.apache.logging.log4j.core.net.ssl.SslConfiguration org.apache.logging.log4j.core.net.ssl.SslConfiguration::createSSLConfiguration(java.lang.String, org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration, org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration, ===boolean===)",
146134 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginElement(\"verifyHostName\")",
147135 "justification": "LOG4J2-TODO"
148 },
149 {
150 "code": "java.class.defaultSerializationChanged",
151 "old": "class org.apache.logging.log4j.core.time.MutableInstant",
152 "new": "class org.apache.logging.log4j.core.time.MutableInstant",
153 "justification": "LOG4J2-3075 MutableInstant extends from TemporalAccessor"
154 },
155 {
156 "code": "java.class.removed",
157 "old": "class org.apache.logging.log4j.core.util.SetUtils",
158 "justification": "only used by web modules"
159 },
160 {
161 "code": "java.method.removed",
162 "old": "method org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>>::setAllowedJndiProtocols(java.lang.String)",
163 "justification": "Removed allowing additional protocols to be added"
164 },
165 {
166 "code": "java.method.removed",
167 "old": "method org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>>::setAllowedLdapClasses(java.lang.String)",
168 "justification": "Removed LDAP support"
169 },
170 {
171 "code": "java.method.removed",
172 "old": "method org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B extends org.apache.logging.log4j.core.appender.mom.JmsAppender.Builder<B>>>::setAllowedLdapHosts(java.lang.String)",
173 "justification": "Removed LDAP support"
174 },
175 {
176 "code": "java.field.removedWithConstant",
177 "old": "field org.apache.logging.log4j.core.net.JndiManager.ALLOWED_CLASSES",
178 "justification": "Removed LDAP support"
179 },
180 {
181 "code": "java.field.removedWithConstant",
182 "old": "field org.apache.logging.log4j.core.net.JndiManager.ALLOWED_HOSTS",
183 "justification": "Removed LDAP support"
184 },
185 {
186 "code": "java.field.removedWithConstant",
187 "old": "field org.apache.logging.log4j.core.net.JndiManager.ALLOWED_PROTOCOLS",
188 "justification": "Removed allowing additional protocols"
189136 }
190137 ]
191138 }
2626 /**
2727 * Responsible for initializing the context data of LogEvents. Context data is data that is set by the application to be
2828 * included in all subsequent log events.
29 * <p><b>NOTE: It is no longer recommended that custom implementations of this interface be provided as it is
30 * difficult to do. Instead, provide a custom ContextDataProvider.</b></p>
31 * <p>
3229 * <p>
3330 * The source of the context data is implementation-specific. The default source for context data is the ThreadContext.
3431 * </p><p>
3232 public interface Filter extends LifeCycle {
3333
3434 /**
35 * The empty array.
36 */
37 Filter[] EMPTY_ARRAY = {};
38
39 /**
4035 * Main {@linkplain org.apache.logging.log4j.core.config.plugins.Plugin#elementType() plugin element type} for
4136 * Filter plugins.
4237 *
2929 import org.apache.logging.log4j.core.config.LoggerConfig;
3030 import org.apache.logging.log4j.core.config.ReliabilityStrategy;
3131 import org.apache.logging.log4j.core.filter.CompositeFilter;
32 import org.apache.logging.log4j.core.impl.LocationAware;
3233 import org.apache.logging.log4j.message.Message;
3334 import org.apache.logging.log4j.message.MessageFactory;
3435 import org.apache.logging.log4j.message.SimpleMessage;
2121 import java.beans.PropertyChangeListener;
2222 import java.io.File;
2323 import java.net.URI;
24 import java.util.ArrayList;
2425 import java.util.Collection;
26 import java.util.Collections;
2527 import java.util.List;
2628 import java.util.Objects;
27 import java.util.concurrent.ConcurrentHashMap;
2829 import java.util.concurrent.ConcurrentMap;
2930 import java.util.concurrent.CopyOnWriteArrayList;
3031 import java.util.concurrent.TimeUnit;
4041 import org.apache.logging.log4j.core.config.NullConfiguration;
4142 import org.apache.logging.log4j.core.config.Reconfigurable;
4243 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
43 import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
4444 import org.apache.logging.log4j.core.jmx.Server;
4545 import org.apache.logging.log4j.core.util.Cancellable;
4646 import org.apache.logging.log4j.core.util.ExecutorServices;
8585
8686 private final LoggerRegistry<Logger> loggerRegistry = new LoggerRegistry<>();
8787 private final CopyOnWriteArrayList<PropertyChangeListener> propertyChangeListeners = new CopyOnWriteArrayList<>();
88 private volatile List<LoggerContextShutdownAware> listeners;
88 private volatile List<LoggerContextShutdownAware> listeners = null;
8989
9090 /**
9191 * The Configuration is volatile to guarantee that initialization of the Configuration has completed before the
9292 * reference is updated.
9393 */
9494 private volatile Configuration configuration = new DefaultConfiguration();
95 private static final String EXTERNAL_CONTEXT_KEY = "__EXTERNAL_CONTEXT_KEY__";
96 private ConcurrentMap<String, Object> externalMap = new ConcurrentHashMap<>();
95 private Object externalContext;
9796 private String contextName;
9897 private volatile URI configLocation;
9998 private Cancellable shutdownCallback;
128127 */
129128 public LoggerContext(final String name, final Object externalContext, final URI configLocn) {
130129 this.contextName = name;
131 if (externalContext == null) {
132 externalMap.remove(EXTERNAL_CONTEXT_KEY);
133 } else {
134 externalMap.put(EXTERNAL_CONTEXT_KEY, externalContext);
135 }
130 this.externalContext = externalContext;
136131 this.configLocation = configLocn;
137 Thread runner = new Thread(new ThreadContextDataTask(), "Thread Context Data Task");
138 runner.setDaemon(true);
139 runner.start();
140132 }
141133
142134 /**
149141 */
150142 public LoggerContext(final String name, final Object externalContext, final String configLocn) {
151143 this.contextName = name;
152 if (externalContext == null) {
153 externalMap.remove(EXTERNAL_CONTEXT_KEY);
154 } else {
155 externalMap.put(EXTERNAL_CONTEXT_KEY, externalContext);
156 }
144 this.externalContext = externalContext;
157145 if (configLocn != null) {
158146 URI uri;
159147 try {
165153 } else {
166154 configLocation = null;
167155 }
168 Thread runner = new Thread(new ThreadContextDataTask(), "Thread Context Data Task");
169 runner.setDaemon(true);
170 runner.start();
171 }
172
173 @Override
156 }
157
174158 public void addShutdownListener(LoggerContextShutdownAware listener) {
175159 if (listeners == null) {
176160 synchronized(this) {
177161 if (listeners == null) {
178 listeners = new CopyOnWriteArrayList<LoggerContextShutdownAware>();
162 listeners = Collections.synchronizedList(new ArrayList<LoggerContextShutdownAware>());
179163 }
180164 }
181165 }
182166 listeners.add(listener);
183167 }
184168
185 @Override
186169 public List<LoggerContextShutdownAware> getListeners() {
187170 return listeners;
188171 }
392375 } else {
393376 prev.stop();
394377 }
395 externalMap.clear();
378 externalContext = null;
396379 LogManager.getFactory().removeContext(this);
397380 } finally {
398381 configLock.unlock();
439422 contextName = Objects.requireNonNull(name);
440423 }
441424
442 @Override
443 public Object getObject(String key) {
444 return externalMap.get(key);
445 }
446
447 @Override
448 public Object putObject(String key, Object value) {
449 return externalMap.put(key, value);
450 }
451
452 @Override
453 public Object putObjectIfAbsent(String key, Object value) {
454 return externalMap.putIfAbsent(key, value);
455 }
456
457 @Override
458 public Object removeObject(String key) {
459 return externalMap.remove(key);
460 }
461
462 @Override
463 public boolean removeObject(String key, Object value) {
464 return externalMap.remove(key, value);
465 }
466
467425 /**
468426 * Sets the external context.
469427 *
470428 * @param context The external context.
471429 */
472430 public void setExternalContext(final Object context) {
473 if (context != null) {
474 this.externalMap.put(EXTERNAL_CONTEXT_KEY, context);
475 } else {
476 this.externalMap.remove(EXTERNAL_CONTEXT_KEY);
477 }
431 this.externalContext = context;
478432 }
479433
480434 /**
484438 */
485439 @Override
486440 public Object getExternalContext() {
487 return this.externalMap.get(EXTERNAL_CONTEXT_KEY);
441 return this.externalContext;
488442 }
489443
490444 /**
615569 final ConcurrentMap<String, String> map = config.getComponent(Configuration.CONTEXT_PROPERTIES);
616570
617571 try { // LOG4J2-719 network access may throw android.os.NetworkOnMainThreadException
618 // LOG4J2-2808 don't block unless necessary
619 map.computeIfAbsent("hostName", s -> NetUtils.getLocalHostname());
572 map.putIfAbsent("hostName", NetUtils.getLocalHostname());
620573 } catch (final Exception ex) {
621574 LOGGER.debug("Ignoring {}, setting hostName to 'unknown'", ex.toString());
622575 map.putIfAbsent("hostName", "unknown");
687640 * Reconfigures the context.
688641 */
689642 private void reconfigure(final URI configURI) {
690 Object externalContext = externalMap.get(EXTERNAL_CONTEXT_KEY);
691643 final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null;
692644 LOGGER.debug("Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}",
693645 contextName, configURI, this, cl);
715667 reconfigure(configLocation);
716668 }
717669
718 public void reconfigure(Configuration configuration) {
719 setConfiguration(configuration);
720 ConfigurationSource source = configuration.getConfigurationSource();
721 if (source != null) {
722 URI uri = source.getURI();
723 if (uri != null) {
724 configLocation = uri;
725 }
726 }
727 }
728
729670 /**
730671 * Causes all Loggers to be updated against the current Configuration.
731672 */
776717 return new Logger(ctx, name, messageFactory);
777718 }
778719
779 private class ThreadContextDataTask implements Runnable {
780
781 @Override
782 public void run() {
783 LOGGER.debug("Initializing Thread Context Data Service Providers");
784 ThreadContextDataInjector.initServiceProviders();
785 LOGGER.debug("Thread Context Data Service Provider initialization complete");
786 }
787 }
788720 }
162162
163163 @Override
164164 public boolean requiresLocation() {
165 return layout instanceof LocationAware && ((LocationAware) layout).requiresLocation();
165 return layout != null && layout instanceof LocationAware && ((LocationAware) layout).requiresLocation();
166166 }
167167
168168 /**
3636 * This class implements {@link AutoCloseable} mostly to allow unit tests to be written safely and succinctly. While
3737 * managers do need to allocate resources (usually on construction) and then free these resources, a manager is longer
3838 * lived than other auto-closeable objects like streams. None the less, making a manager AutoCloseable forces readers to
39 * be aware of the pattern: allocate resources on construction and call {@link #close()} at some point.
39 * be aware of the the pattern: allocate resources on construction and call {@link #close()} at some point.
4040 * </p>
4141 */
4242 public abstract class AbstractManager implements AutoCloseable {
126126 }
127127 }
128128
129 /**
130 * Used by Log4j to update the Manager during reconfiguration. This method should be considered private.
131 * Implementations may not be thread safe. This method may be made protected in a future release.
132 * @param data The data to update.
133 */
134129 public void updateData(final Object data) {
135130 // This default implementation does nothing.
136131 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.concurrent.BlockingQueue;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TransferQueue;
24 import java.util.concurrent.atomic.AtomicLong;
25
26 import org.apache.logging.log4j.core.AbstractLogEvent;
1827 import org.apache.logging.log4j.core.Appender;
1928 import org.apache.logging.log4j.core.Core;
2029 import org.apache.logging.log4j.core.Filter;
4150 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
4251 import org.apache.logging.log4j.core.filter.AbstractFilterable;
4352 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
53 import org.apache.logging.log4j.core.util.Log4jThread;
4454 import org.apache.logging.log4j.spi.AbstractLogger;
45
46 import java.util.ArrayList;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.concurrent.BlockingQueue;
50 import java.util.concurrent.TimeUnit;
51 import java.util.concurrent.TransferQueue;
5255
5356 /**
5457 * Appends to one or more Appenders asynchronously. You can configure an AsyncAppender with one or more Appenders and an
5962 public final class AsyncAppender extends AbstractAppender {
6063
6164 private static final int DEFAULT_QUEUE_SIZE = 1024;
65 private static final LogEvent SHUTDOWN_LOG_EVENT = new AbstractLogEvent() {
66 private static final long serialVersionUID = -1761035149477086330L;
67 };
68
69 private static final AtomicLong THREAD_SEQUENCE = new AtomicLong(1);
6270
6371 private final BlockingQueue<LogEvent> queue;
6472 private final int queueSize;
6977 private final String errorRef;
7078 private final boolean includeLocation;
7179 private AppenderControl errorAppender;
72 private AsyncAppenderEventDispatcher dispatcher;
80 private AsyncThread thread;
7381 private AsyncQueueFullPolicy asyncQueueFullPolicy;
7482
7583 private AsyncAppender(final String name, final Filter filter, final AppenderRef[] appenderRefs,
108116 }
109117 }
110118 if (appenders.size() > 0) {
111 dispatcher = new AsyncAppenderEventDispatcher(
112 getName(), errorAppender, appenders, queue);
119 thread = new AsyncThread(appenders, queue);
120 thread.setName("AsyncAppender-" + getName());
113121 } else if (errorRef == null) {
114122 throw new ConfigurationException("No appenders are available for AsyncAppender " + getName());
115123 }
116124 asyncQueueFullPolicy = AsyncQueueFullPolicyFactory.create();
117125
118 dispatcher.start();
126 thread.start();
119127 super.start();
120128 }
121129
124132 setStopping();
125133 super.stop(timeout, timeUnit, false);
126134 LOGGER.trace("AsyncAppender stopping. Queue still has {} events.", queue.size());
135 thread.shutdown();
127136 try {
128 dispatcher.stop(shutdownTimeout);
129 } catch (final InterruptedException ignored) {
130 // Restore the interrupted flag cleared when the exception is caught.
131 Thread.currentThread().interrupt();
137 thread.join(shutdownTimeout);
138 } catch (final InterruptedException ex) {
132139 LOGGER.warn("Interrupted while stopping AsyncAppender {}", getName());
133140 }
134141 LOGGER.trace("AsyncAppender stopped. Queue has {} events.", queue.size());
161168 logMessageInCurrentThread(logEvent);
162169 } else {
163170 // delegate to the event router (which may discard, enqueue and block, or log in current thread)
164 final EventRoute route = asyncQueueFullPolicy.getRoute(dispatcher.getId(), memento.getLevel());
171 final EventRoute route = asyncQueueFullPolicy.getRoute(thread.getId(), memento.getLevel());
165172 route.logMessage(this, memento);
166173 }
167174 } else {
184191 */
185192 public void logMessageInCurrentThread(final LogEvent logEvent) {
186193 logEvent.setEndOfBatch(queue.isEmpty());
187 dispatcher.dispatch(logEvent);
194 final boolean appendSuccessful = thread.callAppenders(logEvent);
195 logToErrorAppenderIfNecessary(appendSuccessful, logEvent);
188196 }
189197
190198 /**
196204 try {
197205 // wait for free slots in the queue
198206 queue.put(logEvent);
199 } catch (final InterruptedException ignored) {
207 } catch (final InterruptedException e) {
200208 final boolean appendSuccessful = handleInterruptedException(logEvent);
201209 logToErrorAppenderIfNecessary(appendSuccessful, logEvent);
202210 }
366374 }
367375
368376 /**
377 * Thread that calls the Appenders.
378 */
379 private class AsyncThread extends Log4jThread {
380
381 private volatile boolean shutdown = false;
382 private final List<AppenderControl> appenders;
383 private final BlockingQueue<LogEvent> queue;
384
385 public AsyncThread(final List<AppenderControl> appenders, final BlockingQueue<LogEvent> queue) {
386 super("AsyncAppender-" + THREAD_SEQUENCE.getAndIncrement());
387 this.appenders = appenders;
388 this.queue = queue;
389 setDaemon(true);
390 }
391
392 @Override
393 public void run() {
394 while (!shutdown) {
395 LogEvent event;
396 try {
397 event = queue.take();
398 if (event == SHUTDOWN_LOG_EVENT) {
399 shutdown = true;
400 continue;
401 }
402 } catch (final InterruptedException ex) {
403 break; // LOG4J2-830
404 }
405 event.setEndOfBatch(queue.isEmpty());
406 final boolean success = callAppenders(event);
407 if (!success && errorAppender != null) {
408 try {
409 errorAppender.callAppender(event);
410 } catch (final Exception ex) {
411 // Silently accept the error.
412 }
413 }
414 }
415 // Process any remaining items in the queue.
416 LOGGER.trace("AsyncAppender.AsyncThread shutting down. Processing remaining {} queue events.",
417 queue.size());
418 int count = 0;
419 int ignored = 0;
420 while (!queue.isEmpty()) {
421 try {
422 final LogEvent event = queue.take();
423 if (event instanceof Log4jLogEvent) {
424 final Log4jLogEvent logEvent = (Log4jLogEvent) event;
425 logEvent.setEndOfBatch(queue.isEmpty());
426 callAppenders(logEvent);
427 count++;
428 } else {
429 ignored++;
430 LOGGER.trace("Ignoring event of class {}", event.getClass().getName());
431 }
432 } catch (final InterruptedException ex) {
433 // May have been interrupted to shut down.
434 // Here we ignore interrupts and try to process all remaining events.
435 }
436 }
437 LOGGER.trace("AsyncAppender.AsyncThread stopped. Queue has {} events remaining. "
438 + "Processed {} and ignored {} events since shutdown started.", queue.size(), count, ignored);
439 }
440
441 /**
442 * Calls {@link AppenderControl#callAppender(LogEvent) callAppender} on all registered {@code AppenderControl}
443 * objects, and returns {@code true} if at least one appender call was successful, {@code false} otherwise. Any
444 * exceptions are silently ignored.
445 *
446 * @param event the event to forward to the registered appenders
447 * @return {@code true} if at least one appender call succeeded, {@code false} otherwise
448 */
449 boolean callAppenders(final LogEvent event) {
450 boolean success = false;
451 for (final AppenderControl control : appenders) {
452 try {
453 control.callAppender(event);
454 success = true;
455 } catch (final Exception ex) {
456 // If no appender is successful the error appender will get it.
457 }
458 }
459 return success;
460 }
461
462 public void shutdown() {
463 shutdown = true;
464 if (queue.isEmpty()) {
465 queue.offer(SHUTDOWN_LOG_EVENT);
466 }
467 if (getState() == State.TIMED_WAITING || getState() == State.WAITING) {
468 this.interrupt(); // LOG4J2-1422: if underlying appender is stuck in wait/sleep/join/park call
469 }
470 }
471 }
472
473 /**
369474 * Returns the names of the appenders that this asyncAppender delegates to as an array of Strings.
370475 *
371476 * @return the names of the sink appenders
424529 public int getQueueSize() {
425530 return queue.size();
426531 }
427
428532 }
+0
-175
log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventDispatcher.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.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.config.AppenderControl;
21 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
22 import org.apache.logging.log4j.core.util.Log4jThread;
23 import org.apache.logging.log4j.status.StatusLogger;
24
25 import java.util.List;
26 import java.util.concurrent.BlockingQueue;
27 import java.util.concurrent.atomic.AtomicBoolean;
28 import java.util.concurrent.atomic.AtomicLong;
29
30 class AsyncAppenderEventDispatcher extends Log4jThread {
31
32 private static final LogEvent STOP_EVENT = new Log4jLogEvent();
33
34 private static final AtomicLong THREAD_COUNTER = new AtomicLong(0);
35
36 private static final Logger LOGGER = StatusLogger.getLogger();
37
38 private final AppenderControl errorAppender;
39
40 private final List<AppenderControl> appenders;
41
42 private final BlockingQueue<LogEvent> queue;
43
44 private final AtomicBoolean stoppedRef;
45
46 AsyncAppenderEventDispatcher(
47 final String name,
48 final AppenderControl errorAppender,
49 final List<AppenderControl> appenders,
50 final BlockingQueue<LogEvent> queue) {
51 super("AsyncAppenderEventDispatcher-" + THREAD_COUNTER.incrementAndGet() + "-" + name);
52 this.setDaemon(true);
53 this.errorAppender = errorAppender;
54 this.appenders = appenders;
55 this.queue = queue;
56 this.stoppedRef = new AtomicBoolean(false);
57 }
58
59 @Override
60 public void run() {
61 LOGGER.trace("{} has started.", getName());
62 dispatchAll();
63 dispatchRemaining();
64 }
65
66 private void dispatchAll() {
67 while (!stoppedRef.get()) {
68 LogEvent event;
69 try {
70 event = queue.take();
71 } catch (final InterruptedException ignored) {
72 // Restore the interrupted flag cleared when the exception is caught.
73 interrupt();
74 break;
75 }
76 if (event == STOP_EVENT) {
77 break;
78 }
79 event.setEndOfBatch(queue.isEmpty());
80 dispatch(event);
81 }
82 LOGGER.trace("{} has stopped.", getName());
83 }
84
85 private void dispatchRemaining() {
86 int eventCount = 0;
87 while (true) {
88 // Note the non-blocking Queue#poll() method!
89 final LogEvent event = queue.poll();
90 if (event == null) {
91 break;
92 }
93 // Allow events that managed to be submitted after the sentinel.
94 if (event == STOP_EVENT) {
95 continue;
96 }
97 event.setEndOfBatch(queue.isEmpty());
98 dispatch(event);
99 eventCount++;
100 }
101 LOGGER.trace(
102 "{} has processed the last {} remaining event(s).",
103 getName(), eventCount);
104 }
105
106 /**
107 * Dispatches the given {@code event} to the registered appenders <b>in the
108 * current thread</b>.
109 */
110 void dispatch(final LogEvent event) {
111
112 // Dispatch the event to all registered appenders.
113 boolean succeeded = false;
114 // noinspection ForLoopReplaceableByForEach (avoid iterator instantion)
115 for (int appenderIndex = 0; appenderIndex < appenders.size(); appenderIndex++) {
116 final AppenderControl control = appenders.get(appenderIndex);
117 try {
118 control.callAppender(event);
119 succeeded = true;
120 } catch (final Throwable error) {
121 // If no appender is successful, the error appender will get it.
122 // It is okay to simply log it here.
123 LOGGER.trace(
124 "{} has failed to call appender {}",
125 getName(), control.getAppenderName(), error);
126 }
127 }
128
129 // Fallback to the error appender if none has succeeded so far.
130 if (!succeeded && errorAppender != null) {
131 try {
132 errorAppender.callAppender(event);
133 } catch (final Throwable error) {
134 // If the error appender also fails, there is nothing further
135 // we can do about it.
136 LOGGER.trace(
137 "{} has failed to call the error appender {}",
138 getName(), errorAppender.getAppenderName(), error);
139 }
140 }
141
142 }
143
144 void stop(final long timeoutMillis) throws InterruptedException {
145
146 // Mark the completion, if necessary.
147 final boolean stopped = stoppedRef.compareAndSet(false, true);
148 if (stopped) {
149 LOGGER.trace("{} is signaled to stop.", getName());
150 }
151
152 // There is a slight chance that the thread is not started yet, wait for
153 // it to run. Otherwise, interrupt+join might block.
154 // noinspection StatementWithEmptyBody
155 while (Thread.State.NEW.equals(getState()));
156
157 // Enqueue the stop event, if there is sufficient room; otherwise,
158 // fallback to interruption. (We should avoid interrupting the thread if
159 // at all possible due to the subtleties of Java interruption, which
160 // will actually close sockets if any blocking operations are in
161 // progress! This means a socket appender may surprisingly fail to
162 // deliver final events. I recall some oddities with file I/O as well.
163 // — ckozak)
164 final boolean added = queue.offer(STOP_EVENT);
165 if (!added) {
166 interrupt();
167 }
168
169 // Wait for the completion.
170 join(timeoutMillis);
171
172 }
173
174 }
2929 public final Configuration configuration;
3030
3131 public ConfigurationFactoryData(final Configuration configuration) {
32 super();
3233 this.configuration = configuration;
3334 }
3435
2323 import org.apache.logging.log4j.core.LogEvent;
2424 import org.apache.logging.log4j.status.StatusLogger;
2525
26 import static java.util.Objects.requireNonNull;
27
2826 /**
29 * The default {@link ErrorHandler} implementation falling back to {@link StatusLogger}.
30 * <p>
31 * It avoids flooding the {@link StatusLogger} by allowing either the first 3 errors or errors once every 5 minutes.
32 * </p>
27 *
3328 */
3429 public class DefaultErrorHandler implements ErrorHandler {
3530
3631 private static final Logger LOGGER = StatusLogger.getLogger();
3732
38 private static final int MAX_EXCEPTION_COUNT = 3;
33 private static final int MAX_EXCEPTIONS = 3;
3934
40 private static final long EXCEPTION_INTERVAL_NANOS = TimeUnit.MINUTES.toNanos(5);
35 private static final long EXCEPTION_INTERVAL = TimeUnit.MINUTES.toNanos(5);
4136
4237 private int exceptionCount = 0;
4338
44 private long lastExceptionInstantNanos = System.nanoTime() - EXCEPTION_INTERVAL_NANOS - 1;
39 private long lastException = System.nanoTime() - EXCEPTION_INTERVAL - 1;
4540
4641 private final Appender appender;
4742
4843 public DefaultErrorHandler(final Appender appender) {
49 this.appender = requireNonNull(appender, "appender");
44 this.appender = appender;
45 }
46
47
48 /**
49 * Handle an error with a message.
50 * @param msg The message.
51 */
52 @Override
53 public void error(final String msg) {
54 final long current = System.nanoTime();
55 if (current - lastException > EXCEPTION_INTERVAL || exceptionCount++ < MAX_EXCEPTIONS) {
56 LOGGER.error(msg);
57 }
58 lastException = current;
5059 }
5160
5261 /**
53 * Handle an error with a message.
54 * @param msg a message
62 * Handle an error with a message and an exception.
63 * @param msg The message.
64 * @param t The Throwable.
5565 */
5666 @Override
57 public void error(final String msg) {
58 final boolean allowed = acquirePermit();
59 if (allowed) {
60 LOGGER.error(msg);
67 public void error(final String msg, final Throwable t) {
68 final long current = System.nanoTime();
69 if (current - lastException > EXCEPTION_INTERVAL || exceptionCount++ < MAX_EXCEPTIONS) {
70 LOGGER.error(msg, t);
71 }
72 lastException = current;
73 if (!appender.ignoreExceptions() && t != null && !(t instanceof AppenderLoggingException)) {
74 throw new AppenderLoggingException(msg, t);
6175 }
6276 }
6377
6478 /**
65 * Handle an error with a message and an exception.
66 *
67 * @param msg a message
68 * @param error a {@link Throwable}
79 * Handle an error with a message, and exception and a logging event.
80 * @param msg The message.
81 * @param event The LogEvent.
82 * @param t The Throwable.
6983 */
7084 @Override
71 public void error(final String msg, final Throwable error) {
72 final boolean allowed = acquirePermit();
73 if (allowed) {
74 LOGGER.error(msg, error);
85 public void error(final String msg, final LogEvent event, final Throwable t) {
86 final long current = System.nanoTime();
87 if (current - lastException > EXCEPTION_INTERVAL || exceptionCount++ < MAX_EXCEPTIONS) {
88 LOGGER.error(msg, t);
7589 }
76 if (!appender.ignoreExceptions() && error != null && !(error instanceof AppenderLoggingException)) {
77 throw new AppenderLoggingException(msg, error);
78 }
79 }
80
81 /**
82 * Handle an error with a message, an exception, and a logging event.
83 *
84 * @param msg a message
85 * @param event a {@link LogEvent}
86 * @param error a {@link Throwable}
87 */
88 @Override
89 public void error(final String msg, final LogEvent event, final Throwable error) {
90 final boolean allowed = acquirePermit();
91 if (allowed) {
92 LOGGER.error(msg, error);
93 }
94 if (!appender.ignoreExceptions() && error != null && !(error instanceof AppenderLoggingException)) {
95 throw new AppenderLoggingException(msg, error);
96 }
97 }
98
99 private boolean acquirePermit() {
100 final long currentInstantNanos = System.nanoTime();
101 synchronized (this) {
102 if (currentInstantNanos - lastExceptionInstantNanos > EXCEPTION_INTERVAL_NANOS) {
103 lastExceptionInstantNanos = currentInstantNanos;
104 return true;
105 } else if (exceptionCount < MAX_EXCEPTION_COUNT) {
106 exceptionCount++;
107 lastExceptionInstantNanos = currentInstantNanos;
108 return true;
109 } else {
110 return false;
111 }
90 lastException = current;
91 if (!appender.ignoreExceptions() && t != null && !(t instanceof AppenderLoggingException)) {
92 throw new AppenderLoggingException(msg, t);
11293 }
11394 }
11495
11596 public Appender getAppender() {
11697 return appender;
11798 }
118
11999 }
5959
6060 private final long intervalNanos;
6161
62 private volatile long nextCheckNanos;
62 private volatile long nextCheckNanos = 0;
6363
6464 private FailoverAppender(final String name, final Filter filter, final String primary, final String[] failovers,
6565 final int intervalMillis, final Configuration config, final boolean ignoreExceptions,
187187 final String filename = getFileName();
188188 LOGGER.debug("Now writing to {} at {}", filename, new Date());
189189 final File file = new File(filename);
190 createParentDir(file);
191190 final FileOutputStream fos = new FileOutputStream(file, isAppend);
192191 if (file.exists() && file.length() == 0) {
193192 try {
194193 FileTime now = FileTime.fromMillis(System.currentTimeMillis());
195194 Files.setAttribute(file.toPath(), "creationTime", now);
196195 } catch (Exception ex) {
197 LOGGER.warn("Unable to set current file time for {}", filename);
198 }
199 writeHeader(fos);
196 LOGGER.warn("Unable to set current file tiem for {}", filename);
197 }
200198 }
201199 defineAttributeView(Paths.get(filename));
202200 return fos;
203 }
204
205 protected void createParentDir(File file) {
206201 }
207202
208203 protected void defineAttributeView(final Path path) {
209204 if (attributeViewEnabled) {
210205 try {
211 // FileOutputStream may not create new file on all JVM
206 // FileOutputStream may not create new file on all jvm
212207 path.toFile().createNewFile();
213208
214209 FileUtils.defineFilePosixAttributeView(path, filePermissions, fileOwner, fileGroup);
6464 this.method = Objects.requireNonNull(method, "method");
6565 this.connectTimeoutMillis = connectTimeoutMillis;
6666 this.readTimeoutMillis = readTimeoutMillis;
67 this.headers = headers != null ? headers : Property.EMPTY_ARRAY;
67 this.headers = headers != null ? headers : new Property[0];
6868 this.sslConfiguration = sslConfiguration;
6969 if (this.sslConfiguration != null && !isHttps) {
7070 throw new ConfigurationException("SSL configuration can only be specified with URL scheme https");
154154 }
155155
156156 /**
157 * Write the log entry rolling over the file when required.
158 *
159 * @param event The LogEvent.
160 */
161 @Override
162 public void append(final LogEvent event) {
163
164 // Leverage the nice batching behaviour of async Loggers/Appenders:
165 // we can signal the file manager that it needs to flush the buffer
166 // to disk at the end of a batch.
167 // From a user's point of view, this means that all log events are
168 // _always_ available in the log file, without incurring the overhead
169 // of immediateFlush=true.
170 getManager().setEndOfBatch(event.isEndOfBatch()); // FIXME manager's EndOfBatch threadlocal can be deleted
171 super.append(event); // TODO should only call force() if immediateFlush && endOfBatch?
172 }
173
174 /**
157175 * Returns the file name this appender is associated with.
158176 *
159177 * @return The File name.
3636 import org.apache.logging.log4j.core.util.Closer;
3737 import org.apache.logging.log4j.core.util.FileUtils;
3838 import org.apache.logging.log4j.core.util.NullOutputStream;
39 import org.apache.logging.log4j.util.Constants;
4039
4140 //Lines too long...
4241 //CHECKSTYLE:OFF
6968 private final int regionLength;
7069 private final String advertiseURI;
7170 private final RandomAccessFile randomAccessFile;
71 private final ThreadLocal<Boolean> isEndOfBatch = new ThreadLocal<>();
7272 private MappedByteBuffer mappedBuffer;
7373 private long mappingOffset;
7474
7575 protected MemoryMappedFileManager(final RandomAccessFile file, final String fileName, final OutputStream os,
7676 final boolean immediateFlush, final long position, final int regionLength, final String advertiseURI,
7777 final Layout<? extends Serializable> layout, final boolean writeHeader) throws IOException {
78 super(os, fileName, layout, writeHeader, ByteBuffer.wrap(Constants.EMPTY_BYTE_ARRAY));
78 super(os, fileName, layout, writeHeader, ByteBuffer.wrap(new byte[0]));
7979 this.immediateFlush = immediateFlush;
8080 this.randomAccessFile = Objects.requireNonNull(file, "RandomAccessFile");
8181 this.regionLength = regionLength;
8282 this.advertiseURI = advertiseURI;
83 this.isEndOfBatch.set(Boolean.FALSE);
8384 this.mappedBuffer = mmap(randomAccessFile.getChannel(), getFileName(), position, regionLength);
8485 this.byteBuffer = mappedBuffer;
8586 this.mappingOffset = position;
103104 regionLength, advertiseURI, layout), FACTORY));
104105 }
105106
106 /**
107 * No longer used, the {@link org.apache.logging.log4j.core.LogEvent#isEndOfBatch()} attribute is used instead.
108 * @return {@link Boolean#FALSE}.
109 * @deprecated end-of-batch on the event is used instead.
110 */
111 @Deprecated
112107 public Boolean isEndOfBatch() {
113 return Boolean.FALSE;
114 }
115
116 /**
117 * No longer used, the {@link org.apache.logging.log4j.core.LogEvent#isEndOfBatch()} attribute is used instead.
118 * This method is a no-op.
119 * @deprecated end-of-batch on the event is used instead.
120 */
121 @Deprecated
122 public void setEndOfBatch(@SuppressWarnings("unused") final boolean endOfBatch) {
108 return isEndOfBatch.get();
109 }
110
111 public void setEndOfBatch(final boolean endOfBatch) {
112 this.isEndOfBatch.set(Boolean.valueOf(endOfBatch));
123113 }
124114
125115 @Override
222212 private static void unsafeUnmap(final MappedByteBuffer mbb) throws PrivilegedActionException {
223213 LOGGER.debug("MMapAppender unmapping old buffer...");
224214 final long startNanos = System.nanoTime();
225 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
226 final Method getCleanerMethod = mbb.getClass().getMethod("cleaner");
227 getCleanerMethod.setAccessible(true);
228 final Object cleaner = getCleanerMethod.invoke(mbb); // sun.misc.Cleaner instance
229 final Method cleanMethod = cleaner.getClass().getMethod("clean");
230 cleanMethod.invoke(cleaner);
231 return null;
215 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
216 @Override
217 public Object run() throws Exception {
218 final Method getCleanerMethod = mbb.getClass().getMethod("cleaner");
219 getCleanerMethod.setAccessible(true);
220 final Object cleaner = getCleanerMethod.invoke(mbb); // sun.misc.Cleaner instance
221 final Method cleanMethod = cleaner.getClass().getMethod("clean");
222 cleanMethod.invoke(cleaner);
223 return null;
224 }
232225 });
233226 final float millis = (float) ((System.nanoTime() - startNanos) / NANOS_PER_MILLISEC);
234227 LOGGER.debug("MMapAppender unmapped buffer OK in {} millis", millis);
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;
17
18 import java.io.OutputStream;
19 import java.io.Serializable;
20
21 import org.apache.logging.log4j.core.Appender;
22 import org.apache.logging.log4j.core.Core;
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.Layout;
25 import org.apache.logging.log4j.core.config.Property;
26 import org.apache.logging.log4j.core.config.plugins.Plugin;
27 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
28 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29 import org.apache.logging.log4j.core.layout.PatternLayout;
30 import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
31 import org.apache.logging.log4j.core.util.NullOutputStream;
32
33 /**
34 * Appends log events to a given output stream using a layout.
35 * <p>
36 * Character encoding is handled within the Layout.
37 * </p>
38 */
39 @Plugin(name = "OutputStream", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
40 public final class OutputStreamAppender extends AbstractOutputStreamAppender<OutputStreamManager> {
41
42 /**
43 * Builds OutputStreamAppender instances.
44 *
45 * @param <B>
46 * The type to build.
47 */
48 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
49 implements org.apache.logging.log4j.core.util.Builder<OutputStreamAppender> {
50
51 private boolean follow = false;
52
53 private final boolean ignoreExceptions = true;
54
55 private OutputStream target;
56
57 @Override
58 public OutputStreamAppender build() {
59 final Layout<? extends Serializable> layout = getLayout();
60 final Layout<? extends Serializable> actualLayout = layout == null ? PatternLayout.createDefaultLayout()
61 : layout;
62 return new OutputStreamAppender(getName(), actualLayout, getFilter(), getManager(target, follow, actualLayout),
63 ignoreExceptions, getPropertyArray());
64 }
65
66 public B setFollow(final boolean shouldFollow) {
67 this.follow = shouldFollow;
68 return asBuilder();
69 }
70
71 public B setTarget(final OutputStream aTarget) {
72 this.target = aTarget;
73 return asBuilder();
74 }
75 }
76
77 /**
78 * Holds data to pass to factory method.
79 */
80 private static class FactoryData {
81 private final Layout<? extends Serializable> layout;
82 private final String name;
83 private final OutputStream os;
84
85 /**
86 * Builds instances.
87 *
88 * @param os
89 * The OutputStream.
90 * @param type
91 * The name of the target.
92 * @param layout
93 * A Serializable layout
94 */
95 public FactoryData(final OutputStream os, final String type, final Layout<? extends Serializable> layout) {
96 this.os = os;
97 this.name = type;
98 this.layout = layout;
99 }
100 }
101
102 /**
103 * Creates the manager.
104 */
105 private static class OutputStreamManagerFactory implements ManagerFactory<OutputStreamManager, FactoryData> {
106
107 /**
108 * Creates an OutputStreamManager.
109 *
110 * @param name
111 * The name of the entity to manage.
112 * @param data
113 * The data required to create the entity.
114 * @return The OutputStreamManager
115 */
116 @Override
117 public OutputStreamManager createManager(final String name, final FactoryData data) {
118 return new OutputStreamManager(data.os, data.name, data.layout, true);
119 }
120 }
121
122 private static OutputStreamManagerFactory factory = new OutputStreamManagerFactory();
123
124 /**
125 * Creates an OutputStream Appender.
126 *
127 * @param layout
128 * The layout to use or null to get the default layout.
129 * @param filter
130 * The Filter or null.
131 * @param target
132 * an output stream.
133 * @param follow
134 * If true will follow changes to the underlying output stream.
135 * Use false as the default.
136 * @param name
137 * The name of the Appender (required).
138 * @param ignore
139 * If {@code "true"} (default) exceptions encountered when
140 * appending events are logged; otherwise they are propagated to
141 * the caller. Use true as the default.
142 * @return The ConsoleAppender.
143 */
144 @PluginFactory
145 public static OutputStreamAppender createAppender(Layout<? extends Serializable> layout, final Filter filter,
146 final OutputStream target, final String name, final boolean follow, final boolean ignore) {
147 if (name == null) {
148 LOGGER.error("No name provided for OutputStreamAppender");
149 return null;
150 }
151 if (layout == null) {
152 layout = PatternLayout.createDefaultLayout();
153 }
154 return new OutputStreamAppender(name, layout, filter, getManager(target, follow, layout), ignore, null);
155 }
156
157 private static OutputStreamManager getManager(final OutputStream target, final boolean follow,
158 final Layout<? extends Serializable> layout) {
159 final OutputStream os = target == null ? NullOutputStream.getInstance() : new CloseShieldOutputStream(target);
160 final OutputStream targetRef = target == null ? os : target;
161 final String managerName = targetRef.getClass().getName() + "@" + Integer.toHexString(targetRef.hashCode())
162 + '.' + follow;
163 return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory);
164 }
165
166 @PluginBuilderFactory
167 public static <B extends Builder<B>> B newBuilder() {
168 return new Builder<B>().asBuilder();
169 }
170
171 private OutputStreamAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
172 final OutputStreamManager manager, final boolean ignoreExceptions, final Property[] properties) {
173 super(name, layout, filter, ignoreExceptions, true, properties, manager);
174 }
175
176 }
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;
17
18 import java.io.OutputStream;
19 import java.io.Serializable;
20
21 import org.apache.logging.log4j.core.Appender;
22 import org.apache.logging.log4j.core.Core;
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.Layout;
25 import org.apache.logging.log4j.core.config.Property;
26 import org.apache.logging.log4j.core.config.plugins.Plugin;
27 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
28 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29 import org.apache.logging.log4j.core.layout.PatternLayout;
30 import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
31
32 /**
33 * Appends log events to a given output stream using a layout.
34 * <p>
35 * Character encoding is handled within the Layout.
36 * </p>
37 */
38 @Plugin(name = "OutputStream", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
39 public final class OutputStreamAppender extends AbstractOutputStreamAppender<OutputStreamManager> {
40
41 /**
42 * Builds OutputStreamAppender instances.
43 */
44 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
45 implements org.apache.logging.log4j.core.util.Builder<OutputStreamAppender> {
46
47 private Filter filter;
48
49 private boolean follow = false;
50
51 private final boolean ignoreExceptions = true;
52
53 private OutputStream target;
54
55 @Override
56 public OutputStreamAppender build() {
57 final Layout<? extends Serializable> layout = getLayout();
58 final Layout<? extends Serializable> actualLayout = layout == null ? PatternLayout.createDefaultLayout()
59 : layout;
60 return new OutputStreamAppender(getName(), actualLayout, filter, getManager(target, follow, actualLayout),
61 ignoreExceptions, getPropertyArray());
62 }
63
64 public B setFollow(final boolean shouldFollow) {
65 this.follow = shouldFollow;
66 return asBuilder();
67 }
68
69 public B setTarget(final OutputStream aTarget) {
70 this.target = aTarget;
71 return asBuilder();
72 }
73 }
74
75 /**
76 * Holds data to pass to factory method.
77 */
78 private static class FactoryData {
79 private final Layout<? extends Serializable> layout;
80 private final String name;
81 private final OutputStream os;
82
83 /**
84 * Builds instances.
85 *
86 * @param os
87 * The OutputStream.
88 * @param type
89 * The name of the target.
90 * @param layout
91 * A Serializable layout
92 */
93 public FactoryData(final OutputStream os, final String type, final Layout<? extends Serializable> layout) {
94 this.os = os;
95 this.name = type;
96 this.layout = layout;
97 }
98 }
99
100 /**
101 * Creates the manager.
102 */
103 private static class OutputStreamManagerFactory implements ManagerFactory<OutputStreamManager, FactoryData> {
104
105 /**
106 * Creates an OutputStreamManager.
107 *
108 * @param name
109 * The name of the entity to manage.
110 * @param data
111 * The data required to create the entity.
112 * @return The OutputStreamManager
113 */
114 @Override
115 public OutputStreamManager createManager(final String name, final FactoryData data) {
116 return new OutputStreamManager(data.os, data.name, data.layout, true);
117 }
118 }
119
120 private static OutputStreamManagerFactory factory = new OutputStreamManagerFactory();
121
122 /**
123 * Creates an OutputStream Appender.
124 *
125 * @param layout
126 * The layout to use or null to get the default layout.
127 * @param filter
128 * The Filter or null.
129 * @param target
130 * an output stream.
131 * @param follow
132 * If true will follow changes to the underlying output stream.
133 * Use false as the default.
134 * @param name
135 * The name of the Appender (required).
136 * @param ignore
137 * If {@code "true"} (default) exceptions encountered when
138 * appending events are logged; otherwise they are propagated to
139 * the caller. Use true as the default.
140 * @return The ConsoleAppender.
141 */
142 @PluginFactory
143 public static OutputStreamAppender createAppender(Layout<? extends Serializable> layout, final Filter filter,
144 final OutputStream target, final String name, final boolean follow, final boolean ignore) {
145 if (name == null) {
146 LOGGER.error("No name provided for OutputStreamAppender");
147 return null;
148 }
149 if (layout == null) {
150 layout = PatternLayout.createDefaultLayout();
151 }
152 return new OutputStreamAppender(name, layout, filter, getManager(target, follow, layout), ignore, null);
153 }
154
155 private static OutputStreamManager getManager(final OutputStream target, final boolean follow,
156 final Layout<? extends Serializable> layout) {
157 final OutputStream os = new CloseShieldOutputStream(target);
158 final String managerName = target.getClass().getName() + "@" + Integer.toHexString(target.hashCode()) + '.'
159 + follow;
160 return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory);
161 }
162
163 @PluginBuilderFactory
164 public static Builder newBuilder() {
165 return new Builder();
166 }
167
168 private OutputStreamAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
169 final OutputStreamManager manager, final boolean ignoreExceptions, final Property[] properties) {
170 super(name, layout, filter, ignoreExceptions, true, properties, manager);
171 }
172
173 }
5959 super(null, streamName);
6060 this.outputStream = os;
6161 this.layout = layout;
62 if (writeHeader) {
63 writeHeader(os);
62 if (writeHeader && layout != null) {
63 final byte[] header = layout.getHeader();
64 if (header != null) {
65 try {
66 getOutputStream().write(header, 0, header.length);
67 } catch (final IOException e) {
68 logError("Unable to write header", e);
69 }
70 }
6471 }
6572 this.byteBuffer = Objects.requireNonNull(byteBuffer, "byteBuffer");
6673 }
8087 this.layout = layout;
8188 this.byteBuffer = Objects.requireNonNull(byteBuffer, "byteBuffer");
8289 this.outputStream = os;
83 if (writeHeader) {
84 writeHeader(os);
90 if (writeHeader && layout != null) {
91 final byte[] header = layout.getHeader();
92 if (header != null) {
93 try {
94 getOutputStream().write(header, 0, header.length);
95 } catch (final IOException e) {
96 logError("Unable to write header for " + streamName, e);
97 }
98 }
8599 }
86100 }
87101
121135 return closeOutputStream();
122136 }
123137
124 protected void writeHeader(OutputStream os) {
125 if (layout != null && os != null) {
126 final byte[] header = layout.getHeader();
127 if (header != null) {
128 try {
129 os.write(header, 0, header.length);
130 } catch (final IOException e) {
131 logError("Unable to write header", e);
132 }
133 }
134 }
135 }
136
137138 /**
138139 * Writes the footer.
139140 */
167168 }
168169
169170 protected void setOutputStream(final OutputStream os) {
170 this.outputStream = os;
171 final byte[] header = layout.getHeader();
172 if (header != null) {
173 try {
174 os.write(header, 0, header.length);
175 this.outputStream = os; // only update field if os.write() succeeded
176 } catch (final IOException ioe) {
177 logError("Unable to write header", ioe);
178 }
179 } else {
180 this.outputStream = os;
181 }
171182 }
172183
173184 /**
277288 */
278289 protected synchronized void flushBuffer(final ByteBuffer buf) {
279290 ((Buffer) buf).flip();
280 try {
281 if (buf.remaining() > 0) {
282 writeToDestination(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining());
283 }
284 } finally {
285 buf.clear();
286 }
291 if (buf.remaining() > 0) {
292 writeToDestination(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining());
293 }
294 buf.clear();
287295 }
288296
289297 /**
302310 }
303311 try {
304312 stream.close();
305 LOGGER.debug("OutputStream closed");
306313 } catch (final IOException ex) {
307314 logError("Unable to close stream", ex);
308315 return false;
333340 * {@link #flushBuffer(ByteBuffer)} directly instead.
334341 * </p>
335342 *
336 * @param buf the buffer whose contents to write the destination
343 * @param buf the buffer whose contents to write the the destination
337344 * @return the specified buffer
338345 * @since 2.6
339346 */
6161 @PluginBuilderAttribute("advertiseURI")
6262 private String advertiseURI;
6363
64 public Builder() {
65 this.withBufferSize(RandomAccessFileManager.DEFAULT_BUFFER_SIZE);
66 }
67
6864 @Override
6965 public RandomAccessFileAppender build() {
7066 final String name = getName();
7167 if (name == null) {
72 LOGGER.error("No name provided for RandomAccessFileAppender");
68 LOGGER.error("No name provided for FileAppender");
7369 return null;
7470 }
7571
7672 if (fileName == null) {
77 LOGGER.error("No filename provided for RandomAccessFileAppender with name {}", name);
73 LOGGER.error("No filename provided for FileAppender with name " + name);
7874 return null;
7975 }
8076 final Layout<? extends Serializable> layout = getOrCreateLayout();
142138 }
143139 setStopped();
144140 return true;
141 }
142
143 /**
144 * Write the log entry rolling over the file when required.
145 *
146 * @param event The LogEvent.
147 */
148 @Override
149 public void append(final LogEvent event) {
150
151 // Leverage the nice batching behaviour of async Loggers/Appenders:
152 // we can signal the file manager that it needs to flush the buffer
153 // to disk at the end of a batch.
154 // From a user's point of view, this means that all log events are
155 // _always_ available in the log file, without incurring the overhead
156 // of immediateFlush=true.
157 getManager().setEndOfBatch(event.isEndOfBatch()); // FIXME manager's EndOfBatch threadlocal can be deleted
158
159 // LOG4J2-1292 utilize gc-free Layout.encode() method: taken care of in superclass
160 super.append(event);
145161 }
146162
147163 /**
4242
4343 private final String advertiseURI;
4444 private final RandomAccessFile randomAccessFile;
45 private final ThreadLocal<Boolean> isEndOfBatch = new ThreadLocal<>();
4546
4647 protected RandomAccessFileManager(final LoggerContext loggerContext, final RandomAccessFile file, final String fileName,
4748 final OutputStream os, final int bufferSize, final String advertiseURI,
4950 super(loggerContext, os, fileName, false, layout, writeHeader, ByteBuffer.wrap(new byte[bufferSize]));
5051 this.randomAccessFile = file;
5152 this.advertiseURI = advertiseURI;
53 this.isEndOfBatch.set(Boolean.FALSE);
5254 }
5355
5456 /**
7274 new FactoryData(append, immediateFlush, bufferSize, advertiseURI, layout, configuration), FACTORY));
7375 }
7476
75 /**
76 * No longer used, the {@link org.apache.logging.log4j.core.LogEvent#isEndOfBatch()} attribute is used instead.
77 * @return {@link Boolean#FALSE}.
78 * @deprecated end-of-batch on the event is used instead.
79 */
80 @Deprecated
8177 public Boolean isEndOfBatch() {
82 return Boolean.FALSE;
83 }
84
85 /**
86 * No longer used, the {@link org.apache.logging.log4j.core.LogEvent#isEndOfBatch()} attribute is used instead.
87 * This method is a no-op.
88 * @deprecated end-of-batch on the event is used instead.
89 */
90 @Deprecated
91 public void setEndOfBatch(@SuppressWarnings("unused") final boolean endOfBatch) {
78 return isEndOfBatch.get();
79 }
80
81 public void setEndOfBatch(final boolean endOfBatch) {
82 this.isEndOfBatch.set(Boolean.valueOf(endOfBatch));
9283 }
9384
9485 @Override
137137 .build();
138138 }
139139 } else if (fileName == null && !(strategy instanceof DirectFileRolloverStrategy)) {
140 LOGGER.error("RollingFileAppender '{}': When no file name is provided a {} must be configured", getName(), DirectFileRolloverStrategy.class.getSimpleName());
140 LOGGER.error("RollingFileAppender '{}': When no file name is provided a DirectFilenameRolloverStrategy must be configured");
141141 return null;
142142 }
143143
152152 manager.initialize();
153153
154154 return new RollingFileAppender(getName(), layout, getFilter(), manager, fileName, filePattern,
155 isIgnoreExceptions(), !isBufferedIo || isImmediateFlush(),
156 advertise ? getConfiguration().getAdvertiser() : null, getPropertyArray());
155 isIgnoreExceptions(), isImmediateFlush(), advertise ? getConfiguration().getAdvertiser() : null,
156 getPropertyArray());
157157 }
158158
159159 public String getAdvertiseUri() {
5353 implements org.apache.logging.log4j.core.util.Builder<RollingRandomAccessFileAppender> {
5454
5555 public Builder() {
56 super();
5657 withBufferSize(RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE);
5758 setIgnoreExceptions(true);
5859 withImmediateFlush(true);
237238 public void append(final LogEvent event) {
238239 final RollingRandomAccessFileManager manager = getManager();
239240 manager.checkRollover(event);
241
242 // Leverage the nice batching behaviour of async Loggers/Appenders:
243 // we can signal the file manager that it needs to flush the buffer
244 // to disk at the end of a batch.
245 // From a user's point of view, this means that all log events are
246 // _always_ available in the log file, without incurring the overhead
247 // of immediateFlush=true.
248 manager.setEndOfBatch(event.isEndOfBatch()); // FIXME manager's EndOfBatch threadlocal can be deleted
240249
241250 // LOG4J2-1292 utilize gc-free Layout.encode() method: taken care of in superclass
242251 super.append(event);
279279 * @deprecated Use {@link #newBuilder()} to create and configure a {@link Builder} instance.
280280 * @see Builder
281281 */
282 @Deprecated
283282 public static SmtpAppender createAppender(
284283 @PluginConfiguration final Configuration config,
285284 @PluginAttribute("name") @Required final String name,
1616 package org.apache.logging.log4j.core.appender;
1717
1818 import java.nio.charset.StandardCharsets;
19 import java.util.Objects;
2019
2120 import org.apache.logging.log4j.util.Chars;
2221
4645
4746 @Override
4847 public int hashCode() {
49 return 31 + Objects.hashCode(message);
48 final int prime = 31;
49 int result = 1;
50 result = prime * result + ((message == null) ? 0 : message.hashCode());
51 return result;
5052 }
5153
5254 @Override
6163 return false;
6264 }
6365 final TlsSyslogFrame other = (TlsSyslogFrame) obj;
64 if (!Objects.equals(message, other.message)) {
66 if (message == null) {
67 if (other.message != null) {
68 return false;
69 }
70 } else if (!message.equals(other.message)) {
6571 return false;
6672 }
6773 return true;
4343 * Constructs the base factory data.
4444 *
4545 * @param bufferSize The size of the buffer.
46 * @param layout The appender-level layout
46 * @param bufferSize The appender-level layout
4747 */
4848 protected AbstractFactoryData(final int bufferSize, final Layout<? extends Serializable> layout) {
4949 this.bufferSize = bufferSize;
4141 */
4242 @Plugin(name = "ColumnMapping", category = Core.CATEGORY_NAME, printObject = true)
4343 public class ColumnMapping {
44
45 /**
46 * The empty array.
47 */
48 public static final ColumnMapping[] EMPTY_ARRAY = {};
4944
5045 /**
5146 * Builder for {@link ColumnMapping}.
127127
128128 public AbstractDriverManagerConnectionSource(final String driverClassName, final String connectionString,
129129 final String actualConnectionString, final char[] userName, final char[] password, final Property[] properties) {
130 super();
130131 this.driverClassName = driverClassName;
131132 this.connectionString = connectionString;
132133 this.actualConnectionString = actualConnectionString;
161161 private final class Reconnector extends Log4jThread {
162162
163163 private final CountDownLatch latch = new CountDownLatch(1);
164 private volatile boolean shutdown;
164 private volatile boolean shutdown = false;
165165
166166 private Reconnector() {
167167 super("JdbcDatabaseManager-Reconnector");
244244 private ResultSetColumnMetaData(final String schemaName, final String catalogName, final String tableName,
245245 final String name, final String label, final int displaySize, final int type, final String typeName,
246246 final String className, final int precision, final int scale) {
247 super();
247248 this.schemaName = schemaName;
248249 this.catalogName = catalogName;
249250 this.tableName = tableName;
358359 colMapping);
359360 i++;
360361 }
361 }
362 if (data.columnConfigs != null) {
363 for (final ColumnConfig colConfig : data.columnConfigs) {
364 final String columnName = colConfig.getColumnName();
365 appendColumnName(i, columnName, sb);
366 logger().trace(messagePattern, sqlVerb, colConfig.getClass().getSimpleName(), i, columnName,
367 colConfig);
368 i++;
362 if (data.columnConfigs != null) {
363 for (final ColumnConfig colConfig : data.columnConfigs) {
364 final String columnName = colConfig.getColumnName();
365 appendColumnName(i, columnName, sb);
366 logger().trace(messagePattern, sqlVerb, colConfig.getClass().getSimpleName(), i, columnName,
367 colConfig);
368 i++;
369 }
369370 }
370371 }
371372 }
388389 */
389390 @Deprecated
390391 public static JdbcDatabaseManager getJDBCDatabaseManager(final String name, final int bufferSize,
391 final ConnectionSource connectionSource, final String tableName, final ColumnConfig[] columnConfigs) {
392 final ConnectionSource connectionSource, final String tableName, final ColumnConfig[] columnConfigs) {
392393 return getManager(
393 name, new FactoryData(bufferSize, null, connectionSource, tableName, columnConfigs,
394 ColumnMapping.EMPTY_ARRAY, false, AbstractDatabaseAppender.DEFAULT_RECONNECT_INTERVAL_MILLIS, true),
395 getFactory());
394 name, new FactoryData(bufferSize, null, connectionSource, tableName, columnConfigs,
395 new ColumnMapping[0], false, AbstractDatabaseAppender.DEFAULT_RECONNECT_INTERVAL_MILLIS, true),
396 getFactory());
396397 }
397398
398399 /**
745746 * Sets the given Object in the prepared statement. The value is truncated if needed.
746747 */
747748 private void setStatementObject(final int j, final String nameKey, final Object value) throws SQLException {
748 if (statement == null) {
749 throw new AppenderLoggingException("Cannot set a value when the PreparedStatement is null.");
750 }
751 if (value == null) {
752 if (columnMetaData == null) {
753 throw new AppenderLoggingException("Cannot set a value when the column metadata is null.");
754 }
755 // [LOG4J2-2762] [JDBC] MS-SQL Server JDBC driver throws SQLServerException when
756 // inserting a null value for a VARBINARY column.
757 // Calling setNull() instead of setObject() for null values fixes [LOG4J2-2762].
758 this.statement.setNull(j, columnMetaData.get(nameKey).getType());
759 } else {
760 statement.setObject(j, truncate(nameKey, value));
761 }
749 statement.setObject(j, truncate(nameKey, value));
762750 }
763751
764752 @Override
829817 } else {
830818 final Object value = TypeConverters.convert(layout.toSerializable(event),
831819 mapping.getType(), null);
832 setStatementObject(j++, mapping.getNameKey(), value);
820 if (value == null) {
821 // TODO We might need to always initialize the columnMetaData to specify the
822 // type.
823 this.statement.setNull(j++, Types.NULL);
824 } else {
825 setStatementObject(j++, mapping.getNameKey(), value);
826 }
833827 }
834828 }
835829 }
855849 }
856850
857851 if (isBuffered() && this.isBatchSupported) {
858 logger().debug("addBatch for {}", this.statement);
859852 this.statement.addBatch();
860 } else {
861 final int executeUpdate = this.statement.executeUpdate();
862 logger().debug("executeUpdate = {} for {}", executeUpdate, this.statement);
863 if (executeUpdate == 0) {
864 throw new AppenderLoggingException(
865 "No records inserted in database table for log event in JDBC manager [%s].", fieldsToString());
866 }
853 } else if (this.statement.executeUpdate() == 0) {
854 throw new AppenderLoggingException(
855 "No records inserted in database table for log event in JDBC manager [%s].", fieldsToString());
867856 }
868857 } catch (final SQLException e) {
869858 throw new DbAppenderLoggingException(e, "Failed to insert record for log event in JDBC manager: %s [%s]", e,
224224 private volatile JmsManager manager;
225225
226226 /**
227 * Constructs a new instance.
228227 *
229228 * @throws JMSException not thrown as of 2.9 but retained in the signature for compatibility, will be removed in 3.0
230229 */
235234 }
236235
237236 /**
238 * Constructs a new instance.
239237 *
240238 * @throws JMSException not thrown as of 2.9 but retained in the signature for compatibility, will be removed in 3.0
241 * @deprecated Use {@link #JmsAppender(String, Filter, Layout, boolean, Property[], JmsManager)}.
239 * @deprecated
242240 */
243241 @Deprecated
244242 protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
3939 import org.apache.logging.log4j.core.net.JndiManager;
4040 import org.apache.logging.log4j.core.util.Log4jThread;
4141 import org.apache.logging.log4j.status.StatusLogger;
42 import org.apache.logging.log4j.util.BiConsumer;
4243
4344 /**
4445 * Consider this class <b>private</b>; it is only <b>public</b> for access by integration tests.
130131 logger().error("Error creating JmsManager using JmsManagerConfiguration [{}]", data, e);
131132 return null;
132133 }
133 } else {
134 logger().error("JNDI must be enabled by setting log4j2.enableJndiJms=true");
135 return null;
136 }
134 }
135 logger().error("JNDI must be enabled by setting log4j2.enableJndiJms=true");
136 return null;
137137 }
138138 }
139139
144144
145145 private final CountDownLatch latch = new CountDownLatch(1);
146146
147 private volatile boolean shutdown;
147 private volatile boolean shutdown = false;
148148
149149 private final Object owner;
150150
352352 * @param object
353353 * The LogEvent or String message to wrap.
354354 * @return A new JMS message containing the provided object.
355 * @throws JMSException
355 * @throws JMSException if the JMS provider fails to create a message due to some internal error.
356356 */
357357 public Message createMessage(final Serializable object) throws JMSException {
358358 if (object instanceof String) {
373373 * Creates a MessageConsumer on this Destination using the current Session.
374374 *
375375 * @return A MessageConsumer on this Destination.
376 * @throws JMSException
376 * @throws JMSException if the session fails to create a consumer due to some internal error.
377377 */
378378 public MessageConsumer createMessageConsumer() throws JMSException {
379379 return this.session.createConsumer(this.destination);
387387 * @param destination
388388 * The JMS Destination for the MessageProducer
389389 * @return A MessageProducer on this Destination.
390 * @throws JMSException
390 * @throws JMSException if the session fails to create a MessageProducer due to some internal error.
391391 */
392392 public MessageProducer createMessageProducer(final Session session, final Destination destination)
393393 throws JMSException {
420420 private MapMessage map(final org.apache.logging.log4j.message.MapMessage<?, ?> log4jMapMessage,
421421 final MapMessage jmsMapMessage) {
422422 // Map without calling org.apache.logging.log4j.message.MapMessage#getData() which makes a copy of the map.
423 log4jMapMessage.forEach((key, value) -> {
424 try {
425 jmsMapMessage.setObject(key, value);
426 } catch (final JMSException e) {
427 throw new IllegalArgumentException(String.format("%s mapping key '%s' to value '%s': %s",
428 e.getClass(), key, value, e.getLocalizedMessage()), e);
423 log4jMapMessage.forEach(new BiConsumer<String, Object>() {
424 @Override
425 public void accept(final String key, final Object value) {
426 try {
427 jmsMapMessage.setObject(key, value);
428 } catch (final JMSException e) {
429 throw new IllegalArgumentException(String.format("%s mapping key '%s' to value '%s': %s",
430 e.getClass(), key, value, e.getLocalizedMessage()), e);
431 }
429432 }
430433 });
431434 return jmsMapMessage;
2323 import org.apache.logging.log4j.LogManager;
2424 import org.apache.logging.log4j.core.appender.AbstractManager;
2525 import org.apache.logging.log4j.core.appender.ManagerFactory;
26 import org.apache.logging.log4j.core.util.Cancellable;
2726 import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
2827 import org.apache.logging.log4j.util.PropertiesUtil;
2928 import org.zeromq.ZMQ;
4847 private static final JeroMqManagerFactory FACTORY = new JeroMqManagerFactory();
4948 private static final ZMQ.Context CONTEXT;
5049
51 // Retained to avoid garbage collection of the hook
52 private static final Cancellable SHUTDOWN_HOOK;
53
5450 static {
5551 LOGGER.trace("JeroMqManager using ZMQ version {}", ZMQ.getVersionString());
5652
6157 final boolean enableShutdownHook = PropertiesUtil.getProperties().getBooleanProperty(
6258 SYS_PROPERTY_ENABLE_SHUTDOWN_HOOK, true);
6359 if (enableShutdownHook) {
64 SHUTDOWN_HOOK = ((ShutdownCallbackRegistry) LogManager.getFactory()).addShutdownCallback(CONTEXT::close);
65 } else {
66 SHUTDOWN_HOOK = null;
60 ((ShutdownCallbackRegistry) LogManager.getFactory()).addShutdownCallback(new Runnable() {
61 @Override
62 public void run() {
63 CONTEXT.close();
64 }
65 });
6766 }
6867 }
6968
4242 @Plugin(name = "Kafka", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
4343 public final class KafkaAppender extends AbstractAppender {
4444
45 private final Integer retryCount;
45 /**
46 * Builds KafkaAppender instances.
47 * @param <B> The type to build
48 */
49 public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
50 implements org.apache.logging.log4j.core.util.Builder<KafkaAppender> {
4651
47 /**
48 * Builds KafkaAppender instances.
49 *
50 * @param <B> The type to build
51 */
52 public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
53 implements org.apache.logging.log4j.core.util.Builder<KafkaAppender> {
52 @PluginAttribute("topic")
53 private String topic;
5454
55 @PluginAttribute("retryCount")
56 private String retryCount;
55 @PluginAttribute("key")
56 private String key;
5757
58 @PluginAttribute("topic")
59 private String topic;
58 @PluginAttribute(value = "syncSend", defaultBoolean = true)
59 private boolean syncSend;
6060
61 @PluginAttribute("key")
62 private String key;
61 @SuppressWarnings("resource")
62 @Override
63 public KafkaAppender build() {
64 final Layout<? extends Serializable> layout = getLayout();
65 if (layout == null) {
66 AbstractLifeCycle.LOGGER.error("No layout provided for KafkaAppender");
67 return null;
68 }
69 final KafkaManager kafkaManager = KafkaManager.getManager(getConfiguration().getLoggerContext(),
70 getName(), topic, syncSend, getPropertyArray(), key);
71 return new KafkaAppender(getName(), layout, getFilter(), isIgnoreExceptions(), kafkaManager,
72 getPropertyArray());
73 }
6374
64 @PluginAttribute(value = "syncSend", defaultBoolean = true)
65 private boolean syncSend;
75 public String getTopic() {
76 return topic;
77 }
6678
67 @SuppressWarnings("resource")
68 @Override
69 public KafkaAppender build() {
70 final Layout<? extends Serializable> layout = getLayout();
71 if (layout == null) {
72 AbstractLifeCycle.LOGGER.error("No layout provided for KafkaAppender");
73 return null;
74 }
75 final KafkaManager kafkaManager = KafkaManager.getManager(getConfiguration().getLoggerContext(), getName(),
76 topic, syncSend, getPropertyArray(), key);
77 return new KafkaAppender(getName(), layout, getFilter(), isIgnoreExceptions(), kafkaManager,
78 getPropertyArray(), getRetryCount());
79 }
79 public boolean isSyncSend() {
80 return syncSend;
81 }
8082
81 public String getTopic() {
82 return topic;
83 }
83 public B setTopic(final String topic) {
84 this.topic = topic;
85 return asBuilder();
86 }
8487
85 public boolean isSyncSend() {
86 return syncSend;
87 }
88 public B setSyncSend(final boolean syncSend) {
89 this.syncSend = syncSend;
90 return asBuilder();
91 }
8892
89 public B setTopic(final String topic) {
90 this.topic = topic;
91 return asBuilder();
92 }
93 }
9394
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
104 public Integer getRetryCount() {
105 Integer intRetryCount = null;
106 try {
107 intRetryCount = Integer.valueOf(retryCount);
108 } catch (NumberFormatException e) {
109
110 }
111 return intRetryCount;
112
113 }
114
115 }
116
117 @Deprecated
118 public static KafkaAppender createAppender(final Layout<? extends Serializable> layout, final Filter filter,
119 final String name, final boolean ignoreExceptions, final String topic, final Property[] properties,
95 @Deprecated
96 public static KafkaAppender createAppender(
97 final Layout<? extends Serializable> layout,
98 final Filter filter,
99 final String name,
100 final boolean ignoreExceptions,
101 final String topic,
102 final Property[] properties,
120103 final Configuration configuration,
121104 final String key) {
122105
123 if (layout == null) {
124 AbstractLifeCycle.LOGGER.error("No layout provided for KafkaAppender");
125 return null;
126 }
127 final KafkaManager kafkaManager = KafkaManager.getManager(configuration.getLoggerContext(), name, topic, true,
128 properties, key);
129 return new KafkaAppender(name, layout, filter, ignoreExceptions, kafkaManager, null, null);
130 }
106 if (layout == null) {
107 AbstractLifeCycle.LOGGER.error("No layout provided for KafkaAppender");
108 return null;
109 }
110 final KafkaManager kafkaManager = KafkaManager.getManager(configuration.getLoggerContext(), name, topic,
111 true, properties, key);
112 return new KafkaAppender(name, layout, filter, ignoreExceptions, kafkaManager, null);
113 }
131114
132 /**
133 * Creates a builder for a KafkaAppender.
134 *
135 * @return a builder for a KafkaAppender.
136 */
137 @PluginBuilderFactory
138 public static <B extends Builder<B>> B newBuilder() {
139 return new Builder<B>().asBuilder();
140 }
115 /**
116 * Creates a builder for a KafkaAppender.
117 * @return a builder for a KafkaAppender.
118 */
119 @PluginBuilderFactory
120 public static <B extends Builder<B>> B newBuilder() {
121 return new Builder<B>().asBuilder();
122 }
141123
142 private final KafkaManager manager;
124 private final KafkaManager manager;
143125
144 private KafkaAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
145 final boolean ignoreExceptions, final KafkaManager manager, final Property[] properties,
146 final Integer retryCount) {
147 super(name, filter, layout, ignoreExceptions, properties);
148 this.manager = Objects.requireNonNull(manager, "manager");
149 this.retryCount = retryCount;
150 }
126 private KafkaAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
127 final boolean ignoreExceptions, final KafkaManager manager, final Property[] properties) {
128 super(name, filter, layout, ignoreExceptions, properties);
129 this.manager = Objects.requireNonNull(manager, "manager");
130 }
151131
152 @Override
153 public void append(final LogEvent event) {
154 if (event.getLoggerName() != null && event.getLoggerName().startsWith("org.apache.kafka")) {
155 LOGGER.warn("Recursive logging from [{}] for appender [{}].", event.getLoggerName(), getName());
156 } else {
157 try {
158 tryAppend(event);
159 } catch (final Exception e) {
132 @Override
133 public void append(final LogEvent event) {
134 if (event.getLoggerName() != null && event.getLoggerName().startsWith("org.apache.kafka")) {
135 LOGGER.warn("Recursive logging from [{}] for appender [{}].", event.getLoggerName(), getName());
136 } else {
137 try {
138 tryAppend(event);
139 } catch (final Exception e) {
140 error("Unable to write to Kafka in appender [" + getName() + "]", event, e);
141 }
142 }
143 }
160144
161 if (this.retryCount != null) {
162 int currentRetryAttempt = 0;
163 while (currentRetryAttempt < this.retryCount) {
164 currentRetryAttempt++;
165 try {
166 tryAppend(event);
167 break;
168 } catch (Exception e1) {
145 private void tryAppend(final LogEvent event) throws ExecutionException, InterruptedException, TimeoutException {
146 final Layout<? extends Serializable> layout = getLayout();
147 byte[] data;
148 if (layout instanceof SerializedLayout) {
149 final byte[] header = layout.getHeader();
150 final byte[] body = layout.toByteArray(event);
151 data = new byte[header.length + body.length];
152 System.arraycopy(header, 0, data, 0, header.length);
153 System.arraycopy(body, 0, data, header.length, body.length);
154 } else {
155 data = layout.toByteArray(event);
156 }
157 manager.send(data);
158 }
169159
170 }
171 }
172 }
173 error("Unable to write to Kafka in appender [" + getName() + "]", event, e);
174 }
175 }
176 }
160 @Override
161 public void start() {
162 super.start();
163 manager.startup();
164 }
177165
178 private void tryAppend(final LogEvent event) throws ExecutionException, InterruptedException, TimeoutException {
179 final Layout<? extends Serializable> layout = getLayout();
180 byte[] data;
181 if (layout instanceof SerializedLayout) {
182 final byte[] header = layout.getHeader();
183 final byte[] body = layout.toByteArray(event);
184 data = new byte[header.length + body.length];
185 System.arraycopy(header, 0, data, 0, header.length);
186 System.arraycopy(body, 0, data, header.length, body.length);
187 } else {
188 data = layout.toByteArray(event);
189 }
190 manager.send(data);
191 }
166 @Override
167 public boolean stop(final long timeout, final TimeUnit timeUnit) {
168 setStopping();
169 boolean stopped = super.stop(timeout, timeUnit, false);
170 stopped &= manager.stop(timeout, timeUnit);
171 setStopped();
172 return stopped;
173 }
192174
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 }
175 @Override
176 public String toString() {
177 return "KafkaAppender{" +
178 "name=" + getName() +
179 ", state=" + getState() +
180 ", topic=" + manager.getTopic() +
181 '}';
182 }
212183 }
2424 import java.util.concurrent.TimeUnit;
2525 import java.util.concurrent.TimeoutException;
2626
27 import org.apache.kafka.clients.producer.Callback;
2728 import org.apache.kafka.clients.producer.Producer;
2829 import org.apache.kafka.clients.producer.ProducerRecord;
2930 import org.apache.kafka.clients.producer.RecordMetadata;
3536
3637 public class KafkaManager extends AbstractManager {
3738
38 public static final String DEFAULT_TIMEOUT_MILLIS = "30000";
39 public static final String DEFAULT_TIMEOUT_MILLIS = "30000";
3940
40 /**
41 * package-private access for testing.
42 */
43 static KafkaProducerFactory producerFactory = new DefaultKafkaProducerFactory();
41 /**
42 * package-private access for testing.
43 */
44 static KafkaProducerFactory producerFactory = new DefaultKafkaProducerFactory();
4445
45 private final Properties config = new Properties();
46 private Producer<byte[], byte[]> producer;
47 private final int timeoutMillis;
46 private final Properties config = new Properties();
47 private Producer<byte[], byte[]> producer;
48 private final int timeoutMillis;
4849
49 private final String topic;
50 private final String key;
51 private final boolean syncSend;
52 private static final KafkaManagerFactory factory = new KafkaManagerFactory();
50 private final String topic;
51 private final String key;
52 private final boolean syncSend;
53 private static final KafkaManagerFactory factory = new KafkaManagerFactory();
5354
54 /*
55 * The Constructor should have been declared private as all Managers are create
56 * by the internal factory;
57 */
58 public KafkaManager(final LoggerContext loggerContext, final String name, final String topic,
59 final boolean syncSend, final Property[] properties, final String key) {
60 super(loggerContext, name);
61 this.topic = Objects.requireNonNull(topic, "topic");
62 this.syncSend = syncSend;
55 /*
56 * The Constructor should have been declared private as all Managers are create by the internal factory;
57 */
58 public KafkaManager(final LoggerContext loggerContext, final String name, final String topic, final boolean syncSend,
59 final Property[] properties, final String key) {
60 super(loggerContext, name);
61 this.topic = Objects.requireNonNull(topic, "topic");
62 this.syncSend = syncSend;
63 config.setProperty("key.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
64 config.setProperty("value.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
65 config.setProperty("batch.size", "0");
66 for (final Property property : properties) {
67 config.setProperty(property.getName(), property.getValue());
68 }
6369
64 config.setProperty("key.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
65 config.setProperty("value.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
66 config.setProperty("batch.size", "0");
70 this.key = key;
6771
68 for (final Property property : properties) {
69 config.setProperty(property.getName(), property.getValue());
70 }
72 this.timeoutMillis = Integer.parseInt(config.getProperty("timeout.ms", DEFAULT_TIMEOUT_MILLIS));
73 }
7174
72 this.key = key;
75 @Override
76 public boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
77 if (timeout > 0) {
78 closeProducer(timeout, timeUnit);
79 } else {
80 closeProducer(timeoutMillis, TimeUnit.MILLISECONDS);
81 }
82 return true;
83 }
7384
74 this.timeoutMillis = Integer.parseInt(config.getProperty("timeout.ms", DEFAULT_TIMEOUT_MILLIS));
75 }
85 private void closeProducer(final long timeout, final TimeUnit timeUnit) {
86 if (producer != null) {
87 // This thread is a workaround for this Kafka issue: https://issues.apache.org/jira/browse/KAFKA-1660
88 final Thread closeThread = new Log4jThread(new Runnable() {
89 @Override
90 public void run() {
91 if (producer != null) {
92 producer.close();
93 }
94 }
95 }, "KafkaManager-CloseThread");
96 closeThread.setDaemon(true); // avoid blocking JVM shutdown
97 closeThread.start();
98 try {
99 closeThread.join(timeUnit.toMillis(timeout));
100 } catch (final InterruptedException ignore) {
101 Thread.currentThread().interrupt();
102 // ignore
103 }
104 }
105 }
76106
77 @Override
78 public boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
79 if (timeout > 0) {
80 closeProducer(timeout, timeUnit);
81 } else {
82 closeProducer(timeoutMillis, TimeUnit.MILLISECONDS);
83 }
84 return true;
85 }
107 public void send(final byte[] msg) throws ExecutionException, InterruptedException, TimeoutException {
108 if (producer != null) {
109 byte[] newKey = null;
86110
87 private void closeProducer(final long timeout, final TimeUnit timeUnit) {
88 if (producer != null) {
89 // This thread is a workaround for this Kafka issue:
90 // https://issues.apache.org/jira/browse/KAFKA-1660
91 final Thread closeThread = new Log4jThread(() -> {
92 if (producer != null) {
93 producer.close();
94 }
95 }, "KafkaManager-CloseThread");
96 closeThread.setDaemon(true); // avoid blocking JVM shutdown
97 closeThread.start();
98 try {
99 closeThread.join(timeUnit.toMillis(timeout));
100 } catch (final InterruptedException ignore) {
101 Thread.currentThread().interrupt();
102 // ignore
103 }
104 }
105 }
111 if(key != null && key.contains("${")) {
112 newKey = getLoggerContext().getConfiguration().getStrSubstitutor().replace(key).getBytes(StandardCharsets.UTF_8);
113 } else if (key != null) {
114 newKey = key.getBytes(StandardCharsets.UTF_8);
115 }
106116
107 public void send(final byte[] msg) throws ExecutionException, InterruptedException, TimeoutException {
108 if (producer != null) {
109 byte[] newKey = null;
117 final ProducerRecord<byte[], byte[]> newRecord = new ProducerRecord<>(topic, newKey, msg);
118 if (syncSend) {
119 final Future<RecordMetadata> response = producer.send(newRecord);
120 response.get(timeoutMillis, TimeUnit.MILLISECONDS);
121 } else {
122 producer.send(newRecord, new Callback() {
123 @Override
124 public void onCompletion(final RecordMetadata metadata, final Exception e) {
125 if (e != null) {
126 LOGGER.error("Unable to write to Kafka in appender [" + getName() + "]", e);
127 }
128 }
129 });
130 }
131 }
132 }
110133
111 if (key != null && key.contains("${")) {
112 newKey = getLoggerContext().getConfiguration().getStrSubstitutor().replace(key)
113 .getBytes(StandardCharsets.UTF_8);
114 } else if (key != null) {
115 newKey = key.getBytes(StandardCharsets.UTF_8);
116 }
134 public void startup() {
135 producer = producerFactory.newKafkaProducer(config);
136 }
117137
118 final ProducerRecord<byte[], byte[]> newRecord = new ProducerRecord<>(topic, newKey, msg);
119 if (syncSend) {
120 final Future<RecordMetadata> response = producer.send(newRecord);
121 response.get(timeoutMillis, TimeUnit.MILLISECONDS);
122 } else {
123 producer.send(newRecord, (metadata, e) -> {
124 if (e != null) {
125 LOGGER.error("Unable to write to Kafka in appender [" + getName() + "]", e);
126 }
127 });
128 }
129 }
130 }
138 public String getTopic() {
139 return topic;
140 }
131141
132 public void startup() {
133 if (producer == null) {
134 producer = producerFactory.newKafkaProducer(config);
135 }
136 }
142 public static KafkaManager getManager(final LoggerContext loggerContext, final String name, final String topic,
143 final boolean syncSend, final Property[] properties, final String key) {
144 StringBuilder sb = new StringBuilder(name);
145 for (Property prop: properties) {
146 sb.append(" ").append(prop.getName()).append("=").append(prop.getValue());
147 }
148 return getManager(sb.toString(), factory, new FactoryData(loggerContext, topic, syncSend, properties, key));
149 }
137150
138 public String getTopic() {
139 return topic;
140 }
151 private static class FactoryData {
152 private final LoggerContext loggerContext;
153 private final String topic;
154 private final boolean syncSend;
155 private final Property[] properties;
156 private final String key;
141157
142 public static KafkaManager getManager(final LoggerContext loggerContext, final String name, final String topic,
143 final boolean syncSend, final Property[] properties, final String key) {
144 StringBuilder sb = new StringBuilder(name);
145 sb.append(" ").append(topic).append(" ").append(syncSend + "");
146 for (Property prop : properties) {
147 sb.append(" ").append(prop.getName()).append("=").append(prop.getValue());
148 }
149 return getManager(sb.toString(), factory, new FactoryData(loggerContext, topic, syncSend, properties, key));
150 }
158 public FactoryData(final LoggerContext loggerContext, final String topic, final boolean syncSend,
159 final Property[] properties, final String key) {
160 this.loggerContext = loggerContext;
161 this.topic = topic;
162 this.syncSend = syncSend;
163 this.properties = properties;
164 this.key = key;
165 }
151166
152 private static class FactoryData {
153 private final LoggerContext loggerContext;
154 private final String topic;
155 private final boolean syncSend;
156 private final Property[] properties;
157 private final String key;
167 }
158168
159 public FactoryData(final LoggerContext loggerContext, final String topic, final boolean syncSend,
160 final Property[] properties, final String key) {
161 this.loggerContext = loggerContext;
162 this.topic = topic;
163 this.syncSend = syncSend;
164 this.properties = properties;
165 this.key = key;
166 }
167
168 }
169
170 private static class KafkaManagerFactory implements ManagerFactory<KafkaManager, FactoryData> {
171 @Override
172 public KafkaManager createManager(String name, FactoryData data) {
173 return new KafkaManager(data.loggerContext, name, data.topic, data.syncSend, data.properties, data.key);
174 }
175 }
169 private static class KafkaManagerFactory implements ManagerFactory<KafkaManager, FactoryData> {
170 @Override
171 public KafkaManager createManager(String name, FactoryData data) {
172 return new KafkaManager(data.loggerContext, name, data.topic, data.syncSend, data.properties, data.key);
173 }
174 }
176175
177176 }
2525 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
2626 import org.apache.logging.log4j.core.util.Closer;
2727 import org.apache.logging.log4j.message.MapMessage;
28 import org.apache.logging.log4j.util.BiConsumer;
2829 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2930
3031 /**
8485
8586 private void setFields(final MapMessage<?, ?> mapMessage, final NoSqlObject<W> noSqlObject) {
8687 // Map without calling org.apache.logging.log4j.message.MapMessage#getData() which makes a copy of the map.
87 mapMessage.forEach((key, value) -> noSqlObject.set(key, value));
88 mapMessage.forEach(new BiConsumer<String, Object>() {
89 @Override
90 public void accept(final String key, final Object value) {
91 noSqlObject.set(key, value);
92 }
93 });
8894 }
8995
9096 private void setFields(final LogEvent event, final NoSqlObject<W> entity) {
140146 entity.set("contextMap", (Object) null);
141147 } else {
142148 final NoSqlObject<W> contextMapEntity = this.connection.createObject();
143 contextMap.forEach((key, val) -> contextMapEntity.set(key, val));
149 contextMap.forEach(new BiConsumer<String, String>() {
150 @Override
151 public void accept(final String key, final String val) {
152 contextMapEntity.set(key, val);
153 }
154 });
144155 entity.set("contextMap", contextMapEntity);
145156 }
146157
6969 private final Map<Level, Level> map;
7070
7171 private LoggerNameLevelRewritePolicy(final String loggerName, final Map<Level, Level> map) {
72 super();
7273 this.loggerName = loggerName;
7374 this.map = map;
7475 }
9090 final StringBuilder buf = new StringBuilder();
9191 final String pattern = manager.getPatternProcessor().getPattern();
9292 manager.getPatternProcessor().formatFileName(strSubstitutor, buf, NotANumber.NAN);
93 final String fileName = manager.isDirectWrite() ? "" : manager.getFileName();
94 return getEligibleFiles(fileName, buf.toString(), pattern, isAscending);
93 return getEligibleFiles(buf.toString(), pattern, isAscending);
9594 }
9695
9796 protected SortedMap<Integer, Path> getEligibleFiles(final String path, final String pattern) {
98 return getEligibleFiles("", path, pattern, true);
97 return getEligibleFiles(path, pattern, true);
9998 }
10099
101 @Deprecated
102 protected SortedMap<Integer, Path> getEligibleFiles(final String path, final String logfilePattern,
103 final boolean isAscending) {
104 return getEligibleFiles("", path, logfilePattern, isAscending);
105 }
106
107 protected SortedMap<Integer, Path> getEligibleFiles(final String currentFile, final String path,
108 final String logfilePattern, final boolean isAscending) {
100 protected SortedMap<Integer, Path> getEligibleFiles(final String path, final String logfilePattern, final boolean isAscending) {
109101 final TreeMap<Integer, Path> eligibleFiles = new TreeMap<>();
110102 final File file = new File(path);
111103 File parent = file.getParentFile();
120112 final Path dir = parent.toPath();
121113 String fileName = file.getName();
122114 final int suffixLength = suffixLength(fileName);
123 // use Pattern.quote to treat all initial parts of the fileName as literal
124 // this fixes issues with filenames containing 'magic' regex characters
125115 if (suffixLength > 0) {
126 fileName = Pattern.quote(fileName.substring(0, fileName.length() - suffixLength)) + ".*";
127 } else {
128 fileName = Pattern.quote(fileName);
116 fileName = fileName.substring(0, fileName.length() - suffixLength) + ".*";
129117 }
130 // since we insert a pattern inside a regex escaped string,
131 // surround it with quote characters so that (\d) is treated as a pattern and not a literal
132 final String filePattern = fileName.replaceFirst("0?\\u0000", "\\\\E(0?\\\\d+)\\\\Q");
118 final String filePattern = fileName.replace(NotANumber.VALUE, "(\\d+)");
133119 final Pattern pattern = Pattern.compile(filePattern);
134 final Path current = currentFile.length() > 0 ? new File(currentFile).toPath() : null;
135 LOGGER.debug("Current file: {}", currentFile);
136120
137121 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
138122 for (final Path entry: stream) {
139123 final Matcher matcher = pattern.matcher(entry.toFile().getName());
140 if (matcher.matches() && !entry.equals(current)) {
141 try {
142 final Integer index = Integer.parseInt(matcher.group(1));
143 eligibleFiles.put(index, entry);
144 } catch (NumberFormatException ex) {
145 LOGGER.debug("Ignoring file {} which matches pattern but the index is invalid.",
146 entry.toFile().getName());
147 }
124 if (matcher.matches()) {
125 final Integer index = Integer.parseInt(matcher.group(1));
126 eligibleFiles.put(index, entry);
148127 }
149128 }
150129 } catch (final IOException ioe) {
469469 // Retrieve the files in descending order, so the highest key will be first.
470470 final SortedMap<Integer, Path> eligibleFiles = getEligibleFiles(manager, false);
471471 final int maxFiles = highIndex - lowIndex + 1;
472 LOGGER.debug("Eligible files: {}", eligibleFiles);
472
473473 while (eligibleFiles.size() >= maxFiles) {
474474 try {
475475 final Integer key = eligibleFiles.firstKey();
580580 .withBasePath(compressedName)
581581 .withFollowLinks(false)
582582 .withMaxDepth(1)
583 .withPathConditions(PathCondition.EMPTY_ARRAY)
583 .withPathConditions(new PathCondition[0])
584584 .withSubst(getStrSubstitutor())
585585 .withFilePermissions(manager.getFilePermissions())
586586 .withFileOwner(manager.getFileOwner())
383383 .withBasePath(compressedName)
384384 .withFollowLinks(false)
385385 .withMaxDepth(1)
386 .withPathConditions(PathCondition.EMPTY_ARRAY)
386 .withPathConditions(new PathCondition[0])
387387 .withSubst(getStrSubstitutor())
388388 .withFilePermissions(manager.getFilePermissions())
389389 .withFileOwner(manager.getFileOwner())
6060 if (matcher.matches()) {
6161 try {
6262 // Get double precision value
63 final double value = NumberFormat.getNumberInstance(Locale.ROOT).parse(
64 matcher.group(1)).doubleValue();
63 final long value = NumberFormat.getNumberInstance(Locale.getDefault()).parse(
64 matcher.group(1)).longValue();
6565
6666 // Get units specified
6767 final String units = matcher.group(3);
6868
6969 if (units.isEmpty()) {
70 return (long) value;
70 return value;
7171 } else if (units.equalsIgnoreCase("K")) {
72 return (long) (value * KB);
72 return value * KB;
7373 } else if (units.equalsIgnoreCase("M")) {
74 return (long) (value * MB);
74 return value * MB;
7575 } else if (units.equalsIgnoreCase("G")) {
76 return (long) (value * GB);
76 return value * GB;
7777 } else {
7878 LOGGER.error("FileSize units not recognized: " + string);
7979 return defaultValue;
5151
5252 private final ArrayPatternConverter[] patternConverters;
5353 private final FormattingInfo[] patternFields;
54 private final FileExtension fileExtension;
5554
5655 private long prevFileTime = 0;
5756 private long nextFileTime = 0;
8685 patternFields = fields.toArray(infoArray);
8786 final ArrayPatternConverter[] converterArray = new ArrayPatternConverter[converters.size()];
8887 patternConverters = converters.toArray(converterArray);
89 this.fileExtension = FileExtension.lookupForFile(pattern);
9088
9189 for (final ArrayPatternConverter converter : patternConverters) {
9290 if (converter instanceof DatePatternConverter) {
128126 public void setPrevFileTime(final long prevFileTime) {
129127 LOGGER.debug("Setting prev file time to {}", new Date(prevFileTime));
130128 this.prevFileTime = prevFileTime;
131 }
132
133 public FileExtension getFileExtension() {
134 return fileExtension;
135129 }
136130
137131 /**
226220 public void updateTime() {
227221 if (nextFileTime != 0 || !isTimeBased) {
228222 prevFileTime = nextFileTime;
229 currentFileTime = 0;
230223 }
231224 }
232225
2828 import java.util.Collection;
2929 import java.util.Date;
3030 import java.util.concurrent.ArrayBlockingQueue;
31 import java.util.concurrent.CopyOnWriteArrayList;
3231 import java.util.concurrent.ExecutorService;
3332 import java.util.concurrent.Semaphore;
3433 import java.util.concurrent.ThreadPoolExecutor;
6766 private final Log4jThreadFactory threadFactory = Log4jThreadFactory.createThreadFactory("RollingFileManager");
6867 private volatile TriggeringPolicy triggeringPolicy;
6968 private volatile RolloverStrategy rolloverStrategy;
70 private volatile boolean renameEmptyFiles;
71 private volatile boolean initialized;
69 private volatile boolean renameEmptyFiles = false;
70 private volatile boolean initialized = false;
7271 private volatile String fileName;
73 private final boolean directWrite;
74 private final CopyOnWriteArrayList<RolloverListener> rolloverListeners = new CopyOnWriteArrayList<>();
72 private final FileExtension fileExtension;
7573
7674 /* This executor pool will create a new Thread for every work async action to be performed. Using it allows
7775 us to make sure all the Threads are completed when the Manager is stopped. */
110108 this.patternProcessor = new PatternProcessor(pattern);
111109 this.patternProcessor.setPrevFileTime(initialTime);
112110 this.fileName = fileName;
113 this.directWrite = rolloverStrategy instanceof DirectWriteRolloverStrategy;
111 this.fileExtension = FileExtension.lookupForFile(pattern);
114112 }
115113
116114 @Deprecated
127125 this.patternProcessor = new PatternProcessor(pattern);
128126 this.patternProcessor.setPrevFileTime(initialTime);
129127 this.fileName = fileName;
130 this.directWrite = rolloverStrategy instanceof DirectWriteRolloverStrategy;
128 this.fileExtension = FileExtension.lookupForFile(pattern);
131129 }
132130
133131 /**
143141 advertiseURI, layout, filePermissions, fileOwner, fileGroup, writeHeader, buffer);
144142 this.size = size;
145143 this.initialTime = initialTime;
144 this.triggeringPolicy = triggeringPolicy;
145 this.rolloverStrategy = rolloverStrategy;
146146 this.patternProcessor = new PatternProcessor(pattern);
147147 this.patternProcessor.setPrevFileTime(initialTime);
148 this.triggeringPolicy = triggeringPolicy;
149 this.rolloverStrategy = rolloverStrategy;
150148 this.fileName = fileName;
151 this.directWrite = rolloverStrategy instanceof DirectFileRolloverStrategy;
149 this.fileExtension = FileExtension.lookupForFile(pattern);
152150 }
153151
154152 public void initialize() {
156154 if (!initialized) {
157155 LOGGER.debug("Initializing triggering policy {}", triggeringPolicy);
158156 initialized = true;
159 // LOG4J2-2981 - set the file size before initializing the triggering policy.
160 if (directWrite) {
161 // LOG4J2-2485: Initialize size from the most recently written file.
162 File file = new File(getFileName());
163 if (file.exists()) {
164 size = file.length();
165 } else {
166 ((DirectFileRolloverStrategy) rolloverStrategy).clearCurrentFileName();
167 }
168 }
169157 triggeringPolicy.initialize(this);
170158 if (triggeringPolicy instanceof LifeCycle) {
171159 ((LifeCycle) triggeringPolicy).start();
172160 }
173 if (directWrite) {
161 if (rolloverStrategy instanceof DirectFileRolloverStrategy) {
174162 // LOG4J2-2485: Initialize size from the most recently written file.
175163 File file = new File(getFileName());
176164 if (file.exists()) {
219207 }
220208
221209 /**
222 * Add a RolloverListener.
223 * @param listener The RolloverListener.
224 */
225 public void addRolloverListener(RolloverListener listener) {
226 rolloverListeners.add(listener);
227 }
228
229 /**
230 * Remove a RolloverListener.
231 * @param listener The RolloverListener.
232 */
233 public void removeRolloverListener(RolloverListener listener) {
234 rolloverListeners.remove(listener);
235 }
236
237 /**
238210 * Returns the name of the File being managed.
239211 * @return The name of the File being managed.
240212 */
241213 @Override
242214 public String getFileName() {
243 if (directWrite) {
215 if (rolloverStrategy instanceof DirectFileRolloverStrategy) {
244216 fileName = ((DirectFileRolloverStrategy) rolloverStrategy).getCurrentFileName(this);
245217 }
246218 return fileName;
247219 }
248
249 @Override
250 protected void createParentDir(File file) {
251 if (directWrite) {
252 file.getParentFile().mkdirs();
253 }
254 }
255
256 public boolean isDirectWrite() {
257 return directWrite;
258 }
259220
260221 public FileExtension getFileExtension() {
261 return patternProcessor.getFileExtension();
222 return fileExtension;
262223 }
263224
264225 // override to make visible for unit tests
367328 }
368329
369330 public synchronized void rollover() {
370 if (!hasOutputStream() && !isCreateOnDemand() && !isDirectWrite()) {
331 if (!hasOutputStream()) {
371332 return;
372333 }
373 String currentFileName = fileName;
374 if (rolloverListeners.size() > 0) {
375 for (RolloverListener listener : rolloverListeners) {
376 try {
377 listener.rolloverTriggered(currentFileName);
378 } catch (Exception ex) {
379 LOGGER.warn("Rollover Listener {} failed with {}: {}", listener.getClass().getSimpleName(),
380 ex.getClass().getName(), ex.getMessage());
381 }
382 }
383 }
384
385 boolean interrupted = Thread.interrupted(); // clear interrupted state
386 try {
387 if (interrupted) {
388 LOGGER.warn("RollingFileManager cleared thread interrupted state, continue to rollover");
389 }
390
391 if (rollover(rolloverStrategy)) {
392 try {
393 size = 0;
394 initialTime = System.currentTimeMillis();
395 createFileAfterRollover();
396 } catch (final IOException e) {
397 logError("Failed to create file after rollover", e);
398 }
399 }
400 } finally {
401 if (interrupted) { // restore interrupted state
402 Thread.currentThread().interrupt();
403 }
404 }
405 if (rolloverListeners.size() > 0) {
406 for (RolloverListener listener : rolloverListeners) {
407 try {
408 listener.rolloverComplete(currentFileName);
409 } catch (Exception ex) {
410 LOGGER.warn("Rollover Listener {} failed with {}: {}", listener.getClass().getSimpleName(),
411 ex.getClass().getName(), ex.getMessage());
412 }
334 if (rollover(rolloverStrategy)) {
335 try {
336 size = 0;
337 initialTime = System.currentTimeMillis();
338 createFileAfterRollover();
339 } catch (final IOException e) {
340 logError("Failed to create file after rollover", e);
413341 }
414342 }
415343 }
442370 if (policy instanceof LifeCycle) {
443371 ((LifeCycle) policy).stop();
444372 }
445 } else if (triggeringPolicy instanceof LifeCycle) {
446 ((LifeCycle) triggeringPolicy).stop();
373 } else {
374 if (triggeringPolicy instanceof LifeCycle) {
375 ((LifeCycle) triggeringPolicy).stop();
376 }
447377 }
448378 }
449379
464394 public <T extends TriggeringPolicy> T getTriggeringPolicy() {
465395 // TODO We could parameterize this class with a TriggeringPolicy instead of type casting here.
466396 return (T) this.triggeringPolicy;
467 }
468
469 /**
470 * Package-private access for tests only.
471 *
472 * @return The semaphore that controls access to the rollover operation.
473 */
474 Semaphore getSemaphore() {
475 return semaphore;
476397 }
477398
478399 /**
695616 }
696617 }
697618
698 /**
699 * Updates the RollingFileManager's data during a reconfiguration. This method should be considered private.
700 * It is not thread safe and calling it outside of a reconfiguration may lead to errors. This method may be
701 * made protected in a future release.
702 * @param data The data to update.
703 */
704619 @Override
705620 public void updateData(final Object data) {
706621 final FactoryData factoryData = (FactoryData) data;
707622 setRolloverStrategy(factoryData.getRolloverStrategy());
623 setTriggeringPolicy(factoryData.getTriggeringPolicy());
708624 setPatternProcessor(new PatternProcessor(factoryData.getPattern(), getPatternProcessor()));
709 setTriggeringPolicy(factoryData.getTriggeringPolicy());
710625 }
711626
712627 /**
723638 @Override
724639 public RollingFileManager createManager(final String name, final FactoryData data) {
725640 long size = 0;
641 boolean writeHeader = !data.append;
726642 File file = null;
727643 if (data.fileName != null) {
728644 file = new File(data.fileName);
645 // LOG4J2-1140: check writeHeader before creating the file
646 writeHeader = !data.append || !file.exists();
729647
730648 try {
731649 FileUtils.makeParentDirs(file);
743661 final ByteBuffer buffer = ByteBuffer.wrap(new byte[actualSize]);
744662 final OutputStream os = data.createOnDemand || data.fileName == null ? null :
745663 new FileOutputStream(data.fileName, data.append);
746 // LOG4J2-531 create file first so time has valid value.
747 final long initialTime = file == null || !file.exists() ? 0 : initialFileTime(file);
748 final boolean writeHeader = file != null && file.exists() && file.length() == 0;
664 final long initialTime = data.createOnDemand || file == null ?
665 0 : initialFileTime(file); // LOG4J2-531 create file first so time has valid value
749666
750667 final RollingFileManager rm = new RollingFileManager(data.getLoggerContext(), data.fileName, data.pattern, os,
751668 data.append, data.createOnDemand, size, initialTime, data.policy, data.strategy, data.advertiseURI,
2121 import java.io.RandomAccessFile;
2222 import java.io.Serializable;
2323 import java.nio.ByteBuffer;
24 import java.nio.file.Paths;
2524
2625 import org.apache.logging.log4j.core.Layout;
2726 import org.apache.logging.log4j.core.LoggerContext;
4544 private static final RollingRandomAccessFileManagerFactory FACTORY = new RollingRandomAccessFileManagerFactory();
4645
4746 private RandomAccessFile randomAccessFile;
47 private final ThreadLocal<Boolean> isEndOfBatch = new ThreadLocal<>();
4848
4949 @Deprecated
5050 public RollingRandomAccessFileManager(final LoggerContext loggerContext, final RandomAccessFile raf,
6969 super(loggerContext, fileName, pattern, os, append, false, size, initialTime, policy, strategy, advertiseURI,
7070 layout, filePermissions, fileOwner, fileGroup, writeHeader, ByteBuffer.wrap(new byte[bufferSize]));
7171 this.randomAccessFile = raf;
72 isEndOfBatch.set(Boolean.FALSE);
7273 writeHeader();
7374 }
7475
108109 filePermissions, fileOwner, fileGroup, configuration), FACTORY));
109110 }
110111
111 /**
112 * No longer used, the {@link org.apache.logging.log4j.core.LogEvent#isEndOfBatch()} attribute is used instead.
113 * @return {@link Boolean#FALSE}.
114 * @deprecated end-of-batch on the event is used instead.
115 */
116 @Deprecated
117112 public Boolean isEndOfBatch() {
118 return Boolean.FALSE;
119 }
120
121 /**
122 * No longer used, the {@link org.apache.logging.log4j.core.LogEvent#isEndOfBatch()} attribute is used instead.
123 * This method is a no-op.
124 * @deprecated end-of-batch on the event is used instead.
125 */
126 @Deprecated
127 public void setEndOfBatch(@SuppressWarnings("unused") final boolean endOfBatch) {
113 return isEndOfBatch.get();
114 }
115
116 public void setEndOfBatch(final boolean endOfBatch) {
117 this.isEndOfBatch.set(Boolean.valueOf(endOfBatch));
128118 }
129119
130120 // override to make visible for unit tests
158148
159149 private void createFileAfterRollover(final String fileName) throws IOException {
160150 this.randomAccessFile = new RandomAccessFile(fileName, "rw");
161 if (isAttributeViewEnabled()) {
162 defineAttributeView(Paths.get(fileName));
163 }
164151 if (isAppend()) {
165152 randomAccessFile.seek(randomAccessFile.length());
166153 }
329316
330317 }
331318
332 /**
333 * Updates the RollingFileManager's data during a reconfiguration. This method should be considered private.
334 * It is not thread safe and calling it outside of a reconfiguration may lead to errors. This method may be
335 * made protected in a future release.
336 * @param data The data to update.
337 */
338319 @Override
339320 public void updateData(final Object data) {
340321 final FactoryData factoryData = (FactoryData) data;
341322 setRolloverStrategy(factoryData.getRolloverStrategy());
323 setTriggeringPolicy(factoryData.getTriggeringPolicy());
342324 setPatternProcessor(new PatternProcessor(factoryData.getPattern(), getPatternProcessor()));
343 setTriggeringPolicy(factoryData.getTriggeringPolicy());
344325 }
345326 }
+0
-37
log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RolloverListener.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.logging.log4j.core.appender.rolling;
17
18 /**
19 * Implementations of this interface that are registered with the RollingFileManager will be notified before and
20 * after a rollover occurs. This is a synchronous call so Listeners should exit the methods as fast as possible.
21 * It is recommended that they simply notify some other already active thread.
22 */
23 public interface RolloverListener {
24
25 /**
26 * Called before rollover.
27 * @param fileName The name of the file rolling over.
28 */
29 void rolloverTriggered(String fileName);
30
31 /**
32 * Called after rollover.
33 * @param fileName The name of the file rolling over.
34 */
35 void rolloverComplete(String fileName);
36 }
137137 }
138138
139139 /**
140 * Returns the maximum number of directory levels to visit.
140 * Returns the the maximum number of directory levels to visit.
141141 *
142142 * @return the maxDepth
143143 */
1919 import java.io.IOException;
2020 import java.nio.file.FileVisitResult;
2121 import java.nio.file.Files;
22 import java.nio.file.NoSuchFileException;
2322 import java.nio.file.Path;
2423 import java.nio.file.SimpleFileVisitor;
2524 import java.nio.file.attribute.BasicFileAttributes;
7574 return FileVisitResult.CONTINUE;
7675 }
7776
78 @Override
79 public FileVisitResult visitFileFailed(Path file, IOException ioException) throws IOException {
80 // LOG4J2-2677: Appenders may rollover and purge in parallel. SimpleVisitor rethrows exceptions from
81 // failed attempts to load file attributes.
82 if (ioException instanceof NoSuchFileException) {
83 LOGGER.info("File {} could not be accessed, it has likely already been deleted", file, ioException);
84 return FileVisitResult.CONTINUE;
85 } else {
86 return super.visitFileFailed(file, ioException);
87 }
88 }
89
9077 /**
9178 * Deletes the specified file.
9279 *
7777 * @param seconds the length of the duration in seconds, positive or negative
7878 */
7979 private Duration(final long seconds) {
80 super();
8081 this.seconds = seconds;
8182 }
8283
1818 import java.io.File;
1919 import java.io.IOException;
2020 import java.io.PrintWriter;
21 import java.nio.file.AtomicMoveNotSupportedException;
2221 import java.nio.file.Files;
23 import java.nio.file.Path;
2422 import java.nio.file.Paths;
2523 import java.nio.file.StandardCopyOption;
2624
117115 }
118116 try {
119117 try {
120 return moveFile(Paths.get(source.getAbsolutePath()), Paths.get(destination.getAbsolutePath()));
118 Files.move(Paths.get(source.getAbsolutePath()), Paths.get(destination.getAbsolutePath()),
119 StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
120 LOGGER.trace("Renamed file {} to {} with Files.move", source.getAbsolutePath(),
121 destination.getAbsolutePath());
122 return true;
121123 } catch (final IOException exMove) {
122 LOGGER.debug("Unable to move file {} to {}: {} {} - will try to copy and delete",
123 source.getAbsolutePath(), destination.getAbsolutePath(), exMove.getClass().getName(),
124 exMove.getMessage());
124 LOGGER.error("Unable to move file {} to {}: {} {}", source.getAbsolutePath(),
125 destination.getAbsolutePath(), exMove.getClass().getName(), exMove.getMessage());
125126 boolean result = source.renameTo(destination);
126127 if (!result) {
127128 try {
136137 LOGGER.error("Unable to delete file {}: {} {}", source.getAbsolutePath(),
137138 exDelete.getClass().getName(), exDelete.getMessage());
138139 try {
139 result = true;
140140 new PrintWriter(source.getAbsolutePath()).close();
141141 LOGGER.trace("Renamed file {} to {} with copy and truncation",
142142 source.getAbsolutePath(), destination.getAbsolutePath());
172172 return false;
173173 }
174174
175 private static boolean moveFile(Path source, Path target) throws IOException {
176 try {
177 Files.move(source, target,
178 StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
179 LOGGER.trace("Renamed file {} to {} with Files.move", source.toFile().getAbsolutePath(),
180 target.toFile().getAbsolutePath());
181 return true;
182 } catch (final AtomicMoveNotSupportedException ex) {
183 Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
184 LOGGER.trace("Renamed file {} to {} with Files.move", source.toFile().getAbsolutePath(),
185 target.toFile().getAbsolutePath());
186 return true;
187 }
188 }
189
190175 @Override
191176 public String toString() {
192177 return FileRenameAction.class.getSimpleName() + '[' + source + " to " + destination
3939 private int count;
4040 private final PathCondition[] nestedConditions;
4141
42 private IfAccumulatedFileCount(final int thresholdParam, final PathCondition... nestedConditions) {
42 private IfAccumulatedFileCount(final int thresholdParam, final PathCondition[] nestedConditions) {
4343 if (thresholdParam <= 0) {
4444 throw new IllegalArgumentException("Count must be a positive integer but was " + thresholdParam);
4545 }
4646 this.threshold = thresholdParam;
47 this.nestedConditions = PathCondition.copy(nestedConditions);
47 this.nestedConditions = nestedConditions == null ? new PathCondition[0] : Arrays.copyOf(nestedConditions,
48 nestedConditions.length);
4849 }
4950
5051 public int getThresholdCount() {
4040 private long accumulatedSize;
4141 private final PathCondition[] nestedConditions;
4242
43 private IfAccumulatedFileSize(final long thresholdSize, final PathCondition... nestedConditions) {
43 private IfAccumulatedFileSize(final long thresholdSize, final PathCondition[] nestedConditions) {
4444 if (thresholdSize <= 0) {
4545 throw new IllegalArgumentException("Count must be a positive integer but was " + thresholdSize);
4646 }
4747 this.thresholdBytes = thresholdSize;
48 this.nestedConditions = PathCondition.copy(nestedConditions);
48 this.nestedConditions = nestedConditions == null ? new PathCondition[0] : Arrays.copyOf(nestedConditions,
49 nestedConditions.length);
4950 }
5051
5152 public long getThresholdBytes() {
5656 * @param regex the regular expression that matches the baseDir-relative path of the file(s) to delete
5757 * @param nestedConditions nested conditions to evaluate if this condition accepts a path
5858 */
59 private IfFileName(final String glob, final String regex, final PathCondition... nestedConditions) {
59 private IfFileName(final String glob, final String regex, final PathCondition[] nestedConditions) {
6060 if (regex == null && glob == null) {
6161 throw new IllegalArgumentException("Specify either a path glob or a regular expression. "
6262 + "Both cannot be null.");
6363 }
6464 this.syntaxAndPattern = createSyntaxAndPatternString(glob, regex);
6565 this.pathMatcher = FileSystems.getDefault().getPathMatcher(syntaxAndPattern);
66 this.nestedConditions = PathCondition.copy(nestedConditions);
66 this.nestedConditions = nestedConditions == null ? new PathCondition[0] : Arrays.copyOf(nestedConditions,
67 nestedConditions.length);
6768 }
6869
6970 static String createSyntaxAndPatternString(final String glob, final String regex) {
4646
4747 private IfLastModified(final Duration age, final PathCondition[] nestedConditions) {
4848 this.age = Objects.requireNonNull(age, "age");
49 this.nestedConditions = PathCondition.copy(nestedConditions);
49 this.nestedConditions = nestedConditions == null ? new PathCondition[0] : Arrays.copyOf(nestedConditions,
50 nestedConditions.length);
5051 }
5152
5253 public Duration getAge() {
1919 import java.nio.file.Files;
2020 import java.nio.file.Path;
2121 import java.nio.file.attribute.BasicFileAttributes;
22 import java.util.Arrays;
2322
2423 /**
2524 * Filter that accepts or rejects a candidate {@code Path} for deletion.
2625 */
2726 public interface PathCondition {
28
29 /**
30 * The empty array.
31 */
32 static final PathCondition[] EMPTY_ARRAY = {};
3327
34 /**
35 * Copies the given input.
36 *
37 * @param source What to copy
38 * @return a copy, never null.
39 */
40 static PathCondition[] copy(PathCondition... source) {
41 return source == null || source.length == 0 ? EMPTY_ARRAY : Arrays.copyOf(source, source.length);
42 }
43
4428 /**
4529 * Invoked before a new {@linkplain Files#walkFileTree(Path, java.util.Set, int, java.nio.file.FileVisitor) file
4630 * tree walk} is started. Stateful PathConditions can reset their state when this method is called.
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.status.StatusLogger;
21
2219 import java.io.IOException;
2320 import java.nio.file.FileVisitResult;
24 import java.nio.file.NoSuchFileException;
2521 import java.nio.file.Path;
2622 import java.nio.file.SimpleFileVisitor;
2723 import java.nio.file.attribute.BasicFileAttributes;
3531 */
3632 public class SortingVisitor extends SimpleFileVisitor<Path> {
3733
38 private static final Logger LOGGER = StatusLogger.getLogger();
3934 private final PathSorter sorter;
4035 private final List<PathWithAttributes> collected = new ArrayList<>();
4136
5550 return FileVisitResult.CONTINUE;
5651 }
5752
58 @Override
59 public FileVisitResult visitFileFailed(Path file, IOException ioException) throws IOException {
60 // LOG4J2-2677: Appenders may rollover and purge in parallel. SimpleVisitor rethrows exceptions from
61 // failed attempts to load file attributes.
62 if (ioException instanceof NoSuchFileException) {
63 LOGGER.info("File {} could not be accessed, it has likely already been deleted", file, ioException);
64 return FileVisitResult.CONTINUE;
65 } else {
66 return super.visitFileFailed(file, ioException);
67 }
68 }
69
7053 public List<PathWithAttributes> getSortedPaths() {
7154 Collections.sort(collected, sorter);
7255 return collected;
102102 LOGGER.error("A route cannot be configured with an appender reference and an appender definition");
103103 return null;
104104 }
105 } else if (appenderRef == null) {
106 LOGGER.error("A route must specify an appender reference or an appender definition");
107 return null;
105 } else {
106 if (appenderRef == null) {
107 LOGGER.error("A route must specify an appender reference or an appender definition");
108 return null;
109 }
108110 }
109111 return new Route(node, appenderRef, key);
110112 }
6565 LOGGER.error("No Routes configured.");
6666 return null;
6767 }
68 if ((patternScript != null && pattern != null) || (patternScript == null && pattern == null)) {
68 if (patternScript != null && pattern != null) {
6969 LOGGER.warn("In a Routes element, you must configure either a Script element or a pattern attribute.");
7070 }
7171 if (patternScript != null) {
223223 event = rewritePolicy.rewrite(event);
224224 }
225225 final String pattern = routes.getPattern(event, scriptStaticVariables);
226 final String key = pattern != null ? configuration.getStrSubstitutor().replace(event, pattern) :
227 defaultRoute.getKey() != null ? defaultRoute.getKey() : DEFAULT_KEY;
226 final String key = pattern != null ? configuration.getStrSubstitutor().replace(event, pattern) : defaultRoute.getKey();
228227 final RouteAppenderControl control = getControl(key, event);
229228 if (control != null) {
230229 try {
336335 // Don't attempt to stop the appender in a synchronized block, since it may block flushing events
337336 // to disk.
338337 control.tryStopAppender();
339 } else if (referencedAppenders.containsKey(key)) {
340 LOGGER.debug("Route {} using an appender reference may not be removed because " +
341 "the appender may be used outside of the RoutingAppender", key);
342338 } else {
343 LOGGER.debug("Route with {} key already deleted", key);
339 if (referencedAppenders.containsKey(key)) {
340 LOGGER.debug("Route {} using an appender reference may not be removed because " +
341 "the appender may be used outside of the RoutingAppender", key);
342 } else {
343 LOGGER.debug("Route with {} key already deleted", key);
344 }
344345 }
345346 }
346347
432433
433434 private static final class CreatedRouteAppenderControl extends RouteAppenderControl {
434435
435 private volatile boolean pendingDeletion;
436 private volatile boolean pendingDeletion = false;
436437 private final AtomicInteger depth = new AtomicInteger();
437438
438439 CreatedRouteAppenderControl(Appender appender) {
4747 /**
4848 * AsyncLogger is a logger designed for high throughput and low latency logging. It does not perform any I/O in the
4949 * calling (application) thread, but instead hands off the work to another thread as soon as possible. The actual
50 * logging is performed in the background thread. It uses <a href="https://lmax-exchange.github.io/disruptor/">LMAX
51 * Disruptor</a> for inter-thread communication.
50 * logging is performed in the background thread. It uses the LMAX Disruptor library for inter-thread communication. (<a
51 * href="http://lmax-exchange.github.com/disruptor/" >http://lmax-exchange.github.com/disruptor/</a>)
5252 * <p>
5353 * To use AsyncLogger, specify the System property
5454 * {@code -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector} before you obtain a
236236 AsyncQueueFullMessageUtil.logWarningToStatusLogger();
237237 logMessageInCurrentThread(translator.fqcn, translator.level, translator.marker, translator.message,
238238 translator.thrown);
239 translator.clear();
240239 return;
241240 }
242241 final EventRoute eventRoute = loggerDisruptor.getEventRoute(translator.level);
247246 case SYNCHRONOUS:
248247 logMessageInCurrentThread(translator.fqcn, translator.level, translator.marker, translator.message,
249248 translator.thrown);
250 translator.clear();
251249 break;
252250 case DISCARD:
253 translator.clear();
254251 break;
255252 default:
256253 throw new IllegalStateException("Unknown EventRoute " + eventRoute);
4747 * AsyncLoggerConfig is a logger designed for high throughput and low latency
4848 * logging. It does not perform any I/O in the calling (application) thread, but
4949 * instead hands off the work to another thread as soon as possible. The actual
50 * logging is performed in the background thread. It uses
51 * <a href="https://lmax-exchange.github.io/disruptor/">LMAX Disruptor</a> for
52 * inter-thread communication.
50 * logging is performed in the background thread. It uses the LMAX Disruptor
51 * library for inter-thread communication. (<a
52 * href="http://lmax-exchange.github.com/disruptor/"
53 * >http://lmax-exchange.github.com/disruptor/</a>)
5354 * <p>
5455 * To use AsyncLoggerConfig, specify {@code <asyncLogger>} or
5556 * {@code <asyncRoot>} in configuration.
5656
5757 /**
5858 * Notifies the delegate what LogEventFactory an AsyncLoggerConfig is using, so the delegate can determine
59 * whether to populate the ring buffer with mutable log events or not. This method may be invoked multiple times
59 * whether to populate the ring buffer with mutable log events or not. This method may be invoced multiple times
6060 * for all AsyncLoggerConfigs that use this delegate.
6161 *
6262 * @param logEventFactory the factory used
2626 import org.apache.logging.log4j.core.impl.MutableLogEvent;
2727 import org.apache.logging.log4j.core.impl.ReusableLogEventFactory;
2828 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
29 import org.apache.logging.log4j.core.util.Log4jThread;
3029 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
3130 import org.apache.logging.log4j.core.util.Throwables;
3231 import org.apache.logging.log4j.message.ReusableMessage;
130129 * Factory used to populate the RingBuffer with events. These event objects are then re-used during the life of the
131130 * RingBuffer.
132131 */
133 private static final EventFactory<Log4jEventWrapper> FACTORY = Log4jEventWrapper::new;
132 private static final EventFactory<Log4jEventWrapper> FACTORY = new EventFactory<Log4jEventWrapper>() {
133 @Override
134 public Log4jEventWrapper newInstance() {
135 return new Log4jEventWrapper();
136 }
137 };
134138
135139 /**
136140 * Factory used to populate the RingBuffer with events. These event objects are then re-used during the life of the
137141 * RingBuffer.
138142 */
139 private static final EventFactory<Log4jEventWrapper> MUTABLE_FACTORY = () -> new Log4jEventWrapper(new MutableLogEvent());
143 private static final EventFactory<Log4jEventWrapper> MUTABLE_FACTORY = new EventFactory<Log4jEventWrapper>() {
144 @Override
145 public Log4jEventWrapper newInstance() {
146 return new Log4jEventWrapper(new MutableLogEvent());
147 }
148 };
140149
141150 /**
142151 * Object responsible for passing on data to a specific RingBuffer event.
143152 */
144153 private static final EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> TRANSLATOR =
145 (ringBufferElement, sequence, logEvent, loggerConfig) -> {
146 ringBufferElement.event = logEvent;
147 ringBufferElement.loggerConfig = loggerConfig;
148 };
154 new EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig>() {
155
156 @Override
157 public void translateTo(final Log4jEventWrapper ringBufferElement, final long sequence,
158 final LogEvent logEvent, final AsyncLoggerConfig loggerConfig) {
159 ringBufferElement.event = logEvent;
160 ringBufferElement.loggerConfig = loggerConfig;
161 }
162 };
149163
150164 /**
151165 * Object responsible for passing on data to a RingBuffer event with a MutableLogEvent.
152166 */
153167 private static final EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> MUTABLE_TRANSLATOR =
154 (ringBufferElement, sequence, logEvent, loggerConfig) -> {
155 ((MutableLogEvent) ringBufferElement.event).initFrom(logEvent);
156 ringBufferElement.loggerConfig = loggerConfig;
157 };
168 new EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig>() {
169
170 @Override
171 public void translateTo(final Log4jEventWrapper ringBufferElement, final long sequence,
172 final LogEvent logEvent, final AsyncLoggerConfig loggerConfig) {
173 ((MutableLogEvent) ringBufferElement.event).initFrom(logEvent);
174 ringBufferElement.loggerConfig = loggerConfig;
175 }
176 };
158177
159178 private int ringBufferSize;
160179 private AsyncQueueFullPolicy asyncQueueFullPolicy;
164183 private long backgroundThreadId; // LOG4J2-471
165184 private EventFactory<Log4jEventWrapper> factory;
166185 private EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> translator;
167 private volatile boolean alreadyLoggedWarning;
186 private volatile boolean alreadyLoggedWarning = false;
168187
169188 private final Object queueFullEnqueueLock = new Object();
170189
363382 private boolean synchronizeEnqueueWhenQueueFull() {
364383 return DisruptorUtil.ASYNC_CONFIG_SYNCHRONIZE_ENQUEUE_WHEN_QUEUE_FULL
365384 // Background thread must never block
366 && backgroundThreadId != Thread.currentThread().getId()
367 // Threads owned by log4j are most likely to result in
368 // deadlocks because they generally consume events.
369 // This prevents deadlocks between AsyncLoggerContext
370 // disruptors.
371 && !(Thread.currentThread() instanceof Log4jThread);
385 && backgroundThreadId != Thread.currentThread().getId();
372386 }
373387
374388 @Override
2424 import org.apache.logging.log4j.Marker;
2525 import org.apache.logging.log4j.core.AbstractLifeCycle;
2626 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
27 import org.apache.logging.log4j.core.util.Log4jThread;
2827 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
2928 import org.apache.logging.log4j.core.util.Throwables;
3029
8584 contextName);
8685 return;
8786 }
88 if (isStarting()) {
89 LOGGER.trace("[{}] AsyncLoggerDisruptor is already starting.", contextName);
90 return;
91 }
92 setStarting();
9387 LOGGER.trace("[{}] AsyncLoggerDisruptor creating new disruptor for this context.", contextName);
9488 ringBufferSize = DisruptorUtil.calculateRingBufferSize("AsyncLogger.RingBufferSize");
9589 final WaitStrategy waitStrategy = DisruptorUtil.createWaitStrategy("AsyncLogger.WaitStrategy");
286280 private boolean synchronizeEnqueueWhenQueueFull() {
287281 return DisruptorUtil.ASYNC_LOGGER_SYNCHRONIZE_ENQUEUE_WHEN_QUEUE_FULL
288282 // Background thread must never block
289 && backgroundThreadId != Thread.currentThread().getId()
290 // Threads owned by log4j are most likely to result in
291 // deadlocks because they generally consume events.
292 // This prevents deadlocks between AsyncLoggerContext
293 // disruptors.
294 && !(Thread.currentThread() instanceof Log4jThread);
283 && backgroundThreadId != Thread.currentThread().getId();
295284 }
296285
297286 private void logWarningOnNpeFromDisruptorPublish(final RingBufferLogEventTranslator translator) {
+0
-84
log4j-core/src/main/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelector.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.logging.log4j.core.async;
17
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.core.impl.ContextAnchor;
20 import org.apache.logging.log4j.core.selector.ContextSelector;
21
22 import java.net.URI;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.concurrent.TimeUnit;
27
28 /**
29 * Returns either this Thread's context or the default {@link AsyncLoggerContext}.
30 * Single-application instances should prefer this implementation over the {@link AsyncLoggerContextSelector}
31 * due the the reduced overhead avoiding classloader lookups.
32 */
33 public class BasicAsyncLoggerContextSelector implements ContextSelector {
34
35 private static final AsyncLoggerContext CONTEXT = new AsyncLoggerContext("AsyncDefault");
36
37 @Override
38 public void shutdown(String fqcn, ClassLoader loader, boolean currentContext, boolean allContexts) {
39 LoggerContext ctx = getContext(fqcn, loader, currentContext);
40 if (ctx != null && ctx.isStarted()) {
41 ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
42 }
43 }
44
45 @Override
46 public boolean hasContext(String fqcn, ClassLoader loader, boolean currentContext) {
47 LoggerContext ctx = getContext(fqcn, loader, currentContext);
48 return ctx != null && ctx.isStarted();
49 }
50
51 @Override
52 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
53 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
54 return ctx != null ? ctx : CONTEXT;
55 }
56
57
58 @Override
59 public LoggerContext getContext(
60 final String fqcn,
61 final ClassLoader loader,
62 final boolean currentContext,
63 final URI configLocation) {
64 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
65 return ctx != null ? ctx : CONTEXT;
66 }
67
68 @Override
69 public void removeContext(final LoggerContext context) {
70 // does not remove anything
71 }
72
73 @Override
74 public boolean isClassLoaderDependent() {
75 return false;
76 }
77
78 @Override
79 public List<LoggerContext> getLoggerContexts() {
80 return Collections.singletonList(CONTEXT);
81 }
82
83 }
1616 package org.apache.logging.log4j.core.async;
1717
1818 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.util.Log4jThread;
2019
2120 /**
2221 * Default router: enqueue the event for asynchronous logging in the background thread, unless the current thread is the
2928
3029 // LOG4J2-471: prevent deadlock when RingBuffer is full and object
3130 // being logged calls Logger.log() from its toString() method
32 Thread currentThread = Thread.currentThread();
33 if (currentThread.getId() == backgroundThreadId
34 // Threads owned by log4j are most likely to result in
35 // deadlocks because they generally consume events.
36 // This prevents deadlocks between AsyncLoggerContext
37 // disruptors.
38 || currentThread instanceof Log4jThread) {
31 if (Thread.currentThread().getId() == backgroundThreadId) {
3932 return EventRoute.SYNCHRONOUS;
4033 }
4134 return EventRoute.ENQUEUE;
1616
1717 package org.apache.logging.log4j.core.async;
1818
19 import java.util.Locale;
20 import java.util.concurrent.Callable;
1921 import java.util.concurrent.ExecutorService;
2022 import java.util.concurrent.Future;
2123 import java.util.concurrent.TimeUnit;
3335 import org.apache.logging.log4j.core.util.Loader;
3436 import org.apache.logging.log4j.status.StatusLogger;
3537 import org.apache.logging.log4j.util.PropertiesUtil;
36 import org.apache.logging.log4j.util.Strings;
3738
3839 /**
3940 * Utility methods for getting Disruptor related configuration.
5859 private DisruptorUtil() {
5960 }
6061
61 static WaitStrategy createWaitStrategy(final String propertyName) {
62 final String strategy = PropertiesUtil.getProperties().getStringProperty(propertyName, "Timeout");
63 LOGGER.trace("property {}={}", propertyName, strategy);
64 final String strategyUp = Strings.toRootUpperCase(strategy);
65 final long timeoutMillis = parseAdditionalLongProperty(propertyName, "Timeout", 10L);
66 // String (not enum) is deliberately used here to avoid IllegalArgumentException being thrown. In case of
67 // incorrect property value, default WaitStrategy is created.
68 switch (strategyUp) {
69 case "SLEEP":
70 final long sleepTimeNs =
71 parseAdditionalLongProperty(propertyName, "SleepTimeNs", 100L);
72 final String key = getFullPropertyKey(propertyName, "Retries");
73 final int retries =
74 PropertiesUtil.getProperties().getIntegerProperty(key, 200);
75 return new SleepingWaitStrategy(retries, sleepTimeNs);
76 case "YIELD":
77 return new YieldingWaitStrategy();
78 case "BLOCK":
79 return new BlockingWaitStrategy();
80 case "BUSYSPIN":
81 return new BusySpinWaitStrategy();
82 case "TIMEOUT":
83 return new TimeoutBlockingWaitStrategy(timeoutMillis, TimeUnit.MILLISECONDS);
84 default:
85 return new TimeoutBlockingWaitStrategy(timeoutMillis, TimeUnit.MILLISECONDS);
86 }
62 static long getTimeout(final String propertyName, final long defaultTimeout) {
63 return PropertiesUtil.getProperties().getLongProperty(propertyName, defaultTimeout);
8764 }
8865
89 private static String getFullPropertyKey(final String strategyKey, final String additionalKey) {
90 return strategyKey.startsWith("AsyncLogger.")
91 ? "AsyncLogger." + additionalKey
92 : "AsyncLoggerConfig." + additionalKey;
66 static WaitStrategy createWaitStrategy(final String propertyName) {
67 final String key = propertyName.startsWith("AsyncLogger.")
68 ? "AsyncLogger.Timeout"
69 : "AsyncLoggerConfig.Timeout";
70 final long timeoutMillis = DisruptorUtil.getTimeout(key, 10L);
71 return createWaitStrategy(propertyName, timeoutMillis);
9372 }
9473
95 private static long parseAdditionalLongProperty(
96 final String propertyName,
97 final String additionalKey,
98 long defaultValue) {
99 final String key = getFullPropertyKey(propertyName, additionalKey);
100 return PropertiesUtil.getProperties().getLongProperty(key, defaultValue);
74 static WaitStrategy createWaitStrategy(final String propertyName, final long timeoutMillis) {
75 final String strategy = PropertiesUtil.getProperties().getStringProperty(propertyName, "TIMEOUT");
76 LOGGER.trace("property {}={}", propertyName, strategy);
77 final String strategyUp = strategy.toUpperCase(Locale.ROOT); // TODO Refactor into Strings.toRootUpperCase(String)
78 switch (strategyUp) { // TODO Define a DisruptorWaitStrategy enum?
79 case "SLEEP":
80 return new SleepingWaitStrategy();
81 case "YIELD":
82 return new YieldingWaitStrategy();
83 case "BLOCK":
84 return new BlockingWaitStrategy();
85 case "BUSYSPIN":
86 return new BusySpinWaitStrategy();
87 case "TIMEOUT":
88 return new TimeoutBlockingWaitStrategy(timeoutMillis, TimeUnit.MILLISECONDS);
89 default:
90 return new TimeoutBlockingWaitStrategy(timeoutMillis, TimeUnit.MILLISECONDS);
91 }
10192 }
10293
10394 static int calculateRingBufferSize(final String propertyName) {
158149 * @return the thread ID of the background appender thread
159150 */
160151 public static long getExecutorThreadId(final ExecutorService executor) {
161 final Future<Long> result = executor.submit(() -> Thread.currentThread().getId());
152 final Future<Long> result = executor.submit(new Callable<Long>() {
153 @Override
154 public Long call() {
155 return Thread.currentThread().getId();
156 }
157 });
162158 try {
163159 return result.get();
164160 } catch (final Exception ex) {
7070
7171 @Override
7272 public int drainTo(final Collection<? super E> c, final int maxElements) {
73 return drain(e -> c.add(e), maxElements);
73 return drain(new Consumer<E>() {
74 @Override
75 public void accept(final E e) {
76 c.add(e);
77 }
78 }, maxElements);
7479 }
7580
7681 @Override
142147 }
143148
144149 public enum WaitStrategy {
145 SPIN(idleCounter -> idleCounter + 1),
146 YIELD(idleCounter -> {
147 Thread.yield();
148 return idleCounter + 1;
150 SPIN(new Idle() {
151 @Override
152 public int idle(final int idleCounter) {
153 return idleCounter + 1;
154 }
149155 }),
150 PARK(idleCounter -> {
151 LockSupport.parkNanos(1L);
152 return idleCounter + 1;
156 YIELD(new Idle() {
157 @Override
158 public int idle(final int idleCounter) {
159 Thread.yield();
160 return idleCounter + 1;
161 }
153162 }),
154 PROGRESSIVE(idleCounter -> {
155 if (idleCounter > 200) {
163 PARK(new Idle() {
164 @Override
165 public int idle(final int idleCounter) {
156166 LockSupport.parkNanos(1L);
157 } else if (idleCounter > 100) {
158 Thread.yield();
167 return idleCounter + 1;
159168 }
160 return idleCounter + 1;
169 }),
170 PROGRESSIVE(new Idle() {
171 @Override
172 public int idle(final int idleCounter) {
173 if (idleCounter > 200) {
174 LockSupport.parkNanos(1L);
175 } else if (idleCounter > 100) {
176 Thread.yield();
177 }
178 return idleCounter + 1;
179 }
161180 });
162181
163182 private final Idle idle;
5757
5858 @Override
5959 public RingBufferLogEvent newInstance() {
60 return new RingBufferLogEvent();
61 }
62 }
63
64 private boolean populated;
60 final RingBufferLogEvent result = new RingBufferLogEvent();
61 if (Constants.ENABLE_THREADLOCALS) {
62 result.messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
63 result.parameters = new Object[10];
64 }
65 return result;
66 }
67 }
68
6569 private int threadPriority;
6670 private long threadId;
6771 private final MutableInstant instant = new MutableInstant();
107111 this.contextData = mutableContextData;
108112 this.contextStack = aContextStack;
109113 this.asyncLogger = anAsyncLogger;
110 this.populated = true;
111114 }
112115
113116 private void initTime(final Clock clock) {
128131 final ReusableMessage reusable = (ReusableMessage) msg;
129132 reusable.formatTo(getMessageTextForWriting());
130133 messageFormat = reusable.getFormat();
131 parameters = reusable.swapParameters(parameters == null ? new Object[10] : parameters);
132 parameterCount = reusable.getParameterCount();
134 if (parameters != null) {
135 parameters = reusable.swapParameters(parameters);
136 parameterCount = reusable.getParameterCount();
137 }
133138 } else {
134139 this.message = InternalAsyncUtil.makeMessageImmutable(msg);
135140 }
137142
138143 private StringBuilder getMessageTextForWriting() {
139144 if (messageText == null) {
140 // Happens the first time messageText is requested or if a user logs
141 // a custom reused message when Constants.ENABLE_THREADLOCALS is false
145 // Should never happen:
146 // only happens if user logs a custom reused message when Constants.ENABLE_THREADLOCALS is false
142147 messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
143148 }
144149 messageText.setLength(0);
153158 public void execute(final boolean endOfBatch) {
154159 this.endOfBatch = endOfBatch;
155160 asyncLogger.actualAsyncLog(this);
156 }
157
158 /**
159 * @return {@code true} if this event is populated with data, {@code false} otherwise
160 */
161 public boolean isPopulated() {
162 return populated;
163161 }
164162
165163 /**
397395 * Release references held by ring buffer to allow objects to be garbage-collected.
398396 */
399397 public void clear() {
400 this.populated = false;
401
402398 this.asyncLogger = null;
403399 this.loggerName = null;
404400 this.marker = null;
419415 }
420416
421417 // ensure that excessively long char[] arrays are not kept in memory forever
422 if (Constants.ENABLE_THREADLOCALS) {
423 StringBuilders.trimToMaxSize(messageText, Constants.MAX_REUSABLE_MESSAGE_SIZE);
424
425 if (parameters != null) {
426 Arrays.fill(parameters, null);
427 }
428 } else {
429 // A user may have manually logged a ReusableMessage implementation, when thread locals are
430 // disabled we remove the reference in order to avoid permanently holding references to these
431 // buffers.
432 messageText = null;
433 parameters = null;
418 StringBuilders.trimToMaxSize(messageText, Constants.MAX_REUSABLE_MESSAGE_SIZE);
419
420 if (parameters != null) {
421 for (int i = 0; i < parameters.length; i++) {
422 parameters[i] = null;
423 }
434424 }
435425 }
436426
4141 @Override
4242 public void onEvent(final RingBufferLogEvent event, final long sequence,
4343 final boolean endOfBatch) throws Exception {
44 try {
45 // RingBufferLogEvents are populated by an EventTranslator. If an exception is thrown during event
46 // translation, the event may not be fully populated, but Disruptor requires that the associated sequence
47 // still be published since a slot has already been claimed in the ring buffer. Ignore any such unpopulated
48 // events. The exception that occurred during translation will have already been propagated.
49 if (event.isPopulated()) {
50 event.execute(endOfBatch);
51 }
52 }
53 finally {
54 event.clear();
55 // notify the BatchEventProcessor that the sequence has progressed.
56 // Without this callback the sequence would not be progressed
57 // until the batch has completely finished.
58 notifyCallback(sequence);
59 }
44 event.execute(endOfBatch);
45 event.clear();
46 // notify the BatchEventProcessor that the sequence has progressed.
47 // Without this callback the sequence would not be progressed
48 // until the batch has completely finished.
49 notifyCallback(sequence);
6050 }
6151
6252 private void notifyCallback(long sequence) {
3636 public class RingBufferLogEventTranslator implements
3737 EventTranslator<RingBufferLogEvent> {
3838
39 private static final ContextDataInjector INJECTOR = ContextDataInjectorFactory.createInjector();
39 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
4040 private AsyncLogger asyncLogger;
4141 String loggerName;
4242 protected Marker marker;
5555 // @Override
5656 @Override
5757 public void translateTo(final RingBufferLogEvent event, final long sequence) {
58 try {
59 event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, thrown,
60 // config properties are taken care of in the EventHandler thread
61 // in the AsyncLogger#actualAsyncLog method
62 INJECTOR.injectContextData(null, (StringMap) event.getContextData()), contextStack,
63 threadId, threadName, threadPriority, location, clock, nanoClock);
64 } finally {
65 clear(); // clear the translator
66 }
58
59 event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, thrown,
60 // config properties are taken care of in the EventHandler thread
61 // in the AsyncLogger#actualAsyncLog method
62 injector.injectContextData(null, (StringMap) event.getContextData()), contextStack,
63 threadId, threadName, threadPriority, location, clock, nanoClock);
64
65 clear(); // clear the translator
6766 }
6867
6968 /**
7069 * Release references held by this object to allow objects to be garbage-collected.
7170 */
72 void clear() {
71 private void clear() {
7372 setBasicValues(null, // asyncLogger
7473 null, // loggerName
7574 null, // marker
1616
1717 package org.apache.logging.log4j.core.async;
1818
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
21
2219 import org.apache.logging.log4j.status.StatusLogger;
23 import org.apache.logging.log4j.util.Constants;
2420 import org.apache.logging.log4j.util.PropertiesUtil;
2521
2622 /**
4743
4844 private static final StatusLogger LOGGER = StatusLogger.getLogger();
4945 private static final ThreadLocal<String> THREADLOCAL_NAME = new ThreadLocal<>();
50 static final ThreadNameCachingStrategy DEFAULT_STRATEGY = isAllocatingThreadGetName() ? CACHED : UNCACHED;
5146
5247 abstract String getThreadName();
5348
5449 public static ThreadNameCachingStrategy create() {
50 final String defaultStrategy = System.getProperty("java.version").compareTo("1.8.0_102") < 0
51 ? "CACHED" // LOG4J2-2052 JDK 8u102 removed the String allocation in Thread.getName()
52 : "UNCACHED";
5553 final String name = PropertiesUtil.getProperties().getStringProperty("AsyncLogger.ThreadNameStrategy");
5654 try {
57 final ThreadNameCachingStrategy result = name != null ? ThreadNameCachingStrategy.valueOf(name) : DEFAULT_STRATEGY;
55 final ThreadNameCachingStrategy result = ThreadNameCachingStrategy.valueOf(
56 name != null ? name : defaultStrategy);
5857 LOGGER.debug("AsyncLogger.ThreadNameStrategy={} (user specified {}, default is {})",
59 result.name(), name, DEFAULT_STRATEGY.name());
58 result, name, defaultStrategy);
6059 return result;
6160 } catch (final Exception ex) {
6261 LOGGER.debug("Using AsyncLogger.ThreadNameStrategy.{}: '{}' not valid: {}",
63 DEFAULT_STRATEGY.name(), name, ex.toString());
64 return DEFAULT_STRATEGY;
62 defaultStrategy, name, ex.toString());
63 return ThreadNameCachingStrategy.valueOf(defaultStrategy);
6564 }
6665 }
67
68 static boolean isAllocatingThreadGetName() {
69 // LOG4J2-2052, LOG4J2-2635 JDK 8u102 ("1.8.0_102") removed the String allocation in Thread.getName()
70 if (Constants.JAVA_MAJOR_VERSION == 8) {
71 try {
72 Pattern javaVersionPattern = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)_(\\d+)");
73 Matcher m = javaVersionPattern.matcher(System.getProperty("java.version"));
74 if (m.matches()) {
75 return Integer.parseInt(m.group(3)) == 0 && Integer.parseInt(m.group(4)) < 102;
76 }
77 return true;
78 } catch (Exception e) {
79 return true;
80 }
81 } else {
82 return Constants.JAVA_MAJOR_VERSION < 8;
83 }
84 }
85 }
66 }
4848 import org.apache.logging.log4j.core.async.AsyncLoggerConfig;
4949 import org.apache.logging.log4j.core.async.AsyncLoggerConfigDelegate;
5050 import org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor;
51 import org.apache.logging.log4j.core.config.arbiters.Arbiter;
52 import org.apache.logging.log4j.core.config.arbiters.SelectArbiter;
5351 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
5452 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
5553 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
251249 protected void initializeWatchers(Reconfigurable reconfigurable, ConfigurationSource configSource,
252250 int monitorIntervalSeconds) {
253251 if (configSource.getFile() != null || configSource.getURL() != null) {
254 if (monitorIntervalSeconds > 0) {
255 watchManager.setIntervalSeconds(monitorIntervalSeconds);
256 if (configSource.getFile() != null) {
257 final Source cfgSource = new Source(configSource);
258 final long lastModifeid = configSource.getFile().lastModified();
259 final ConfigurationFileWatcher watcher = new ConfigurationFileWatcher(this, reconfigurable,
260 listeners, lastModifeid);
261 watchManager.watch(cfgSource, watcher);
262 } else if (configSource.getURL() != null) {
263 monitorSource(reconfigurable, configSource);
264 }
265 } else if (watchManager.hasEventListeners() && configSource.getURL() != null
266 && monitorIntervalSeconds >= 0) {
267 monitorSource(reconfigurable, configSource);
268 }
252 if (monitorIntervalSeconds > 0) {
253 watchManager.setIntervalSeconds(monitorIntervalSeconds);
254 if (configSource.getFile() != null) {
255 final Source cfgSource = new Source(configSource);
256 final long lastModifeid = configSource.getFile().lastModified();
257 final ConfigurationFileWatcher watcher = new ConfigurationFileWatcher(this, reconfigurable,
258 listeners, lastModifeid);
259 watchManager.watch(cfgSource, watcher);
260 } else {
261 if (configSource.getURL() != null) {
262 monitorSource(reconfigurable, configSource);
263 }
264 }
265 } else if (watchManager.hasEventListeners() && configSource.getURL() != null && monitorIntervalSeconds >= 0) {
266 monitorSource(reconfigurable, configSource);
267 }
269268 }
270269 }
271270
373372 asyncLoggerConfigDisruptor.stop(timeout, timeUnit);
374373 }
375374
376 LOGGER.trace("{} notifying ReliabilityStrategies that appenders will be stopped.", cls);
377 for (final LoggerConfig loggerConfig : loggerConfigs.values()) {
378 loggerConfig.getReliabilityStrategy().beforeStopAppenders();
379 }
380 root.getReliabilityStrategy().beforeStopAppenders();
381
382375 // Stop the appenders in reverse order in case they still have activity.
383376 final Appender[] array = appenders.values().toArray(new Appender[appenders.size()]);
384377 final List<Appender> async = getAsyncAppenders(array);
393386 }
394387 }
395388 }
389
390 LOGGER.trace("{} notifying ReliabilityStrategies that appenders will be stopped.", cls);
391 for (final LoggerConfig loggerConfig : loggerConfigs.values()) {
392 loggerConfig.getReliabilityStrategy().beforeStopAppenders();
393 }
394 root.getReliabilityStrategy().beforeStopAppenders();
396395
397396 LOGGER.trace("{} stopping remaining Appenders.", cls);
398397 int appenderCount = 0;
529528 }
530529 }
531530
532 /**
533 * Process conditions by evaluating them and including the children of conditions that are true
534 * and discarding those that are not.
535 * @param node The node to evaluate.
536 */
537 protected void processConditionals(final Node node) {
538 try {
539 List<Node> addList = new ArrayList<>();
540 List<Node> removeList = new ArrayList<>();
541 for (final Node child : node.getChildren()) {
542 final PluginType<?> type = child.getType();
543 if (type != null && Arbiter.ELEMENT_TYPE.equals(type.getElementName())) {
544 final Class<?> clazz = type.getPluginClass();
545 if (SelectArbiter.class.isAssignableFrom(clazz)) {
546 removeList.add(child);
547 addList.addAll(processSelect(child, type));
548 } else if (Arbiter.class.isAssignableFrom(clazz)) {
549 removeList.add(child);
550 try {
551 Arbiter condition = (Arbiter) createPluginObject(type, child, null);
552 if (condition.isCondition()) {
553 addList.addAll(child.getChildren());
554 processConditionals(child);
555 }
556 } catch (final Exception inner) {
557 LOGGER.error("Exception processing {}: Ignoring and including children",
558 type.getPluginClass());
559 processConditionals(child);
560 }
561 } else {
562 LOGGER.error("Encountered Condition Plugin that does not implement Condition: {}",
563 child.getName());
564 processConditionals(child);
565 }
566 } else {
567 processConditionals(child);
568 }
569 }
570 if (!removeList.isEmpty()) {
571 List<Node> children = node.getChildren();
572 children.removeAll(removeList);
573 children.addAll(addList);
574 for (Node grandChild : addList) {
575 grandChild.setParent(node);
576 }
577 }
578 } catch (final Exception ex) {
579 LOGGER.error("Error capturing node data for node " + node.getName(), ex);
580 }
581 }
582
583 /**
584 * Handle Select nodes. This finds the first child condition that returns true and attaches its children
585 * to the parent of the Select Node. Other Nodes are discarded.
586 * @param selectNode The Select Node.
587 * @param type The PluginType of the Select Node.
588 * @return The list of Nodes to be added to the parent.
589 */
590 protected List<Node> processSelect(Node selectNode, PluginType<?> type) {
591 List<Node> addList = new ArrayList<>();
592 SelectArbiter select = (SelectArbiter) createPluginObject(type, selectNode, null);
593 List<Arbiter> conditions = new ArrayList<>();
594 for (Node child : selectNode.getChildren()) {
595 PluginType<?> nodeType = child.getType();
596 if (nodeType != null) {
597 if (Arbiter.class.isAssignableFrom(nodeType.getPluginClass())) {
598 Arbiter condition = (Arbiter) createPluginObject(nodeType, child, null);
599 conditions.add(condition);
600 child.setObject(condition);
601 } else {
602 LOGGER.error("Invalid Node {} for Select. Must be a Condition",
603 child.getName());
604 }
605 } else {
606 LOGGER.error("No PluginType for node {}", child.getName());
607 }
608 }
609 Arbiter condition = select.evaluateConditions(conditions);
610 if (condition != null) {
611 for (Node child : selectNode.getChildren()) {
612 if (condition == child.getObject()) {
613 addList.addAll(child.getChildren());
614 processConditionals(child);
615 }
616 }
617 }
618 return addList;
619 }
620
621531 protected void doConfigure() {
622 processConditionals(rootNode);
623532 preConfigure(rootNode);
624533 configurationScheduler.start();
625534 if (rootNode.hasChildren() && rootNode.getChildren().get(0).getName().equalsIgnoreCase("Properties")) {
656565 if (script instanceof ScriptRef) {
657566 LOGGER.error("Script reference to {} not added. Scripts definition cannot contain script references",
658567 script.getName());
659 } else if (scriptManager != null) {
660 scriptManager.addScript(script);
661 }
568 } else {
569 if (scriptManager != null) {
570 scriptManager.addScript(script);
571 }}
662572 }
663573 } else if (child.getName().equalsIgnoreCase("Appenders")) {
664574 appenders = child.getObject();
811721 return subst;
812722 }
813723
814 @Override
815724 public StrSubstitutor getConfigurationStrSubstitutor() {
816725 return configurationStrSubstitutor;
817726 }
1043952 } else {
1044953 node.setObject(createPluginObject(type, node, event));
1045954 }
1046 }
1047 }
1048
1049 /**
1050 * This method is used by Arbiters to create specific children.
1051 * @param type The PluginType.
1052 * @param node The Node.
1053 * @return The created object or null;
1054 */
1055 public Object createPluginObject(final PluginType<?> type, final Node node) {
1056 if (this.getState().equals(State.INITIALIZING)) {
1057 return createPluginObject(type, node, null);
1058 } else {
1059 LOGGER.warn("Plugin Object creation is not allowed after initialization");
1060 return null;
1061955 }
1062956 }
1063957
3030 * Wraps an {@link Appender} with details an appender implementation shouldn't need to know about.
3131 */
3232 public class AppenderControl extends AbstractFilterable {
33
34 /**
35 * The empty array.
36 */
37 static final AppenderControl[] EMPTY_ARRAY = {};
3833
3934 private final ThreadLocal<AppenderControl> recursive = new ThreadLocal<>();
4035 private final Appender appender;
158153 private void tryCallAppender(final LogEvent event) {
159154 try {
160155 appender.append(event);
161 } catch (final RuntimeException error) {
162 handleAppenderError(event, error);
163 } catch (final Throwable throwable) {
164 handleAppenderError(event, new AppenderLoggingException(throwable));
156 } catch (final RuntimeException ex) {
157 handleAppenderError(event, ex);
158 } catch (final Throwable t) {
159 handleAppenderError(event, new AppenderLoggingException(t));
165160 }
166161 }
167162
1919 import java.util.HashMap;
2020 import java.util.Map;
2121 import java.util.Objects;
22 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
22 import java.util.concurrent.atomic.AtomicReference;
2323
2424 import org.apache.logging.log4j.core.Appender;
2525 import org.apache.logging.log4j.util.PerformanceSensitive;
3131 */
3232 @PerformanceSensitive
3333 public class AppenderControlArraySet {
34 private static final AtomicReferenceFieldUpdater<AppenderControlArraySet, AppenderControl[]> appenderArrayUpdater =
35 AtomicReferenceFieldUpdater.newUpdater(AppenderControlArraySet.class, AppenderControl[].class, "appenderArray");
36 private volatile AppenderControl[] appenderArray = AppenderControl.EMPTY_ARRAY;
34 private final AtomicReference<AppenderControl[]> appenderArray = new AtomicReference<>(new AppenderControl[0]);
3735
3836 /**
3937 * Adds an AppenderControl to this set. If this set already contains the element, the call leaves the set unchanged
4543 public boolean add(final AppenderControl control) {
4644 boolean success;
4745 do {
48 final AppenderControl[] original = appenderArray;
46 final AppenderControl[] original = appenderArray.get();
4947 for (final AppenderControl existing : original) {
5048 if (existing.equals(control)) {
5149 return false; // the appender is already in the list
5351 }
5452 final AppenderControl[] copy = Arrays.copyOf(original, original.length + 1);
5553 copy[copy.length - 1] = control;
56 success = appenderArrayUpdater.compareAndSet(this, original, copy);
54 success = appenderArray.compareAndSet(original, copy);
5755 } while (!success); // could not swap: array was modified by another thread
5856 return true; // successfully added
5957 }
6866 boolean success;
6967 do {
7068 success = true;
71 final AppenderControl[] original = appenderArray;
69 final AppenderControl[] original = appenderArray.get();
7270 for (int i = 0; i < original.length; i++) {
7371 final AppenderControl appenderControl = original[i];
7472 if (Objects.equals(name, appenderControl.getAppenderName())) {
7573 final AppenderControl[] copy = removeElementAt(i, original);
76 if (appenderArrayUpdater.compareAndSet(this, original, copy)) {
74 if (appenderArray.compareAndSet(original, copy)) {
7775 return appenderControl; // successfully removed
7876 }
7977 success = false; // could not swap: array was modified by another thread
9795 */
9896 public Map<String, Appender> asMap() {
9997 final Map<String, Appender> result = new HashMap<>();
100 for (final AppenderControl appenderControl : appenderArray) {
98 for (final AppenderControl appenderControl : appenderArray.get()) {
10199 result.put(appenderControl.getAppenderName(), appenderControl.getAppender());
102100 }
103101 return result;
109107 * @return the contents before this collection was cleared.
110108 */
111109 public AppenderControl[] clear() {
112 return appenderArrayUpdater.getAndSet(this, AppenderControl.EMPTY_ARRAY);
110 return appenderArray.getAndSet(new AppenderControl[0]);
113111 }
114112
115113 public boolean isEmpty() {
116 return appenderArray.length == 0;
114 return appenderArray.get().length == 0;
117115 }
118116
119117 /**
122120 * @return the array supporting this collection
123121 */
124122 public AppenderControl[] get() {
125 return appenderArray;
123 return appenderArray.get();
126124 }
127125
128126 @Override
129127 public String toString() {
130 return "AppenderControlArraySet [appenderArray=" + Arrays.toString(appenderArray) + "]";
128 return "AppenderControlArraySet [appenderArray=" + appenderArray + "]";
131129 }
132130 }
2626 import org.apache.logging.log4j.core.LoggerContext;
2727 import org.apache.logging.log4j.core.async.AsyncLoggerConfigDelegate;
2828 import org.apache.logging.log4j.core.filter.Filterable;
29 import org.apache.logging.log4j.core.lookup.ConfigurationStrSubstitutor;
3029 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
3130 import org.apache.logging.log4j.core.net.Advertiser;
3231 import org.apache.logging.log4j.core.script.ScriptManager;
116115
117116 StrSubstitutor getStrSubstitutor();
118117
119 default StrSubstitutor getConfigurationStrSubstitutor() {
120 StrSubstitutor defaultSubstitutor = getStrSubstitutor();
121 if (defaultSubstitutor == null) {
122 return new ConfigurationStrSubstitutor();
123 }
124 return new ConfigurationStrSubstitutor(defaultSubstitutor);
125 }
126
127118 void createConfiguration(Node node, LogEvent event);
128119
129120 <T> T getComponent(String name);
140131
141132 ConfigurationScheduler getScheduler();
142133
143 /**
144 * Returns the source of this configuration.
145 *
146 * @return the source of this configuration, never {@code null}, but may be
147 * {@link org.apache.logging.log4j.core.config.ConfigurationSource#NULL_SOURCE}
148 * or
149 * {@link org.apache.logging.log4j.core.config.ConfigurationSource#COMPOSITE_SOURCE}
150 */
134 /**
135 * Returns the source of this configuration.
136 *
137 * @return the source of this configuration, never {@code null}, but may be
138 * {@link org.apache.logging.log4j.core.config.ConfigurationSource#NULL_SOURCE}.
139 */
151140 ConfigurationSource getConfigurationSource();
152141
153142 /**
1414 * limitations under the license.
1515 */
1616 package org.apache.logging.log4j.core.config;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.net.URI;
22 import java.net.URL;
23 import java.net.URLConnection;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.locks.Lock;
30 import java.util.concurrent.locks.ReentrantLock;
1731
1832 import org.apache.logging.log4j.Level;
1933 import org.apache.logging.log4j.Logger;
3650 import org.apache.logging.log4j.util.LoaderUtil;
3751 import org.apache.logging.log4j.util.PropertiesUtil;
3852 import org.apache.logging.log4j.util.Strings;
39
40 import java.io.File;
41 import java.io.FileInputStream;
42 import java.io.FileNotFoundException;
43 import java.io.UnsupportedEncodingException;
44 import java.net.URI;
45 import java.net.URISyntaxException;
46 import java.net.URL;
47 import java.net.URLConnection;
48 import java.net.URLDecoder;
49 import java.util.ArrayList;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.concurrent.locks.Lock;
55 import java.util.concurrent.locks.ReentrantLock;
5653
5754 /**
5855 * Factory class for parsed {@link Configuration} objects from a configuration file.
8077 public abstract class ConfigurationFactory extends ConfigurationBuilderFactory {
8178
8279 public ConfigurationFactory() {
80 super();
8381 // TEMP For breakpoints
8482 }
8583
9290 * Allows the location of the configuration file to be specified as a system property.
9391 */
9492 public static final String CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile";
95
96 public static final String LOG4J1_CONFIGURATION_FILE_PROPERTY = "log4j.configuration";
97
98 public static final String LOG4J1_EXPERIMENTAL = "log4j1.compatibility";
9993
10094 public static final String AUTHORIZATION_PROVIDER = "log4j2.authorizationProvider";
10195
122116 */
123117 protected static final String DEFAULT_PREFIX = "log4j2";
124118
125 protected static final String LOG4J1_VERSION = "1";
126 protected static final String LOG4J2_VERSION = "2";
127
128119 /**
129120 * The name of the classloader URI scheme.
130121 */
135126 */
136127 private static final String CLASS_PATH_SCHEME = "classpath";
137128
138 private static final String OVERRIDE_PARAM = "override";
139
140 private static volatile List<ConfigurationFactory> factories;
129 private static volatile List<ConfigurationFactory> factories = null;
141130
142131 private static ConfigurationFactory configFactory = new Factory();
143132
148137 private static final String HTTPS = "https";
149138 private static final String HTTP = "http";
150139
151 private static volatile AuthorizationProvider authorizationProvider;
140 private static AuthorizationProvider authorizationProvider = null;
152141
153142 /**
154143 * Returns the ConfigurationFactory.
185174 // see above comments about double-checked locking
186175 //noinspection NonThreadSafeLazyInitialization
187176 factories = Collections.unmodifiableList(list);
188 authorizationProvider = authorizationProvider(props);
177 final String authClass = props.getStringProperty(AUTHORIZATION_PROVIDER);
178 if (authClass != null) {
179 try {
180 Object obj = LoaderUtil.newInstanceOf(authClass);
181 if (obj instanceof AuthorizationProvider) {
182 authorizationProvider = (AuthorizationProvider) obj;
183 } else {
184 LOGGER.warn("{} is not an AuthorizationProvider, using default", obj.getClass().getName());
185 }
186 } catch (Exception ex) {
187 LOGGER.warn("Unable to create {}, using default: {}", authClass, ex.getMessage());
188 }
189 }
190 if (authorizationProvider == null) {
191 authorizationProvider = new BasicAuthorizationProvider(props);
192 }
189193 }
190194 } finally {
191195 LOCK.unlock();
194198
195199 LOGGER.debug("Using configurationFactory {}", configFactory);
196200 return configFactory;
197 }
198
199 public static AuthorizationProvider authorizationProvider(PropertiesUtil props) {
200 final String authClass = props.getStringProperty(AUTHORIZATION_PROVIDER);
201 AuthorizationProvider provider = null;
202 if (authClass != null) {
203 try {
204 Object obj = LoaderUtil.newInstanceOf(authClass);
205 if (obj instanceof AuthorizationProvider) {
206 provider = (AuthorizationProvider) obj;
207 } else {
208 LOGGER.warn("{} is not an AuthorizationProvider, using default", obj.getClass().getName());
209 }
210 } catch (Exception ex) {
211 LOGGER.warn("Unable to create {}, using default: {}", authClass, ex.getMessage());
212 }
213 }
214 if (provider == null) {
215 provider = new BasicAuthorizationProvider(props);
216 }
217 return provider;
218201 }
219202
220203 public static AuthorizationProvider getAuthorizationProvider() {
265248 }
266249
267250 protected abstract String[] getSupportedTypes();
268
269 protected String getTestPrefix() {
270 return TEST_PREFIX;
271 }
272
273 protected String getDefaultPrefix() {
274 return DEFAULT_PREFIX;
275 }
276
277 protected String getVersion() {
278 return LOG4J2_VERSION;
279 }
280251
281252 protected boolean isActive() {
282253 return true;
359330 File file = FileUtils.fileFromUri(url.toURI());
360331 if (file != null) {
361332 return new ConfigurationSource(urlConnection.getInputStream(), FileUtils.fileFromUri(url.toURI()));
362 }
363 return new ConfigurationSource(urlConnection.getInputStream(), url, urlConnection.getLastModified());
333 } else {
334 return new ConfigurationSource(urlConnection.getInputStream(), url, urlConnection.getLastModified());
335 }
364336 } catch (final Exception ex) {
365337 final ConfigurationSource source = ConfigurationSource.fromResource(config, loader);
366338 if (source == null) {
396368 final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties()
397369 .getStringProperty(CONFIGURATION_FILE_PROPERTY));
398370 if (configLocationStr != null) {
399 String[] sources = parseConfigLocations(configLocationStr);
371 final String[] sources = configLocationStr.split(",");
400372 if (sources.length > 1) {
401373 final List<AbstractConfiguration> configs = new ArrayList<>();
402374 for (final String sourceLocation : sources) {
403375 final Configuration config = getConfiguration(loggerContext, sourceLocation.trim());
404 if (config != null) {
405 if (config instanceof AbstractConfiguration) {
406 configs.add((AbstractConfiguration) config);
407 } else {
408 LOGGER.error("Failed to created configuration at {}", sourceLocation);
409 return null;
410 }
376 if (config != null && config instanceof AbstractConfiguration) {
377 configs.add((AbstractConfiguration) config);
411378 } else {
412 LOGGER.warn("Unable to create configuration for {}, ignoring", sourceLocation);
379 LOGGER.error("Failed to created configuration at {}", sourceLocation);
380 return null;
413381 }
414382 }
415 if (configs.size() > 1) {
416 return new CompositeConfiguration(configs);
417 } else if (configs.size() == 1) {
418 return configs.get(0);
419 }
383 return new CompositeConfiguration(configs);
420384 }
421385 return getConfiguration(loggerContext, configLocationStr);
422 }
423 final String log4j1ConfigStr = this.substitutor.replace(PropertiesUtil.getProperties()
424 .getStringProperty(LOG4J1_CONFIGURATION_FILE_PROPERTY));
425 if (log4j1ConfigStr != null) {
426 System.setProperty(LOG4J1_EXPERIMENTAL, "true");
427 return getConfiguration(LOG4J1_VERSION, loggerContext, log4j1ConfigStr);
428386 }
429387 for (final ConfigurationFactory factory : getFactories()) {
430388 final String[] types = factory.getSupportedTypes();
440398 }
441399 }
442400 } else {
443 String[] sources = parseConfigLocations(configLocation);
444 if (sources.length > 1) {
445 final List<AbstractConfiguration> configs = new ArrayList<>();
446 for (final String sourceLocation : sources) {
447 final Configuration config = getConfiguration(loggerContext, sourceLocation.trim());
448 if (config instanceof AbstractConfiguration) {
449 configs.add((AbstractConfiguration) config);
450 } else {
451 LOGGER.error("Failed to created configuration at {}", sourceLocation);
452 return null;
453 }
454 }
455 return new CompositeConfiguration(configs);
456 }
457401 // configLocation != null
458402 final String configLocationStr = configLocation.toString();
459403 for (final ConfigurationFactory factory : getFactories()) {
484428 if (config != null) {
485429 return config;
486430 }
487 LOGGER.warn("No Log4j 2 configuration file found. " +
431 LOGGER.error("No Log4j 2 configuration file found. " +
488432 "Using default configuration (logging only errors to the console), " +
489433 "or user programmatically provided configurations. " +
490434 "Set system property 'log4j2.debug' " +
494438 }
495439
496440 private Configuration getConfiguration(final LoggerContext loggerContext, final String configLocationStr) {
497 return getConfiguration(null, loggerContext, configLocationStr);
498 }
499
500 private Configuration getConfiguration(String requiredVersion, final LoggerContext loggerContext,
501 final String configLocationStr) {
502441 ConfigurationSource source = null;
503442 try {
504443 source = ConfigurationSource.fromUri(NetUtils.toURI(configLocationStr));
512451 }
513452 if (source != null) {
514453 for (final ConfigurationFactory factory : getFactories()) {
515 if (requiredVersion != null && !factory.getVersion().equals(requiredVersion)) {
516 continue;
517 }
518454 final String[] types = factory.getSupportedTypes();
519455 if (types != null) {
520456 for (final String type : types) {
536472 final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();
537473 for (final ConfigurationFactory factory : getFactories()) {
538474 String configName;
539 final String prefix = isTest ? factory.getTestPrefix() : factory.getDefaultPrefix();
475 final String prefix = isTest ? TEST_PREFIX : DEFAULT_PREFIX;
540476 final String [] types = factory.getSupportedTypes();
541477 if (types == null) {
542478 continue;
589525 LOGGER.error("Cannot process configuration, input source is null");
590526 return null;
591527 }
592
593 private String[] parseConfigLocations(URI configLocations) {
594 final String[] uris = configLocations.toString().split("\\?");
595 final List<String> locations = new ArrayList<>();
596 if (uris.length > 1) {
597 locations.add(uris[0]);
598 final String[] pairs = configLocations.getQuery().split("&");
599 for (String pair : pairs) {
600 final int idx = pair.indexOf("=");
601 try {
602 final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
603 if (key.equalsIgnoreCase(OVERRIDE_PARAM)) {
604 locations.add(URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
605 }
606 } catch (UnsupportedEncodingException ex) {
607 LOGGER.warn("Invalid query parameter in {}", configLocations);
608 }
609 }
610 return locations.toArray(Strings.EMPTY_ARRAY);
611 }
612 return new String[] {uris[0]};
613 }
614
615 private String[] parseConfigLocations(String configLocations) {
616 final String[] uris = configLocations.split(",");
617 if (uris.length > 1) {
618 return uris;
619 }
620 try {
621 return parseConfigLocations(new URI(configLocations));
622 } catch (URISyntaxException ex) {
623 LOGGER.warn("Error parsing URI {}", configLocations);
624 }
625 return new String[] {configLocations};
626 }
627528 }
628529
629530 static List<ConfigurationFactory> getFactories() {
3737 this.lastModifiedMillis = lastModifiedMillis;
3838 }
3939
40 @Override
4140 public long getLastModified() {
4241 return file != null ? file.lastModified() : 0;
4342 }
3838 private static final String SIMPLE_NAME = "Log4j2 " + ConfigurationScheduler.class.getSimpleName();
3939 private static final int MAX_SCHEDULED_ITEMS = 5;
4040
41 private volatile ScheduledExecutorService executorService;
41 private ScheduledExecutorService executorService;
4242 private int scheduledItems = 0;
4343 private final String name;
4444
4747 }
4848
4949 public ConfigurationScheduler(final String name) {
50 super();
5051 this.name = name;
5152 }
5253
191192
192193 private ScheduledExecutorService getExecutorService() {
193194 if (executorService == null) {
194 synchronized (this) {
195 if (executorService == null) {
196 if (scheduledItems > 0) {
197 LOGGER.debug("{} starting {} threads", name, scheduledItems);
198 scheduledItems = Math.min(scheduledItems, MAX_SCHEDULED_ITEMS);
199 final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(scheduledItems,
200 Log4jThreadFactory.createDaemonThreadFactory("Scheduled"));
201 executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
202 executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
203 this.executorService = executor;
204
205 } else {
206 LOGGER.debug("{}: No scheduled items", name);
207 }
208 }
195 if (scheduledItems > 0) {
196 LOGGER.debug("{} starting {} threads", name, scheduledItems);
197 scheduledItems = Math.min(scheduledItems, MAX_SCHEDULED_ITEMS);
198 final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(scheduledItems,
199 Log4jThreadFactory.createDaemonThreadFactory("Scheduled"));
200 executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
201 executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
202 this.executorService = executor;
203
204 } else {
205 LOGGER.debug("{}: No scheduled items", name);
209206 }
210207 }
211208 return executorService;
3030 import java.net.URLConnection;
3131 import java.util.Objects;
3232
33 import javax.net.ssl.HttpsURLConnection;
34
33 import org.apache.logging.log4j.Level;
3534 import org.apache.logging.log4j.core.net.UrlConnectionFactory;
36 import org.apache.logging.log4j.core.net.ssl.LaxHostnameVerifier;
37 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
38 import org.apache.logging.log4j.core.net.ssl.SslConfigurationFactory;
39 import org.apache.logging.log4j.core.util.AuthorizationProvider;
4035 import org.apache.logging.log4j.core.util.FileUtils;
4136 import org.apache.logging.log4j.core.util.Loader;
4237 import org.apache.logging.log4j.core.util.Source;
43 import org.apache.logging.log4j.util.Constants;
4438 import org.apache.logging.log4j.util.LoaderUtil;
45 import org.apache.logging.log4j.util.PropertiesUtil;
4639
4740 /**
4841 * Represents the source for the logging configuration.
5245 /**
5346 * ConfigurationSource to use with Configurations that do not require a "real" configuration source.
5447 */
55 public static final ConfigurationSource NULL_SOURCE = new ConfigurationSource(Constants.EMPTY_BYTE_ARRAY, null, 0);
56
57 /**
58 * ConfigurationSource to use with {@link org.apache.logging.log4j.core.config.composite.CompositeConfiguration}.
59 */
60 public static final ConfigurationSource COMPOSITE_SOURCE = new ConfigurationSource(Constants.EMPTY_BYTE_ARRAY, null, 0);
48 public static final ConfigurationSource NULL_SOURCE = new ConfigurationSource(new byte[0], null, 0);
6149 private static final String HTTPS = "https";
50 private static final String HTTP = "http";
6251
6352 private final File file;
6453 private final URL url;
6554 private final String location;
6655 private final InputStream stream;
6756 private volatile byte[] data;
68 private volatile Source source;
57 private volatile Source source = null;
6958 private final long lastModified;
7059 // Set when the configuration has been updated so reset can use it for the next lastModified timestamp.
7160 private volatile long modifiedMillis;
147136 }
148137
149138 private ConfigurationSource(final byte[] data, final URL url, long lastModified) {
150 this.data = Objects.requireNonNull(data, "data is null");
139 Objects.requireNonNull(data, "data is null");
151140 this.stream = new ByteArrayInputStream(data);
152141 this.file = null;
153142 this.url = url;
154143 this.location = null;
155144 this.lastModified = lastModified;
156 if ( url == null ) {
157 this.data = data;
158 }
159145 }
160146
161147 /**
319305 if (ConfigurationFactory.isClassLoaderUri(configLocation)) {
320306 final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();
321307 final String path = ConfigurationFactory.extractClassLoaderUriPath(configLocation);
322 return fromResource(path, loader);
308 final ConfigurationSource source = fromResource(path, loader);
309 if (source != null) {
310 return source;
311 }
323312 }
324313 if (!configLocation.isAbsolute()) { // LOG4J2-704 avoid confusing error message thrown by uri.toURL()
325314 ConfigurationFactory.LOGGER.error("File not found in file system or classpath: {}", configLocation.toString());
331320 InputStream is = urlConnection.getInputStream();
332321 long lastModified = urlConnection.getLastModified();
333322 return new ConfigurationSource(is, configLocation.toURL(), lastModified);
334 } catch (final FileNotFoundException ex) {
335 ConfigurationFactory.LOGGER.warn("Could not locate file {}", configLocation.toString());
336323 } catch (final MalformedURLException ex) {
337324 ConfigurationFactory.LOGGER.error("Invalid URL {}", configLocation.toString(), ex);
338325 } catch (final Exception ex) {
352339 if (url == null) {
353340 return null;
354341 }
355 return getConfigurationSource(url);
356 }
357
358 private static ConfigurationSource getConfigurationSource(URL url) {
342 InputStream is = null;
359343 try {
360 URLConnection urlConnection = url.openConnection();
361 AuthorizationProvider provider = ConfigurationFactory.authorizationProvider(PropertiesUtil.getProperties());
362 provider.addAuthorization(urlConnection);
363 if (url.getProtocol().equals(HTTPS)) {
364 SslConfiguration sslConfiguration = SslConfigurationFactory.getSslConfiguration();
365 if (sslConfiguration != null) {
366 ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslConfiguration.getSslSocketFactory());
367 if (!sslConfiguration.isVerifyHostName()) {
368 ((HttpsURLConnection) urlConnection).setHostnameVerifier(LaxHostnameVerifier.INSTANCE);
369 }
370 }
371 }
372 File file = FileUtils.fileFromUri(url.toURI());
344 is = url.openStream();
345 } catch (final IOException ioe) {
346 ConfigurationFactory.LOGGER.catching(Level.DEBUG, ioe);
347 return null;
348 }
349 if (is == null) {
350 return null;
351 }
352
353 if (FileUtils.isFile(url)) {
373354 try {
374 if (file != null) {
375 return new ConfigurationSource(urlConnection.getInputStream(), FileUtils.fileFromUri(url.toURI()));
376 } else {
377 return new ConfigurationSource(urlConnection.getInputStream(), url, urlConnection.getLastModified());
378 }
379 } catch (FileNotFoundException ex) {
380 ConfigurationFactory.LOGGER.info("Unable to locate file {}, ignoring.", url.toString());
381 return null;
382 }
383 } catch (IOException | URISyntaxException ex) {
384 ConfigurationFactory.LOGGER.warn("Error accessing {} due to {}, ignoring.", url.toString(),
385 ex.getMessage());
386 return null;
387 }
355 return new ConfigurationSource(is, FileUtils.fileFromUri(url.toURI()));
356 } catch (final URISyntaxException ex) {
357 // Just ignore the exception.
358 ConfigurationFactory.LOGGER.catching(Level.DEBUG, ex);
359 }
360 }
361 return new ConfigurationSource(is, url);
388362 }
389363 }
1515 */
1616 package org.apache.logging.log4j.core.config;
1717
18 import java.net.URI;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.concurrent.TimeUnit;
23
1824 import org.apache.logging.log4j.Level;
1925 import org.apache.logging.log4j.LogManager;
2026 import org.apache.logging.log4j.Logger;
2531 import org.apache.logging.log4j.status.StatusLogger;
2632 import org.apache.logging.log4j.util.Strings;
2733
28 import java.net.URI;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.TimeUnit;
33
3434 /**
3535 * Initializes and configure the Logging system. This class provides several ways to construct a LoggerContext using
3636 * the location of a configuration file, a context name, and various optional parameters.
4545 final LoggerContextFactory factory = LogManager.getFactory();
4646 if (factory instanceof Log4jContextFactory) {
4747 return (Log4jContextFactory) factory;
48 }
49 if (factory != null) {
48 } else if (factory != null) {
5049 LOGGER.error("LogManager returned an instance of {} which does not implement {}. Unable to initialize Log4j.",
5150 factory.getClass().getName(), Log4jContextFactory.class.getName());
51 return null;
5252 } else {
5353 LOGGER.fatal("LogManager did not return a LoggerContextFactory. This indicates something has gone terribly wrong!");
54 }
55 return null;
54 return null;
55 }
5656 }
5757
5858 /**
163163 return null;
164164 }
165165
166 /**
167 * Initializes the Logging Context.
168 * @param name The Context name.
169 * @param loader The ClassLoader for the Context (or null).
170 * @param configLocation The configuration for the logging context (or null).
171 * @param entry The external context entry to be attached to the LoggerContext
172 * @return The LoggerContext.
173 */
174 public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation,
175 final Map.Entry<String, Object> entry) {
176
177 try {
178 final Log4jContextFactory factory = getFactory();
179 return factory == null ? null :
180 factory.getContext(FQCN, loader, entry, false, configLocation, name);
181 } catch (final Exception ex) {
182 LOGGER.error("There was a problem initializing the LoggerContext [{}] using configuration at [{}].",
183 name, configLocation, ex);
184 }
185 return null;
186 }
187
188166 public static LoggerContext initialize(final String name, final ClassLoader loader, final List<URI> configLocations,
189167 final Object externalContext) {
190168 try {
245223 configuration.getName(), ex);
246224 }
247225 return null;
248 }
249
250 /**
251 * Reconfigure using an already constructed Configuration.
252 * @param configuration The configuration.
253 * @since 2.13.0
254 */
255 public static void reconfigure(final Configuration configuration) {
256 try {
257 final Log4jContextFactory factory = getFactory();
258 if (factory != null) {
259 factory.getContext(FQCN, null, null, false)
260 .reconfigure(configuration);
261 }
262 } catch (final Exception ex) {
263 LOGGER.error("There was a problem initializing the LoggerContext using configuration {}",
264 configuration.getName(), ex);
265 }
266226 }
267227
268228 /**
365325 final LoggerContext loggerContext = LoggerContext.getContext(false);
366326 if (Strings.isEmpty(loggerName)) {
367327 setRootLevel(level);
368 } else if (setLevel(loggerName, level, loggerContext.getConfiguration())) {
369 loggerContext.updateLoggers();
328 } else {
329 if (setLevel(loggerName, level, loggerContext.getConfiguration())) {
330 loggerContext.updateLoggers();
331 }
370332 }
371333 }
372334
2929 */
3030 @Plugin(name = "CustomLevel", category = Core.CATEGORY_NAME, printObject = true)
3131 public final class CustomLevelConfig {
32
33 /**
34 * The empty array.
35 */
36 static final CustomLevelConfig[] EMPTY_ARRAY = {};
3732
3833 private final String levelName;
3934 private final int intLevel;
4646 @PluginFactory
4747 public static CustomLevels createCustomLevels(//
4848 @PluginElement("CustomLevels") final CustomLevelConfig[] customLevels) {
49 return new CustomLevels(customLevels == null ? CustomLevelConfig.EMPTY_ARRAY : customLevels);
49 return new CustomLevels(customLevels == null ? new CustomLevelConfig[0] : customLevels);
5050 }
5151
5252 /**
1717
1818 import org.apache.logging.log4j.Level;
1919 import org.apache.logging.log4j.Marker;
20 import org.apache.logging.log4j.core.config.LoggerConfig;
2021 import org.apache.logging.log4j.message.Message;
2122 import org.apache.logging.log4j.util.Supplier;
2223
2323 import org.apache.logging.log4j.Level;
2424 import org.apache.logging.log4j.Marker;
2525 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.impl.LocationAware;
2627 import org.apache.logging.log4j.message.Message;
2728 import org.apache.logging.log4j.util.Supplier;
2829
3233 public class LockingReliabilityStrategy implements ReliabilityStrategy, LocationAwareReliabilityStrategy {
3334 private final LoggerConfig loggerConfig;
3435 private final ReadWriteLock reconfigureLock = new ReentrantReadWriteLock();
35 private volatile boolean isStopping;
36 private volatile boolean isStopping = false;
3637
3738 public LockingReliabilityStrategy(final LoggerConfig loggerConfig) {
3839 this.loggerConfig = Objects.requireNonNull(loggerConfig, "loggerConfig was null");
380380 @PerformanceSensitive("allocation")
381381 public void log(final String loggerName, final String fqcn, final Marker marker, final Level level,
382382 final Message data, final Throwable t) {
383 final List<Property> props = getProperties(loggerName, fqcn, marker, level, data, t);
384 final LogEvent logEvent = logEventFactory.createEvent(
385 loggerName, marker, fqcn, location(fqcn), level, data, props, t);
383 List<Property> props = null;
384 if (!propertiesRequireLookup) {
385 props = properties;
386 } else {
387 if (properties != null) {
388 props = new ArrayList<>(properties.size());
389 final LogEvent event = Log4jLogEvent.newBuilder()
390 .setMessage(data)
391 .setMarker(marker)
392 .setLevel(level)
393 .setLoggerName(loggerName)
394 .setLoggerFqcn(fqcn)
395 .setThrown(t)
396 .build();
397 for (int i = 0; i < properties.size(); i++) {
398 final Property prop = properties.get(i);
399 final String value = prop.isValueNeedsLookup() // since LOG4J2-1575
400 ? config.getStrSubstitutor().replace(event, prop.getValue()) //
401 : prop.getValue();
402 props.add(Property.createProperty(prop.getName(), value));
403 }
404 }
405 }
406 final LogEvent logEvent = logEventFactory instanceof LocationAwareLogEventFactory ?
407 ((LocationAwareLogEventFactory) logEventFactory).createEvent(loggerName, marker, fqcn, requiresLocation() ?
408 StackLocatorUtil.calcLocation(fqcn) : null, level, data, props, t) :
409 logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t);
386410 try {
387411 log(logEvent, LoggerConfigPredicate.ALL);
388412 } finally {
389413 // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString())
390414 ReusableLogEventFactory.release(logEvent);
391415 }
392 }
393
394 private StackTraceElement location(String fqcn) {
395 return requiresLocation() ?
396 StackLocatorUtil.calcLocation(fqcn) : null;
397416 }
398417
399418 /**
410429 @PerformanceSensitive("allocation")
411430 public void log(final String loggerName, final String fqcn, final StackTraceElement location, final Marker marker,
412431 final Level level, final Message data, final Throwable t) {
413 final List<Property> props = getProperties(loggerName, fqcn, marker, level, data, t);
414 final LogEvent logEvent = logEventFactory.createEvent(loggerName, marker, fqcn, location, level, data, props, t);
432 List<Property> props = null;
433 if (!propertiesRequireLookup) {
434 props = properties;
435 } else {
436 if (properties != null) {
437 props = new ArrayList<>(properties.size());
438 final LogEvent event = Log4jLogEvent.newBuilder()
439 .setMessage(data)
440 .setMarker(marker)
441 .setLevel(level)
442 .setLoggerName(loggerName)
443 .setLoggerFqcn(fqcn)
444 .setThrown(t)
445 .build();
446 for (int i = 0; i < properties.size(); i++) {
447 final Property prop = properties.get(i);
448 final String value = prop.isValueNeedsLookup() // since LOG4J2-1575
449 ? config.getStrSubstitutor().replace(event, prop.getValue()) //
450 : prop.getValue();
451 props.add(Property.createProperty(prop.getName(), value));
452 }
453 }
454 }
455 final LogEvent logEvent = logEventFactory instanceof LocationAwareLogEventFactory ?
456 ((LocationAwareLogEventFactory) logEventFactory).createEvent(loggerName, marker, fqcn, location, level,
457 data, props, t) : logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t);
415458 try {
416459 log(logEvent, LoggerConfigPredicate.ALL);
417460 } finally {
420463 }
421464 }
422465
423 private List<Property> getProperties(
424 final String loggerName,
425 final String fqcn,
426 final Marker marker,
427 final Level level,
428 final Message data,
429 final Throwable t) {
430 List<Property> snapshot = properties;
431 if (snapshot == null || !propertiesRequireLookup) {
432 return snapshot;
433 }
434 return getPropertiesWithLookups(loggerName, fqcn, marker, level, data, t, snapshot);
435 }
436
437 private List<Property> getPropertiesWithLookups(
438 final String loggerName,
439 final String fqcn,
440 final Marker marker,
441 final Level level,
442 final Message data,
443 final Throwable t,
444 final List<Property> props) {
445 List<Property> results = new ArrayList<>(props.size());
446 final LogEvent event = Log4jLogEvent.newBuilder()
447 .setMessage(data)
448 .setMarker(marker)
449 .setLevel(level)
450 .setLoggerName(loggerName)
451 .setLoggerFqcn(fqcn)
452 .setThrown(t)
453 .build();
454 for (int i = 0; i < props.size(); i++) {
455 final Property prop = props.get(i);
456 final String value = prop.isValueNeedsLookup() // since LOG4J2-1575
457 ? config.getStrSubstitutor().replace(event, prop.getValue()) //
458 : prop.getValue();
459 results.add(Property.createProperty(prop.getName(), value));
460 }
461 return results;
462 }
463
464466 /**
465467 * Logs an event.
466468 *
501503 logParent(event, predicate);
502504 }
503505
504 @Override
505506 public boolean requiresLocation() {
506507 if (!includeLocation) {
507508 return false;
3535 */
3636 public static final String CATEGORY = "Core";
3737
38 private Node parent;
38 private final Node parent;
3939 private final String name;
4040 private String value;
4141 private final PluginType<?> type;
7474 this.children.add(new Node(child));
7575 }
7676 this.object = node.object;
77 }
78
79 public void setParent(Node parent) {
80 this.parent = parent;
8177 }
8278
8379 public Map<String, String> getAttributes() {
3434 /**
3535 * @since 2.11.2
3636 */
37 public static final Property[] EMPTY_ARRAY = {};
37 public static final Property[] EMPTY_ARRAY = new Property[0];
3838
3939 private static final Logger LOGGER = StatusLogger.getLogger();
4040
+0
-27
log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/Arbiter.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.logging.log4j.core.config.arbiters;
17
18 /**
19 * Interface used to check for portions of the configuration that may be optionally included.
20 */
21 public interface Arbiter {
22
23 String ELEMENT_TYPE = "Arbiter";
24
25 boolean isCondition();
26 }
+0
-75
log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/ClassArbiter.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.logging.log4j.core.config.arbiters;
17
18 import org.apache.logging.log4j.core.config.Node;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
21 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
22 import org.apache.logging.log4j.util.LoaderUtil;
23
24 /**
25 * Conditional that determines if the specified class is present.
26 */
27 @Plugin(name = "ClassArbiter", category = Node.CATEGORY, elementType = Arbiter.ELEMENT_TYPE,
28 printObject = true, deferChildren = true)
29 public class ClassArbiter implements Arbiter {
30
31 private final String className;
32
33 private ClassArbiter(final String className) {
34 this.className = className;
35 }
36
37 @Override
38 public boolean isCondition() {
39 return LoaderUtil.isClassAvailable(className);
40 }
41
42 @PluginBuilderFactory
43 public static SystemPropertyArbiter.Builder newBuilder() {
44 return new SystemPropertyArbiter.Builder();
45 }
46
47 public static class Builder implements org.apache.logging.log4j.core.util.Builder<ClassArbiter> {
48
49 public static final String ATTR_CLASS_NAME = "className";
50
51 @PluginBuilderAttribute(ATTR_CLASS_NAME)
52 private String className;
53
54
55 /**
56 * Sets the Class name.
57 * @param className the class name.
58 * @return this
59 */
60 public Builder setClassName(final String className) {
61 this.className = className;
62 return asBuilder();
63 }
64
65 public Builder asBuilder() {
66 return this;
67 }
68
69 public ClassArbiter build() {
70 return new ClassArbiter(className);
71 }
72
73 }
74 }
+0
-53
log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/DefaultArbiter.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.logging.log4j.core.config.arbiters;
17
18 import org.apache.logging.log4j.core.config.Node;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
21
22 /**
23 * Default Condition for a Select Condition.
24 */
25 @Plugin(name = "DefaultArbiter", category = Node.CATEGORY, elementType = Arbiter.ELEMENT_TYPE,
26 deferChildren = true, printObject = true)
27 public class DefaultArbiter implements Arbiter {
28
29 /**
30 * Always returns true since it is the default.
31 */
32 @Override
33 public boolean isCondition() {
34 return true;
35 }
36
37 @PluginBuilderFactory
38 public static Builder newBuilder() {
39 return new Builder();
40 }
41
42 public static class Builder implements org.apache.logging.log4j.core.util.Builder<DefaultArbiter> {
43
44 public Builder asBuilder() {
45 return this;
46 }
47
48 public DefaultArbiter build() {
49 return new DefaultArbiter();
50 }
51 }
52 }
+0
-121
log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiter.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.logging.log4j.core.config.arbiters;
17
18 import javax.script.SimpleBindings;
19
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.config.AbstractConfiguration;
22 import org.apache.logging.log4j.core.config.Configuration;
23 import org.apache.logging.log4j.core.config.Node;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
26 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
27 import org.apache.logging.log4j.core.config.plugins.PluginNode;
28 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
29 import org.apache.logging.log4j.core.script.AbstractScript;
30 import org.apache.logging.log4j.core.script.ScriptRef;
31 import org.apache.logging.log4j.status.StatusLogger;
32
33 /**
34 * Condition that evaluates a script.
35 */
36 @Plugin(name = "ScriptArbiter", category = Node.CATEGORY, elementType = Arbiter.ELEMENT_TYPE,
37 deferChildren = true, printObject = true)
38 public class ScriptArbiter implements Arbiter {
39
40 private final AbstractScript script;
41 private final Configuration configuration;
42
43 private ScriptArbiter(final Configuration configuration, final AbstractScript script) {
44 this.configuration = configuration;
45 this.script = script;
46 if (!(script instanceof ScriptRef)) {
47 configuration.getScriptManager().addScript(script);
48 }
49 }
50
51 /**
52 * Returns the boolean result of the Script.
53 */
54 @Override
55 public boolean isCondition() {
56 final SimpleBindings bindings = new SimpleBindings();
57 bindings.putAll(configuration.getProperties());
58 bindings.put("substitutor", configuration.getStrSubstitutor());
59 final Object object = configuration.getScriptManager().execute(script.getName(), bindings);
60 return Boolean.parseBoolean(object.toString());
61 }
62
63 @PluginBuilderFactory
64 public static Builder newBuilder() {
65 return new Builder();
66 }
67
68 public static class Builder implements org.apache.logging.log4j.core.util.Builder<ScriptArbiter> {
69
70 private static final Logger LOGGER = StatusLogger.getLogger();
71
72 @PluginConfiguration
73 private AbstractConfiguration configuration;
74
75 @PluginNode
76 private Node node;
77
78 public Builder setConfiguration(final AbstractConfiguration configuration) {
79 this.configuration = configuration;
80 return asBuilder();
81 }
82
83 public Builder setNode(final Node node) {
84 this.node = node;
85 return asBuilder();
86 }
87
88 public Builder asBuilder() {
89 return this;
90 }
91
92 public ScriptArbiter build() {
93 AbstractScript script = null;
94 for (Node child : node.getChildren()) {
95 PluginType<?> type = child.getType();
96 if (type == null) {
97 LOGGER.error("Node {} is missing a Plugintype", child.getName());
98 continue;
99 }
100 if (AbstractScript.class.isAssignableFrom(type.getPluginClass())) {
101 script = (AbstractScript) configuration.createPluginObject(type, child);
102 node.getChildren().remove(child);
103 break;
104 }
105 }
106
107 if (script == null) {
108 LOGGER.error("A Script, ScriptFile or ScriptRef element must be provided for this ScriptFilter");
109 return null;
110 }
111 if (script instanceof ScriptRef) {
112 if (configuration.getScriptManager().getScript(script.getName()) == null) {
113 LOGGER.error("No script with name {} has been declared.", script.getName());
114 return null;
115 }
116 }
117 return new ScriptArbiter(configuration, script);
118 }
119 }
120 }
+0
-64
log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/SelectArbiter.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.logging.log4j.core.config.arbiters;
17
18 import java.util.List;
19 import java.util.Optional;
20
21 import org.apache.logging.log4j.core.config.Node;
22 import org.apache.logging.log4j.core.config.plugins.Plugin;
23 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
24
25 /**
26 * Class Description goes here.
27 */
28 @Plugin(name = "Select", category = Node.CATEGORY, elementType = Arbiter.ELEMENT_TYPE, deferChildren = true,
29 printObject = true)
30 public class SelectArbiter {
31
32 public Arbiter evaluateConditions(List<Arbiter> conditions) {
33 Optional<Arbiter> opt = conditions.stream().filter((c) -> c instanceof DefaultArbiter)
34 .reduce((a, b) -> {
35 throw new IllegalStateException("Multiple elements: " + a + ", " + b);
36 });
37 for (Arbiter condition : conditions) {
38 if (condition instanceof DefaultArbiter) {
39 continue;
40 }
41 if (condition.isCondition()) {
42 return condition;
43 }
44 }
45 return opt.orElse(null);
46 }
47
48 @PluginBuilderFactory
49 public static Builder newBuilder() {
50 return new Builder();
51 }
52
53 public static class Builder implements org.apache.logging.log4j.core.util.Builder<SelectArbiter> {
54
55 public Builder asBuilder() {
56 return this;
57 }
58
59 public SelectArbiter build() {
60 return new SelectArbiter();
61 }
62 }
63 }
+0
-93
log4j-core/src/main/java/org/apache/logging/log4j/core/config/arbiters/SystemPropertyArbiter.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.logging.log4j.core.config.arbiters;
17
18 import org.apache.logging.log4j.core.config.Node;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
21 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
22
23 /**
24 * Condition that determines if the specified property is set.
25 */
26 @Plugin(name = "SystemPropertyArbiter", category = Node.CATEGORY, elementType = Arbiter.ELEMENT_TYPE,
27 deferChildren = true, printObject = true)
28 public class SystemPropertyArbiter implements Arbiter {
29
30 private final String propertyName;
31 private final String propertyValue;
32
33 private SystemPropertyArbiter(final String propertyName, final String propertyValue) {
34 this.propertyName = propertyName;
35 this.propertyValue = propertyValue;
36 }
37
38
39 /**
40 * Returns true if either the property name is defined (it has any value) or the property value
41 * matches the requested value.
42 */
43 @Override
44 public boolean isCondition() {
45 String value = System.getProperty(propertyName);
46 return value != null && (propertyValue == null || value.equals(propertyValue));
47 }
48
49 @PluginBuilderFactory
50 public static Builder newBuilder() {
51 return new Builder();
52 }
53
54 public static class Builder implements org.apache.logging.log4j.core.util.Builder<SystemPropertyArbiter> {
55
56 public static final String ATTR_PROPERTY_NAME = "propertyName";
57 public static final String ATTR_PROPERTY_VALUE = "propertyValue";
58
59 @PluginBuilderAttribute(ATTR_PROPERTY_NAME)
60 private String propertyName;
61
62 @PluginBuilderAttribute(ATTR_PROPERTY_VALUE)
63 private String propertyValue;
64 /**
65 * Sets the Property Name.
66 * @param propertyName the property name.
67 * @return this
68 */
69 public Builder setPropertyName(final String propertyName) {
70 this.propertyName = propertyName;
71 return asBuilder();
72 }
73
74 /**
75 * Sets the Property Value.
76 * @param propertyValue the property name.
77 * @return this
78 */
79 public Builder setPropertyValue(final String propertyValue) {
80 this.propertyName = propertyValue;
81 return asBuilder();
82 }
83
84 public Builder asBuilder() {
85 return this;
86 }
87
88 public SystemPropertyArbiter build() {
89 return new SystemPropertyArbiter(propertyName, propertyValue);
90 }
91 }
92 }
1717
1818 import java.io.IOException;
1919 import java.io.OutputStream;
20 import java.io.StringReader;
2120 import java.io.StringWriter;
2221 import java.lang.reflect.Constructor;
2322 import java.util.List;
2423 import java.util.Map;
2524 import java.util.concurrent.TimeUnit;
26
2725 import javax.xml.stream.XMLOutputFactory;
2826 import javax.xml.stream.XMLStreamException;
2927 import javax.xml.stream.XMLStreamWriter;
30 import javax.xml.transform.OutputKeys;
31 import javax.xml.transform.Result;
32 import javax.xml.transform.Source;
33 import javax.xml.transform.Transformer;
34 import javax.xml.transform.TransformerConfigurationException;
35 import javax.xml.transform.TransformerException;
36 import javax.xml.transform.TransformerFactory;
37 import javax.xml.transform.TransformerFactoryConfigurationError;
38 import javax.xml.transform.stream.StreamResult;
39 import javax.xml.transform.stream.StreamSource;
4028
4129 import org.apache.logging.log4j.Level;
4230 import org.apache.logging.log4j.core.Filter;
6856 public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implements ConfigurationBuilder<T> {
6957
7058 private static final String INDENT = " ";
59 private static final String EOL = System.lineSeparator();
7160
7261 private final Component root = new Component();
7362 private Component loggers;
8978 private LoggerContext loggerContext;
9079 private String name;
9180
92 public static void formatXml(final Source source, final Result result)
93 throws TransformerConfigurationException, TransformerFactoryConfigurationError, TransformerException {
94 final Transformer transformer = TransformerFactory.newInstance().newTransformer();
95 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", Integer.toString(INDENT.length()));
96 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
97 transformer.transform(source, result);
98 }
99
10081 @SuppressWarnings("unchecked")
10182 public DefaultConfigurationBuilder() {
10283 this((Class<T>) BuiltConfiguration.class);
224205 return configuration;
225206 }
226207
227 private String formatXml(String xml)
228 throws TransformerConfigurationException, TransformerException, TransformerFactoryConfigurationError {
229 final StringWriter writer = new StringWriter();
230 formatXml(new StreamSource(new StringReader(xml)), new StreamResult(writer));
231 return writer.toString();
232 }
233
234208 @Override
235209 public void writeXmlConfiguration(final OutputStream output) throws IOException {
236210 try {
239213 xmlWriter.close();
240214 } catch (final XMLStreamException e) {
241215 if (e.getNestedException() instanceof IOException) {
242 throw (IOException) e.getNestedException();
216 throw (IOException)e.getNestedException();
243217 }
244218 Throwables.rethrow(e);
245219 }
247221
248222 @Override
249223 public String toXmlConfiguration() {
250 final StringWriter writer = new StringWriter();
224 final StringWriter sw = new StringWriter();
251225 try {
252 final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
226 final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(sw);
253227 writeXmlConfiguration(xmlWriter);
254228 xmlWriter.close();
255 return formatXml(writer.toString());
256 } catch (final XMLStreamException | TransformerException e) {
229 } catch (final XMLStreamException e) {
257230 Throwables.rethrow(e);
258231 }
259 return writer.toString();
232 return sw.toString();
260233 }
261234
262235 private void writeXmlConfiguration(final XMLStreamWriter xmlWriter) throws XMLStreamException {
263236 xmlWriter.writeStartDocument();
237 xmlWriter.writeCharacters(EOL);
238
264239 xmlWriter.writeStartElement("Configuration");
265240 if (name != null) {
266241 xmlWriter.writeAttribute("name", name);
289264 if (monitorInterval > 0) {
290265 xmlWriter.writeAttribute("monitorInterval", String.valueOf(monitorInterval));
291266 }
267
268 xmlWriter.writeCharacters(EOL);
292269
293270 writeXmlSection(xmlWriter, properties);
294271 writeXmlSection(xmlWriter, scripts);
295272 writeXmlSection(xmlWriter, customLevels);
296273 if (filters.getComponents().size() == 1) {
297 writeXmlComponent(xmlWriter, filters.getComponents().get(0));
274 writeXmlComponent(xmlWriter, filters.getComponents().get(0), 1);
298275 } else if (filters.getComponents().size() > 1) {
299276 writeXmlSection(xmlWriter, filters);
300277 }
302279 writeXmlSection(xmlWriter, loggers);
303280
304281 xmlWriter.writeEndElement(); // "Configuration"
282 xmlWriter.writeCharacters(EOL);
283
305284 xmlWriter.writeEndDocument();
306285 }
307286
308287 private void writeXmlSection(final XMLStreamWriter xmlWriter, final Component component) throws XMLStreamException {
309288 if (!component.getAttributes().isEmpty() || !component.getComponents().isEmpty() || component.getValue() != null) {
310 writeXmlComponent(xmlWriter, component);
311 }
312 }
313
314 private void writeXmlComponent(final XMLStreamWriter xmlWriter, final Component component) throws XMLStreamException {
289 writeXmlComponent(xmlWriter, component, 1);
290 }
291 }
292
293 private void writeXmlComponent(final XMLStreamWriter xmlWriter, final Component component, final int nesting) throws XMLStreamException {
315294 if (!component.getComponents().isEmpty() || component.getValue() != null) {
295 writeXmlIndent(xmlWriter, nesting);
316296 xmlWriter.writeStartElement(component.getPluginType());
317297 writeXmlAttributes(xmlWriter, component);
298 if (!component.getComponents().isEmpty()) {
299 xmlWriter.writeCharacters(EOL);
300 }
318301 for (final Component subComponent : component.getComponents()) {
319 writeXmlComponent(xmlWriter, subComponent);
302 writeXmlComponent(xmlWriter, subComponent, nesting + 1);
320303 }
321304 if (component.getValue() != null) {
322305 xmlWriter.writeCharacters(component.getValue());
323306 }
307 if (!component.getComponents().isEmpty()) {
308 writeXmlIndent(xmlWriter, nesting);
309 }
324310 xmlWriter.writeEndElement();
325311 } else {
312 writeXmlIndent(xmlWriter, nesting);
326313 xmlWriter.writeEmptyElement(component.getPluginType());
327314 writeXmlAttributes(xmlWriter, component);
315 }
316 xmlWriter.writeCharacters(EOL);
317 }
318
319 private void writeXmlIndent(final XMLStreamWriter xmlWriter, final int nesting) throws XMLStreamException {
320 for (int i = 0; i < nesting; i++) {
321 xmlWriter.writeCharacters(INDENT);
328322 }
329323 }
330324
387381
388382 @Override
389383 public LoggerComponentBuilder newAsyncLogger(final String name, final String level, final boolean includeLocation) {
390 return new DefaultLoggerComponentBuilder(this, name, level, "AsyncLogger", includeLocation);
384 return new DefaultLoggerComponentBuilder(this, name, level, "AsyncLogger");
391385 }
392386
393387 @Override
5555 private MergeStrategy mergeStrategy;
5656
5757 /**
58 * Construct the CompositeConfiguration.
58 * Construct the ComponsiteConfiguration.
5959 *
6060 * @param configurations The List of Configurations to merge.
6161 */
6262 public CompositeConfiguration(final List<? extends AbstractConfiguration> configurations) {
63 super(configurations.get(0).getLoggerContext(), ConfigurationSource.COMPOSITE_SOURCE);
63 super(configurations.get(0).getLoggerContext(), ConfigurationSource.NULL_SOURCE);
6464 rootNode = configurations.get(0).getRootNode();
6565 this.configurations = configurations;
6666 final String mergeStrategyClassName = PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY,
4040 * configurations.</li>
4141 * <li>Filters are aggregated under a CompositeFilter if more than one Filter is defined. Since Filters are not named
4242 * duplicates may be present.</li>
43 * <li>Scripts and ScriptFile references are aggregated. Duplicate definitions replace those in previous
43 * <li>Scripts and ScriptFile references are aggregated. Duplicate definiations replace those in previous
4444 * configurations.</li>
4545 * <li>Appenders are aggregated. Appenders with the same name are replaced by those in later configurations, including
4646 * all of the Appender's subcomponents.</li>
8484 if (sourceLevel != null) {
8585 targetAttribute.setValue(attribute.getValue());
8686 }
87 } else if (attribute.getKey().equalsIgnoreCase("monitorInterval")) {
88 final int sourceInterval = Integer.parseInt(attribute.getValue());
89 final int targetInterval = Integer.parseInt(targetAttribute.getValue());
90 if (targetInterval == 0 || sourceInterval < targetInterval) {
87 } else {
88 if (attribute.getKey().equalsIgnoreCase("monitorInterval")) {
89 final int sourceInterval = Integer.parseInt(attribute.getValue());
90 final int targetInterval = Integer.parseInt(targetAttribute.getValue());
91 if (targetInterval == 0 || sourceInterval < targetInterval) {
92 targetAttribute.setValue(attribute.getValue());
93 }
94 } else {
9195 targetAttribute.setValue(attribute.getValue());
9296 }
93 } else if (attribute.getKey().equalsIgnoreCase("packages")) {
94 String sourcePackages = attribute.getValue();
95 String targetPackages = targetAttribute.getValue();
96 if (sourcePackages != null) {
97 if (targetPackages != null) {
98 targetAttribute.setValue(targetPackages + "," + sourcePackages);
99 }
100 else {
101 targetAttribute.setValue(sourcePackages);
102 }
103 }
104 }
105 else {
106 targetAttribute.setValue(attribute.getValue());
10797 }
10898 isFound = true;
10999 }
2020
2121 import org.apache.logging.log4j.Logger;
2222 import org.apache.logging.log4j.status.StatusLogger;
23 import org.apache.logging.log4j.util.Constants;
2423 import org.apache.logging.log4j.util.LoaderUtil;
2524
2625 /**
4039 decoder = getDecoder.invoke(null, (Object[]) null);
4140 clazz = decoder.getClass();
4241 method = clazz.getMethod("decode", String.class);
43 } catch (final ClassNotFoundException | NoSuchMethodException | IllegalAccessException |
44 InvocationTargetException ex) {
45 // ignore
42 } catch (final ClassNotFoundException ex) {
43
44 } catch (final NoSuchMethodException ex) {
45
46 } catch (final IllegalAccessException ex) {
47
48 } catch (final InvocationTargetException ex) {
49
4650 }
4751 if (method == null) {
4852 try {
6367 } else {
6468 try {
6569 return (byte[]) method.invoke(decoder, encoded);
66 } catch (final IllegalAccessException | InvocationTargetException ex) {
70 } catch (final IllegalAccessException ex) {
71 LOGGER.error("Error decoding string - " + ex.getMessage());
72 } catch (final InvocationTargetException ex) {
6773 LOGGER.error("Error decoding string - " + ex.getMessage());
6874 }
6975 }
70 return Constants.EMPTY_BYTE_ARRAY;
76 return new byte[0];
7177 }
7278 }
8585 if (clazz.isEnum()) {
8686 @SuppressWarnings({"unchecked","rawtypes"})
8787 final EnumConverter<? extends Enum> converter = new EnumConverter(clazz.asSubclass(Enum.class));
88 synchronized (INSTANCE_LOCK) {
89 return registerConverter(type, converter);
90 }
88 registry.putIfAbsent(type, converter);
89 return converter;
9190 }
9291 }
9392 // look for compatible converters
9695 if (TypeUtil.isAssignable(type, key)) {
9796 LOGGER.debug("Found compatible TypeConverter<{}> for type [{}].", key, type);
9897 final TypeConverter<?> value = entry.getValue();
99 synchronized (INSTANCE_LOCK) {
100 return registerConverter(type, value);
101 }
98 registry.putIfAbsent(type, value);
99 return value;
102100 }
103101 }
104102 throw new UnknownFormatConversionException(type.toString());
120118 final Class<? extends TypeConverter> pluginClass = clazz.asSubclass(TypeConverter.class);
121119 final Type conversionType = getTypeConverterSupportedType(pluginClass);
122120 final TypeConverter<?> converter = ReflectionUtil.instantiate(pluginClass);
123 registerConverter(conversionType, converter);
121 if (registry.putIfAbsent(conversionType, converter) != null) {
122 LOGGER.warn("Found a TypeConverter [{}] for type [{}] that already exists.", converter,
123 conversionType);
124 }
124125 }
125 }
126 }
127
128 /**
129 * Attempts to register the given converter and returns the effective
130 * converter associated with the given type.
131 * <p>
132 * Registration will fail if there already exists a converter for the given
133 * type and neither the existing, nor the provided converter extends from {@link Comparable}.
134 */
135 private TypeConverter<?> registerConverter(
136 final Type conversionType,
137 final TypeConverter<?> converter) {
138 final TypeConverter<?> conflictingConverter = registry.get(conversionType);
139 if (conflictingConverter != null) {
140 final boolean overridable;
141 if (converter instanceof Comparable) {
142 @SuppressWarnings("unchecked")
143 final Comparable<TypeConverter<?>> comparableConverter =
144 (Comparable<TypeConverter<?>>) converter;
145 overridable = comparableConverter.compareTo(conflictingConverter) < 0;
146 } else if (conflictingConverter instanceof Comparable) {
147 @SuppressWarnings("unchecked")
148 final Comparable<TypeConverter<?>> comparableConflictingConverter =
149 (Comparable<TypeConverter<?>>) conflictingConverter;
150 overridable = comparableConflictingConverter.compareTo(converter) > 0;
151 } else {
152 overridable = false;
153 }
154 if (overridable) {
155 LOGGER.debug(
156 "Replacing TypeConverter [{}] for type [{}] with [{}] after comparison.",
157 conflictingConverter, conversionType, converter);
158 registry.put(conversionType, converter);
159 return converter;
160 } else {
161 LOGGER.warn(
162 "Ignoring TypeConverter [{}] for type [{}] that conflicts with [{}], since they are not comparable.",
163 converter, conversionType, conflictingConverter);
164 return conflictingConverter;
165 }
166 } else {
167 registry.put(conversionType, converter);
168 return converter;
169126 }
170127 }
171128
3838 import org.apache.logging.log4j.core.config.plugins.Plugin;
3939 import org.apache.logging.log4j.core.util.CronExpression;
4040 import org.apache.logging.log4j.status.StatusLogger;
41 import org.apache.logging.log4j.util.Constants;
4241 import org.apache.logging.log4j.util.LoaderUtil;
4342
4443 /**
109108 public byte[] convert(final String value) {
110109 byte[] bytes;
111110 if (value == null || value.isEmpty()) {
112 bytes = Constants.EMPTY_BYTE_ARRAY;
111 bytes = new byte[0];
113112 } else if (value.startsWith(PREFIX_BASE64)) {
114113 final String lexicalXSDBase64Binary = value.substring(PREFIX_BASE64.length());
115114 bytes = Base64Converter.parseBase64Binary(lexicalXSDBase64Binary);
2424 import java.io.OutputStream;
2525 import java.net.URL;
2626 import java.util.Enumeration;
27 import java.util.LinkedHashMap;
2728 import java.util.Map;
28 import java.util.TreeMap;
2929
3030 /**
3131 *
3232 */
3333 public class PluginCache {
3434 private final Map<String, Map<String, PluginEntry>> categories =
35 new TreeMap<>();
35 new LinkedHashMap<>();
3636
3737 /**
3838 * Returns all categories of plugins in this cache.
5252 */
5353 public Map<String, PluginEntry> getCategory(final String category) {
5454 final String key = category.toLowerCase();
55 return categories.computeIfAbsent(key, ignored -> new TreeMap<>());
55 if (!categories.containsKey(key)) {
56 categories.put(key, new LinkedHashMap<String, PluginEntry>());
57 }
58 return categories.get(key);
5659 }
5760
5861 /**
100103 final Map<String, PluginEntry> m = getCategory(category);
101104 final int entries = in.readInt();
102105 for (int j = 0; j < entries; j++) {
103 // Must always read all parts of the entry, even if not adding, so that the stream progresses
104 final String key = in.readUTF();
105 final String className = in.readUTF();
106 final String name = in.readUTF();
107 final boolean printable = in.readBoolean();
108 final boolean defer = in.readBoolean();
109 m.computeIfAbsent(key, k -> {
110 final PluginEntry entry = new PluginEntry();
111 entry.setKey(k);
112 entry.setClassName(className);
113 entry.setName(name);
114 entry.setPrintable(printable);
115 entry.setDefer(defer);
116 entry.setCategory(category);
117 return entry;
118 });
106 final PluginEntry entry = new PluginEntry();
107 entry.setKey(in.readUTF());
108 entry.setClassName(in.readUTF());
109 entry.setName(in.readUTF());
110 entry.setPrintable(in.readBoolean());
111 entry.setDefer(in.readBoolean());
112 entry.setCategory(category);
113 if (!m.containsKey(entry.getKey())) {
114 m.put(entry.getKey(), entry);
115 }
119116 }
120117 }
121118 }
2626 import java.util.Objects;
2727 import java.util.Set;
2828 import javax.annotation.processing.AbstractProcessor;
29 import javax.annotation.processing.Messager;
3029 import javax.annotation.processing.RoundEnvironment;
3130 import javax.annotation.processing.SupportedAnnotationTypes;
3231 import javax.lang.model.SourceVersion;
6766
6867 @Override
6968 public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
70 Messager messager = processingEnv.getMessager();
71 messager.printMessage(Kind.NOTE, "Processing Log4j annotations");
69 System.out.println("Processing annotations");
7270 try {
7371 final Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Plugin.class);
7472 if (elements.isEmpty()) {
75 messager.printMessage(Kind.NOTE, "No elements to process");
73 System.out.println("No elements to process");
7674 return false;
7775 }
7876 collectPlugins(elements);
7977 writeCacheFile(elements.toArray(new Element[elements.size()]));
80 messager.printMessage(Kind.NOTE, "Annotations processed");
78 System.out.println("Annotations processed");
8179 return true;
80 } catch (final IOException e) {
81 e.printStackTrace();
82 error(e.getMessage());
83 return false;
8284 } catch (final Exception ex) {
8385 ex.printStackTrace();
8486 error(ex.getMessage());
3939 import org.apache.logging.log4j.core.config.plugins.validation.ConstraintValidators;
4040 import org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitor;
4141 import org.apache.logging.log4j.core.config.plugins.visitors.PluginVisitors;
42 import org.apache.logging.log4j.core.lookup.ConfigurationStrSubstitutor;
4243 import org.apache.logging.log4j.core.util.Builder;
4344 import org.apache.logging.log4j.core.util.ReflectionUtil;
4445 import org.apache.logging.log4j.core.util.TypeUtil;
180181 .setAnnotation(a)
181182 .setConversionType(field.getType())
182183 .setStrSubstitutor(event == null
183 ? configuration.getConfigurationStrSubstitutor()
184 ? new ConfigurationStrSubstitutor(configuration.getStrSubstitutor())
184185 : configuration.getStrSubstitutor())
185186 .setMember(field)
186187 .visit(configuration, node, event, log);
255256 .setAnnotation(a)
256257 .setConversionType(types[i])
257258 .setStrSubstitutor(event == null
258 ? configuration.getConfigurationStrSubstitutor()
259 ? new ConfigurationStrSubstitutor(configuration.getStrSubstitutor())
259260 : configuration.getStrSubstitutor())
260261 .setMember(factory)
261262 .visit(configuration, node, event, log);
188188 }
189189 }
190190 }
191 final int numPlugins = pluginCount;
192 LOGGER.debug(() -> {
193 final long endTime = System.nanoTime();
194 StringBuilder sb = new StringBuilder("Took ");
195 final DecimalFormat numFormat = new DecimalFormat("#0.000000");
196 sb.append(numFormat.format((endTime - startTime) * 1e-9));
197 sb.append(" seconds to load ").append(numPlugins);
198 sb.append(" plugins from ").append(loader);
199 return sb.toString();
200 });
191
192 final long endTime = System.nanoTime();
193 final DecimalFormat numFormat = new DecimalFormat("#0.000000");
194 final double seconds = (endTime - startTime) * 1e-9;
195 LOGGER.debug("Took {} seconds to load {} plugins from {}",
196 numFormat.format(seconds), pluginCount, loader);
201197 return newPluginsByCategory;
202198 }
203199
259255 }
260256 }
261257 }
262 LOGGER.debug(() -> {
263 final long endTime = System.nanoTime();
264 StringBuilder sb = new StringBuilder("Took ");
265 final DecimalFormat numFormat = new DecimalFormat("#0.000000");
266 sb.append(numFormat.format((endTime - startTime) * 1e-9));
267 sb.append(" seconds to load ").append(resolver.getClasses().size());
268 sb.append(" plugins from package ").append(pkg);
269 return sb.toString();
270 });
258
259 final long endTime = System.nanoTime();
260 final DecimalFormat numFormat = new DecimalFormat("#0.000000");
261 final double seconds = (endTime - startTime) * 1e-9;
262 LOGGER.debug("Took {} seconds to load {} plugins from package {}",
263 numFormat.format(seconds), resolver.getClasses().size(), pkg);
271264
272265 // Note multiple threads could be calling this method concurrently. Both will do the work,
273266 // but only one will be allowed to store the result in the outer map.
+0
-96
log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/util/PluginUtil.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.logging.log4j.core.config.plugins.util;
17
18 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
19
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.Modifier;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27
28 /**
29 * {@link org.apache.logging.log4j.core.config.plugins.Plugin} utilities.
30 *
31 * @see PluginManager
32 */
33 public final class PluginUtil {
34
35 private PluginUtil() {}
36
37 /**
38 * Shortcut for collecting plugins matching with the given {@code category}.
39 */
40 public static Map<String, PluginType<?>> collectPluginsByCategory(final String category) {
41 Objects.requireNonNull(category, "category");
42 return collectPluginsByCategoryAndPackage(category, Collections.emptyList());
43 }
44
45 /**
46 * Short for collecting plugins matching with the given {@code category} in provided {@code packages}.
47 */
48 public static Map<String, PluginType<?>> collectPluginsByCategoryAndPackage(
49 final String category,
50 final List<String> packages) {
51 Objects.requireNonNull(category, "category");
52 Objects.requireNonNull(packages, "packages");
53 final PluginManager pluginManager = new PluginManager(category);
54 pluginManager.collectPlugins(packages);
55 return pluginManager.getPlugins();
56 }
57
58 /**
59 * Instantiates the given plugin using its no-arg {@link PluginFactory}-annotated static method.
60 * @throws IllegalStateException if instantiation fails
61 */
62 public static <V> V instantiatePlugin(Class<V> pluginClass) {
63 Objects.requireNonNull(pluginClass, "pluginClass");
64 final Method pluginFactoryMethod = findPluginFactoryMethod(pluginClass);
65 try {
66 @SuppressWarnings("unchecked")
67 final V instance = (V) pluginFactoryMethod.invoke(null);
68 return instance;
69 } catch (IllegalAccessException | InvocationTargetException error) {
70 final String message = String.format(
71 "failed to instantiate plugin of type %s using the factory method %s",
72 pluginClass, pluginFactoryMethod);
73 throw new IllegalStateException(message, error);
74 }
75 }
76
77 /**
78 * Finds the {@link PluginFactory}-annotated static method of the given class.
79 * @throws IllegalStateException if no such method could be found
80 */
81 public static Method findPluginFactoryMethod(final Class<?> pluginClass) {
82 Objects.requireNonNull(pluginClass, "pluginClass");
83 for (final Method method : pluginClass.getDeclaredMethods()) {
84 final boolean methodAnnotated = method.isAnnotationPresent(PluginFactory.class);
85 if (methodAnnotated) {
86 final boolean methodStatic = Modifier.isStatic(method.getModifiers());
87 if (methodStatic) {
88 return method;
89 }
90 }
91 }
92 throw new IllegalStateException("no factory method found for class " + pluginClass);
93 }
94
95 }
2222 import org.apache.logging.log4j.core.config.Configuration;
2323 import org.apache.logging.log4j.core.config.Node;
2424 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
25 import org.apache.logging.log4j.core.util.NameUtil;
2526 import org.apache.logging.log4j.util.StringBuilders;
2627
2728 /**
4142 final String replacedValue = this.substitutor.replace(event, rawValue);
4243 final Object defaultValue = findDefaultValue(event);
4344 final Object value = convert(replacedValue, defaultValue);
44 final Object debugValue = this.annotation.sensitive() ? "*****" : value;
45 final Object debugValue = this.annotation.sensitive() ? NameUtil.md5(value + this.getClass().getName()) : value;
4546 StringBuilders.appendKeyDqValue(log, name, debugValue);
4647 return value;
4748 }
2222 import org.apache.logging.log4j.core.config.Configuration;
2323 import org.apache.logging.log4j.core.config.Node;
2424 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
25 import org.apache.logging.log4j.core.util.NameUtil;
2526 import org.apache.logging.log4j.util.StringBuilders;
2627
2728 /**
4647 final String rawValue = removeAttributeValue(attributes, name, this.aliases);
4748 final String replacedValue = this.substitutor.replace(event, rawValue);
4849 final Object value = convert(replacedValue, null);
49 final Object debugValue = this.annotation.sensitive() ? "*****" : value;
50 final Object debugValue = this.annotation.sensitive() ? NameUtil.md5(value + this.getClass().getName()) : value;
5051 StringBuilders.appendKeyDqValue(log, name, debugValue);
5152 return value;
5253 }
3636 final StringBuilder log) {
3737 final String name = this.annotation.value();
3838 final String elementValue = node.getValue();
39 final String attributeValue = node.getAttributes().get(name);
39 final String attributeValue = node.getAttributes().get("value");
4040 String rawValue = null; // if neither is specified, return null (LOG4J2-1313)
4141 if (Strings.isNotEmpty(elementValue)) {
4242 if (Strings.isNotEmpty(attributeValue)) {
4646 }
4747 rawValue = elementValue;
4848 } else {
49 rawValue = removeAttributeValue(node.getAttributes(), name);
49 rawValue = removeAttributeValue(node.getAttributes(), "value");
5050 }
5151 final String value = this.substitutor.replace(event, rawValue);
5252 StringBuilders.appendKeyDqValue(log, name, value);
227227 private FilterComponentBuilder createFilter(final String key, final Properties properties) {
228228 final String type = (String) properties.remove(CONFIG_TYPE);
229229 if (Strings.isEmpty(type)) {
230 throw new ConfigurationException("No type attribute provided for Filter " + key);
230 throw new ConfigurationException("No type attribute provided for Appender " + key);
231231 }
232232 final String onMatch = (String) properties.remove(AbstractFilterBuilder.ATTR_ON_MATCH);
233233 final String onMismatch = (String) properties.remove(AbstractFilterBuilder.ATTR_ON_MISMATCH);
269269 } else {
270270 throw new ConfigurationException("Unknown Logger type " + type + " for Logger " + name);
271271 }
272 } else if (location != null) {
273 includeLocation = Boolean.parseBoolean(location);
274 loggerBuilder = builder.newLogger(name, level, includeLocation);
275 } else {
276 loggerBuilder = builder.newLogger(name, level);
272 } else {
273 if (location != null) {
274 includeLocation = Boolean.parseBoolean(location);
275 loggerBuilder = builder.newLogger(name, level, includeLocation);
276 } else {
277 loggerBuilder = builder.newLogger(name, level);
278 }
277279 }
278280 addLoggersToComponent(loggerBuilder, properties);
279281 addFiltersToComponent(loggerBuilder, properties);
301303 } else {
302304 throw new ConfigurationException("Unknown Logger type for root logger" + type);
303305 }
304 } else if (location != null) {
305 includeLocation = Boolean.parseBoolean(location);
306 loggerBuilder = builder.newRootLogger(level, includeLocation);
307 } else {
308 loggerBuilder = builder.newRootLogger(level);
306 } else {
307 if (location != null) {
308 includeLocation = Boolean.parseBoolean(location);
309 loggerBuilder = builder.newRootLogger(level, includeLocation);
310 } else {
311 loggerBuilder = builder.newRootLogger(level);
312 }
309313 }
310314 addLoggersToComponent(loggerBuilder, properties);
311315 return addFiltersToComponent(loggerBuilder, properties);
2323 import java.net.URI;
2424 import java.net.URISyntaxException;
2525 import java.util.Collection;
26 import java.util.concurrent.LinkedBlockingQueue;
26 import java.util.Collections;
27 import java.util.LinkedList;
2728
2829 import org.apache.logging.log4j.Level;
2930 import org.apache.logging.log4j.core.util.FileUtils;
4243 private static final Level DEFAULT_STATUS = Level.ERROR;
4344 private static final Verbosity DEFAULT_VERBOSITY = Verbosity.QUIET;
4445
45 private final Collection<String> errorMessages = new LinkedBlockingQueue<>();
46 private final Collection<String> errorMessages = Collections.synchronizedCollection(new LinkedList<String>());
4647 private final StatusLogger logger = StatusLogger.getLogger();
4748
48 private volatile boolean initialized;
49 private volatile boolean initialized = false;
4950
5051 private PrintStream destination = DEFAULT_STREAM;
5152 private Level status = DEFAULT_STATUS;
4545 * <code>
4646 * &lt;Console name="console"&gt;<br>
4747 * &nbsp;&lt;PatternLayout pattern="%-5p %d{dd-MMM-yyyy HH:mm:ss} %x %t %m%n"/&gt;<br>
48 * &nbsp;&lt;Filters&gt;<br>
49 * &nbsp;&nbsp;&lt;BurstFilter level="INFO" rate="16" maxBurst="100"/&gt;<br>
50 * &nbsp;&lt;/Filters&gt;<br>
48 * &nbsp;&lt;filters&gt;<br>
49 * &nbsp;&nbsp;&lt;Burst level="INFO" rate="16" maxBurst="100"/&gt;<br>
50 * &nbsp;&lt;/filters&gt;<br>
5151 * &lt;/Console&gt;<br>
5252 * </code><br>
5353 */
4343 @PerformanceSensitive("allocation")
4444 public final class CompositeFilter extends AbstractLifeCycle implements Iterable<Filter>, Filter {
4545
46 private static final Filter[] EMPTY_FILTERS = new Filter[0];
4647 private final Filter[] filters;
4748
4849 private CompositeFilter() {
49 this.filters = Filter.EMPTY_ARRAY;
50 this.filters = EMPTY_FILTERS;
5051 }
5152
5253 private CompositeFilter(final Filter[] filters) {
53 this.filters = filters == null ? Filter.EMPTY_ARRAY : filters;
54 this.filters = filters == null ? EMPTY_FILTERS : filters;
5455 }
5556
5657 public CompositeFilter addFilter(final Filter filter) {
+0
-155
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DenyAllFilter.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.logging.log4j.core.filter;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Marker;
20 import org.apache.logging.log4j.core.Filter;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.Logger;
23 import org.apache.logging.log4j.core.config.Node;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
26 import org.apache.logging.log4j.message.Message;
27 import org.apache.logging.log4j.util.PerformanceSensitive;
28
29 /**
30 * This filter causes all logging events to be dropped.
31 */
32 @Plugin(name = "DenyAllFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
33 @PerformanceSensitive("allocation")
34 public final class DenyAllFilter extends AbstractFilter {
35
36 private DenyAllFilter(final Result onMatch, final Result onMismatch) {
37 super(onMatch, onMismatch);
38 }
39
40 @Override
41 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
42 final Object... params) {
43 return Result.DENY;
44 }
45
46 @Override
47 public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
48 final Throwable t) {
49 return Result.DENY;
50 }
51
52 @Override
53 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
54 final Throwable t) {
55 return Result.DENY;
56 }
57
58 @Override
59 public Result filter(final LogEvent event) {
60 return Result.DENY;
61 }
62
63 private Result filter(final Marker marker) {
64 return Result.DENY;
65 }
66
67 @Override
68 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
69 final Object p0) {
70 return Result.DENY;
71 }
72
73 @Override
74 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
75 final Object p0, final Object p1) {
76 return Result.DENY;
77 }
78
79 @Override
80 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
81 final Object p0, final Object p1, final Object p2) {
82 return filter(marker);
83 }
84
85 @Override
86 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
87 final Object p0, final Object p1, final Object p2, final Object p3) {
88 return Result.DENY;
89 }
90
91 @Override
92 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
93 final Object p0, final Object p1, final Object p2, final Object p3,
94 final Object p4) {
95 return Result.DENY;
96 }
97
98 @Override
99 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
100 final Object p0, final Object p1, final Object p2, final Object p3,
101 final Object p4, final Object p5) {
102 return Result.DENY;
103 }
104
105 @Override
106 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
107 final Object p0, final Object p1, final Object p2, final Object p3,
108 final Object p4, final Object p5, final Object p6) {
109 return Result.DENY;
110 }
111
112 @Override
113 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
114 final Object p0, final Object p1, final Object p2, final Object p3,
115 final Object p4, final Object p5, final Object p6,
116 final Object p7) {
117 return Result.DENY;
118 }
119
120 @Override
121 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
122 final Object p0, final Object p1, final Object p2, final Object p3,
123 final Object p4, final Object p5, final Object p6,
124 final Object p7, final Object p8) {
125 return Result.DENY;
126 }
127
128 @Override
129 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
130 final Object p0, final Object p1, final Object p2, final Object p3,
131 final Object p4, final Object p5, final Object p6,
132 final Object p7, final Object p8, final Object p9) {
133 return Result.DENY;
134 }
135
136 @Override
137 public String toString() {
138 return "DenyAll";
139 }
140
141 @PluginBuilderFactory
142 public static DenyAllFilter.Builder newBuilder() {
143 return new DenyAllFilter.Builder();
144 }
145
146 public static class Builder extends AbstractFilterBuilder<DenyAllFilter.Builder> implements org.apache.logging.log4j.core.util.Builder<DenyAllFilter> {
147
148 @Override
149 public DenyAllFilter build() {
150 return new DenyAllFilter(this.getOnMatch(), this.getOnMismatch());
151 }
152 }
153
154 }
9797 return false;
9898 }
9999 final DynamicThresholdFilter other = (DynamicThresholdFilter) obj;
100 if (!Objects.equals(defaultThreshold, other.defaultThreshold)) {
101 return false;
102 }
103 if (!Objects.equals(key, other.key)) {
104 return false;
105 }
106 if (!Objects.equals(levelMap, other.levelMap)) {
100 if (defaultThreshold == null) {
101 if (other.defaultThreshold != null) {
102 return false;
103 }
104 } else if (!defaultThreshold.equals(other.defaultThreshold)) {
105 return false;
106 }
107 if (key == null) {
108 if (other.key != null) {
109 return false;
110 }
111 } else if (!key.equals(other.key)) {
112 return false;
113 }
114 if (levelMap == null) {
115 if (other.levelMap != null) {
116 return false;
117 }
118 } else if (!levelMap.equals(other.levelMap)) {
107119 return false;
108120 }
109121 return true;
+0
-173
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelMatchFilter.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.logging.log4j.core.filter;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Marker;
20 import org.apache.logging.log4j.core.Filter;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.Logger;
23 import org.apache.logging.log4j.core.config.Node;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
26 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
27 import org.apache.logging.log4j.message.Message;
28 import org.apache.logging.log4j.util.PerformanceSensitive;
29
30 /**
31 * This filter returns the onMatch result if the logging level in the event matches the specified logging level
32 * exactly.
33 */
34 @Plugin(name = "LevelMatchFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
35 @PerformanceSensitive("allocation")
36 public final class LevelMatchFilter extends AbstractFilter {
37
38 public static final String ATTR_MATCH = "match";
39 private final Level level;
40
41 private LevelMatchFilter(final Level level, final Result onMatch, final Result onMismatch) {
42 super(onMatch, onMismatch);
43 this.level = level;
44 }
45
46 @Override
47 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
48 final Object... params) {
49 return filter(level);
50 }
51
52 @Override
53 public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
54 final Throwable t) {
55 return filter(level);
56 }
57
58 @Override
59 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
60 final Throwable t) {
61 return filter(level);
62 }
63
64 @Override
65 public Result filter(final LogEvent event) {
66 return filter(event.getLevel());
67 }
68
69 private Result filter(final Level level) {
70 return level == this.level ? onMatch : onMismatch;
71 }
72
73 @Override
74 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
75 final Object p0) {
76 return filter(level);
77 }
78
79 @Override
80 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
81 final Object p0, final Object p1) {
82 return filter(level);
83 }
84
85 @Override
86 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
87 final Object p0, final Object p1, final Object p2) {
88 return filter(level);
89 }
90
91 @Override
92 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
93 final Object p0, final Object p1, final Object p2, final Object p3) {
94 return filter(level);
95 }
96
97 @Override
98 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
99 final Object p0, final Object p1, final Object p2, final Object p3,
100 final Object p4) {
101 return filter(level);
102 }
103
104 @Override
105 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
106 final Object p0, final Object p1, final Object p2, final Object p3,
107 final Object p4, final Object p5) {
108 return filter(level);
109 }
110
111 @Override
112 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
113 final Object p0, final Object p1, final Object p2, final Object p3,
114 final Object p4, final Object p5, final Object p6) {
115 return filter(level);
116 }
117
118 @Override
119 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
120 final Object p0, final Object p1, final Object p2, final Object p3,
121 final Object p4, final Object p5, final Object p6,
122 final Object p7) {
123 return filter(level);
124 }
125
126 @Override
127 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
128 final Object p0, final Object p1, final Object p2, final Object p3,
129 final Object p4, final Object p5, final Object p6,
130 final Object p7, final Object p8) {
131 return filter(level);
132 }
133
134 @Override
135 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
136 final Object p0, final Object p1, final Object p2, final Object p3,
137 final Object p4, final Object p5, final Object p6,
138 final Object p7, final Object p8, final Object p9) {
139 return filter(level);
140 }
141
142 @Override
143 public String toString() {
144 return level.toString();
145 }
146
147 @PluginBuilderFactory
148 public static LevelMatchFilter.Builder newBuilder() {
149 return new LevelMatchFilter.Builder();
150 }
151
152 public static class Builder extends AbstractFilterBuilder<LevelMatchFilter.Builder> implements org.apache.logging.log4j.core.util.Builder<LevelMatchFilter> {
153 @PluginBuilderAttribute
154 private Level level = Level.ERROR;
155
156 /**
157 * Sets the logging level to use.
158 * @param level the logging level to use.
159 * @return this
160 */
161 public LevelMatchFilter.Builder setLevel(final Level level) {
162 this.level = level;
163 return this;
164 }
165
166 @Override
167 public LevelMatchFilter build() {
168 return new LevelMatchFilter(this.level, this.getOnMatch(), this.getOnMismatch());
169 }
170 }
171
172 }
3434 import org.apache.logging.log4j.core.util.KeyValuePair;
3535 import org.apache.logging.log4j.message.MapMessage;
3636 import org.apache.logging.log4j.message.Message;
37 import org.apache.logging.log4j.util.BiConsumer;
3738 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
3839 import org.apache.logging.log4j.util.IndexedStringMap;
3940 import org.apache.logging.log4j.util.PerformanceSensitive;
214215 @Deprecated
215216 protected Map<String, List<String>> getMap() {
216217 final Map<String, List<String>> result = new HashMap<>(map.size());
217 map.forEach((key, value) -> result.put(key, (List<String>) value));
218 map.forEach(new BiConsumer<String, List<String>>() {
219 @Override
220 public void accept(final String key, final List<String> value) {
221 result.put(key, value);
222 }
223 });
218224 return result;
219225 }
220226
106106 * @param regex
107107 * The regular expression to match.
108108 * @param patternFlags
109 * An array of Strings where each String is a {@link Pattern#compile(String, int)} compilation flag.
109 * An array of Stirngs where each String is a {@link Pattern#compile(String, int)} compilation flag.
110110 * @param useRawMsg
111111 * If true, the raw message will be used, otherwise the formatted message will be used.
112112 * @param match
141141 return DEFAULT_PATTERN_FLAGS;
142142 }
143143 final Field[] fields = Pattern.class.getDeclaredFields();
144 final Comparator<Field> comparator = (f1, f2) -> f1.getName().compareTo(f2.getName());
144 final Comparator<Field> comparator = new Comparator<Field>() {
145
146 @Override
147 public int compare(final Field f1, final Field f2) {
148 return f1.getName().compareTo(f2.getName());
149 }
150 };
145151 Arrays.sort(fields, comparator);
146152 final String[] fieldNames = new String[fields.length];
147153 for (int i = 0; i < fields.length; i++) {
+0
-175
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StringMatchFilter.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.logging.log4j.core.filter;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Marker;
20 import org.apache.logging.log4j.core.Filter;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.Logger;
23 import org.apache.logging.log4j.core.config.Node;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
26 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
27 import org.apache.logging.log4j.message.Message;
28 import org.apache.logging.log4j.util.PerformanceSensitive;
29
30 /**
31 * This filter returns the onMatch result if the logging level in the event matches the specified logging level
32 * exactly.
33 */
34 @Plugin(name = "StringMatchFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
35 @PerformanceSensitive("allocation")
36 public final class StringMatchFilter extends AbstractFilter {
37
38 public static final String ATTR_MATCH = "match";
39 private final String text;
40
41 private StringMatchFilter(final String text, final Result onMatch, final Result onMismatch) {
42 super(onMatch, onMismatch);
43 this.text = text;
44 }
45
46 @Override
47 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
48 final Object... params) {
49 return filter(logger.getMessageFactory().newMessage(msg, params).getFormattedMessage());
50 }
51
52 @Override
53 public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
54 final Throwable t) {
55 return filter(logger.getMessageFactory().newMessage(msg).getFormattedMessage());
56 }
57
58 @Override
59 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
60 final Throwable t) {
61 return filter(msg.getFormattedMessage());
62 }
63
64 @Override
65 public Result filter(final LogEvent event) {
66 return filter(event.getMessage().getFormattedMessage());
67 }
68
69 private Result filter(final String msg) {
70 return msg.contains(this.text) ? onMatch : onMismatch;
71 }
72
73 @Override
74 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
75 final Object p0) {
76 return filter(logger.getMessageFactory().newMessage(msg, p0).getFormattedMessage());
77 }
78
79 @Override
80 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
81 final Object p0, final Object p1) {
82 return filter(logger.getMessageFactory().newMessage(msg, p0, p1).getFormattedMessage());
83 }
84
85 @Override
86 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
87 final Object p0, final Object p1, final Object p2) {
88 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2).getFormattedMessage());
89 }
90
91 @Override
92 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
93 final Object p0, final Object p1, final Object p2, final Object p3) {
94 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2, p3).getFormattedMessage());
95 }
96
97 @Override
98 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
99 final Object p0, final Object p1, final Object p2, final Object p3,
100 final Object p4) {
101 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2, p3, p4).getFormattedMessage());
102 }
103
104 @Override
105 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
106 final Object p0, final Object p1, final Object p2, final Object p3,
107 final Object p4, final Object p5) {
108 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2, p3, p4, p5).getFormattedMessage());
109 }
110
111 @Override
112 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
113 final Object p0, final Object p1, final Object p2, final Object p3,
114 final Object p4, final Object p5, final Object p6) {
115 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2, p3, p4, p5, p6).getFormattedMessage());
116 }
117
118 @Override
119 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
120 final Object p0, final Object p1, final Object p2, final Object p3,
121 final Object p4, final Object p5, final Object p6,
122 final Object p7) {
123 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2, p3, p4, p5, p6, p7).getFormattedMessage());
124 }
125
126 @Override
127 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
128 final Object p0, final Object p1, final Object p2, final Object p3,
129 final Object p4, final Object p5, final Object p6,
130 final Object p7, final Object p8) {
131 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2, p3, p4, p5, p6, p7, p8)
132 .getFormattedMessage());
133 }
134
135 @Override
136 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
137 final Object p0, final Object p1, final Object p2, final Object p3,
138 final Object p4, final Object p5, final Object p6,
139 final Object p7, final Object p8, final Object p9) {
140 return filter(logger.getMessageFactory().newMessage(msg, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)
141 .getFormattedMessage());
142 }
143
144 @Override
145 public String toString() {
146 return text;
147 }
148
149 @PluginBuilderFactory
150 public static StringMatchFilter.Builder newBuilder() {
151 return new StringMatchFilter.Builder();
152 }
153
154 public static class Builder extends AbstractFilterBuilder<StringMatchFilter.Builder> implements org.apache.logging.log4j.core.util.Builder<StringMatchFilter> {
155 @PluginBuilderAttribute
156 private String text = "";
157
158 /**
159 * Sets the logging level to use.
160 * @param level the logging level to use.
161 * @return this
162 */
163 public StringMatchFilter.Builder setMatchString(final String text) {
164 this.text = text;
165 return this;
166 }
167
168 @Override
169 public StringMatchFilter build() {
170 return new StringMatchFilter(this.text, this.getOnMatch(), this.getOnMismatch());
171 }
172 }
173
174 }
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import java.time.Duration;
19 import java.time.Instant;
20 import java.time.LocalDate;
21 import java.time.LocalTime;
22 import java.time.ZoneId;
23 import java.time.ZonedDateTime;
24 import java.time.format.DateTimeFormatter;
18 import java.text.ParseException;
19 import java.text.SimpleDateFormat;
20 import java.util.Calendar;
21 import java.util.TimeZone;
2522
2623 import org.apache.logging.log4j.Level;
2724 import org.apache.logging.log4j.Marker;
4441 @PerformanceSensitive("allocation")
4542 public final class TimeFilter extends AbstractFilter {
4643 private static final Clock CLOCK = ClockFactory.getClock();
47 private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
4844
4945 /**
5046 * Length of hour in milliseconds.
5147 */
5248 private static final long HOUR_MS = 3600000;
5349
54 private static final long DAY_MS = HOUR_MS * 24;
50 /**
51 * Length of minute in milliseconds.
52 */
53 private static final long MINUTE_MS = 60000;
54
55 /**
56 * Length of second in milliseconds.
57 */
58 private static final long SECOND_MS = 1000;
5559
5660 /**
5761 * Starting offset from midnight in milliseconds.
5862 */
59 private volatile long start;
60 private final LocalTime startTime;
61
63 private final long start;
64
6265 /**
6366 * Ending offset from midnight in milliseconds.
6467 */
65 private volatile long end;
66 private final LocalTime endTime;
67
68 private final long duration;
68 private final long end;
6969
7070 /**
7171 * Timezone.
7272 */
73 private final ZoneId timeZone;
74
75 /*
76 * Expose for unit testing.
77 */
78 TimeFilter(final LocalTime start, final LocalTime end, final ZoneId timeZone, final Result onMatch,
79 final Result onMismatch, LocalDate now) {
73 private final TimeZone timeZone;
74
75 private long midnightToday;
76 private long midnightTomorrow;
77
78
79 private TimeFilter(final long start, final long end, final TimeZone timeZone, final Result onMatch,
80 final Result onMismatch) {
8081 super(onMatch, onMismatch);
81 this.startTime = start;
82 this.endTime = end;
82 this.start = start;
83 this.end = end;
8384 this.timeZone = timeZone;
84 this.start = ZonedDateTime.of(now, startTime, timeZone).withEarlierOffsetAtOverlap().toInstant().toEpochMilli();
85 long endMillis = ZonedDateTime.of(now, endTime, timeZone).withEarlierOffsetAtOverlap().toInstant().toEpochMilli();
86 if (end.isBefore(start)) {
87 // End time must be tomorrow.
88 endMillis += DAY_MS;
89 }
90 duration = startTime.isBefore(endTime) ? Duration.between(startTime, endTime).toMillis() :
91 Duration.between(startTime, endTime).plusHours(24).toMillis();
92 long difference = (endMillis - this.start) - duration;
93 if (difference != 0) {
94 // Handle switch from standard time to daylight time and daylight time to standard time.
95 endMillis -= difference;
96 }
97 this.end = endMillis;
98 }
99
100 private TimeFilter(final LocalTime start, final LocalTime end, final ZoneId timeZone, final Result onMatch,
101 final Result onMismatch) {
102 this(start, end, timeZone, onMatch, onMismatch, LocalDate.now(timeZone));
103 }
104
105 private synchronized void adjustTimes(long currentTimeMillis) {
106 if (currentTimeMillis <= end) {
107 return;
108 }
109 LocalDate date = Instant.ofEpochMilli(currentTimeMillis).atZone(timeZone).toLocalDate();
110 this.start = ZonedDateTime.of(date, startTime, timeZone).withEarlierOffsetAtOverlap().toInstant().toEpochMilli();
111 long endMillis = ZonedDateTime.of(date, endTime, timeZone).withEarlierOffsetAtOverlap().toInstant().toEpochMilli();
112 if (endTime.isBefore(startTime)) {
113 // End time must be tomorrow.
114 endMillis += DAY_MS;
115 }
116 long difference = (endMillis - this.start) - duration;
117 if (difference != 0) {
118 // Handle switch from standard time to daylight time and daylight time to standard time.
119 endMillis -= difference;
120 }
121 this.end = endMillis;
85 initMidnight(start);
86 }
87
88 /**
89 * Initializes the midnight boundaries to midnight in the specified time zone.
90 * @param now a time in milliseconds since the epoch, used to pinpoint the current date
91 */
92 void initMidnight(final long now) {
93 final Calendar calendar = Calendar.getInstance(timeZone);
94 calendar.setTimeInMillis(now);
95 calendar.set(Calendar.HOUR_OF_DAY, 0);
96 calendar.set(Calendar.MINUTE, 0);
97 calendar.set(Calendar.SECOND, 0);
98 calendar.set(Calendar.MILLISECOND, 0);
99 midnightToday = calendar.getTimeInMillis();
100
101 calendar.add(Calendar.DATE, 1);
102 midnightTomorrow = calendar.getTimeInMillis();
122103 }
123104
124105 /**
129110 * @return the action to perform
130111 */
131112 Result filter(final long currentTimeMillis) {
132 if (currentTimeMillis > end) {
133 adjustTimes(currentTimeMillis);
113 if (currentTimeMillis >= midnightTomorrow || currentTimeMillis < midnightToday) {
114 initMidnight(currentTimeMillis);
134115 }
135 return currentTimeMillis >= start && currentTimeMillis <= end ? onMatch : onMismatch;
116 return currentTimeMillis >= midnightToday + start && currentTimeMillis <= midnightToday + end //
117 ? onMatch // within window
118 : onMismatch;
136119 }
137120
138121 @Override
252235 @PluginAttribute("timezone") final String tz,
253236 @PluginAttribute("onMatch") final Result match,
254237 @PluginAttribute("onMismatch") final Result mismatch) {
255 final LocalTime startTime = parseTimestamp(start, LocalTime.MIN);
256 final LocalTime endTime = parseTimestamp(end, LocalTime.MAX);
257 final ZoneId timeZone = tz == null ? ZoneId.systemDefault() : ZoneId.of(tz);
238 final long s = parseTimestamp(start, 0);
239 final long e = parseTimestamp(end, Long.MAX_VALUE);
240 final TimeZone timeZone = tz == null ? TimeZone.getDefault() : TimeZone.getTimeZone(tz);
258241 final Result onMatch = match == null ? Result.NEUTRAL : match;
259242 final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
260 return new TimeFilter(startTime, endTime, timeZone, onMatch, onMismatch);
261 }
262
263 private static LocalTime parseTimestamp(final String timestamp, final LocalTime defaultValue) {
243 return new TimeFilter(s, e, timeZone, onMatch, onMismatch);
244 }
245
246 private static long parseTimestamp(final String timestamp, final long defaultValue) {
264247 if (timestamp == null) {
265248 return defaultValue;
266249 }
267
250 final SimpleDateFormat stf = new SimpleDateFormat("HH:mm:ss");
251 stf.setTimeZone(TimeZone.getTimeZone("UTC"));
268252 try {
269 return LocalTime.parse(timestamp, FORMATTER);
270 } catch (final Exception e) {
253 return stf.parse(timestamp).getTime();
254 } catch (final ParseException e) {
271255 LOGGER.warn("Error parsing TimeFilter timestamp value {}", timestamp, e);
272256 return defaultValue;
273257 }
1515 */
1616 package org.apache.logging.log4j.core.impl;
1717
18 import java.lang.reflect.Constructor;
18 import java.lang.invoke.MethodHandle;
19 import java.lang.invoke.MethodHandles;
20 import java.lang.invoke.MethodType;
1921 import java.util.Map;
2022 import java.util.Map.Entry;
2123
4547 * @since 2.7
4648 */
4749 public class ContextDataFactory {
50 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
4851 private static final String CLASS_NAME = PropertiesUtil.getProperties().getStringProperty("log4j2.ContextData");
4952 private static final Class<? extends StringMap> CACHED_CLASS = createCachedClass(CLASS_NAME);
50
51 /**
52 * In LOG4J2-2649 (https://issues.apache.org/jira/browse/LOG4J2-2649),
53 * the reporter said some reason about using graalvm to static compile.
54 * In graalvm doc (https://github.com/oracle/graal/blob/master/substratevm/LIMITATIONS.md),
55 * graalvm is not support MethodHandle now, so the Constructor need not to return MethodHandle.
56 */
57 private static final Constructor<?> DEFAULT_CONSTRUCTOR = createDefaultConstructor(CACHED_CLASS);
58 private static final Constructor<?> INITIAL_CAPACITY_CONSTRUCTOR = createInitialCapacityConstructor(CACHED_CLASS);
53 private static final MethodHandle DEFAULT_CONSTRUCTOR = createDefaultConstructor(CACHED_CLASS);
54 private static final MethodHandle INITIAL_CAPACITY_CONSTRUCTOR = createInitialCapacityConstructor(CACHED_CLASS);
5955
6056 private static final StringMap EMPTY_STRING_MAP = createContextData(0);
6157
7470 }
7571 }
7672
77 private static Constructor<?> createDefaultConstructor(final Class<? extends StringMap> cachedClass){
73 private static MethodHandle createDefaultConstructor(final Class<? extends StringMap> cachedClass) {
7874 if (cachedClass == null) {
7975 return null;
8076 }
8177 try {
82 return cachedClass.getConstructor();
83 } catch (final NoSuchMethodException | IllegalAccessError ignored) {
78 return LOOKUP.findConstructor(cachedClass, MethodType.methodType(void.class));
79 } catch (final NoSuchMethodException | IllegalAccessException ignored) {
8480 return null;
8581 }
8682 }
8783
88 private static Constructor<?> createInitialCapacityConstructor(final Class<? extends StringMap> cachedClass){
84 private static MethodHandle createInitialCapacityConstructor(final Class<? extends StringMap> cachedClass) {
8985 if (cachedClass == null) {
9086 return null;
9187 }
9288 try {
93 return cachedClass.getConstructor(int.class);
94 } catch (final NoSuchMethodException | IllegalAccessError ignored) {
89 return LOOKUP.findConstructor(cachedClass, MethodType.methodType(void.class, int.class));
90 } catch (final NoSuchMethodException | IllegalAccessException ignored) {
9591 return null;
9692 }
9793 }
10197 return new SortedArrayStringMap();
10298 }
10399 try {
104 return (IndexedStringMap) DEFAULT_CONSTRUCTOR.newInstance();
100 return (IndexedStringMap) DEFAULT_CONSTRUCTOR.invoke();
105101 } catch (final Throwable ignored) {
106102 return new SortedArrayStringMap();
107103 }
112108 return new SortedArrayStringMap(initialCapacity);
113109 }
114110 try {
115 return (IndexedStringMap) INITIAL_CAPACITY_CONSTRUCTOR.newInstance(initialCapacity);
111 return (IndexedStringMap) INITIAL_CAPACITY_CONSTRUCTOR.invoke(initialCapacity);
116112 } catch (final Throwable ignored) {
117113 return new SortedArrayStringMap(initialCapacity);
118114 }
4747 * {@code ContextDataInjector} classes defined in {@link ThreadContextDataInjector} which is most appropriate for
4848 * the ThreadContext implementation.
4949 * <p>
50 * <b>Note:</b> It is no longer recommended that users provide a custom implementation of the ContextDataInjector.
51 * Instead, provide a {@code ContextDataProvider}.
52 * </p>
53 * <p>
5450 * Users may use this system property to specify the fully qualified class name of a class that implements the
5551 * {@code ContextDataInjector} interface.
5652 * </p><p>
1616 package org.apache.logging.log4j.core.impl;
1717
1818 import java.io.Serializable;
19 import java.util.Objects;
2019
2120 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
2221 import org.apache.logging.log4j.core.pattern.TextRenderer;
4241 * @param version
4342 */
4443 public ExtendedClassInfo(final boolean exact, final String location, final String version) {
44 super();
4545 this.exact = exact;
4646 this.location = location;
4747 this.version = version;
6262 if (this.exact != other.exact) {
6363 return false;
6464 }
65 if (!Objects.equals(this.location, other.location)) {
65 if (this.location == null) {
66 if (other.location != null) {
67 return false;
68 }
69 } else if (!this.location.equals(other.location)) {
6670 return false;
6771 }
68 if (!Objects.equals(this.version, other.version)) {
72 if (this.version == null) {
73 if (other.version != null) {
74 return false;
75 }
76 } else if (!this.version.equals(other.version)) {
6977 return false;
7078 }
7179 return true;
8593
8694 @Override
8795 public int hashCode() {
88 return Objects.hash(exact, location, version);
96 final int prime = 31;
97 int result = 1;
98 result = prime * result + (this.exact ? 1231 : 1237);
99 result = prime * result + ((this.location == null) ? 0 : this.location.hashCode());
100 result = prime * result + ((this.version == null) ? 0 : this.version.hashCode());
101 return result;
89102 }
90103
91104 public void renderOn(final StringBuilder output, final TextRenderer textRenderer) {
1616 package org.apache.logging.log4j.core.impl;
1717
1818 import java.io.Serializable;
19 import java.util.Objects;
2019
2120 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
2221 import org.apache.logging.log4j.core.pattern.TextRenderer;
3332 * </ul>
3433 */
3534 public final class ExtendedStackTraceElement implements Serializable {
36
37 static final ExtendedStackTraceElement[] EMPTY_ARRAY = {};
3835
3936 private static final long serialVersionUID = -2171069569241280505L;
4037
6966 return false;
7067 }
7168 final ExtendedStackTraceElement other = (ExtendedStackTraceElement) obj;
72 if (!Objects.equals(this.extraClassInfo, other.extraClassInfo)) {
69 if (this.extraClassInfo == null) {
70 if (other.extraClassInfo != null) {
71 return false;
72 }
73 } else if (!this.extraClassInfo.equals(other.extraClassInfo)) {
7374 return false;
7475 }
75 if (!Objects.equals(this.stackTraceElement, other.stackTraceElement)) {
76 if (this.stackTraceElement == null) {
77 if (other.stackTraceElement != null) {
78 return false;
79 }
80 } else if (!this.stackTraceElement.equals(other.stackTraceElement)) {
7681 return false;
7782 }
7883 return true;
116121
117122 @Override
118123 public int hashCode() {
119 return Objects.hash(extraClassInfo, stackTraceElement);
124 final int prime = 31;
125 int result = 1;
126 result = prime * result + ((this.extraClassInfo == null) ? 0 : this.extraClassInfo.hashCode());
127 result = prime * result + ((this.stackTraceElement == null) ? 0 : this.stackTraceElement.hashCode());
128 return result;
120129 }
121130
122131 public boolean isNativeMethod() {
2929 /**
3030 * Provides a read-only {@code StringMap} view of a {@code Map<String, String>}.
3131 */
32 public class JdkMapAdapterStringMap implements StringMap {
32 class JdkMapAdapterStringMap implements StringMap {
3333 private static final long serialVersionUID = -7348247784983193612L;
3434 private static final String FROZEN = "Frozen collection cannot be modified";
35 private static final Comparator<? super String> NULL_FIRST_COMPARATOR = (left, right) -> {
36 if (left == null) {
37 return -1;
38 }
39 if (right == null) {
40 return 1;
41 }
42 return left.compareTo(right);
35 private static final Comparator<? super String> NULL_FIRST_COMPARATOR = new Comparator<String>() {
36 @Override
37 public int compare(final String left, final String right) {
38 if (left == null) {
39 return -1;
40 }
41 if (right == null) {
42 return 1;
43 }
44 return left.compareTo(right);
45 }
4346 };
4447
4548 private final Map<String, String> map;
139142 sortedKeys = null;
140143 }
141144
142 private static TriConsumer<String, String, Map<String, String>> PUT_ALL = (key, value, stringStringMap) -> stringStringMap.put(key, value);
145 private static TriConsumer<String, String, Map<String, String>> PUT_ALL = new TriConsumer<String, String, Map<String, String>>() {
146 @Override
147 public void accept(final String key, final String value, final Map<String, String> stringStringMap) {
148 stringStringMap.put(key, value);
149 }
150 };
143151
144152 @Override
145153 public void putValue(final String key, final Object value) {
1818 import java.net.URI;
1919 import java.util.ArrayList;
2020 import java.util.List;
21 import java.util.Map;
2221 import java.util.Objects;
2322
2423 import org.apache.logging.log4j.core.LifeCycle;
2524 import org.apache.logging.log4j.core.LoggerContext;
2625 import org.apache.logging.log4j.core.config.AbstractConfiguration;
27 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2826 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
2927 import org.apache.logging.log4j.core.config.Configuration;
3028 import org.apache.logging.log4j.core.config.ConfigurationFactory;
247245 return ctx;
248246 }
249247
250 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Map.Entry<String, Object> entry,
251 final boolean currentContext, final URI configLocation, final String name) {
252 final LoggerContext ctx = selector.getContext(fqcn, loader, entry, currentContext, configLocation);
253 if (name != null) {
254 ctx.setName(name);
255 }
256 if (ctx.getState() == LifeCycle.State.INITIALIZED) {
257 if (configLocation != null || name != null) {
258 ContextAnchor.THREAD_CONTEXT.set(ctx);
259 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(ctx, name, configLocation);
260 LOGGER.debug("Starting LoggerContext[name={}] from configuration at {}", ctx.getName(), configLocation);
261 ctx.start(config);
262 ContextAnchor.THREAD_CONTEXT.remove();
263 } else {
264 ctx.start();
265 }
266 }
267 return ctx;
268 }
269
270248 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
271249 final boolean currentContext, final List<URI> configLocations, final String name) {
272250 final LoggerContext ctx = selector
284262 for (final URI configLocation : configLocations) {
285263 final Configuration currentReadConfiguration = ConfigurationFactory.getInstance()
286264 .getConfiguration(ctx, name, configLocation);
287 if (currentReadConfiguration != null) {
288 if (currentReadConfiguration instanceof DefaultConfiguration) {
289 LOGGER.warn("Unable to locate configuration {}, ignoring", configLocation.toString());
290 }
291 else if (currentReadConfiguration instanceof AbstractConfiguration) {
292 configurations.add((AbstractConfiguration) currentReadConfiguration);
293 } else {
294 LOGGER.error(
295 "Found configuration {}, which is not an AbstractConfiguration and can't be handled by CompositeConfiguration",
296 configLocation);
297 }
265 if (currentReadConfiguration instanceof AbstractConfiguration) {
266 configurations.add((AbstractConfiguration) currentReadConfiguration);
298267 } else {
299 LOGGER.info("Unable to access configuration {}, ignoring", configLocation.toString());
268 LOGGER.error(
269 "Found configuration {}, which is not an AbstractConfiguration and can't be handled by CompositeConfiguration",
270 configLocation);
300271 }
301272 }
302 if (configurations.isEmpty()) {
303 LOGGER.error("No configurations could be created for {}", configLocations.toString());
304 } else if (configurations.size() == 1) {
305 AbstractConfiguration config = configurations.get(0);
306 LOGGER.debug("Starting LoggerContext[name={}] from configuration at {}", ctx.getName(),
307 config.getConfigurationSource().getLocation());
308 ctx.start(config);
309 } else {
310 final CompositeConfiguration compositeConfiguration = new CompositeConfiguration(configurations);
311 LOGGER.debug("Starting LoggerContext[name={}] from configurations at {}", ctx.getName(),
312 configLocations);
313 ctx.start(compositeConfiguration);
314 }
315
273 final CompositeConfiguration compositeConfiguration = new CompositeConfiguration(configurations);
274 LOGGER.debug("Starting LoggerContext[name={}] from configurations at {}", ctx.getName(),
275 configLocations);
276 ctx.start(compositeConfiguration);
316277 ContextAnchor.THREAD_CONTEXT.remove();
317278 } else {
318279 ctx.start();
319280 }
320281 }
321282 return ctx;
322 }
323
324 @Override
325 public void shutdown(String fqcn, ClassLoader loader, boolean currentContext, boolean allContexts) {
326 if (selector.hasContext(fqcn, loader, currentContext)) {
327 selector.shutdown(fqcn, loader, currentContext, allContexts);
328 }
329 }
330
331 /**
332 * Checks to see if a LoggerContext is installed.
333 * @param fqcn The fully qualified class name of the caller.
334 * @param loader The ClassLoader to use or null.
335 * @param currentContext If true returns the current Context, if false returns the Context appropriate
336 * for the caller if a more appropriate Context can be determined.
337 * @return true if a LoggerContext has been installed, false otherwise.
338 * @since 3.0
339 */
340 @Override
341 public boolean hasContext(String fqcn, ClassLoader loader, boolean currentContext) {
342 return selector.hasContext(fqcn, loader, currentContext);
343283 }
344284
345285 /**
373313 }
374314
375315 @Override
376 public boolean isClassLoaderDependent() {
377 return selector.isClassLoaderDependent();
378 }
379
380 @Override
381316 public Cancellable addShutdownCallback(final Runnable callback) {
382317 return isShutdownHookEnabled() ? shutdownCallbackRegistry.addShutdownCallback(callback) : null;
383318 }
2727 /**
2828 *
2929 */
30 public interface LogEventFactory extends LocationAwareLogEventFactory {
30 public interface LogEventFactory {
3131
3232 LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message data,
3333 List<Property> properties, Throwable t);
34
35 @Override
36 default LogEvent createEvent(
37 String loggerName,
38 Marker marker,
39 String fqcn,
40 @SuppressWarnings("unused") StackTraceElement location,
41 Level level,
42 Message data,
43 List<Property> properties,
44 Throwable t) {
45 return createEvent(loggerName, marker, fqcn, level, data, properties, t);
46 }
4734 }
6666 transient boolean reserved = false;
6767
6868 public MutableLogEvent() {
69 // messageText and the parameter array are lazily initialized
70 this(null, null);
69 this(new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE), new Object[10]);
7170 }
7271
7372 public MutableLogEvent(final StringBuilder msgText, final Object[] replacementParameters) {
146145 StringBuilders.trimToMaxSize(messageText, Constants.MAX_REUSABLE_MESSAGE_SIZE);
147146
148147 if (parameters != null) {
149 Arrays.fill(parameters, null);
148 for (int i = 0; i < parameters.length; i++) {
149 parameters[i] = null;
150 }
150151 }
151152
152153 // primitive fields that cannot be cleared:
210211 final ReusableMessage reusable = (ReusableMessage) msg;
211212 reusable.formatTo(getMessageTextForWriting());
212213 this.messageFormat = msg.getFormat();
213 parameters = reusable.swapParameters(parameters == null ? new Object[10] : parameters);
214 parameterCount = reusable.getParameterCount();
214 if (parameters != null) {
215 parameters = reusable.swapParameters(parameters);
216 parameterCount = reusable.getParameterCount();
217 }
215218 } else {
216219 this.message = InternalAsyncUtil.makeMessageImmutable(msg);
217220 }
219222
220223 private StringBuilder getMessageTextForWriting() {
221224 if (messageText == null) {
222 // Happens the first time messageText is requested
225 // Should never happen:
226 // only happens if user logs a custom reused message when Constants.ENABLE_THREADLOCALS is false
223227 messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
224228 }
225229 messageText.setLength(0);
3737 private static final ThreadNameCachingStrategy THREAD_NAME_CACHING_STRATEGY = ThreadNameCachingStrategy.create();
3838 private static final Clock CLOCK = ClockFactory.getClock();
3939
40 private static final ThreadLocal<MutableLogEvent> mutableLogEventThreadLocal = new ThreadLocal<>();
40 private static ThreadLocal<MutableLogEvent> mutableLogEventThreadLocal = new ThreadLocal<>();
4141 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
4242
4343 /**
7676 public LogEvent createEvent(final String loggerName, final Marker marker, final String fqcn,
7777 final StackTraceElement location, final Level level, final Message message,
7878 final List<Property> properties, final Throwable t) {
79 MutableLogEvent result = getOrCreateMutableLogEvent();
79 MutableLogEvent result = mutableLogEventThreadLocal.get();
80 if (result == null || result.reserved) {
81 final boolean initThreadLocal = result == null;
82 result = new MutableLogEvent();
83
84 // usually no need to re-initialize thread-specific fields since the event is stored in a ThreadLocal
85 result.setThreadId(Thread.currentThread().getId());
86 result.setThreadName(Thread.currentThread().getName()); // Thread.getName() allocates Objects on each call
87 result.setThreadPriority(Thread.currentThread().getPriority());
88 if (initThreadLocal) {
89 mutableLogEventThreadLocal.set(result);
90 }
91 }
8092 result.reserved = true;
81 // No need to clear here, values are cleared in release when reserved is set to false.
82 // If the event was dirty we'd create a new one.
93 result.clear(); // ensure any previously cached values (thrownProxy, source, etc.) are cleared
8394
8495 result.setLoggerName(loggerName);
8596 result.setMarker(marker);
99110 return result;
100111 }
101112
102 private static MutableLogEvent getOrCreateMutableLogEvent() {
103 MutableLogEvent result = mutableLogEventThreadLocal.get();
104 return result == null || result.reserved ? createInstance(result) : result;
105 }
106
107 private static MutableLogEvent createInstance(MutableLogEvent existing) {
108 MutableLogEvent result = new MutableLogEvent();
109
110 // usually no need to re-initialize thread-specific fields since the event is stored in a ThreadLocal
111 result.setThreadId(Thread.currentThread().getId());
112 result.setThreadName(Thread.currentThread().getName()); // Thread.getName() allocates Objects on each call
113 result.setThreadPriority(Thread.currentThread().getPriority());
114 if (existing == null) {
115 mutableLogEventThreadLocal.set(result);
116 }
117 return result;
118 }
119
120113 /**
121114 * Switches the {@code reserved} flag off if the specified event is a MutableLogEvent, otherwise does nothing.
122115 * This flag is used internally to verify that a reusable log event is no longer in use and can be reused.
1515 */
1616 package org.apache.logging.log4j.core.impl;
1717
18 import java.util.ArrayList;
19 import java.util.Collection;
2018 import java.util.HashMap;
2119 import java.util.List;
2220 import java.util.Map;
23 import java.util.ServiceLoader;
24 import java.util.concurrent.ConcurrentLinkedDeque;
25 import java.util.concurrent.locks.Lock;
26 import java.util.concurrent.locks.ReentrantLock;
2721
28 import org.apache.logging.log4j.Logger;
2922 import org.apache.logging.log4j.ThreadContext;
3023 import org.apache.logging.log4j.core.ContextDataInjector;
3124 import org.apache.logging.log4j.core.config.Property;
32 import org.apache.logging.log4j.core.util.ContextDataProvider;
3325 import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap;
34 import org.apache.logging.log4j.status.StatusLogger;
35 import org.apache.logging.log4j.util.LoaderUtil;
3626 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3727 import org.apache.logging.log4j.util.StringMap;
3828
5343 */
5444 public class ThreadContextDataInjector {
5545
56 private static final Logger LOGGER = StatusLogger.getLogger();
57
58 /**
59 * ContextDataProviders loaded via OSGi.
60 */
61 public static Collection<ContextDataProvider> contextDataProviders =
62 new ConcurrentLinkedDeque<>();
63
64 private static volatile List<ContextDataProvider> serviceProviders = null;
65 private static final Lock providerLock = new ReentrantLock();
66
67 public static void initServiceProviders() {
68 if (serviceProviders == null) {
69 providerLock.lock();
70 try {
71 if (serviceProviders == null) {
72 serviceProviders = getServiceProviders();
73 }
74 } finally {
75 providerLock.unlock();
76 }
77 }
78 }
79
80 private static List<ContextDataProvider> getServiceProviders() {
81 List<ContextDataProvider> providers = new ArrayList<>();
82 for (final ClassLoader classLoader : LoaderUtil.getClassLoaders()) {
83 try {
84 for (final ContextDataProvider provider : ServiceLoader.load(ContextDataProvider.class, classLoader)) {
85 if (providers.stream().noneMatch(p -> p.getClass().isAssignableFrom(provider.getClass()))) {
86 providers.add(provider);
87 }
88 }
89 } catch (final Throwable ex) {
90 LOGGER.debug("Unable to access Context Data Providers {}", ex.getMessage());
91 }
92 }
93 return providers;
94 }
95
9646 /**
9747 * Default {@code ContextDataInjector} for the legacy {@code Map<String, String>}-based ThreadContext (which is
9848 * also the ThreadContext implementation used for web applications).
10151 */
10252 public static class ForDefaultThreadContextMap implements ContextDataInjector {
10353
104 private final List<ContextDataProvider> providers;
105
106 public ForDefaultThreadContextMap() {
107 providers = getProviders();
108 }
109
11054 /**
11155 * Puts key-value pairs from both the specified list of properties as well as the thread context into the
11256 * specified reusable StringMap.
11357 *
11458 * @param props list of configuration properties, may be {@code null}
115 * @param contextData a {@code StringMap} instance from the log event
59 * @param ignore a {@code StringMap} instance from the log event
11660 * @return a {@code StringMap} combining configuration properties with thread context data
11761 */
11862 @Override
119 public StringMap injectContextData(final List<Property> props, final StringMap contextData) {
63 public StringMap injectContextData(final List<Property> props, final StringMap ignore) {
12064
121 final Map<String, String> copy;
122
123 if (providers.size() == 1) {
124 copy = providers.get(0).supplyContextData();
125 } else {
126 copy = new HashMap<>();
127 for (ContextDataProvider provider : providers) {
128 copy.putAll(provider.supplyContextData());
129 }
130 }
65 final Map<String, String> copy = ThreadContext.getImmutableContext();
13166
13267 // The DefaultThreadContextMap stores context data in a Map<String, String>.
13368 // This is a copy-on-write data structure so we are sure ThreadContext changes will not affect our copy.
134 // If there are no configuration properties or providers returning a thin wrapper around the copy
69 // If there are no configuration properties returning a thin wrapper around the copy
13570 // is faster than copying the elements into the LogEvent's reusable StringMap.
136 if ((props == null || props.isEmpty())) {
71 if (props == null || props.isEmpty()) {
13772 // this will replace the LogEvent's context data with the returned instance.
13873 // NOTE: must mark as frozen or downstream components may attempt to modify (UnsupportedOperationEx)
13974 return copy.isEmpty() ? ContextDataFactory.emptyFrozenContextData() : frozenStringMap(copy);
178113 * This injector always puts key-value pairs into the specified reusable StringMap.
179114 */
180115 public static class ForGarbageFreeThreadContextMap implements ContextDataInjector {
181 private final List<ContextDataProvider> providers;
182
183 public ForGarbageFreeThreadContextMap() {
184 this.providers = getProviders();
185 }
186
187116 /**
188117 * Puts key-value pairs from both the specified list of properties as well as the thread context into the
189118 * specified reusable StringMap.
198127 // StringMap. We cannot return the ThreadContext's internal data structure because it may be modified later
199128 // and such modifications should not be reflected in the log event.
200129 copyProperties(props, reusable);
201 for (int i = 0; i < providers.size(); ++i) {
202 reusable.putAll(providers.get(i).supplyStringMap());
203 }
130
131 final ReadOnlyStringMap immutableCopy = ThreadContext.getThreadContextMap().getReadOnlyContextData();
132 reusable.putAll(immutableCopy);
204133 return reusable;
205134 }
206135
219148 * specified reusable StringMap.
220149 */
221150 public static class ForCopyOnWriteThreadContextMap implements ContextDataInjector {
222 private final List<ContextDataProvider> providers;
223
224 public ForCopyOnWriteThreadContextMap() {
225 this.providers = getProviders();
226 }
227151 /**
228152 * If there are no configuration properties, this injector will return the thread context's internal data
229153 * structure. Otherwise the configuration properties are combined with the thread context key-value pairs into the
237161 public StringMap injectContextData(final List<Property> props, final StringMap ignore) {
238162 // If there are no configuration properties we want to just return the ThreadContext's StringMap:
239163 // it is a copy-on-write data structure so we are sure ThreadContext changes will not affect our copy.
240 if (providers.size() == 1 && (props == null || props.isEmpty())) {
241 // this will replace the LogEvent's context data with the returned instance
242 return providers.get(0).supplyStringMap();
243 }
244 int count = props == null ? 0 : props.size();
245 StringMap[] maps = new StringMap[providers.size()];
246 for (int i = 0; i < providers.size(); ++i) {
247 maps[i] = providers.get(i).supplyStringMap();
248 count += maps[i].size();
164 final StringMap immutableCopy = ThreadContext.getThreadContextMap().getReadOnlyContextData();
165 if (props == null || props.isEmpty()) {
166 return immutableCopy; // this will replace the LogEvent's context data with the returned instance
249167 }
250168 // However, if the list of Properties is non-empty we need to combine the properties and the ThreadContext
251169 // data. Note that we cannot reuse the specified StringMap: some Loggers may have properties defined
252170 // and others not, so the LogEvent's context data may have been replaced with an immutable copy from
253171 // the ThreadContext - this will throw an UnsupportedOperationException if we try to modify it.
254 final StringMap result = ContextDataFactory.createContextData(count);
172 final StringMap result = ContextDataFactory.createContextData(props.size() + immutableCopy.size());
255173 copyProperties(props, result);
256 for (StringMap map : maps) {
257 result.putAll(map);
258 }
174 result.putAll(immutableCopy);
259175 return result;
260176 }
261177
279195 }
280196 }
281197 }
282
283 private static List<ContextDataProvider> getProviders() {
284 initServiceProviders();
285 final List<ContextDataProvider> providers = new ArrayList<>(contextDataProviders);
286 if (serviceProviders != null) {
287 providers.addAll(serviceProviders);
288 }
289 return providers;
290 }
291198 }
+0
-39
log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataProvider.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.logging.log4j.core.impl;
17
18 import org.apache.logging.log4j.ThreadContext;
19 import org.apache.logging.log4j.core.util.ContextDataProvider;
20 import org.apache.logging.log4j.util.StringMap;
21
22 import java.util.Map;
23
24 /**
25 * ContextDataProvider for ThreadContext data.
26 */
27 public class ThreadContextDataProvider implements ContextDataProvider {
28
29 @Override
30 public Map<String, String> supplyContextData() {
31 return ThreadContext.getImmutableContext();
32 }
33
34 @Override
35 public StringMap supplyStringMap() {
36 return ThreadContext.getThreadContextMap().getReadOnlyContextData();
37 }
38 }
2121 import java.util.HashSet;
2222 import java.util.List;
2323 import java.util.Map;
24 import java.util.Objects;
2524 import java.util.Set;
2625 import java.util.Stack;
2726
4847 */
4948 public class ThrowableProxy implements Serializable {
5049
51 static final ThrowableProxy[] EMPTY_ARRAY = {};
52
5350 private static final char EOL = '\n';
5451
5552 private static final String EOL_STR = String.valueOf(EOL);
7673 * For JSON and XML IO via Jackson.
7774 */
7875 @SuppressWarnings("unused")
79 ThrowableProxy() {
76 private ThrowableProxy() {
8077 this.throwable = null;
8178 this.name = null;
82 this.extendedStackTrace = ExtendedStackTraceElement.EMPTY_ARRAY;
79 this.extendedStackTrace = null;
8380 this.causeProxy = null;
8481 this.message = null;
8582 this.localizedMessage = null;
86 this.suppressedProxies = ThrowableProxy.EMPTY_ARRAY;
83 this.suppressedProxies = ThrowableProxyHelper.EMPTY_THROWABLE_PROXY_ARRAY;
8784 }
8885
8986 /**
154151 return false;
155152 }
156153 final ThrowableProxy other = (ThrowableProxy) obj;
157 if (!Objects.equals(this.causeProxy, other.causeProxy)) {
154 if (this.causeProxy == null) {
155 if (other.causeProxy != null) {
156 return false;
157 }
158 } else if (!this.causeProxy.equals(other.causeProxy)) {
158159 return false;
159160 }
160161 if (this.commonElementCount != other.commonElementCount) {
161162 return false;
162163 }
163 if (!Objects.equals(this.name, other.name)) {
164 if (this.name == null) {
165 if (other.name != null) {
166 return false;
167 }
168 } else if (!this.name.equals(other.name)) {
164169 return false;
165170 }
166171 if (!Arrays.equals(this.extendedStackTrace, other.extendedStackTrace)) {
3333 * instance.
3434 */
3535 class ThrowableProxyHelper {
36
37 static final ThrowableProxy[] EMPTY_THROWABLE_PROXY_ARRAY = new ThrowableProxy[0];
3638
3739 private ThrowableProxyHelper() {
3840 // Utility Class
125127 try {
126128 final Throwable[] suppressed = thrown.getSuppressed();
127129 if (suppressed == null || suppressed.length == 0) {
128 return ThrowableProxy.EMPTY_ARRAY;
130 return EMPTY_THROWABLE_PROXY_ARRAY;
129131 }
130132 final List<ThrowableProxy> proxies = new ArrayList<>(suppressed.length);
131133 if (suppressedVisited == null) {
165167 int index = str.lastIndexOf("/");
166168 if (index >= 0 && index == str.length() - 1) {
167169 index = str.lastIndexOf("/", index - 1);
170 location = str.substring(index + 1);
171 } else {
172 location = str.substring(index + 1);
168173 }
169 location = str.substring(index + 1);
170174 }
171175 }
172176 } catch (final Exception ex) {
4949 }
5050
5151 private static final TriConsumer<String, Object, JsonGenerator> WRITE_STRING_FIELD_INTO =
52 (key, value, jsonGenerator) -> {
53 try {
54 if (value == null) {
55 jsonGenerator.writeNullField(key);
56 } else {
52 new TriConsumer<String, Object, JsonGenerator>() {
53
54 @Override
55 public void accept(final String key, final Object value, final JsonGenerator jsonGenerator) {
56 try {
5757 jsonGenerator.writeStringField(key, String.valueOf(value));
58 } catch (final Exception ex) {
59 throw new IllegalStateException("Problem with key " + key, ex);
5860 }
59 } catch (final Exception ex) {
60 throw new IllegalStateException("Problem with key " + key, ex);
6161 }
6262 };
6363 }
3131 public static final String ELT_EXTENDED_STACK_TRACE = "extendedStackTrace";
3232 public static final String ELT_NANO_TIME = "nanoTime";
3333 public static final String ELT_INSTANT = "instant";
34 public static final String ELT_TIME_MILLIS = "timeMillis";
3534 }
3232 private final boolean stacktraceAsString;
3333
3434 Log4jXmlModule(final boolean includeStacktrace, final boolean stacktraceAsString) {
35 super();
3536 this.includeStacktrace = includeStacktrace;
3637 this.stacktraceAsString = stacktraceAsString;
3738 // MUST init here.
4040 @JsonRootName(XmlConstants.ELT_EVENT)
4141 @JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
4242 @JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
43 @JsonPropertyOrder({ "timeMillis", JsonConstants.ELT_INSTANT, "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP,
43 @JsonPropertyOrder({ "timeMillis", XmlConstants.ELT_INSTANT, "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP,
4444 JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch" })
4545 abstract class LogEventJsonMixIn implements LogEvent {
4646
126126 @Override
127127 public abstract ThrowableProxy getThrownProxy();
128128
129 @JsonProperty(value = JsonConstants.ELT_TIME_MILLIS, access = JsonProperty.Access.READ_ONLY)
130 @JacksonXmlProperty(isAttribute = true)
129 @JsonIgnore // ignore from 2.11
130 // @JsonProperty()
131 // @JacksonXmlProperty(isAttribute = true)
131132 @Override
132133 public abstract long getTimeMillis();
133134
125125 @Override
126126 public abstract ThrowableProxy getThrownProxy();
127127
128 @JsonProperty(value = JsonConstants.ELT_TIME_MILLIS, access = JsonProperty.Access.READ_ONLY)
129 @JacksonXmlProperty(isAttribute = true)
128 @JsonIgnore // ignore from 2.11
129 // @JsonProperty()
130 // @JacksonXmlProperty(isAttribute = true)
130131 @Override
131132 public abstract long getTimeMillis();
132133
2626 public static final String ELT_EVENT = "Event";
2727 public static final String ELT_EXTENDED_STACK_TRACE = "ExtendedStackTrace";
2828 public static final String ELT_EXTENDED_STACK_TRACE_ITEM = "ExtendedStackTraceItem";
29 public static final String ELT_TIME_MILLIS = "TimeMillis";
3029 public static final String ELT_INSTANT = "Instant";
3130 public static final String ELT_MARKER = "Marker";
3231 public static final String ELT_MESSAGE = "Message";
4242 * @param selector the instrumented object
4343 */
4444 public ContextSelectorAdmin(final String contextName, final ContextSelector selector) {
45 super();
4546 this.selector = Objects.requireNonNull(selector, "ContextSelector");
4647 try {
4748 final String mbeanName = String.format(PATTERN, Server.escape(contextName));
388388
389389 private static void register(final MBeanServer mbs, final Object mbean, final ObjectName objectName)
390390 throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
391 if (mbs.isRegistered(objectName)) {
392 try {
393 mbs.unregisterMBean(objectName);
394 } catch (MBeanRegistrationException | InstanceNotFoundException ex) {
395 LOGGER.trace("Failed to unregister MBean {}", objectName);
396 }
397 }
398391 LOGGER.debug("Registering MBean {}", objectName);
399392 mbs.registerMBean(mbean, objectName);
400393 }
401
402394 }
2828 import org.apache.logging.log4j.core.config.Configuration;
2929 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
3030 import org.apache.logging.log4j.core.config.plugins.PluginElement;
31 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3231 import org.apache.logging.log4j.core.impl.ThrowableProxy;
3332 import org.apache.logging.log4j.core.jackson.XmlConstants;
3433 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
8281 @PluginBuilderAttribute
8382 private boolean includeNullDelimiter = false;
8483
85 @PluginBuilderAttribute
86 private boolean includeTimeMillis = false;
87
8884 @PluginElement("AdditionalField")
8985 private KeyValuePair[] additionalFields;
9086
129125 }
130126
131127 public boolean isIncludeNullDelimiter() { return includeNullDelimiter; }
132
133 public boolean isIncludeTimeMillis() {
134 return includeTimeMillis;
135 }
136128
137129 public KeyValuePair[] getAdditionalFields() {
138130 return additionalFields;
195187 */
196188 public B setIncludeNullDelimiter(final boolean includeNullDelimiter) {
197189 this.includeNullDelimiter = includeNullDelimiter;
198 return asBuilder();
199 }
200
201 /**
202 * Whether to include the timestamp (in addition to the Instant) (optional, default to false).
203 *
204 * @return this builder
205 */
206 public B setIncludeTimeMillis(final boolean includeTimeMillis) {
207 this.includeTimeMillis = includeTimeMillis;
208190 return asBuilder();
209191 }
210192
260242 private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config, final KeyValuePair[] additionalFields) {
261243 if (additionalFields == null || additionalFields.length == 0) {
262244 // No fields set
263 return ResolvableKeyValuePair.EMPTY_ARRAY;
245 return new ResolvableKeyValuePair[0];
264246 }
265247
266248 // Convert to specific class which already determines whether values needs lookup during serialization
297279 }
298280 }
299281
300 private static LogEvent convertMutableToLog4jEvent(final LogEvent event) {
301 // TODO Jackson-based layouts have certain filters set up for Log4jLogEvent.
302 // TODO Need to set up the same filters for MutableLogEvent but don't know how...
303 // This is a workaround.
304 return event instanceof Log4jLogEvent ? event : Log4jLogEvent.createMemento(event);
305 }
306
307282 protected Object wrapLogEvent(final LogEvent event) {
308283 if (additionalFields.length > 0) {
309284 // Construct map for serialization - note that we are intentionally using original LogEvent
340315
341316 public void toSerializable(final LogEvent event, final Writer writer)
342317 throws JsonGenerationException, JsonMappingException, IOException {
343 objectWriter.writeValue(writer, wrapLogEvent(convertMutableToLog4jEvent(event)));
318 objectWriter.writeValue(writer, wrapLogEvent(event));
344319 writer.write(eol);
345320 if (includeNullDelimiter) {
346321 writer.write('\0');
373348 }
374349
375350 protected static class ResolvableKeyValuePair {
376
377 /**
378 * The empty array.
379 */
380 static final ResolvableKeyValuePair[] EMPTY_ARRAY = {};
381351
382352 final String key;
383353 final String value;
135135 * The footer to add when the stream is closed. May be null.
136136 */
137137 public AbstractLayout(final Configuration configuration, final byte[] header, final byte[] footer) {
138 super();
138139 this.configuration = configuration;
139140 this.header = header;
140141 this.footer = footer;
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import java.io.UnsupportedEncodingException;
1819 import java.nio.charset.Charset;
1920 import java.nio.charset.StandardCharsets;
2021
4041 * performance: all characters are simply cast to bytes.
4142 * </p>
4243 */
44 /*
45 * Implementation note: prefer String.getBytes(String) to String.getBytes(Charset) for performance reasons. See
46 * https://issues.apache.org/jira/browse/LOG4J2-935 for details.
47 */
4348 public abstract class AbstractStringLayout extends AbstractLayout<String> implements StringLayout, LocationAware {
4449
4550 public abstract static class Builder<B extends Builder<B>> extends AbstractLayout.Builder<B> {
8287
8388 }
8489
85 @Override
8690 public boolean requiresLocation() {
8791 return false;
8892 }
8993
90 public interface Serializer extends Serializer2 {
94 public interface Serializer {
9195 String toSerializable(final LogEvent event);
92
93 @Override
94 default StringBuilder toSerializable(final LogEvent event, final StringBuilder builder) {
95 builder.append(toSerializable(event));
96 return builder;
97 }
9896 }
9997
10098 /**
10199 * Variation of {@link Serializer} that avoids allocating temporary objects.
102 * As of 2.13 this interface was merged into the Serializer interface.
103100 * @since 2.6
104101 */
105102 public interface Serializer2 {
136133 return result;
137134 }
138135
136 // LOG4J2-1151: If the built-in JDK 8 encoders are available we should use them.
137 private static boolean isPreJava8() {
138 return org.apache.logging.log4j.util.Constants.JAVA_MAJOR_VERSION < 8;
139 }
140
139141 private static int size(final String property, final int defaultValue) {
140142 return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue);
141143 }
148150 /**
149151 * The charset for the formatted message.
150152 */
151 private final Charset charset;
153 // LOG4J2-1099: Charset cannot be final due to serialization needs, so we serialize as Charset name instead
154 private transient Charset charset;
155
156 private final String charsetName;
152157
153158 private final Serializer footerSerializer;
154159
155160 private final Serializer headerSerializer;
161
162 private final boolean useCustomEncoding;
156163
157164 protected AbstractStringLayout(final Charset charset) {
158165 this(charset, (byte[]) null, (byte[]) null);
170177 this.headerSerializer = null;
171178 this.footerSerializer = null;
172179 this.charset = aCharset == null ? StandardCharsets.UTF_8 : aCharset;
180 this.charsetName = this.charset.name();
181 useCustomEncoding = isPreJava8()
182 && (StandardCharsets.ISO_8859_1.equals(aCharset) || StandardCharsets.US_ASCII.equals(aCharset));
173183 textEncoder = Constants.ENABLE_DIRECT_ENCODERS ? new StringBuilderEncoder(charset) : null;
174184 }
175185
187197 this.headerSerializer = headerSerializer;
188198 this.footerSerializer = footerSerializer;
189199 this.charset = aCharset == null ? StandardCharsets.UTF_8 : aCharset;
200 this.charsetName = this.charset.name();
201 useCustomEncoding = isPreJava8()
202 && (StandardCharsets.ISO_8859_1.equals(aCharset) || StandardCharsets.US_ASCII.equals(aCharset));
190203 textEncoder = Constants.ENABLE_DIRECT_ENCODERS ? new StringBuilderEncoder(charset) : null;
191204 }
192205
193206 protected byte[] getBytes(final String s) {
194 return s.getBytes(charset);
207 if (useCustomEncoding) { // rely on branch prediction to eliminate this check if false
208 return StringEncoder.encodeSingleByteChars(s);
209 }
210 try { // LOG4J2-935: String.getBytes(String) gives better performance
211 return s.getBytes(charsetName);
212 } catch (final UnsupportedEncodingException e) {
213 return s.getBytes(charset);
214 }
195215 }
196216
197217 @Override
253273
254274 protected byte[] serializeToBytes(final Serializer serializer, final byte[] defaultValue) {
255275 final String serializable = serializeToString(serializer);
256 if (serializable == null) {
276 if (serializer == null) {
257277 return defaultValue;
258278 }
259279 return StringEncoder.toBytes(serializable, getCharset());
2121 import java.io.PrintWriter;
2222 import java.io.StringWriter;
2323 import java.nio.charset.StandardCharsets;
24 import java.util.ArrayList;
2524 import java.util.Collections;
26 import java.util.List;
2725 import java.util.Map;
28 import java.util.Objects;
2926 import java.util.zip.DeflaterOutputStream;
3027 import java.util.zip.GZIPOutputStream;
3128
3936 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
4037 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
4138 import org.apache.logging.log4j.core.config.plugins.PluginElement;
42 import org.apache.logging.log4j.core.layout.internal.ExcludeChecker;
43 import org.apache.logging.log4j.core.layout.internal.IncludeChecker;
44 import org.apache.logging.log4j.core.layout.internal.ListChecker;
4539 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
4640 import org.apache.logging.log4j.core.net.Severity;
4741 import org.apache.logging.log4j.core.util.JsonUtils;
4842 import org.apache.logging.log4j.core.util.KeyValuePair;
4943 import org.apache.logging.log4j.core.util.NetUtils;
50 import org.apache.logging.log4j.core.util.Patterns;
51 import org.apache.logging.log4j.message.MapMessage;
5244 import org.apache.logging.log4j.message.Message;
5345 import org.apache.logging.log4j.status.StatusLogger;
5446 import org.apache.logging.log4j.util.StringBuilderFormattable;
10496 private final String host;
10597 private final boolean includeStacktrace;
10698 private final boolean includeThreadContext;
107 private final boolean includeMapMessage;
10899 private final boolean includeNullDelimiter;
109 private final boolean includeNewLineDelimiter;
110 private final boolean omitEmptyFields;
111 private final PatternLayout layout;
112 private final FieldWriter mdcWriter;
113 private final FieldWriter mapWriter;
114100
115101 public static class Builder<B extends Builder<B>> extends AbstractStringLayout.Builder<B>
116102 implements org.apache.logging.log4j.core.util.Builder<GelfLayout> {
136122 @PluginBuilderAttribute
137123 private boolean includeNullDelimiter = false;
138124
139 @PluginBuilderAttribute
140 private boolean includeNewLineDelimiter = false;
141
142 @PluginBuilderAttribute
143 private String threadContextIncludes = null;
144
145 @PluginBuilderAttribute
146 private String threadContextExcludes = null;
147
148 @PluginBuilderAttribute
149 private String mapMessageIncludes = null;
150
151 @PluginBuilderAttribute
152 private String mapMessageExcludes = null;
153
154 @PluginBuilderAttribute
155 private boolean includeMapMessage = true;
156
157 @PluginBuilderAttribute
158 private boolean omitEmptyFields = false;
159
160 @PluginBuilderAttribute
161 private String messagePattern = null;
162
163 @PluginBuilderAttribute
164 private String threadContextPrefix = "";
165
166 @PluginBuilderAttribute
167 private String mapPrefix = "";
168
169 @PluginElement("PatternSelector")
170 private PatternSelector patternSelector = null;
171
172125 public Builder() {
126 super();
173127 setCharset(StandardCharsets.UTF_8);
174128 }
175129
176130 @Override
177131 public GelfLayout build() {
178 ListChecker mdcChecker = createChecker(threadContextExcludes, threadContextIncludes);
179 ListChecker mapChecker = createChecker(mapMessageExcludes, mapMessageIncludes);
180 PatternLayout patternLayout = null;
181 if (messagePattern != null && patternSelector != null) {
182 LOGGER.error("A message pattern and PatternSelector cannot both be specified on GelfLayout, "
183 + "ignoring message pattern");
184 messagePattern = null;
185 }
186 if (messagePattern != null) {
187 patternLayout = PatternLayout.newBuilder().withPattern(messagePattern)
188 .withAlwaysWriteExceptions(includeStacktrace)
189 .withConfiguration(getConfiguration())
190 .build();
191 }
192 if (patternSelector != null) {
193 patternLayout = PatternLayout.newBuilder().withPatternSelector(patternSelector)
194 .withAlwaysWriteExceptions(includeStacktrace)
195 .withConfiguration(getConfiguration())
196 .build();
197 }
198132 return new GelfLayout(getConfiguration(), host, additionalFields, compressionType, compressionThreshold,
199 includeStacktrace, includeThreadContext, includeMapMessage, includeNullDelimiter,
200 includeNewLineDelimiter, omitEmptyFields, mdcChecker, mapChecker, patternLayout,
201 threadContextPrefix, mapPrefix);
202 }
203
204 private ListChecker createChecker(String excludes, String includes) {
205 ListChecker checker = null;
206 if (excludes != null) {
207 final String[] array = excludes.split(Patterns.COMMA_SEPARATOR);
208 if (array.length > 0) {
209 List<String> excludeList = new ArrayList<>(array.length);
210 for (final String str : array) {
211 excludeList.add(str.trim());
212 }
213 checker = new ExcludeChecker(excludeList);
214 }
215 }
216 if (includes != null) {
217 final String[] array = includes.split(Patterns.COMMA_SEPARATOR);
218 if (array.length > 0) {
219 List<String> includeList = new ArrayList<>(array.length);
220 for (final String str : array) {
221 includeList.add(str.trim());
222 }
223 checker = new IncludeChecker(includeList);
224 }
225 }
226 if (checker == null) {
227 checker = ListChecker.NOOP_CHECKER;
228 }
229 return checker;
133 includeStacktrace, includeThreadContext, includeNullDelimiter);
230134 }
231135
232136 public String getHost() {
251155
252156 public boolean isIncludeNullDelimiter() { return includeNullDelimiter; }
253157
254 public boolean isIncludeNewLineDelimiter() {
255 return includeNewLineDelimiter;
256 }
257
258158 public KeyValuePair[] getAdditionalFields() {
259159 return additionalFields;
260160 }
322222 }
323223
324224 /**
325 * Whether to include newline (LF) as delimiter after each event (optional, default to false).
326 *
327 * @return this builder
328 */
329 public B setIncludeNewLineDelimiter(final boolean includeNewLineDelimiter) {
330 this.includeNewLineDelimiter = includeNewLineDelimiter;
331 return asBuilder();
332 }
333
334 /**
335225 * Additional fields to set on each log event.
336226 *
337227 * @return this builder
338228 */
339229 public B setAdditionalFields(final KeyValuePair[] additionalFields) {
340230 this.additionalFields = additionalFields;
341 return asBuilder();
342 }
343
344 /**
345 * The pattern to use to format the message.
346 * @param pattern the pattern string.
347 * @return this builder
348 */
349 public B setMessagePattern(final String pattern) {
350 this.messagePattern = pattern;
351 return asBuilder();
352 }
353
354 /**
355 * The PatternSelector to use to format the message.
356 * @param patternSelector the PatternSelector.
357 * @return this builder
358 */
359 public B setPatternSelector(final PatternSelector patternSelector) {
360 this.patternSelector = patternSelector;
361 return asBuilder();
362 }
363
364 /**
365 * A comma separated list of thread context keys to include;
366 * @param mdcIncludes the list of keys.
367 * @return this builder
368 */
369 public B setMdcIncludes(final String mdcIncludes) {
370 this.threadContextIncludes = mdcIncludes;
371 return asBuilder();
372 }
373
374 /**
375 * A comma separated list of thread context keys to include;
376 * @param mdcExcludes the list of keys.
377 * @return this builder
378 */
379 public B setMdcExcludes(final String mdcExcludes) {
380 this.threadContextExcludes = mdcExcludes;
381 return asBuilder();
382 }
383
384 /**
385 * Whether to include MapMessage fields as additional fields (optional, default to true).
386 *
387 * @return this builder
388 */
389 public B setIncludeMapMessage(final boolean includeMapMessage) {
390 this.includeMapMessage = includeMapMessage;
391 return asBuilder();
392 }
393
394 /**
395 * A comma separated list of thread context keys to include;
396 * @param mapMessageIncludes the list of keys.
397 * @return this builder
398 */
399 public B setMapMessageIncludes(final String mapMessageIncludes) {
400 this.mapMessageIncludes = mapMessageIncludes;
401 return asBuilder();
402 }
403
404 /**
405 * A comma separated list of MapMessage keys to exclude;
406 * @param mapMessageExcludes the list of keys.
407 * @return this builder
408 */
409 public B setMapMessageExcludes(final String mapMessageExcludes) {
410 this.mapMessageExcludes = mapMessageExcludes;
411 return asBuilder();
412 }
413
414 /**
415 * The String to prefix the ThreadContext attributes.
416 * @param prefix The prefix value. Null values will be ignored.
417 * @return this builder.
418 */
419 public B setThreadContextPrefix(final String prefix) {
420 if (prefix != null) {
421 this.threadContextPrefix = prefix;
422 }
423 return asBuilder();
424 }
425
426 /**
427 * The String to prefix the MapMessage attributes.
428 * @param prefix The prefix value. Null values will be ignored.
429 * @return this builder.
430 */
431 public B setMapPrefix(final String prefix) {
432 if (prefix != null) {
433 this.mapPrefix = prefix;
434 }
435231 return asBuilder();
436232 }
437233 }
442238 @Deprecated
443239 public GelfLayout(final String host, final KeyValuePair[] additionalFields, final CompressionType compressionType,
444240 final int compressionThreshold, final boolean includeStacktrace) {
445 this(null, host, additionalFields, compressionType, compressionThreshold, includeStacktrace, true, true,
446 false, false, false, null, null, null, "", "");
447 }
448
449 private GelfLayout(final Configuration config, final String host, final KeyValuePair[] additionalFields,
450 final CompressionType compressionType, final int compressionThreshold, final boolean includeStacktrace,
451 final boolean includeThreadContext, final boolean includeMapMessage, final boolean includeNullDelimiter,
452 final boolean includeNewLineDelimiter, final boolean omitEmptyFields, final ListChecker mdcChecker,
453 final ListChecker mapChecker, final PatternLayout patternLayout, final String mdcPrefix,
454 final String mapPrefix) {
241 this(null, host, additionalFields, compressionType, compressionThreshold, includeStacktrace, true, false);
242 }
243
244 private GelfLayout(final Configuration config, final String host, final KeyValuePair[] additionalFields, final CompressionType compressionType,
245 final int compressionThreshold, final boolean includeStacktrace, final boolean includeThreadContext, final boolean includeNullDelimiter) {
455246 super(config, StandardCharsets.UTF_8, null, null);
456247 this.host = host != null ? host : NetUtils.getLocalHostname();
457 this.additionalFields = additionalFields != null ? additionalFields : KeyValuePair.EMPTY_ARRAY;
248 this.additionalFields = additionalFields != null ? additionalFields : new KeyValuePair[0];
458249 if (config == null) {
459250 for (final KeyValuePair additionalField : this.additionalFields) {
460251 if (valueNeedsLookup(additionalField.getValue())) {
466257 this.compressionThreshold = compressionThreshold;
467258 this.includeStacktrace = includeStacktrace;
468259 this.includeThreadContext = includeThreadContext;
469 this.includeMapMessage = includeMapMessage;
470260 this.includeNullDelimiter = includeNullDelimiter;
471 this.includeNewLineDelimiter = includeNewLineDelimiter;
472 this.omitEmptyFields = omitEmptyFields;
473261 if (includeNullDelimiter && compressionType != CompressionType.OFF) {
474262 throw new IllegalArgumentException("null delimiter cannot be used with compression");
475263 }
476 this.mdcWriter = new FieldWriter(mdcChecker, mdcPrefix);
477 this.mapWriter = new FieldWriter(mapChecker, mapPrefix);
478 this.layout = patternLayout;
479 }
480
481 @Override
482 public String toString() {
483 StringBuilder sb = new StringBuilder();
484 sb.append("host=").append(host);
485 sb.append(", compressionType=").append(compressionType.toString());
486 sb.append(", compressionThreshold=").append(compressionThreshold);
487 sb.append(", includeStackTrace=").append(includeStacktrace);
488 sb.append(", includeThreadContext=").append(includeThreadContext);
489 sb.append(", includeNullDelimiter=").append(includeNullDelimiter);
490 sb.append(", includeNewLineDelimiter=").append(includeNewLineDelimiter);
491 String threadVars = mdcWriter.getChecker().toString();
492 if (threadVars.length() > 0) {
493 sb.append(", ").append(threadVars);
494 }
495 String mapVars = mapWriter.getChecker().toString();
496 if (mapVars.length() > 0) {
497 sb.append(", ").append(mapVars);
498 }
499 if (layout != null) {
500 sb.append(", PatternLayout{").append(layout.toString()).append("}");
501 }
502 return sb.toString();
503264 }
504265
505266 /**
517278 @PluginAttribute(value = "includeStacktrace",
518279 defaultBoolean = true) final boolean includeStacktrace) {
519280 // @formatter:on
520 return new GelfLayout(null, host, additionalFields, compressionType, compressionThreshold, includeStacktrace,
521 true, true, false, false, false, null, null, null, "", "");
281 return new GelfLayout(null, host, additionalFields, compressionType, compressionThreshold, includeStacktrace, true, false);
522282 }
523283
524284 @PluginBuilderFactory
552312 final StringBuilder text = toText(event, getStringBuilder(), true);
553313 final Encoder<StringBuilder> helper = getStringBuilderEncoder();
554314 helper.encode(text, destination);
555 }
556
557 @Override
558 public boolean requiresLocation() {
559 return Objects.nonNull(layout) && layout.requiresLocation();
560315 }
561316
562317 private byte[] compress(final byte[] bytes) {
603358 if (additionalFields.length > 0) {
604359 final StrSubstitutor strSubstitutor = getConfiguration().getStrSubstitutor();
605360 for (final KeyValuePair additionalField : additionalFields) {
361 builder.append(QU);
362 JsonUtils.quoteAsString(additionalField.getKey(), builder);
363 builder.append("\":\"");
606364 final String value = valueNeedsLookup(additionalField.getValue())
607 ? strSubstitutor.replace(event, additionalField.getValue())
608 : additionalField.getValue();
609 if (Strings.isNotEmpty(value) || !omitEmptyFields) {
610 builder.append(QU);
611 JsonUtils.quoteAsString(additionalField.getKey(), builder);
612 builder.append("\":\"");
613 JsonUtils.quoteAsString(toNullSafeString(value), builder);
614 builder.append(QC);
615 }
365 ? strSubstitutor.replace(event, additionalField.getValue())
366 : additionalField.getValue();
367 JsonUtils.quoteAsString(toNullSafeString(value), builder);
368 builder.append(QC);
616369 }
617370 }
618371 if (includeThreadContext) {
619 event.getContextData().forEach(mdcWriter, builder);
620 }
621 if (includeMapMessage && event.getMessage() instanceof MapMessage) {
622 ((MapMessage<?, Object>) event.getMessage()).forEach((key, value) -> mapWriter.accept(key, value, builder));
623 }
624
625 if (event.getThrown() != null || layout != null) {
372 event.getContextData().forEach(WRITE_KEY_VALUES_INTO, builder);
373 }
374 if (event.getThrown() != null) {
626375 builder.append("\"full_message\":\"");
627 if (layout != null) {
628 final StringBuilder messageBuffer = getMessageStringBuilder();
629 layout.serialize(event, messageBuffer);
630 JsonUtils.quoteAsString(messageBuffer, builder);
631 } else if (includeStacktrace) {
376 if (includeStacktrace) {
632377 JsonUtils.quoteAsString(formatThrowable(event.getThrown()), builder);
633378 } else {
634379 JsonUtils.quoteAsString(event.getThrown().toString(), builder);
639384 builder.append("\"short_message\":\"");
640385 final Message message = event.getMessage();
641386 if (message instanceof CharSequence) {
642 JsonUtils.quoteAsString(((CharSequence) message), builder);
387 JsonUtils.quoteAsString(((CharSequence)message), builder);
643388 } else if (gcFree && message instanceof StringBuilderFormattable) {
644389 final StringBuilder messageBuffer = getMessageStringBuilder();
645390 try {
656401 if (includeNullDelimiter) {
657402 builder.append('\0');
658403 }
659 if (includeNewLineDelimiter) {
660 builder.append('\n');
661 }
662404 return builder;
663405 }
664406
666408 return value != null && value.contains("${");
667409 }
668410
669 private class FieldWriter implements TriConsumer<String, Object, StringBuilder> {
670 private final ListChecker checker;
671 private final String prefix;
672
673 FieldWriter(ListChecker checker, String prefix) {
674 this.checker = checker;
675 this.prefix = prefix;
676 }
677
411 private static final TriConsumer<String, Object, StringBuilder> WRITE_KEY_VALUES_INTO = new TriConsumer<String, Object, StringBuilder>() {
678412 @Override
679413 public void accept(final String key, final Object value, final StringBuilder stringBuilder) {
680 String stringValue = String.valueOf(value);
681 if (checker.check(key) && (Strings.isNotEmpty(stringValue) || !omitEmptyFields)) {
682 stringBuilder.append(QU);
683 JsonUtils.quoteAsString(Strings.concat(prefix, key), stringBuilder);
684 stringBuilder.append("\":\"");
685 JsonUtils.quoteAsString(toNullSafeString(stringValue), stringBuilder);
686 stringBuilder.append(QC);
687 }
688 }
689
690 public ListChecker getChecker() {
691 return checker;
692 }
693 }
414 stringBuilder.append(QU);
415 JsonUtils.quoteAsString(key, stringBuilder);
416 stringBuilder.append("\":\"");
417 JsonUtils.quoteAsString(toNullSafeString(String.valueOf(value)), stringBuilder);
418 stringBuilder.append(QC);
419 }
420 };
694421
695422 private static final ThreadLocal<StringBuilder> messageStringBuilder = new ThreadLocal<>();
696423
3636 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
3737 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
3838 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
39 import org.apache.logging.log4j.core.pattern.DatePatternConverter;
4039 import org.apache.logging.log4j.core.util.Transform;
4140 import org.apache.logging.log4j.util.Strings;
4241
5958 private static final String REGEXP = Strings.LINE_SEPARATOR.equals("\n") ? "\n" : Strings.LINE_SEPARATOR + "|\n";
6059 private static final String DEFAULT_TITLE = "Log4j Log Messages";
6160 private static final String DEFAULT_CONTENT_TYPE = "text/html";
62 private static final String DEFAULT_DATE_PATTERN = "JVM_ELAPSE_TIME";
6361
6462 private final long jvmStartTime = ManagementFactory.getRuntimeMXBean().getStartTime();
6563
7068 private final String font;
7169 private final String fontSize;
7270 private final String headerSize;
73 private final DatePatternConverter datePatternConverter;
7471
7572 /**Possible font sizes */
7673 public static enum FontSize {
10299 }
103100
104101 private HtmlLayout(final boolean locationInfo, final String title, final String contentType, final Charset charset,
105 final String font, final String fontSize, final String headerSize, String datePattern, String timezone) {
102 final String font, final String fontSize, final String headerSize) {
106103 super(charset);
107104 this.locationInfo = locationInfo;
108105 this.title = title;
110107 this.font = font;
111108 this.fontSize = fontSize;
112109 this.headerSize = headerSize;
113 this.datePatternConverter = DEFAULT_DATE_PATTERN.equals(datePattern) ? null
114 : DatePatternConverter.newInstance(new String[] {datePattern, timezone});
115110 }
116111
117112 /**
153148 sbuf.append(Strings.LINE_SEPARATOR).append("<tr>").append(Strings.LINE_SEPARATOR);
154149
155150 sbuf.append("<td>");
156
157 if (datePatternConverter == null) {
158 sbuf.append(event.getTimeMillis() - jvmStartTime);
159 } else {
160 datePatternConverter.format(event, sbuf);
161 }
151 sbuf.append(event.getTimeMillis() - jvmStartTime);
162152 sbuf.append("</td>").append(Strings.LINE_SEPARATOR);
163153
164154 final String escapedThread = Transform.escapeHtmlTags(event.getThreadName());
348338 * @param font The font to use for the text.
349339 * @return An HTML Layout.
350340 */
351 @Deprecated
352341 @PluginFactory
353342 public static HtmlLayout createLayout(
354343 @PluginAttribute(value = "locationInfo") final boolean locationInfo,
363352 if (contentType == null) {
364353 contentType = DEFAULT_CONTENT_TYPE + "; charset=" + charset;
365354 }
366 return new HtmlLayout(locationInfo, title, contentType, charset, font, fontSize, headerSize, DEFAULT_DATE_PATTERN,
367 null);
355 return new HtmlLayout(locationInfo, title, contentType, charset, font, fontSize, headerSize);
368356 }
369357
370358 /**
401389 @PluginBuilderAttribute
402390 private String fontName = DEFAULT_FONT_FAMILY;
403391
404 @PluginBuilderAttribute
405 private String datePattern = DEFAULT_DATE_PATTERN;
406
407 @PluginBuilderAttribute
408 private String timezone = null; // null means default timezone
409
410392 private Builder() {
411393 }
412394
437419
438420 public Builder withFontName(final String fontName) {
439421 this.fontName = fontName;
440 return this;
441 }
442
443 public Builder setDatePattern(final String datePattern) {
444 this.datePattern = datePattern;
445 return this;
446 }
447
448 public Builder setTimezone(final String timezone) {
449 this.timezone = timezone;
450422 return this;
451423 }
452424
457429 contentType = DEFAULT_CONTENT_TYPE + "; charset=" + charset;
458430 }
459431 return new HtmlLayout(locationInfo, title, contentType, charset, fontName, fontSize.getFontSize(),
460 fontSize.larger().getFontSize(), datePattern, timezone);
432 fontSize.larger().getFontSize());
461433 }
462434 }
463435 }
5959 }
6060
6161 @Override
62 protected String getPropertyNameForTimeMillis() {
63 return JsonConstants.ELT_TIME_MILLIS;
64 }
65
66 @Override
67 protected String getPropertyNameForInstant() {
68 return JsonConstants.ELT_INSTANT;
69 }
70
71 @Override
7262 protected String getPropertNameForSource() {
7363 return JsonConstants.ELT_SOURCE;
7464 }
10999 }
110100
111101 @Override
112 protected String getPropertyNameForTimeMillis() {
113 return XmlConstants.ELT_TIME_MILLIS;
114 }
115
116 @Override
117 protected String getPropertyNameForInstant() {
118 return XmlConstants.ELT_INSTANT;
119 }
120
121 @Override
122102 protected String getPropertNameForContextMap() {
123103 return XmlConstants.ELT_CONTEXT_MAP;
124104 }
159139 public YAML(final boolean includeStacktrace, final boolean stacktraceAsString) {
160140 this.includeStacktrace = includeStacktrace;
161141 this.stacktraceAsString = stacktraceAsString;
162 }
163
164 @Override
165 protected String getPropertyNameForTimeMillis() {
166 return JsonConstants.ELT_TIME_MILLIS;
167 }
168
169 @Override
170 protected String getPropertyNameForInstant() {
171 return JsonConstants.ELT_INSTANT;
172142 }
173143
174144 @Override
236206
237207 }
238208
239 abstract protected String getPropertyNameForTimeMillis();
240
241 abstract protected String getPropertyNameForInstant();
242
243209 abstract protected String getPropertNameForContextMap();
244210
245211 abstract protected String getPropertNameForSource();
253219 abstract protected PrettyPrinter newPrettyPrinter();
254220
255221 ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact) {
256 return newWriter(locationInfo, properties, compact, false);
257 }
258
259 ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact,
260 final boolean includeMillis) {
261222 final SimpleFilterProvider filters = new SimpleFilterProvider();
262 final Set<String> except = new HashSet<>(3);
223 final Set<String> except = new HashSet<>(2);
263224 if (!locationInfo) {
264225 except.add(this.getPropertNameForSource());
265226 }
266227 if (!properties) {
267228 except.add(this.getPropertNameForContextMap());
268 }
269 if (includeMillis) {
270 except.add(getPropertyNameForInstant());
271 } else {
272 except.add(getPropertyNameForTimeMillis());
273229 }
274230 except.add(this.getPropertNameForNanoTime());
275231 filters.addFilter(Log4jLogEvent.class.getName(), SimpleBeanPropertyFilter.serializeAllExcept(except));
3434 import org.apache.logging.log4j.core.util.KeyValuePair;
3535
3636 /**
37 * Note: The JsonLayout should be considered to be deprecated. Please use JsonTemplateLayout instead.
38 *
3937 * Appends a series of JSON events as strings serialized as bytes.
4038 *
4139 * <h3>Complete well-formed JSON vs. fragment JSON</h3>
8886 private KeyValuePair[] additionalFields;
8987
9088 public Builder() {
89 super();
9190 setCharset(StandardCharsets.UTF_8);
9291 }
9392
9897 final String footerPattern = toStringOrNull(getFooter());
9998 return new JsonLayout(getConfiguration(), isLocationInfo(), isProperties(), encodeThreadContextAsList,
10099 isComplete(), isCompact(), getEventEol(), getEndOfLine(), headerPattern, footerPattern, getCharset(),
101 isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter(), isIncludeTimeMillis(),
100 isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter(),
102101 getAdditionalFields(), getObjectMessageAsJsonObject());
103102 }
104103
153152 final boolean complete, final boolean compact, final boolean eventEol, final String endOfLine,
154153 final String headerPattern, final String footerPattern, final Charset charset,
155154 final boolean includeStacktrace, final boolean stacktraceAsString,
156 final boolean includeNullDelimiter, final boolean includeTimeMillis,
155 final boolean includeNullDelimiter,
157156 final KeyValuePair[] additionalFields, final boolean objectMessageAsJsonObject) {
158157 super(config, new JacksonFactory.JSON(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, objectMessageAsJsonObject).newWriter(
159 locationInfo, properties, compact, includeTimeMillis),
158 locationInfo, properties, compact),
160159 charset, compact, complete, eventEol, endOfLine,
161160 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
162161 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
265264 final boolean includeStacktrace) {
266265 final boolean encodeThreadContextAsList = properties && propertiesAsList;
267266 return new JsonLayout(config, locationInfo, properties, encodeThreadContextAsList, complete, compact, eventEol,
268 null, headerPattern, footerPattern, charset, includeStacktrace, false, false, false, null, false);
267 null, headerPattern, footerPattern, charset, includeStacktrace, false, false, null, false);
269268 }
270269
271270 @PluginBuilderFactory
280279 */
281280 public static JsonLayout createDefaultLayout() {
282281 return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, false, null,
283 DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, false, null, false);
282 DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, null, false);
284283 }
285284
286285 @Override
+0
-240
log4j-core/src/main/java/org/apache/logging/log4j/core/layout/LevelPatternSelector.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.logging.log4j.core.layout;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
26 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
27 import org.apache.logging.log4j.core.config.plugins.PluginElement;
28 import org.apache.logging.log4j.core.impl.LocationAware;
29 import org.apache.logging.log4j.core.pattern.PatternFormatter;
30 import org.apache.logging.log4j.core.pattern.PatternParser;
31 import org.apache.logging.log4j.status.StatusLogger;
32
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36
37 /**
38 * Selects the pattern to use based on the Level in the LogEvent.
39 */
40 @Plugin(name = "LevelPatternSelector", category = Node.CATEGORY, elementType = PatternSelector.ELEMENT_TYPE, printObject = true)
41 public class LevelPatternSelector implements PatternSelector, LocationAware {
42
43 /**
44 * Custom MarkerPatternSelector builder. Use the {@link LevelPatternSelector#newBuilder() builder factory method} to create this.
45 */
46 public static class Builder implements org.apache.logging.log4j.core.util.Builder<LevelPatternSelector> {
47
48 @PluginElement("PatternMatch")
49 private PatternMatch[] properties;
50
51 @PluginBuilderAttribute("defaultPattern")
52 private String defaultPattern;
53
54 @PluginBuilderAttribute(value = "alwaysWriteExceptions")
55 private boolean alwaysWriteExceptions = true;
56
57 @PluginBuilderAttribute(value = "disableAnsi")
58 private boolean disableAnsi;
59
60 @PluginBuilderAttribute(value = "noConsoleNoAnsi")
61 private boolean noConsoleNoAnsi;
62
63 @PluginConfiguration
64 private Configuration configuration;
65
66 @Override
67 public LevelPatternSelector build() {
68 if (defaultPattern == null) {
69 defaultPattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
70 }
71 if (properties == null || properties.length == 0) {
72 LOGGER.warn("No marker patterns were provided with PatternMatch");
73 return null;
74 }
75 return new LevelPatternSelector(properties, defaultPattern, alwaysWriteExceptions, disableAnsi,
76 noConsoleNoAnsi, configuration);
77 }
78
79 public Builder setProperties(final PatternMatch[] properties) {
80 this.properties = properties;
81 return this;
82 }
83
84 public Builder setDefaultPattern(final String defaultPattern) {
85 this.defaultPattern = defaultPattern;
86 return this;
87 }
88
89 public Builder setAlwaysWriteExceptions(final boolean alwaysWriteExceptions) {
90 this.alwaysWriteExceptions = alwaysWriteExceptions;
91 return this;
92 }
93
94 public Builder setDisableAnsi(final boolean disableAnsi) {
95 this.disableAnsi = disableAnsi;
96 return this;
97 }
98
99 public Builder setNoConsoleNoAnsi(final boolean noConsoleNoAnsi) {
100 this.noConsoleNoAnsi = noConsoleNoAnsi;
101 return this;
102 }
103
104 public Builder setConfiguration(final Configuration configuration) {
105 this.configuration = configuration;
106 return this;
107 }
108
109 }
110
111 private final Map<String, PatternFormatter[]> formatterMap = new HashMap<>();
112
113 private final Map<String, String> patternMap = new HashMap<>();
114
115 private final PatternFormatter[] defaultFormatters;
116
117 private final String defaultPattern;
118
119 private static Logger LOGGER = StatusLogger.getLogger();
120
121 private final boolean requiresLocation;
122
123 /**
124 * @deprecated Use {@link #newBuilder()} instead. This will be private in a future version.
125 */
126 @Deprecated
127 public LevelPatternSelector(final PatternMatch[] properties, final String defaultPattern,
128 final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi,
129 final Configuration config) {
130 this(properties, defaultPattern, alwaysWriteExceptions, false, noConsoleNoAnsi, config);
131 }
132
133 private LevelPatternSelector(final PatternMatch[] properties, final String defaultPattern,
134 final boolean alwaysWriteExceptions, final boolean disableAnsi,
135 final boolean noConsoleNoAnsi, final Configuration config) {
136 boolean needsLocation = false;
137 final PatternParser parser = PatternLayout.createPatternParser(config);
138 for (final PatternMatch property : properties) {
139 try {
140 final List<PatternFormatter> list = parser.parse(property.getPattern(), alwaysWriteExceptions,
141 disableAnsi, noConsoleNoAnsi);
142 PatternFormatter[] formatters = list.toArray(PatternFormatter.EMPTY_ARRAY);
143 formatterMap.put(property.getKey(), formatters);
144 for (int i = 0; !needsLocation && i < formatters.length; ++i) {
145 needsLocation = formatters[i].requiresLocation();
146 }
147
148 patternMap.put(property.getKey(), property.getPattern());
149 } catch (final RuntimeException ex) {
150 throw new IllegalArgumentException("Cannot parse pattern '" + property.getPattern() + "'", ex);
151 }
152 }
153 try {
154 final List<PatternFormatter> list = parser.parse(defaultPattern, alwaysWriteExceptions, disableAnsi,
155 noConsoleNoAnsi);
156 defaultFormatters = list.toArray(PatternFormatter.EMPTY_ARRAY);
157 this.defaultPattern = defaultPattern;
158 for (int i = 0; !needsLocation && i < defaultFormatters.length; ++i) {
159 needsLocation = defaultFormatters[i].requiresLocation();
160 }
161 } catch (final RuntimeException ex) {
162 throw new IllegalArgumentException("Cannot parse pattern '" + defaultPattern + "'", ex);
163 }
164 requiresLocation = needsLocation;
165 }
166
167 @Override
168 public boolean requiresLocation() {
169 return requiresLocation;
170 }
171
172 @Override
173 public PatternFormatter[] getFormatters(final LogEvent event) {
174 final Level level = event.getLevel();
175 if (level == null) {
176 return defaultFormatters;
177 }
178 for (final String key : formatterMap.keySet()) {
179 if (level.name().equalsIgnoreCase(key)) {
180 return formatterMap.get(key);
181 }
182 }
183 return defaultFormatters;
184 }
185
186 /**
187 * Creates a builder for a custom ScriptPatternSelector.
188 *
189 * @return a ScriptPatternSelector builder.
190 */
191 @PluginBuilderFactory
192 public static Builder newBuilder() {
193 return new Builder();
194 }
195
196 /**
197 * Deprecated, use {@link #newBuilder()} instead.
198 * @param properties
199 * @param defaultPattern
200 * @param alwaysWriteExceptions
201 * @param noConsoleNoAnsi
202 * @param configuration
203 * @return a new MarkerPatternSelector.
204 * @deprecated Use {@link #newBuilder()} instead.
205 */
206 @Deprecated
207 public static LevelPatternSelector createSelector(
208 final PatternMatch[] properties,
209 final String defaultPattern,
210 final boolean alwaysWriteExceptions,
211 final boolean noConsoleNoAnsi,
212 final Configuration configuration) {
213 final Builder builder = newBuilder();
214 builder.setProperties(properties);
215 builder.setDefaultPattern(defaultPattern);
216 builder.setAlwaysWriteExceptions(alwaysWriteExceptions);
217 builder.setNoConsoleNoAnsi(noConsoleNoAnsi);
218 builder.setConfiguration(configuration);
219 return builder.build();
220 }
221
222 @Override
223 public String toString() {
224 final StringBuilder sb = new StringBuilder();
225 boolean first = true;
226 for (final Map.Entry<String, String> entry : patternMap.entrySet()) {
227 if (!first) {
228 sb.append(", ");
229 }
230 sb.append("key=\"").append(entry.getKey()).append("\", pattern=\"").append(entry.getValue()).append("\"");
231 first = false;
232 }
233 if (!first) {
234 sb.append(", ");
235 }
236 sb.append("default=\"").append(defaultPattern).append("\"");
237 return sb.toString();
238 }
239 }
139139 try {
140140 final List<PatternFormatter> list = parser.parse(property.getPattern(), alwaysWriteExceptions,
141141 disableAnsi, noConsoleNoAnsi);
142 PatternFormatter[] formatters = list.toArray(PatternFormatter.EMPTY_ARRAY);
142 PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
143143 formatterMap.put(property.getKey(), formatters);
144144 for (int i = 0; !needsLocation && i < formatters.length; ++i) {
145145 needsLocation = formatters[i].requiresLocation();
153153 try {
154154 final List<PatternFormatter> list = parser.parse(defaultPattern, alwaysWriteExceptions, disableAnsi,
155155 noConsoleNoAnsi);
156 defaultFormatters = list.toArray(PatternFormatter.EMPTY_ARRAY);
156 defaultFormatters = list.toArray(new PatternFormatter[0]);
157157 this.defaultPattern = defaultPattern;
158158 for (int i = 0; !needsLocation && i < defaultFormatters.length; ++i) {
159159 needsLocation = defaultFormatters[i].requiresLocation();
3434 import org.apache.logging.log4j.core.config.plugins.PluginElement;
3535 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
3636 import org.apache.logging.log4j.core.impl.LocationAware;
37 import org.apache.logging.log4j.core.pattern.FormattingInfo;
3837 import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
3938 import org.apache.logging.log4j.core.pattern.PatternFormatter;
4039 import org.apache.logging.log4j.core.pattern.PatternParser;
216215 return eventSerializer.toSerializable(event);
217216 }
218217
219 public void serialize(final LogEvent event, StringBuilder stringBuilder) {
220 eventSerializer.toSerializable(event, stringBuilder);
221 }
222
223218 @Override
224219 public void encode(final LogEvent event, final ByteBufferDestination destination) {
225 final StringBuilder text = toText(eventSerializer, event, getStringBuilder());
220 if (!(eventSerializer instanceof Serializer2)) {
221 super.encode(event, destination);
222 return;
223 }
224 final StringBuilder text = toText((Serializer2) eventSerializer, event, getStringBuilder());
226225 final Encoder<StringBuilder> encoder = getStringBuilderEncoder();
227226 encoder.encode(text, destination);
228227 trimToMaxSize(text);
313312 .build();
314313 }
315314
316 private interface PatternSerializer extends Serializer, Serializer2, LocationAware {}
317
318 private static final class NoFormatPatternSerializer implements PatternSerializer {
319
320 private final LogEventPatternConverter[] converters;
321
322 private NoFormatPatternSerializer(final PatternFormatter[] formatters) {
323 this.converters = new LogEventPatternConverter[formatters.length];
324 for (int i = 0; i < formatters.length; i++) {
325 converters[i] = formatters[i].getConverter();
326 }
315 private static class PatternSerializer implements Serializer, Serializer2, LocationAware {
316
317 private final PatternFormatter[] formatters;
318 private final RegexReplacement replace;
319
320 private PatternSerializer(final PatternFormatter[] formatters, final RegexReplacement replace) {
321 super();
322 this.formatters = formatters;
323 this.replace = replace;
327324 }
328325
329326 @Override
338335
339336 @Override
340337 public StringBuilder toSerializable(final LogEvent event, final StringBuilder buffer) {
341 for (LogEventPatternConverter converter : converters) {
342 converter.format(event, buffer);
343 }
344 return buffer;
345 }
346
347 @Override
348 public boolean requiresLocation() {
349 for (LogEventPatternConverter converter : converters) {
350 if (converter instanceof LocationAware && ((LocationAware) converter).requiresLocation()) {
351 return true;
352 }
353 }
354 return false;
355 }
356
357 @Override
358 public String toString() {
359 return super.toString() + "[converters=" + Arrays.toString(converters) + "]";
360 }
361 }
362
363 private static final class PatternFormatterPatternSerializer implements PatternSerializer {
364
365 private final PatternFormatter[] formatters;
366
367 private PatternFormatterPatternSerializer(final PatternFormatter[] formatters) {
368 this.formatters = formatters;
369 }
370
371 @Override
372 public String toSerializable(final LogEvent event) {
373 final StringBuilder sb = getStringBuilder();
374 try {
375 return toSerializable(event, sb).toString();
376 } finally {
377 trimToMaxSize(sb);
378 }
379 }
380
381 @Override
382 public StringBuilder toSerializable(final LogEvent event, final StringBuilder buffer) {
383 for (PatternFormatter formatter : formatters) {
384 formatter.format(event, buffer);
338 final int len = formatters.length;
339 for (int i = 0; i < len; i++) {
340 formatters[i].format(event, buffer);
341 }
342 if (replace != null) { // creates temporary objects
343 String str = buffer.toString();
344 str = replace.format(str);
345 buffer.setLength(0);
346 buffer.append(str);
385347 }
386348 return buffer;
387349 }
398360
399361 @Override
400362 public String toString() {
401 return super.toString() +
402 "[formatters=" +
403 Arrays.toString(formatters) +
404 "]";
405 }
406 }
407
408 private static final class PatternSerializerWithReplacement implements Serializer, Serializer2, LocationAware {
409
410 private final PatternSerializer delegate;
411 private final RegexReplacement replace;
412
413 private PatternSerializerWithReplacement(final PatternSerializer delegate, final RegexReplacement replace) {
414 this.delegate = delegate;
415 this.replace = replace;
416 }
417
418 @Override
419 public String toSerializable(final LogEvent event) {
420 final StringBuilder sb = getStringBuilder();
421 try {
422 return toSerializable(event, sb).toString();
423 } finally {
424 trimToMaxSize(sb);
425 }
426 }
427
428 @Override
429 public StringBuilder toSerializable(final LogEvent event, final StringBuilder buf) {
430 StringBuilder buffer = delegate.toSerializable(event, buf);
431 String str = buffer.toString();
432 str = replace.format(str);
433 buffer.setLength(0);
434 buffer.append(str);
435 return buffer;
436 }
437
438 @Override
439 public boolean requiresLocation() {
440 return delegate.requiresLocation();
441 }
442
443 @Override
444 public String toString() {
445 return super.toString() +
446 "[delegate=" +
447 delegate +
448 ", replace=" +
449 replace +
450 "]";
363 final StringBuilder builder = new StringBuilder();
364 builder.append(super.toString());
365 builder.append("[formatters=");
366 builder.append(Arrays.toString(formatters));
367 builder.append(", replace=");
368 builder.append(replace);
369 builder.append("]");
370 return builder.toString();
451371 }
452372 }
453373
472392 final PatternParser parser = createPatternParser(configuration);
473393 final List<PatternFormatter> list = parser.parse(pattern == null ? defaultPattern : pattern,
474394 alwaysWriteExceptions, disableAnsi, noConsoleNoAnsi);
475 final PatternFormatter[] formatters = list.toArray(PatternFormatter.EMPTY_ARRAY);
476 boolean hasFormattingInfo = false;
477 for (PatternFormatter formatter : formatters) {
478 FormattingInfo info = formatter.getFormattingInfo();
479 if (info != null && info != FormattingInfo.getDefault()) {
480 hasFormattingInfo = true;
481 break;
482 }
483 }
484 PatternSerializer serializer = hasFormattingInfo
485 ? new PatternFormatterPatternSerializer(formatters)
486 : new NoFormatPatternSerializer(formatters);
487 return replace == null ? serializer : new PatternSerializerWithReplacement(serializer, replace);
395 final PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
396 return new PatternSerializer(formatters, replace);
488397 } catch (final RuntimeException ex) {
489398 throw new IllegalArgumentException("Cannot parse pattern '" + pattern + "'", ex);
490399 }
534443
535444 }
536445
537 private static final class PatternSelectorSerializer implements Serializer, Serializer2, LocationAware {
446 private static class PatternSelectorSerializer implements Serializer, Serializer2, LocationAware {
538447
539448 private final PatternSelector patternSelector;
540449 private final RegexReplacement replace;
541450
542451 private PatternSelectorSerializer(final PatternSelector patternSelector, final RegexReplacement replace) {
452 super();
543453 this.patternSelector = patternSelector;
544454 this.replace = replace;
545455 }
556466
557467 @Override
558468 public StringBuilder toSerializable(final LogEvent event, final StringBuilder buffer) {
559 for (PatternFormatter formatter : patternSelector.getFormatters(event)) {
560 formatter.format(event, buffer);
469 final PatternFormatter[] formatters = patternSelector.getFormatters(event);
470 final int len = formatters.length;
471 for (int i = 0; i < len; i++) {
472 formatters[i].format(event, buffer);
561473 }
562474 if (replace != null) { // creates temporary objects
563475 String str = buffer.toString();
1818
1919 import java.io.ObjectStreamException;
2020 import java.io.Serializable;
21 import java.util.Objects;
2221
2322 import org.apache.logging.log4j.core.config.Node;
2423 import org.apache.logging.log4j.core.config.plugins.Plugin;
104103
105104 @Override
106105 public int hashCode() {
107 return Objects.hash(key, pattern);
106 final int prime = 31;
107 int result = 1;
108 result = prime * result + ((key == null) ? 0 : key.hashCode());
109 result = prime * result + ((pattern == null) ? 0 : pattern.hashCode());
110 return result;
108111 }
109112
110113 @Override
119122 return false;
120123 }
121124 final PatternMatch other = (PatternMatch) obj;
122 if (!Objects.equals(key, other.key)) {
125 if (key == null) {
126 if (other.key != null) {
127 return false;
128 }
129 } else if (!key.equals(other.key)) {
123130 return false;
124131 }
125 if (!Objects.equals(pattern, other.pattern)) {
132 if (pattern == null) {
133 if (other.pattern != null) {
134 return false;
135 }
136 } else if (!pattern.equals(other.pattern)) {
126137 return false;
127138 }
128139 return true;
3434 import org.apache.logging.log4j.core.LogEvent;
3535 import org.apache.logging.log4j.core.appender.TlsSyslogFrame;
3636 import org.apache.logging.log4j.core.config.Configuration;
37 import org.apache.logging.log4j.core.layout.internal.ExcludeChecker;
38 import org.apache.logging.log4j.core.layout.internal.IncludeChecker;
39 import org.apache.logging.log4j.core.layout.internal.ListChecker;
4037 import org.apache.logging.log4j.core.config.Node;
4138 import org.apache.logging.log4j.core.config.plugins.Plugin;
4239 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
114111 private final List<String> mdcIncludes;
115112 private final List<String> mdcRequired;
116113 private final ListChecker listChecker;
114 private final ListChecker noopChecker = new NoopChecker();
117115 private final boolean includeNewLine;
118116 private final String escapeNewLine;
119117 private final boolean useTlsMessageFormat;
147145 this.messageId = messageId;
148146 this.useTlsMessageFormat = useTLSMessageFormat;
149147 this.localHostName = NetUtils.getLocalHostname();
150 ListChecker checker = null;
148 ListChecker c = null;
151149 if (excludes != null) {
152150 final String[] array = excludes.split(Patterns.COMMA_SEPARATOR);
153151 if (array.length > 0) {
152 c = new ExcludeChecker();
154153 mdcExcludes = new ArrayList<>(array.length);
155154 for (final String str : array) {
156155 mdcExcludes.add(str.trim());
157156 }
158 checker = new ExcludeChecker(mdcExcludes);
159157 } else {
160158 mdcExcludes = null;
161159 }
165163 if (includes != null) {
166164 final String[] array = includes.split(Patterns.COMMA_SEPARATOR);
167165 if (array.length > 0) {
166 c = new IncludeChecker();
168167 mdcIncludes = new ArrayList<>(array.length);
169168 for (final String str : array) {
170169 mdcIncludes.add(str.trim());
171170 }
172 checker = new IncludeChecker(mdcIncludes);
173171 } else {
174172 mdcIncludes = null;
175173 }
190188 } else {
191189 mdcRequired = null;
192190 }
193 this.listChecker = checker != null ? checker : ListChecker.NOOP_CHECKER;
191 this.listChecker = c != null ? c : noopChecker;
194192 final String name = config == null ? null : config.getName();
195193 configName = Strings.isNotEmpty(name) ? name : null;
196194 this.fieldFormatters = createFieldFormatters(loggerFields, config);
514512 sb.append('[');
515513 sb.append(id);
516514 if (!mdcSdId.toString().equals(id)) {
517 appendMap(data.getPrefix(), data.getFields(), sb, ListChecker.NOOP_CHECKER);
515 appendMap(data.getPrefix(), data.getFields(), sb, noopChecker);
518516 } else {
519517 appendMap(data.getPrefix(), data.getFields(), sb, checker);
520518 }
565563
566564 private String escapeSDParams(final String value) {
567565 return PARAM_VALUE_ESCAPE_PATTERN.matcher(value).replaceAll("\\\\$0");
566 }
567
568 /**
569 * Interface used to check keys in a Map.
570 */
571 private interface ListChecker {
572 boolean check(String key);
573 }
574
575 /**
576 * Includes only the listed keys.
577 */
578 private class IncludeChecker implements ListChecker {
579 @Override
580 public boolean check(final String key) {
581 return mdcIncludes.contains(key);
582 }
583 }
584
585 /**
586 * Excludes the listed keys.
587 */
588 private class ExcludeChecker implements ListChecker {
589 @Override
590 public boolean check(final String key) {
591 return !mdcExcludes.contains(key);
592 }
593 }
594
595 /**
596 * Does nothing.
597 */
598 private class NoopChecker implements ListChecker {
599 @Override
600 public boolean check(final String key) {
601 return true;
602 }
568603 }
569604
570605 @Override
3838 import org.apache.logging.log4j.status.StatusLogger;
3939
4040 /**
41 * Selects the pattern to use based on the result of executing a Script. The returned value will be used as the "key"
42 * to choose between one of the configured patterns. If no key is returned or there is no match the default
43 * pattern will be used.
41 * Selects the pattern to use based on the Marker in the LogEvent.
4442 */
4543 @Plugin(name = "ScriptPatternSelector", category = Node.CATEGORY, elementType = PatternSelector.ELEMENT_TYPE, printObject = true)
4644 public class ScriptPatternSelector implements PatternSelector, LocationAware {
164162 for (final PatternMatch property : properties) {
165163 try {
166164 final List<PatternFormatter> list = parser.parse(property.getPattern(), alwaysWriteExceptions, disableAnsi, noConsoleNoAnsi);
167 PatternFormatter[] formatters = list.toArray(PatternFormatter.EMPTY_ARRAY);
165 PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
168166 formatterMap.put(property.getKey(), formatters);
169167 patternMap.put(property.getKey(), property.getPattern());
170168 for (int i = 0; !needsLocation && i < formatters.length; ++i) {
176174 }
177175 try {
178176 final List<PatternFormatter> list = parser.parse(defaultPattern, alwaysWriteExceptions, disableAnsi, noConsoleNoAnsi);
179 defaultFormatters = list.toArray(PatternFormatter.EMPTY_ARRAY);
177 defaultFormatters = list.toArray(new PatternFormatter[0]);
180178 this.defaultPattern = defaultPattern;
181179 for (int i = 0; !needsLocation && i < defaultFormatters.length; ++i) {
182180 needsLocation = defaultFormatters[i].requiresLocation();
5757 implements org.apache.logging.log4j.core.util.Builder<SyslogLayout> {
5858
5959 public Builder() {
60 super();
6061 setCharset(StandardCharsets.UTF_8);
6162 }
6263
6767 implements org.apache.logging.log4j.core.util.Builder<XmlLayout> {
6868
6969 public Builder() {
70 super();
7071 setCharset(StandardCharsets.UTF_8);
7172 }
7273
7475 public XmlLayout build() {
7576 return new XmlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(),
7677 isCompact(), getEndOfLine(), getCharset(), isIncludeStacktrace(), isStacktraceAsString(),
77 isIncludeNullDelimiter(), isIncludeTimeMillis(), getAdditionalFields());
78 isIncludeNullDelimiter(), getAdditionalFields());
7879 }
7980 }
8081
8485 @Deprecated
8586 protected XmlLayout(final boolean locationInfo, final boolean properties, final boolean complete,
8687 final boolean compact, final Charset charset, final boolean includeStacktrace) {
87 this(null, locationInfo, properties, complete, compact, null, charset, includeStacktrace,
88 false, false, false, null);
88 this(null, locationInfo, properties, complete, compact, null, charset, includeStacktrace, false, false, null);
8989 }
9090
9191 private XmlLayout(final Configuration config, final boolean locationInfo, final boolean properties,
9292 final boolean complete, final boolean compact, final String endOfLine, final Charset charset,
9393 final boolean includeStacktrace, final boolean stacktraceAsString,
94 final boolean includeNullDelimiter, final boolean includeTimeMillis,
94 final boolean includeNullDelimiter,
9595 final KeyValuePair[] additionalFields) {
9696 super(config, new JacksonFactory.XML(includeStacktrace, stacktraceAsString).newWriter(
97 locationInfo, properties, compact, includeTimeMillis),
97 locationInfo, properties, compact),
9898 charset, compact, complete, false, endOfLine, null, null, includeNullDelimiter,
9999 additionalFields);
100100 }
188188 final Charset charset,
189189 final boolean includeStacktrace) {
190190 return new XmlLayout(null, locationInfo, properties, complete, compact, null, charset, includeStacktrace, false,
191 false, false, null);
191 false, null);
192192 }
193193
194194 @PluginBuilderFactory
202202 * @return an XML Layout.
203203 */
204204 public static XmlLayout createDefaultLayout() {
205 return new XmlLayout(null, false, false, false, false, null, StandardCharsets.UTF_8, true, false, false,
206 false, null);
205 return new XmlLayout(null, false, false, false, false, null, StandardCharsets.UTF_8, true, false, false, null);
207206 }
208207 }
5757 implements org.apache.logging.log4j.core.util.Builder<YamlLayout> {
5858
5959 public Builder() {
60 super();
6061 setCharset(StandardCharsets.UTF_8);
6162 }
6263
6768 return new YamlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(),
6869 isCompact(), getEventEol(), getEndOfLine(), headerPattern, footerPattern, getCharset(),
6970 isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter(),
70 isIncludeTimeMillis(), getAdditionalFields());
71 getAdditionalFields());
7172 }
7273 }
7374
8990 final boolean complete, final boolean compact, final boolean eventEol, final String endOfLine,
9091 final String headerPattern, final String footerPattern, final Charset charset,
9192 final boolean includeStacktrace, final boolean stacktraceAsString,
92 final boolean includeNullDelimiter, final boolean includeTimeMillis,
93 final boolean includeNullDelimiter,
9394 final KeyValuePair[] additionalFields) {
94 super(config, new JacksonFactory.YAML(includeStacktrace, stacktraceAsString)
95 .newWriter(locationInfo, properties, compact, includeTimeMillis),
95 super(config, new JacksonFactory.YAML(includeStacktrace, stacktraceAsString).newWriter(locationInfo, properties, compact),
9696 charset, compact, complete, eventEol, endOfLine,
9797 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
9898 PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
185185 final Charset charset,
186186 final boolean includeStacktrace) {
187187 return new YamlLayout(config, locationInfo, properties, false, false, true, null, headerPattern, footerPattern,
188 charset, includeStacktrace, false, false, false, null);
188 charset, includeStacktrace, false, false, null);
189189 }
190190
191191 @PluginBuilderFactory
200200 */
201201 public static AbstractJacksonLayout createDefaultLayout() {
202202 return new YamlLayout(new DefaultConfiguration(), false, false, false, false, false, null, DEFAULT_HEADER,
203 DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, false, null);
203 DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, null);
204204 }
205205 }
+0
-40
log4j-core/src/main/java/org/apache/logging/log4j/core/layout/internal/ExcludeChecker.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.logging.log4j.core.layout.internal;
17
18 import java.util.List;
19
20 /**
21 * Excludes the listed keys.
22 */
23 public class ExcludeChecker implements ListChecker {
24 private final List<String> list;
25
26 public ExcludeChecker(final List<String> list) {
27 this.list = list;
28 }
29
30 @Override
31 public boolean check(final String key) {
32 return !list.contains(key);
33 }
34
35 @Override
36 public String toString() {
37 return "ThreadContextExcludes=" + list.toString();
38 }
39 }
+0
-40
log4j-core/src/main/java/org/apache/logging/log4j/core/layout/internal/IncludeChecker.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.logging.log4j.core.layout.internal;
17
18 import java.util.List;
19
20 /**
21 * Includes only the listed keys.
22 */
23 public class IncludeChecker implements ListChecker {
24 private final List<String> list;
25
26 public IncludeChecker(final List<String> list) {
27 this.list = list;
28 }
29 @Override
30 public boolean check(final String key) {
31 return list.contains(key);
32 }
33
34 @Override
35 public String toString() {
36 return "ThreadContextIncludes=" + list.toString();
37 }
38 }
39
+0
-43
log4j-core/src/main/java/org/apache/logging/log4j/core/layout/internal/ListChecker.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.logging.log4j.core.layout.internal;
17
18 /**
19 * Class Description goes here.
20 */
21
22 public interface ListChecker {
23
24 static final NoopChecker NOOP_CHECKER = new NoopChecker();
25
26 boolean check(final String key);
27
28 /**
29 * Does nothing.
30 */
31 public class NoopChecker implements ListChecker {
32 @Override
33 public boolean check(final String key) {
34 return true;
35 }
36
37 @Override
38 public String toString() {
39 return "";
40 }
41 }
42 }
5454 */
5555 @Override
5656 public String lookup(final LogEvent event, final String key) {
57 return event == null ? null : event.getContextData().getValue(key);
57 return event == null ? null : event.getContextData().<String>getValue(key);
5858 }
5959 }
+0
-75
log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/EventLookup.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.logging.log4j.core.lookup;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20
21 /**
22 * Looks up values from the log event.
23 */
24 @Plugin(name = "event", category = StrLookup.CATEGORY)
25 public class EventLookup extends AbstractLookup {
26
27 /**
28 * Looks up the value from the logging event.
29 * @param event The current LogEvent.
30 * @param key the key to be looked up.
31 * @return The value of the specified log event field.
32 */
33 @Override
34 public String lookup(final LogEvent event, final String key) {
35 if (event == null) {
36 return null;
37 }
38 switch (key) {
39 case "Marker": {
40 return event.getMarker() != null ? event.getMarker().getName() : null;
41 }
42 case "ThreadName": {
43 return event.getThreadName();
44 }
45 case "Level": {
46 return event.getLevel().toString();
47 }
48 case "ThreadId": {
49 return Long.toString(event.getThreadId());
50 }
51 case "Timestamp": {
52 return Long.toString(event.getTimeMillis());
53 }
54 case "Exception": {
55 if (event.getThrown() != null) {
56 return event.getThrown().getClass().getSimpleName();
57 }
58 if (event.getThrownProxy() != null) {
59 return event.getThrownProxy().getName();
60 }
61 return null;
62 }
63 case "Logger": {
64 return event.getLoggerName();
65 }
66 case "Message": {
67 return event.getMessage().getFormattedMessage();
68 }
69 default: {
70 return null;
71 }
72 }
73 }
74 }
3636 */
3737 public class Interpolator extends AbstractConfigurationAwareLookup {
3838
39 private static final String LOOKUP_KEY_WEB = "web";
40
41 private static final String LOOKUP_KEY_DOCKER = "docker";
42
43 private static final String LOOKUP_KEY_JNDI = "jndi";
44
45 private static final String LOOKUP_KEY_JVMRUNARGS = "jvmrunargs";
46
47 private static final Logger LOGGER = StatusLogger.getLogger();
48
3949 /** Constant for the prefix separator. */
40 public static final char PREFIX_SEPARATOR = ':';
41
42 private static final String LOOKUP_KEY_WEB = "web";
43
44 private static final String LOOKUP_KEY_DOCKER = "docker";
45
46 private static final String LOOKUP_KEY_KUBERNETES = "kubernetes";
47
48 private static final String LOOKUP_KEY_SPRING = "spring";
49
50 private static final String LOOKUP_KEY_JNDI = "jndi";
51
52 private static final String LOOKUP_KEY_JVMRUNARGS = "jvmrunargs";
53
54 private static final Logger LOGGER = StatusLogger.getLogger();
50 static final char PREFIX_SEPARATOR = ':';
5551
5652 private final Map<String, StrLookup> strLookupMap = new HashMap<>();
5753
105101 strLookupMap.put("main", MainMapLookup.MAIN_SINGLETON);
106102 strLookupMap.put("marker", new MarkerLookup());
107103 strLookupMap.put("java", new JavaLookup());
108 strLookupMap.put("lower", new LowerLookup());
109 strLookupMap.put("upper", new UpperLookup());
110104 // JNDI
111105 if (JndiManager.isJndiLookupEnabled()) {
112106 try {
144138 } catch (final Exception ignored) {
145139 handleError(LOOKUP_KEY_DOCKER, ignored);
146140 }
147 try {
148 strLookupMap.put(LOOKUP_KEY_SPRING,
149 Loader.newCheckedInstanceOf("org.apache.logging.log4j.spring.cloud.config.client.SpringLookup", StrLookup.class));
150 } catch (final Exception ignored) {
151 handleError(LOOKUP_KEY_SPRING, ignored);
152 }
153 try {
154 strLookupMap.put(LOOKUP_KEY_KUBERNETES,
155 Loader.newCheckedInstanceOf("org.apache.logging.log4j.kubernetes.KubernetesLookup", StrLookup.class));
156 } catch (final Exception | NoClassDefFoundError error) {
157 handleError(LOOKUP_KEY_KUBERNETES, error);
158 }
159141 }
160142
161143 public Map<String, StrLookup> getStrLookupMap() {
181163 "available. If you want better web container support, please add the log4j-web JAR to your " +
182164 "web archive or server lib directory.");
183165 break;
184 case LOOKUP_KEY_DOCKER: case LOOKUP_KEY_SPRING:
185 break;
186 case LOOKUP_KEY_KUBERNETES:
187 if (t instanceof NoClassDefFoundError) {
188 LOGGER.warn("Unable to create Kubernetes lookup due to missing dependency: {}", t.getMessage());
189 }
166 case LOOKUP_KEY_DOCKER:
190167 break;
191168 default:
192169 LOGGER.error("Unable to create Lookup for {}", lookupKey, t);
4141 * Constructor when used directly as a plugin.
4242 */
4343 public JmxRuntimeInputArgumentsLookup() {
44 super();
4445 }
4546
4647 public JmxRuntimeInputArgumentsLookup(final Map<String, String> map) {
8585 }
8686 } catch (final URISyntaxException use) {
8787 LOGGER.error(use);
88 return null;
8889 }
8990 }
9091 }
+0
-48
log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/LowerLookup.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.logging.log4j.core.lookup;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20
21 /**
22 * Converts values to lower case. The passed in "key" should be the value of another lookup.
23 */
24 @Plugin(name = "lower", category = StrLookup.CATEGORY)
25 public class LowerLookup implements StrLookup {
26
27 /**
28 * Converts the "key" to lower case.
29 * @param key the key to be looked up, may be null
30 * @return The value associated with the key.
31 */
32 @Override
33 public String lookup(final String key) {
34 return key != null ? key.toLowerCase() : null;
35 }
36
37 /**
38 * Converts the "key" to lower case.
39 * @param event The current LogEvent.
40 * @param key the key to be looked up, may be null
41 * @return The value associated with the key.
42 */
43 @Override
44 public String lookup(final LogEvent event, final String key) {
45 return lookup(key);
46 }
47 }
6363 * Second using the argument at position n as the key to access the value at n+1.
6464 * </p>
6565 * <ul>
66 * <li>{@code "main:\--file"} = {@code "path/file.txt"}</li>
67 * <li>{@code "main:\-x"} = {@code "2"}</li>
66 * <li>{@code "main:--file"} = {@code "path/file.txt"}</li>
67 * <li>{@code "main:-x"} = {@code "2"}</li>
6868 * </ul>
69 *<p>Note: Many applications use leading dashes to identify command arguments. Specifying {@code "main:--file}
70 * would result in the lookup failing because it would look for a variable named "main" with a default
71 * value of "-file". To avoid this the ":" separating the Lookup name from the key must be followed by
72 * a backslash as an escape character.</p>
7369 *
7470 * @param args
7571 * An application's {@code public static main(String[])} arguments.
275275 * @param chars the characters to match, must not be null
276276 */
277277 CharSetMatcher(final char[] chars) {
278 super();
278279 this.chars = chars.clone();
279280 Arrays.sort(this.chars);
280281 }
308309 * @param ch the character to match
309310 */
310311 CharMatcher(final char ch) {
312 super();
311313 this.ch = ch;
312314 }
313315
340342 * @param str the string to match, must not be null
341343 */
342344 StringMatcher(final String str) {
345 super();
343346 chars = str.toCharArray();
344347 }
345348
383386 * Constructs a new instance of <code>NoMatcher</code>.
384387 */
385388 NoMatcher() {
389 super();
386390 }
387391
388392 /**
410414 * Constructs a new instance of <code>TrimMatcher</code>.
411415 */
412416 TrimMatcher() {
417 super();
413418 }
414419
415420 /**
+0
-48
log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/UpperLookup.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.logging.log4j.core.lookup;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20
21 /**
22 * Converts values to upper case. The passed in "key" should be the value of another lookup.
23 */
24 @Plugin(name = "upper", category = StrLookup.CATEGORY)
25 public class UpperLookup implements StrLookup {
26
27 /**
28 * Converts the "key" to upper case.
29 * @param key the key to be looked up, may be null
30 * @return The value associated with the key.
31 */
32 @Override
33 public String lookup(final String key) {
34 return key != null ? key.toUpperCase() : null;
35 }
36
37 /**
38 * Converts the "key" to upper case.
39 * @param event The current LogEvent.
40 * @param key the key to be looked up, may be null
41 * @return The value associated with the key.
42 */
43 @Override
44 public String lookup(final LogEvent event, final String key) {
45 return lookup(key);
46 }
47 }
3131 import org.apache.logging.log4j.util.PropertiesUtil;
3232
3333 /**
34 * Manages a JNDI {@link javax.naming.directory.DirContext}.
34 * Manages a JNDI {@link javax.naming.Context}.
3535 *
3636 * @since 2.1
3737 */
4141 private static final String PREFIX = "log4j2.enableJndi";
4242 private static final String JAVA_SCHEME = "java";
4343
44 private final InitialContext context;
44 private final Context context;
4545
4646 private static boolean isJndiEnabled(final String subKey) {
4747 return PropertiesUtil.getProperties().getBooleanProperty(PREFIX + subKey, false);
6363 return isJndiEnabled("Lookup");
6464 }
6565
66 private JndiManager(final String name, final InitialContext context) {
66 private JndiManager(final String name, final Context context) {
6767 super(null, name);
6868 this.context = context;
6969 }
222222 return null;
223223 }
224224 }
225
225226 }
226227
227228 @Override
188188 try {
189189 jmDNSClass = LoaderUtil.loadClass("javax.jmdns.JmDNS");
190190 serviceInfoClass = LoaderUtil.loadClass("javax.jmdns.ServiceInfo");
191 // if version 3 is available, use it to construct a serviceInfo instance, otherwise support the version1 API
191 // if version 3 is available, use it to constuct a serviceInfo instance, otherwise support the version1 API
192192 boolean isVersion3 = false;
193193 try {
194194 // create method is in version 3, not version 1
4242 import org.apache.logging.log4j.core.appender.AbstractManager;
4343 import org.apache.logging.log4j.core.appender.ManagerFactory;
4444 import org.apache.logging.log4j.core.config.Configuration;
45 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
46 import org.apache.logging.log4j.core.impl.MutableLogEvent;
4547 import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
4648 import org.apache.logging.log4j.core.layout.PatternLayout;
4749 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
4850 import org.apache.logging.log4j.core.util.CyclicBuffer;
51 import org.apache.logging.log4j.core.util.NameUtil;
4952 import org.apache.logging.log4j.core.util.NetUtils;
53 import org.apache.logging.log4j.message.ReusableMessage;
5054 import org.apache.logging.log4j.util.PropertiesUtil;
5155 import org.apache.logging.log4j.util.Strings;
5256
8286 }
8387
8488 public void add(LogEvent event) {
85 buffer.add(event.toImmutable());
89 if (event instanceof Log4jLogEvent && event.getMessage() instanceof ReusableMessage) {
90 ((Log4jLogEvent) event).makeMessageImmutable();
91 } else if (event instanceof MutableLogEvent) {
92 event = ((MutableLogEvent) event).createMemento();
93 }
94 buffer.add(event);
8695 }
8796
8897 public static SmtpManager getSmtpManager(
97106 protocol = "smtp";
98107 }
99108
100 final String name = createManagerName(to, cc, bcc, from, replyTo, subject, protocol, host, port, username, isDebug, filterName);
109 final StringBuilder sb = new StringBuilder();
110 if (to != null) {
111 sb.append(to);
112 }
113 sb.append(':');
114 if (cc != null) {
115 sb.append(cc);
116 }
117 sb.append(':');
118 if (bcc != null) {
119 sb.append(bcc);
120 }
121 sb.append(':');
122 if (from != null) {
123 sb.append(from);
124 }
125 sb.append(':');
126 if (replyTo != null) {
127 sb.append(replyTo);
128 }
129 sb.append(':');
130 if (subject != null) {
131 sb.append(subject);
132 }
133 sb.append(':');
134 sb.append(protocol).append(':').append(host).append(':').append("port").append(':');
135 if (username != null) {
136 sb.append(username);
137 }
138 sb.append(':');
139 if (password != null) {
140 sb.append(password);
141 }
142 sb.append(isDebug ? ":debug:" : "::");
143 sb.append(filterName);
144
145 final String name = "SMTP:" + NameUtil.md5(sb.toString());
101146 final Serializer subjectSerializer = PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(subject).build();
102147
103148 return getManager(name, FACTORY, new FactoryData(to, cc, bcc, from, replyTo, subjectSerializer,
104149 protocol, host, port, username, password, isDebug, numElements, sslConfiguration));
105
106 }
107
108 /**
109 * Creates a unique-per-configuration name for an smtp manager using the specified the parameters.<br>
110 * Using such a name allows us to maintain singletons per unique configurations.
111 *
112 * @return smtp manager name
113 */
114 static String createManagerName(
115 final String to,
116 final String cc,
117 final String bcc,
118 final String from,
119 final String replyTo,
120 final String subject,
121 final String protocol,
122 final String host,
123 final int port,
124 final String username,
125 final boolean isDebug,
126 final String filterName) {
127
128 final StringBuilder sb = new StringBuilder();
129
130 if (to != null) {
131 sb.append(to);
132 }
133 sb.append(':');
134 if (cc != null) {
135 sb.append(cc);
136 }
137 sb.append(':');
138 if (bcc != null) {
139 sb.append(bcc);
140 }
141 sb.append(':');
142 if (from != null) {
143 sb.append(from);
144 }
145 sb.append(':');
146 if (replyTo != null) {
147 sb.append(replyTo);
148 }
149 sb.append(':');
150 if (subject != null) {
151 sb.append(subject);
152 }
153 sb.append(':');
154 sb.append(protocol).append(':').append(host).append(':').append(port).append(':');
155 if (username != null) {
156 sb.append(username);
157 }
158 sb.append(isDebug ? ":debug:" : "::");
159 sb.append(filterName);
160
161 return "SMTP:" + sb.toString();
162150 }
163151
164152 /**
171159 connect(appendEvent);
172160 }
173161 try {
174 final LogEvent[] priorEvents = removeAllBufferedEvents();
162 final LogEvent[] priorEvents = buffer.removeAll();
175163 // LOG4J-310: log appendEvent even if priorEvents is empty
176164
177165 final byte[] rawBytes = formatContentToBytes(priorEvents, appendEvent, layout);
183171 final InternetHeaders headers = getHeaders(contentType, encoding);
184172 final MimeMultipart mp = getMimeMultipart(encodedBytes, headers);
185173
186 final String subject = data.subject.toSerializable(appendEvent);
187
188 sendMultipartMessage(message, mp, subject);
174 sendMultipartMessage(message, mp);
189175 } catch (final MessagingException | IOException | RuntimeException e) {
190176 logError("Caught exception while sending e-mail notification.", e);
191177 throw new LoggingException("Error occurred while sending email", e);
192178 }
193 }
194
195 LogEvent[] removeAllBufferedEvents() {
196 return buffer.removeAll();
197179 }
198180
199181 protected byte[] formatContentToBytes(final LogEvent[] priorEvents, final LogEvent appendEvent,
270252 return mp;
271253 }
272254
273 /**
274 * @deprecated Please use the {@link #sendMultipartMessage(MimeMessage, MimeMultipart, String)} method instead.
275 */
276 @Deprecated
277255 protected void sendMultipartMessage(final MimeMessage msg, final MimeMultipart mp) throws MessagingException {
278256 synchronized (msg) {
279257 msg.setContent(mp);
280258 msg.setSentDate(new Date());
281 Transport.send(msg);
282 }
283 }
284
285 protected void sendMultipartMessage(final MimeMessage msg, final MimeMultipart mp, final String subject) throws MessagingException {
286 synchronized (msg) {
287 msg.setContent(mp);
288 msg.setSentDate(new Date());
289 msg.setSubject(subject);
290259 Transport.send(msg);
291260 }
292261 }
217217 try {
218218 writeAndFlush(bytes, offset, length, immediateFlush);
219219 } catch (final IOException causeEx) {
220 final String config = inetAddress + ":" + port;
221220 if (retry && reconnector == null) {
221 final String config = inetAddress + ":" + port;
222222 reconnector = createReconnector();
223223 try {
224224 reconnector.reconnect();
237237 config),
238238 causeEx);
239239 }
240 return;
241240 }
242 final String message = String.format("Error writing to %s for connection %s", getName(), config);
243 throw new AppenderLoggingException(message, causeEx);
244241 }
245242 }
246243 }
478475 os = socket.getOutputStream();
479476 return createManager(name, os, socket, inetAddress, data);
480477 } catch (final IOException ex) {
481 LOGGER.error("TcpSocketManager ({}) caught exception and will continue:", name, ex);
478 LOGGER.error("TcpSocketManager ({}) caught exception and will continue:", name, ex, ex);
482479 os = NullOutputStream.getInstance();
483480 }
484481 if (data.reconnectDelayMillis == 0) {
2323 import java.security.NoSuchAlgorithmException;
2424 import java.security.cert.CertificateException;
2525 import java.util.Arrays;
26 import java.util.Objects;
2726
2827 import org.apache.logging.log4j.core.config.ConfigurationSource;
2928 import org.apache.logging.log4j.core.util.NetUtils;
9493 LOGGER.error("The keystore file {} is not found", loadLocation, e);
9594 throw new StoreConfigurationException(loadLocation, e);
9695 } catch (final IOException e) {
97 LOGGER.error("Something is wrong with the format of the keystore or the given password for location {}", loadLocation, e);
96 LOGGER.error("Something is wrong with the format of the keystore or the given password for location", loadLocation, e);
9897 throw new StoreConfigurationException(loadLocation, e);
9998 }
10099 }
128127 return false;
129128 }
130129 final AbstractKeyStoreConfiguration other = (AbstractKeyStoreConfiguration) obj;
131 if (!Objects.equals(keyStore, other.keyStore)) {
130 if (keyStore == null) {
131 if (other.keyStore != null) {
132 return false;
133 }
134 } else if (!keyStore.equals(other.keyStore)) {
132135 return false;
133136 }
134 if (!Objects.equals(keyStoreType, other.keyStoreType)) {
137 if (keyStoreType == null) {
138 if (other.keyStoreType != null) {
139 return false;
140 }
141 } else if (!keyStoreType.equals(other.keyStoreType)) {
135142 return false;
136143 }
137144 return true;
1919 import java.security.NoSuchAlgorithmException;
2020 import java.security.UnrecoverableKeyException;
2121 import java.util.Arrays;
22 import java.util.Objects;
2322
2423 import javax.net.ssl.KeyManagerFactory;
2524
197196 return false;
198197 }
199198 final KeyStoreConfiguration other = (KeyStoreConfiguration) obj;
200 if (!Objects.equals(keyManagerFactoryAlgorithm, other.keyManagerFactoryAlgorithm)) {
199 if (keyManagerFactoryAlgorithm == null) {
200 if (other.keyManagerFactoryAlgorithm != null) {
201 return false;
202 }
203 } else if (!keyManagerFactoryAlgorithm.equals(other.keyManagerFactoryAlgorithm)) {
201204 return false;
202205 }
203206 return true;
1919 import java.security.KeyStoreException;
2020 import java.security.NoSuchAlgorithmException;
2121 import java.security.UnrecoverableKeyException;
22 import java.util.Objects;
2322
2423 import javax.net.ssl.KeyManager;
2524 import javax.net.ssl.KeyManagerFactory;
129128 try {
130129 return createSslContext(true, false);
131130 } catch (final KeyStoreConfigurationException dummy) {
132 LOGGER.debug("Exception occurred while using default keystore. This should be a BUG");
131 LOGGER.debug("Exception occured while using default keystore. This should be a BUG");
133132 return null;
134133 }
135134 }
139138 return createSslContext(false, true);
140139 }
141140 catch (final TrustStoreConfigurationException dummy) {
142 LOGGER.debug("Exception occurred while using default truststore. This should be a BUG");
141 LOGGER.debug("Exception occured while using default truststore. This should be a BUG");
143142 return null;
144143 }
145144 }
243242 * @param protocol The protocol, see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
244243 * @param keyStoreConfig The KeyStoreConfiguration.
245244 * @param trustStoreConfig The TrustStoreConfiguration.
246 * @param verifyHostName whether or not to perform host name verification
247245 * @return a new SslConfiguration
248246 * @since 2.12
249247 */
252250 @PluginAttribute("protocol") final String protocol,
253251 @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig,
254252 @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig,
255 @PluginAttribute("verifyHostName") final boolean verifyHostName) {
253 @PluginElement("verifyHostName") final boolean verifyHostName) {
256254 // @formatter:on
257255 return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig, verifyHostName);
258256 }
259257
260258 @Override
261259 public int hashCode() {
262 return Objects.hash(keyStoreConfig, protocol, sslContext, trustStoreConfig);
260 final int prime = 31;
261 int result = 1;
262 result = prime * result + ((keyStoreConfig == null) ? 0 : keyStoreConfig.hashCode());
263 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
264 result = prime * result + ((sslContext == null) ? 0 : sslContext.hashCode());
265 result = prime * result + ((trustStoreConfig == null) ? 0 : trustStoreConfig.hashCode());
266 return result;
263267 }
264268
265269 @Override
274278 return false;
275279 }
276280 final SslConfiguration other = (SslConfiguration) obj;
277 if (!Objects.equals(keyStoreConfig, other.keyStoreConfig)) {
278 return false;
279 }
280 if (!Objects.equals(protocol, other.protocol)) {
281 return false;
282 }
283 if (!Objects.equals(sslContext, other.sslContext)) {
284 return false;
285 }
286 if (!Objects.equals(trustStoreConfig, other.trustStoreConfig)) {
281 if (keyStoreConfig == null) {
282 if (other.keyStoreConfig != null) {
283 return false;
284 }
285 } else if (!keyStoreConfig.equals(other.keyStoreConfig)) {
286 return false;
287 }
288 if (protocol == null) {
289 if (other.protocol != null) {
290 return false;
291 }
292 } else if (!protocol.equals(other.protocol)) {
293 return false;
294 }
295 if (sslContext == null) {
296 if (other.sslContext != null) {
297 return false;
298 }
299 } else if (!sslContext.equals(other.sslContext)) {
300 return false;
301 }
302 if (trustStoreConfig == null) {
303 if (other.trustStoreConfig != null) {
304 return false;
305 }
306 } else if (!trustStoreConfig.equals(other.trustStoreConfig)) {
287307 return false;
288308 }
289309 return true;
120120 return false;
121121 }
122122 final StoreConfiguration<?> other = (StoreConfiguration<?>) obj;
123 if (!Objects.equals(location, other.location)) {
123 if (location == null) {
124 if (other.location != null) {
125 return false;
126 }
127 } else if (!location.equals(other.location)) {
124128 return false;
125129 }
126130 if (!Arrays.equals(passwordProvider.getPassword(), other.passwordProvider.getPassword())) {
1818 import java.security.KeyStoreException;
1919 import java.security.NoSuchAlgorithmException;
2020 import java.util.Arrays;
21 import java.util.Objects;
2221
2322 import javax.net.ssl.TrustManagerFactory;
2423
177176 return false;
178177 }
179178 final TrustStoreConfiguration other = (TrustStoreConfiguration) obj;
180 if (!Objects.equals(trustManagerFactoryAlgorithm, other.trustManagerFactoryAlgorithm)) {
179 if (trustManagerFactoryAlgorithm == null) {
180 if (other.trustManagerFactoryAlgorithm != null) {
181 return false;
182 }
183 } else if (!trustManagerFactoryAlgorithm.equals(other.trustManagerFactoryAlgorithm)) {
181184 return false;
182185 }
183186 return true;
1616
1717 package org.apache.logging.log4j.core.osgi;
1818
19 import java.util.Collection;
2019 import java.util.Hashtable;
2120 import java.util.concurrent.atomic.AtomicReference;
2221
2423 import org.apache.logging.log4j.Logger;
2524 import org.apache.logging.log4j.core.config.plugins.util.PluginRegistry;
2625 import org.apache.logging.log4j.core.impl.Log4jProvider;
27 import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
28 import org.apache.logging.log4j.core.impl.ThreadContextDataProvider;
2926 import org.apache.logging.log4j.core.util.Constants;
30 import org.apache.logging.log4j.core.util.ContextDataProvider;
3127 import org.apache.logging.log4j.spi.Provider;
3228 import org.apache.logging.log4j.status.StatusLogger;
3329 import org.apache.logging.log4j.util.PropertiesUtil;
3531 import org.osgi.framework.BundleActivator;
3632 import org.osgi.framework.BundleContext;
3733 import org.osgi.framework.BundleEvent;
38 import org.osgi.framework.InvalidSyntaxException;
39 import org.osgi.framework.ServiceReference;
4034 import org.osgi.framework.ServiceRegistration;
4135 import org.osgi.framework.SynchronousBundleListener;
4236 import org.osgi.framework.wiring.BundleWiring;
5145 private final AtomicReference<BundleContext> contextRef = new AtomicReference<>();
5246
5347 ServiceRegistration provideRegistration = null;
54 ServiceRegistration contextDataRegistration = null;
5548
5649 @Override
5750 public void start(final BundleContext context) throws Exception {
5851 final Provider provider = new Log4jProvider();
5952 final Hashtable<String, String> props = new Hashtable<>();
6053 props.put("APIVersion", "2.60");
61 final ContextDataProvider threadContextProvider = new ThreadContextDataProvider();
6254 provideRegistration = context.registerService(Provider.class.getName(), provider, props);
63 contextDataRegistration = context.registerService(ContextDataProvider.class.getName(), threadContextProvider,
64 null);
65 loadContextProviders(context);
6655 // allow the user to override the default ContextSelector (e.g., by using BasicContextSelector for a global cfg)
6756 if (PropertiesUtil.getProperties().getStringProperty(Constants.LOG4J_CONTEXT_SELECTOR) == null) {
6857 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, BundleContextSelector.class.getName());
9281 }
9382 }
9483
95 private static void loadContextProviders(final BundleContext bundleContext) {
96 try {
97 final Collection<ServiceReference<ContextDataProvider>> serviceReferences =
98 bundleContext.getServiceReferences(ContextDataProvider.class, null);
99 for (final ServiceReference<ContextDataProvider> serviceReference : serviceReferences) {
100 final ContextDataProvider provider = bundleContext.getService(serviceReference);
101 ThreadContextDataInjector.contextDataProviders.add(provider);
102 }
103 } catch (final InvalidSyntaxException ex) {
104 LOGGER.error("Error accessing context data provider", ex);
105 }
106 }
107
10884 private static void stopBundlePlugins(final Bundle bundle) {
10985 LOGGER.trace("Stopping bundle [{}] plugins.", bundle.getSymbolicName());
11086 // TODO: plugin lifecycle code
11490 @Override
11591 public void stop(final BundleContext context) throws Exception {
11692 provideRegistration.unregister();
117 contextDataRegistration.unregister();
11893 this.contextRef.compareAndSet(context, null);
11994 LogManager.shutdown();
12095 }
1818 import java.lang.ref.WeakReference;
1919 import java.net.URI;
2020 import java.util.Objects;
21 import java.util.concurrent.TimeUnit;
2221 import java.util.concurrent.atomic.AtomicReference;
2322
2423 import org.apache.logging.log4j.core.LoggerContext;
3938 public class BundleContextSelector extends ClassLoaderContextSelector {
4039
4140 @Override
42 public void shutdown(final String fqcn, final ClassLoader loader, final boolean currentContext,
43 final boolean allContexts) {
44 LoggerContext ctx = null;
45 Bundle bundle = null;
46 if (currentContext) {
47 ctx = ContextAnchor.THREAD_CONTEXT.get();
48 ContextAnchor.THREAD_CONTEXT.remove();
49 }
50 if (ctx == null && loader instanceof BundleReference) {
51 bundle = ((BundleReference) loader).getBundle();
52 ctx = getLoggerContext(bundle);
53 removeLoggerContext(ctx);
54 }
55 if (ctx == null) {
56 final Class<?> callerClass = StackLocatorUtil.getCallerClass(fqcn);
57 if (callerClass != null) {
58 bundle = FrameworkUtil.getBundle(callerClass);
59 ctx = getLoggerContext(FrameworkUtil.getBundle(callerClass));
60 removeLoggerContext(ctx);
61 }
62 }
63 if (ctx == null) {
64 ctx = ContextAnchor.THREAD_CONTEXT.get();
65 ContextAnchor.THREAD_CONTEXT.remove();
66 }
67 if (ctx != null) {
68 ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
69 }
70 if (bundle != null && allContexts) {
71 final Bundle[] bundles = bundle.getBundleContext().getBundles();
72 for (final Bundle bdl : bundles) {
73 ctx = getLoggerContext(bdl);
74 if (ctx != null) {
75 ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
76 }
77 }
78 }
79 }
80 private LoggerContext getLoggerContext(final Bundle bundle) {
81 final String name = Objects.requireNonNull(bundle, "No Bundle provided").getSymbolicName();
82 final AtomicReference<WeakReference<LoggerContext>> ref = CONTEXT_MAP.get(name);
83 if (ref != null && ref.get() != null) {
84 return ref.get().get();
85 }
86 return null;
87 }
88
89 private void removeLoggerContext(LoggerContext context) {
90 CONTEXT_MAP.remove(context.getName());
91 }
92
93 @Override
94 public boolean hasContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
95 if (currentContext && ContextAnchor.THREAD_CONTEXT.get() != null) {
96 return ContextAnchor.THREAD_CONTEXT.get().isStarted();
97 }
98 if (loader instanceof BundleReference) {
99 return hasContext(((BundleReference) loader).getBundle());
100 }
101 final Class<?> callerClass = StackLocatorUtil.getCallerClass(fqcn);
102 if (callerClass != null) {
103 return hasContext(FrameworkUtil.getBundle(callerClass));
104 }
105 return ContextAnchor.THREAD_CONTEXT.get() != null && ContextAnchor.THREAD_CONTEXT.get().isStarted();
106 }
107 @Override
10841 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
10942 final URI configLocation) {
11043 if (currentContext) {
12457 }
12558 final LoggerContext lc = ContextAnchor.THREAD_CONTEXT.get();
12659 return lc == null ? getDefault() : lc;
127 }
128
129 private static boolean hasContext(final Bundle bundle) {
130 final String name = Objects.requireNonNull(bundle, "No Bundle provided").getSymbolicName();
131 final AtomicReference<WeakReference<LoggerContext>> ref = CONTEXT_MAP.get(name);
132 return ref != null && ref.get() != null && ref.get().get() != null && ref.get().get().isStarted();
13360 }
13461
13562 private static LoggerContext locateContext(final Bundle bundle, final URI configLocation) {
330330 try {
331331 final Constructor<T> constructor = asnConverterClass.getConstructor(List.class, String.class);
332332 return constructor.newInstance(formatters, AnsiEscape.createSequence(name));
333 } catch (final SecurityException | NoSuchMethodException | IllegalArgumentException | InstantiationException |
334 IllegalAccessException | InvocationTargetException e) {
333 } catch (final SecurityException e) {
334 LOGGER.error(e.toString(), e);
335 } catch (final NoSuchMethodException e) {
336 LOGGER.error(e.toString(), e);
337 } catch (final IllegalArgumentException e) {
338 LOGGER.error(e.toString(), e);
339 } catch (final InstantiationException e) {
340 LOGGER.error(e.toString(), e);
341 } catch (final IllegalAccessException e) {
342 LOGGER.error(e.toString(), e);
343 } catch (final InvocationTargetException e) {
335344 LOGGER.error(e.toString(), e);
336345 }
337346 return null;
2222
2323 import org.apache.logging.log4j.core.util.Patterns;
2424 import org.apache.logging.log4j.util.EnglishEnums;
25 import org.apache.logging.log4j.util.Strings;
2625
2726 /**
2827 * Converts text into ANSI escape sequences.
289288 * @return a new map
290289 */
291290 public static Map<String, String> createMap(final String[] values, final String[] dontEscapeKeys) {
292 final String[] sortedIgnoreKeys = dontEscapeKeys != null ? dontEscapeKeys.clone() : Strings.EMPTY_ARRAY;
291 final String[] sortedIgnoreKeys = dontEscapeKeys != null ? dontEscapeKeys.clone() : new String[0];
293292 Arrays.sort(sortedIgnoreKeys);
294293 final Map<String, String> map = new HashMap<>();
295294 for (final String string : values) {
103103 void formatToBuffer(final Instant instant, final StringBuilder destination) {
104104 final long epochSecond = instant.getEpochSecond();
105105 final int nanoOfSecond = instant.getNanoOfSecond();
106 if (!fixedDateFormat.isEquivalent(previousTime, nanos, epochSecond, nanoOfSecond)) {
106 if (previousTime != epochSecond || nanos != nanoOfSecond) {
107107 length = fixedDateFormat.formatInstant(instant, cachedBuffer, 0);
108108 previousTime = epochSecond;
109109 nanos = nanoOfSecond;
1616 package org.apache.logging.log4j.core.pattern;
1717
1818 import java.util.List;
19 import java.util.function.Function;
20 import java.util.stream.Stream;
2119
2220 import org.apache.logging.log4j.core.LogEvent;
2321 import org.apache.logging.log4j.core.config.Configuration;
5048 super("encode", "encode");
5149 this.formatters = formatters;
5250 this.escapeFormat = escapeFormat;
53 }
54
55 @Override
56 public boolean handlesThrowable() {
57 return formatters != null && formatters.stream()
58 .map(PatternFormatter::getConverter)
59 .anyMatch(LogEventPatternConverter::handlesThrowable);
6051 }
6152
6253 /**
9990 HTML {
10091 @Override
10192 void escape(final StringBuilder toAppendTo, final int start) {
102
103 // do this in two passes to keep O(n) time complexity
104
105 final int origLength = toAppendTo.length();
106 int firstSpecialChar = origLength;
107
108 for (int i = origLength - 1; i >= start; i--) {
93 for (int i = toAppendTo.length() - 1; i >= start; i--) { // backwards: length may change
10994 final char c = toAppendTo.charAt(i);
110 final String escaped = escapeChar(c);
111 if (escaped != null) {
112 firstSpecialChar = i;
113 for (int j = 0; j < escaped.length() - 1; j++) {
114 toAppendTo.append(' '); // make room for the escape sequence
115 }
95 switch (c) {
96 case '\r':
97 toAppendTo.setCharAt(i, '\\');
98 toAppendTo.insert(i + 1, 'r');
99 break;
100 case '\n':
101 toAppendTo.setCharAt(i, '\\');
102 toAppendTo.insert(i + 1, 'n');
103 break;
104 case '&':
105 toAppendTo.setCharAt(i, '&');
106 toAppendTo.insert(i + 1, "amp;");
107 break;
108 case '<':
109 toAppendTo.setCharAt(i, '&');
110 toAppendTo.insert(i + 1, "lt;");
111 break;
112 case '>':
113 toAppendTo.setCharAt(i, '&');
114 toAppendTo.insert(i + 1, "gt;");
115 break;
116 case '"':
117 toAppendTo.setCharAt(i, '&');
118 toAppendTo.insert(i + 1, "quot;");
119 break;
120 case '\'':
121 toAppendTo.setCharAt(i, '&');
122 toAppendTo.insert(i + 1, "apos;");
123 break;
124 case '/':
125 toAppendTo.setCharAt(i, '&');
126 toAppendTo.insert(i + 1, "#x2F;");
127 break;
116128 }
117 }
118
119 for (int i = origLength - 1, j = toAppendTo.length(); i >= firstSpecialChar; i--) {
120 final char c = toAppendTo.charAt(i);
121 final String escaped = escapeChar(c);
122 if (escaped == null) {
123 toAppendTo.setCharAt(--j, c);
124 } else {
125 toAppendTo.replace(j - escaped.length(), j, escaped);
126 j -= escaped.length();
127 }
128 }
129 }
130
131 private String escapeChar(char c) {
132 switch (c) {
133 case '\r':
134 return "\\r";
135 case '\n':
136 return "\\n";
137 case '&':
138 return "&amp;";
139 case '<':
140 return "&lt;";
141 case '>':
142 return "&gt;";
143 case '"':
144 return "&quot;";
145 case '\'':
146 return "&apos;";
147 case '/':
148 return "&#x2F;";
149 default:
150 return null;
151129 }
152130 }
153131 },
167145 CRLF {
168146 @Override
169147 void escape(final StringBuilder toAppendTo, final int start) {
170
171 // do this in two passes to keep O(n) time complexity
172
173 final int origLength = toAppendTo.length();
174 int firstSpecialChar = origLength;
175
176 for (int i = origLength - 1; i >= start; i--) {
177 final char c = toAppendTo.charAt(i);
178 if (c == '\r' || c == '\n') {
179 firstSpecialChar = i;
180 toAppendTo.append(' '); // make room for the escape sequence
181 }
182 }
183
184 for (int i = origLength - 1, j = toAppendTo.length(); i >= firstSpecialChar; i--) {
148 for (int i = toAppendTo.length() - 1; i >= start; i--) { // backwards: length may change
185149 final char c = toAppendTo.charAt(i);
186150 switch (c) {
187151 case '\r':
188 toAppendTo.setCharAt(--j, 'r');
189 toAppendTo.setCharAt(--j, '\\');
152 toAppendTo.setCharAt(i, '\\');
153 toAppendTo.insert(i + 1, 'r');
190154 break;
191155 case '\n':
192 toAppendTo.setCharAt(--j, 'n');
193 toAppendTo.setCharAt(--j, '\\');
156 toAppendTo.setCharAt(i, '\\');
157 toAppendTo.insert(i + 1, 'n');
194158 break;
195 default:
196 toAppendTo.setCharAt(--j, c);
197159 }
198160 }
199161 }
3131 @Plugin(name = "LevelPatternConverter", category = PatternConverter.CATEGORY)
3232 @ConverterKeys({ "p", "level" })
3333 @PerformanceSensitive("allocation")
34 public class LevelPatternConverter extends LogEventPatternConverter {
34 public final class LevelPatternConverter extends LogEventPatternConverter {
3535 private static final String OPTION_LENGTH = "length";
3636 private static final String OPTION_LOWER = "lowerCase";
3737
3838 /**
3939 * Singleton.
4040 */
41 private static final LevelPatternConverter INSTANCE = new SimpleLevelPatternConverter();
41 private static final LevelPatternConverter INSTANCE = new LevelPatternConverter(null);
42
43 private final Map<Level, String> levelMap;
4244
4345 /**
4446 * Private constructor.
4547 */
46 private LevelPatternConverter() {
48 private LevelPatternConverter(final Map<Level, String> map) {
4749 super("Level", "level");
50 this.levelMap = map;
4851 }
4952
5053 /**
9396 levelMap.put(level, lowerCase ? left.toLowerCase(Locale.US) : left);
9497 }
9598 }
96 return new LevelMapLevelPatternConverter(levelMap);
99 return new LevelPatternConverter(levelMap);
97100 }
98101
99102 /**
119122 */
120123 @Override
121124 public void format(final LogEvent event, final StringBuilder output) {
122 throw new UnsupportedOperationException("Overridden by subclasses");
125 output.append(levelMap == null ? event.getLevel().toString() : levelMap.get(event.getLevel()));
123126 }
124127
125128 /**
133136
134137 return "level";
135138 }
136
137 private static final class SimpleLevelPatternConverter extends LevelPatternConverter {
138
139 /**
140 * {@inheritDoc}
141 */
142 @Override
143 public void format(final LogEvent event, final StringBuilder output) {
144 output.append(event.getLevel());
145 }
146 }
147
148 private static final class LevelMapLevelPatternConverter extends LevelPatternConverter {
149
150 private final Map<Level, String> levelMap;
151
152 private LevelMapLevelPatternConverter(final Map<Level, String> levelMap) {
153 this.levelMap = levelMap;
154 }
155
156 /**
157 * {@inheritDoc}
158 */
159 @Override
160 public void format(final LogEvent event, final StringBuilder output) {
161 output.append(levelMap.get(event.getLevel()));
162 }
163 }
164139 }
3434 private static final LineSeparatorPatternConverter INSTANCE = new LineSeparatorPatternConverter();
3535
3636 /**
37 * Line separator.
38 */
39 private final String lineSep;
40
41 /**
3742 * Private constructor.
3843 */
3944 private LineSeparatorPatternConverter() {
4045 super("Line Sep", "lineSep");
46 lineSep = Strings.LINE_SEPARATOR;
4147 }
4248
4349 /**
5561 * {@inheritDoc}
5662 */
5763 @Override
58 public void format(final LogEvent ignored, final StringBuilder toAppendTo) {
59 toAppendTo.append(Strings.LINE_SEPARATOR);
60 }
61
62 /**
63 * {@inheritDoc}
64 */
65 @Override
66 public void format(final Object ignored, final StringBuilder output) {
67 output.append(Strings.LINE_SEPARATOR);
68 }
69
70 @Override
71 public boolean isVariable() {
72 return false;
64 public void format(final LogEvent event, final StringBuilder toAppendTo) {
65 toAppendTo.append(lineSep);
7366 }
7467 }
4848 super("Literal", "literal");
4949 this.literal = convertBackslashes ? OptionConverter.convertSpecialChars(literal) : literal; // LOG4J2-829
5050 this.config = config;
51 substitute = config != null && containsSubstitutionSequence(literal);
52 }
53
54 static boolean containsSubstitutionSequence(final String literal) {
55 return literal != null && literal.contains("${");
51 substitute = config != null && literal.contains("${");
5652 }
5753
5854 /**
7777 return new MdcPatternConverter(options);
7878 }
7979
80 private static final TriConsumer<String, Object, StringBuilder> WRITE_KEY_VALUES_INTO = (key, value, sb) -> {
81 sb.append(key).append('=');
82 StringBuilders.appendValue(sb, value);
83 sb.append(", ");
80 private static final TriConsumer<String, Object, StringBuilder> WRITE_KEY_VALUES_INTO = new TriConsumer<String, Object, StringBuilder>() {
81 @Override
82 public void accept(final String key, final Object value, final StringBuilder sb) {
83 sb.append(key).append('=');
84 StringBuilders.appendValue(sb, value);
85 sb.append(", ");
86 }
8487 };
8588
8689 /**
9295 // if there is no additional options, we output every single
9396 // Key/Value pair for the MDC in a similar format to Hashtable.toString()
9497 if (full) {
95 if (contextData == null || contextData.isEmpty()) {
98 if (contextData == null || contextData.size() == 0) {
9699 toAppendTo.append("{}");
97100 return;
98101 }
99102 appendFully(contextData, toAppendTo);
100 } else if (keys != null) {
101 if (contextData == null || contextData.isEmpty()) {
102 toAppendTo.append("{}");
103 return;
104 }
105 appendSelectedKeys(keys, contextData, toAppendTo);
106 } else if (contextData != null){
107 // otherwise they just want a single key output
108 final Object value = contextData.getValue(key);
109 if (value != null) {
110 StringBuilders.appendValue(toAppendTo, value);
103 } else {
104 if (keys != null) {
105 if (contextData == null || contextData.size() == 0) {
106 toAppendTo.append("{}");
107 return;
108 }
109 appendSelectedKeys(keys, contextData, toAppendTo);
110 } else if (contextData != null){
111 // otherwise they just want a single key output
112 final Object value = contextData.getValue(key);
113 if (value != null) {
114 StringBuilders.appendValue(toAppendTo, value);
115 }
111116 }
112117 }
113118 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import java.util.ArrayList;
19 import java.util.List;
2018 import java.util.Locale;
2119
22 import org.apache.logging.log4j.Logger;
2320 import org.apache.logging.log4j.core.LogEvent;
2421 import org.apache.logging.log4j.core.config.Configuration;
2522 import org.apache.logging.log4j.core.config.plugins.Plugin;
23 import org.apache.logging.log4j.core.util.ArrayUtils;
24 import org.apache.logging.log4j.core.util.Constants;
2625 import org.apache.logging.log4j.core.util.Loader;
2726 import org.apache.logging.log4j.message.Message;
2827 import org.apache.logging.log4j.message.MultiformatMessage;
3736 @Plugin(name = "MessagePatternConverter", category = PatternConverter.CATEGORY)
3837 @ConverterKeys({ "m", "msg", "message" })
3938 @PerformanceSensitive("allocation")
40 public class MessagePatternConverter extends LogEventPatternConverter {
41
42 private static final String LOOKUPS = "lookups";
39 public final class MessagePatternConverter extends LogEventPatternConverter {
40
4341 private static final String NOLOOKUPS = "nolookups";
4442
45 private MessagePatternConverter() {
43 private final String[] formats;
44 private final Configuration config;
45 private final TextRenderer textRenderer;
46
47 /**
48 * Private constructor.
49 *
50 * @param options
51 * options, may be null.
52 */
53 private MessagePatternConverter(final Configuration config, final String[] options) {
4654 super("Message", "message");
55 this.formats = options;
56 this.config = config;
57 final int noLookupsIdx = loadNoLookups(options);
58 this.textRenderer = loadMessageRenderer(noLookupsIdx >= 0 ? ArrayUtils.remove(options, noLookupsIdx) : options);
4759 }
4860
49 private static TextRenderer loadMessageRenderer(final String[] options) {
61 private int loadNoLookups(final String[] options) {
62 if (options != null) {
63 for (int i = 0; i < options.length; i++) {
64 final String option = options[i];
65 if (NOLOOKUPS.equalsIgnoreCase(option)) {
66 return i;
67 }
68 }
69 }
70 return -1;
71 }
72
73 private TextRenderer loadMessageRenderer(final String[] options) {
5074 if (options != null) {
5175 for (final String option : options) {
5276 switch (option.toUpperCase(Locale.ROOT)) {
7599 * @return instance of pattern converter.
76100 */
77101 public static MessagePatternConverter newInstance(final Configuration config, final String[] options) {
78 String[] formats = withoutLookupOptions(options);
79 TextRenderer textRenderer = loadMessageRenderer(formats);
80 MessagePatternConverter result = formats == null || formats.length == 0
81 ? SimpleMessagePatternConverter.INSTANCE
82 : new FormattedMessagePatternConverter(formats);
83 if (textRenderer != null) {
84 result = new RenderingPatternConverter(result, textRenderer);
85 }
86 return result;
102 return new MessagePatternConverter(config, options);
87103 }
88104
89 private static String[] withoutLookupOptions(final String[] options) {
90 if (options == null || options.length == 0) {
91 return options;
92 }
93 List<String> results = new ArrayList<>(options.length);
94 for (String option : options) {
95 if (LOOKUPS.equalsIgnoreCase(option) || NOLOOKUPS.equalsIgnoreCase(option)) {
96 LOGGER.info("The {} option will be ignored. Message Lookups are no longer supported.", option);
97 } else {
98 results.add(option);
99 }
100 }
101 return results.toArray(new String[0]);
102 }
103
105 /**
106 * {@inheritDoc}
107 */
104108 @Override
105109 public void format(final LogEvent event, final StringBuilder toAppendTo) {
106 throw new UnsupportedOperationException();
107 }
110 final Message msg = event.getMessage();
111 if (msg instanceof StringBuilderFormattable) {
108112
109 private static final class SimpleMessagePatternConverter extends MessagePatternConverter {
110 private static final MessagePatternConverter INSTANCE = new SimpleMessagePatternConverter();
113 final boolean doRender = textRenderer != null;
114 final StringBuilder workingBuilder = doRender ? new StringBuilder(80) : toAppendTo;
111115
112 /**
113 * {@inheritDoc}
114 */
115 @Override
116 public void format(final LogEvent event, final StringBuilder toAppendTo) {
117 Message msg = event.getMessage();
118 if (msg instanceof StringBuilderFormattable) {
119 ((StringBuilderFormattable) msg).formatTo(toAppendTo);
120 } else if (msg != null) {
121 toAppendTo.append(msg.getFormattedMessage());
116 if (msg instanceof MultiFormatStringBuilderFormattable) {
117 ((MultiFormatStringBuilderFormattable) msg).formatTo(formats, workingBuilder);
118 } else {
119 ((StringBuilderFormattable) msg).formatTo(workingBuilder);
120 }
121
122 if (doRender) {
123 textRenderer.render(workingBuilder, toAppendTo);
124 }
125 return;
126 }
127 if (msg != null) {
128 String result;
129 if (msg instanceof MultiformatMessage) {
130 result = ((MultiformatMessage) msg).getFormattedMessage(formats);
131 } else {
132 result = msg.getFormattedMessage();
133 }
134 if (result != null) {
135 toAppendTo.append(result);
136 } else {
137 toAppendTo.append("null");
122138 }
123139 }
124140 }
125
126 private static final class FormattedMessagePatternConverter extends MessagePatternConverter {
127
128 private final String[] formats;
129
130 FormattedMessagePatternConverter(final String[] formats) {
131 this.formats = formats;
132 }
133
134 /**
135 * {@inheritDoc}
136 */
137 @Override
138 public void format(final LogEvent event, final StringBuilder toAppendTo) {
139 Message msg = event.getMessage();
140 if (msg instanceof StringBuilderFormattable) {
141 if (msg instanceof MultiFormatStringBuilderFormattable) {
142 ((MultiFormatStringBuilderFormattable) msg).formatTo(formats, toAppendTo);
143 } else {
144 ((StringBuilderFormattable) msg).formatTo(toAppendTo);
145 }
146 } else if (msg != null) {
147 toAppendTo.append(msg instanceof MultiformatMessage
148 ? ((MultiformatMessage) msg).getFormattedMessage(formats)
149 : msg.getFormattedMessage());
150 }
151 }
152 }
153
154 private static final class RenderingPatternConverter extends MessagePatternConverter {
155
156 private final MessagePatternConverter delegate;
157 private final TextRenderer textRenderer;
158
159 RenderingPatternConverter(final MessagePatternConverter delegate, final TextRenderer textRenderer) {
160 this.delegate = delegate;
161 this.textRenderer = textRenderer;
162 }
163
164 /**
165 * {@inheritDoc}
166 */
167 @Override
168 public void format(final LogEvent event, final StringBuilder toAppendTo) {
169 StringBuilder workingBuilder = new StringBuilder(80);
170 delegate.format(event, workingBuilder);
171 textRenderer.render(workingBuilder, toAppendTo);
172 }
173
174 }
175141 }
9292 if (trimmed.charAt(pos) == '*') {
9393 charCount = Integer.MAX_VALUE;
9494 ellipsisPos++;
95 } else if (trimmed.charAt(pos) >= '0' && trimmed.charAt(pos) <= '9') {
96 charCount = trimmed.charAt(pos) - '0';
97 ellipsisPos++;
9895 } else {
99 charCount = 0;
96 if (trimmed.charAt(pos) >= '0' && trimmed.charAt(pos) <= '9') {
97 charCount = trimmed.charAt(pos) - '0';
98 ellipsisPos++;
99 } else {
100 charCount = 0;
101 }
100102 }
101103
102104 ellipsis = '\0';
256258 /**
257259 * Fragment of an pattern abbreviator.
258260 */
259 private static final class PatternAbbreviatorFragment {
261 private static class PatternAbbreviatorFragment {
260262 /**
261263 * Count of initial characters of element to output.
262264 */
275277 * @param ellipsis character to represent elimination of characters,
276278 * '\0' if no ellipsis is desired.
277279 */
278 PatternAbbreviatorFragment(
280 public PatternAbbreviatorFragment(
279281 final int charCount, final char ellipsis) {
280282 this.charCount = charCount;
281283 this.ellipsis = ellipsis;
284286 /**
285287 * Abbreviate element of name.
286288 *
287 * @param input input string which is being written to the output {@code buf}.
288 * @param inputIndex starting index of name element in the {@code input} string.
289 * @param buf buffer to receive element.
290 * @return starting index of next element.
291 */
292 int abbreviate(final String input, final int inputIndex, final StringBuilder buf) {
293 // Note that indexOf(char) performs worse than indexOf(String) on pre-16 JREs
294 // due to missing intrinsics for the character implementation. The difference
295 // is a few nanoseconds in most cases, so we opt to give the jre as much
296 // information as possible for best performance on new runtimes, with the
297 // possibility that such optimizations may be back-ported.
298 // See https://bugs.openjdk.java.net/browse/JDK-8173585
299 int nextDot = input.indexOf('.', inputIndex);
300 if (nextDot < 0) {
301 buf.append(input, inputIndex, input.length());
302 return nextDot;
303 }
304 if (nextDot - inputIndex > charCount) {
305 buf.append(input, inputIndex, inputIndex + charCount);
306 if (ellipsis != '\0') {
307 buf.append(ellipsis);
308 }
309 buf.append('.');
310 } else {
311 // Include the period to reduce interactions with the buffer
312 buf.append(input, inputIndex, nextDot + 1);
313 }
314 return nextDot + 1;
289 * @param buf buffer to receive element.
290 * @param startPos starting index of name element.
291 * @return starting index of next element.
292 */
293 public int abbreviate(final StringBuilder buf, final int startPos) {
294 final int start = (startPos < 0) ? 0 : startPos;
295 final int max = buf.length();
296 int nextDot = -1;
297 for (int i = start; i < max; i++) {
298 if (buf.charAt(i) == '.') {
299 nextDot = i;
300 break;
301 }
302 }
303 if (nextDot != -1) {
304 if (nextDot - startPos > charCount) {
305 buf.delete(startPos + charCount, nextDot);
306 nextDot = startPos + charCount;
307
308 if (ellipsis != '\0') {
309 buf.insert(nextDot, ellipsis);
310 nextDot++;
311 }
312 }
313 nextDot++;
314 }
315 return nextDot;
315316 }
316317 }
317318
318319 /**
319320 * Pattern abbreviator.
320321 */
321 private static final class PatternAbbreviator extends NameAbbreviator {
322 private static class PatternAbbreviator extends NameAbbreviator {
322323 /**
323324 * Element abbreviation patterns.
324325 */
329330 *
330331 * @param fragments element abbreviation patterns.
331332 */
332 PatternAbbreviator(final List<PatternAbbreviatorFragment> fragments) {
333 public PatternAbbreviator(final List<PatternAbbreviatorFragment> fragments) {
333334 if (fragments.isEmpty()) {
334335 throw new IllegalArgumentException(
335336 "fragments must have at least one element");
336337 }
337338
338 this.fragments = fragments.toArray(new PatternAbbreviatorFragment[0]);
339 this.fragments = new PatternAbbreviatorFragment[fragments.size()];
340 fragments.toArray(this.fragments);
339341 }
340342
341343 /**
346348 */
347349 @Override
348350 public void abbreviate(final String original, final StringBuilder destination) {
349 // non-terminal patterns are executed once
350 int originalIndex = 0;
351 int iteration = 0;
352 int originalLength = original.length();
353 while (originalIndex >= 0 && originalIndex < originalLength) {
354 originalIndex = fragment(iteration++).abbreviate(original, originalIndex, destination);
355 }
356 }
357
358 PatternAbbreviatorFragment fragment(int index) {
359 return fragments[Math.min(index, fragments.length - 1)];
351 //
352 // all non-terminal patterns are executed once
353 //
354 int pos = destination.length();
355 final int max = pos + original.length();
356
357 destination.append(original);
358
359 int fragmentIndex = 0;
360 while (pos < max && pos >= 0) {
361 pos = fragments[fragmentIndex].abbreviate(destination, pos);
362 // last pattern in executed repeatedly
363 if (fragmentIndex < fragments.length - 1) {
364 fragmentIndex++;
365 }
366 }
360367 }
361368 }
362369 }
2222 *
2323 */
2424 public class PatternFormatter {
25
26 /**
27 * The empty array.
28 */
29 public static final PatternFormatter[] EMPTY_ARRAY = {};
30
3125 private final LogEventPatternConverter converter;
3226 private final FormattingInfo field;
3327 private final boolean skipFormattingInfo;
191191 pc = (LogEventPatternConverter) converter;
192192 handlesThrowable |= pc.handlesThrowable();
193193 } else {
194 pc = SimpleLiteralPatternConverter.of(Strings.EMPTY);
194 pc = new LiteralPatternConverter(config, Strings.EMPTY, true);
195195 }
196196
197197 FormattingInfo field;
375375 default:
376376
377377 if (currentLiteral.length() != 0) {
378 patternConverters.add(literalPattern(currentLiteral.toString(), convertBackslashes));
378 patternConverters.add(new LiteralPatternConverter(config, currentLiteral.toString(),
379 convertBackslashes));
379380 formattingInfos.add(FormattingInfo.getDefault());
380381 }
381382
492493
493494 // while
494495 if (currentLiteral.length() != 0) {
495 patternConverters.add(literalPattern(currentLiteral.toString(), convertBackslashes));
496 patternConverters.add(new LiteralPatternConverter(config, currentLiteral.toString(), convertBackslashes));
496497 formattingInfos.add(FormattingInfo.getDefault());
497498 }
498499 }
667668 msg.append("] starting at position ");
668669 }
669670
670 msg.append(i);
671 msg.append(Integer.toString(i));
671672 msg.append(" in conversion pattern.");
672673
673674 LOGGER.error(msg.toString());
674675
675 patternConverters.add(literalPattern(currentLiteral.toString(), convertBackslashes));
676 patternConverters.add(new LiteralPatternConverter(config, currentLiteral.toString(), convertBackslashes));
676677 formattingInfos.add(FormattingInfo.getDefault());
677678 } else {
678679 patternConverters.add(pc);
680681
681682 if (currentLiteral.length() > 0) {
682683 patternConverters
683 .add(literalPattern(currentLiteral.toString(), convertBackslashes));
684 .add(new LiteralPatternConverter(config, currentLiteral.toString(), convertBackslashes));
684685 formattingInfos.add(FormattingInfo.getDefault());
685686 }
686687 }
689690
690691 return i;
691692 }
692
693 // Create a literal pattern converter with support for substitutions if necessary
694 private LogEventPatternConverter literalPattern(String literal, boolean convertBackslashes) {
695 if (config != null && LiteralPatternConverter.containsSubstitutionSequence(literal)) {
696 return new LiteralPatternConverter(config, literal, convertBackslashes);
697 }
698 return SimpleLiteralPatternConverter.of(literal, convertBackslashes);
699 }
700693 }
+0
-103
log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/RepeatPatternConverter.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.logging.log4j.core.pattern;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.Configuration;
20 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.util.PerformanceSensitive;
22 import org.apache.logging.log4j.util.Strings;
23
24 /**
25 * Equals pattern converter.
26 */
27 @Plugin(name = "repeat", category = PatternConverter.CATEGORY)
28 @ConverterKeys({ ":|","repeat" })
29 @PerformanceSensitive("allocation")
30 public final class RepeatPatternConverter extends LogEventPatternConverter {
31
32 private final String result;
33
34 /**
35 * Gets an instance of the class.
36 *
37 * @param config The current Configuration.
38 * @param options pattern options, an array of two elements: repeatString and count.
39 * @return instance of class.
40 */
41 public static RepeatPatternConverter newInstance(final Configuration config, final String[] options) {
42 if (options.length != 2) {
43 LOGGER.error("Incorrect number of options on repeat. Expected 2 received " + options.length);
44 return null;
45 }
46 if (options[0] == null) {
47 LOGGER.error("No string supplied on repeat");
48 return null;
49 }
50 if (options[1] == null) {
51 LOGGER.error("No repeat count supplied on repeat");
52 return null;
53 }
54 int count = 0;
55 String result = options[0];
56 try {
57 count = Integer.parseInt(options[1].trim());
58 result = Strings.repeat(options[0], count);
59 } catch (Exception ex) {
60 LOGGER.error("The repeat count is not an integer: {}", options[1].trim());
61 }
62
63 return new RepeatPatternConverter(result);
64 }
65
66 /**
67 * Construct the converter.
68 *
69 * @param result The repeated String
70
71 */
72 private RepeatPatternConverter(final String result) {
73 super("repeat", "repeat");
74 this.result = result;
75 }
76
77 /**
78 * Adds the repeated String to the buffer.
79 *
80 * @param obj event to format, may not be null.
81 * @param toAppendTo string buffer to which the formatted event will be appended. May not be null.
82 */
83 public void format(final Object obj, final StringBuilder toAppendTo) {
84 format(toAppendTo);
85 }
86
87 /**
88 * Adds the repeated String to the buffer.
89 *
90 * @param event event to format, may not be null.
91 * @param toAppendTo string buffer to which the formatted event will be appended. May not be null.
92 */
93 public void format(final LogEvent event, final StringBuilder toAppendTo) {
94 format(toAppendTo);
95 }
96
97 private void format(final StringBuilder toAppendTo) {
98 if (result != null) {
99 toAppendTo.append(result);
100 }
101 }
102 }
+0
-118
log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/SimpleLiteralPatternConverter.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.logging.log4j.core.pattern;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.util.OptionConverter;
20 import org.apache.logging.log4j.util.PerformanceSensitive;
21
22
23 /**
24 * Formats a string literal without substitution.
25 *
26 * This is an effectively-sealed internal type.
27 */
28 @PerformanceSensitive("allocation")
29 abstract class SimpleLiteralPatternConverter extends LogEventPatternConverter implements ArrayPatternConverter {
30
31 private SimpleLiteralPatternConverter() {
32 super("SimpleLiteral", "literal");
33 }
34
35 static LogEventPatternConverter of(final String literal, final boolean convertBackslashes) {
36 String value = convertBackslashes ? OptionConverter.convertSpecialChars(literal) : literal;
37 return of(value);
38 }
39
40 static LogEventPatternConverter of(final String literal) {
41 if (literal == null || literal.isEmpty()) {
42 return Noop.INSTANCE;
43 }
44 if (" ".equals(literal)) {
45 return Space.INSTANCE;
46 }
47 return new StringValue(literal);
48 }
49
50 /**
51 * {@inheritDoc}
52 */
53 @Override
54 public final void format(final LogEvent ignored, final StringBuilder output) {
55 format(output);
56 }
57
58 /**
59 * {@inheritDoc}
60 */
61 @Override
62 public final void format(final Object ignored, final StringBuilder output) {
63 format(output);
64 }
65
66 /**
67 * {@inheritDoc}
68 */
69 @Override
70 public final void format(final StringBuilder output, final Object... args) {
71 format(output);
72 }
73
74 abstract void format(final StringBuilder output);
75
76 @Override
77 public final boolean isVariable() {
78 return false;
79 }
80
81 @Override
82 public final boolean handlesThrowable() {
83 return false;
84 }
85
86 private static final class Noop extends SimpleLiteralPatternConverter {
87 private static final Noop INSTANCE = new Noop();
88
89 @Override
90 void format(final StringBuilder output) {
91 // no-op
92 }
93 }
94
95 private static final class Space extends SimpleLiteralPatternConverter {
96 private static final Space INSTANCE = new Space();
97
98 @Override
99 void format(final StringBuilder output) {
100 output.append(' ');
101 }
102 }
103
104 private static final class StringValue extends SimpleLiteralPatternConverter {
105
106 private final String literal;
107
108 StringValue(final String literal) {
109 this.literal = literal;
110 }
111
112 @Override
113 void format(final StringBuilder output) {
114 output.append(literal);
115 }
116 }
117 }
151151 public void fileModified(final File file) {
152152 final ScriptRunner runner = scriptRunners.get(file.toString());
153153 if (runner == null) {
154 logger.info("{} is not a running script", file.getName());
154 logger.info("{} is not a running script");
155155 return;
156156 }
157157 final ScriptEngine engine = runner.getScriptEngine();
167167 public Object execute(final String name, final Bindings bindings) {
168168 final ScriptRunner scriptRunner = scriptRunners.get(name);
169169 if (scriptRunner == null) {
170 logger.warn("No script named {} could be found", name);
170 logger.warn("No script named {} could be found");
171171 return null;
172172 }
173 return AccessController.doPrivileged((PrivilegedAction<Object>) () -> scriptRunner.execute(bindings));
173 return AccessController.doPrivileged(new PrivilegedAction<Object>() {
174 @Override
175 public Object run() {
176 return scriptRunner.execute(bindings);
177 }
178 });
174179 }
175180
176181 private interface ScriptRunner {
195200 CompiledScript compiled = null;
196201 if (scriptEngine instanceof Compilable) {
197202 logger.debug("Script {} is compilable", script.getName());
198 compiled = AccessController.doPrivileged((PrivilegedAction<CompiledScript>) () -> {
199 try {
200 return ((Compilable) scriptEngine).compile(script.getScriptText());
201 } catch (final Throwable ex) {
202 /*
203 * ScriptException is what really should be caught here. However, beanshell's ScriptEngine
204 * implements Compilable but then throws Error when the compile method is called!
205 */
206 logger.warn("Error compiling script", ex);
207 return null;
203 compiled = AccessController.doPrivileged(new PrivilegedAction<CompiledScript>() {
204 @Override
205 public CompiledScript run() {
206 try {
207 return ((Compilable) scriptEngine).compile(script.getScriptText());
208 } catch (final Throwable ex) {
209 /*
210 * ScriptException is what really should be caught here. However, beanshell's ScriptEngine
211 * implements Compilable but then throws Error when the compile method is called!
212 */
213 logger.warn("Error compiling script", ex);
214 return null;
215 }
208216 }
209217 });
210218 }
1919 import java.util.ArrayList;
2020 import java.util.Collections;
2121 import java.util.List;
22 import java.util.concurrent.TimeUnit;
2322
2423 import org.apache.logging.log4j.core.LoggerContext;
2524 import org.apache.logging.log4j.core.impl.ContextAnchor;
3231 private static final LoggerContext CONTEXT = new LoggerContext("Default");
3332
3433 @Override
35 public void shutdown(String fqcn, ClassLoader loader, boolean currentContext, boolean allContexts) {
36 LoggerContext ctx = getContext(fqcn, loader, currentContext);
37 if (ctx != null && ctx.isStarted()) {
38 ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
39 }
40 }
34 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
4135
42 @Override
43 public boolean hasContext(String fqcn, ClassLoader loader, boolean currentContext) {
44 LoggerContext ctx = getContext(fqcn, loader, currentContext);
45 return ctx != null && ctx.isStarted();
46 }
47
48 @Override
49 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
5036 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
5137 return ctx != null ? ctx : CONTEXT;
5238 }
7056 }
7157
7258 @Override
73 public boolean isClassLoaderDependent() {
74 return false;
75 }
76
77 @Override
7859 public List<LoggerContext> getLoggerContexts() {
7960 final List<LoggerContext> list = new ArrayList<>();
8061 list.add(CONTEXT);
2424 import java.util.Map;
2525 import java.util.concurrent.ConcurrentHashMap;
2626 import java.util.concurrent.ConcurrentMap;
27 import java.util.concurrent.TimeUnit;
2827 import java.util.concurrent.atomic.AtomicReference;
2928
3029 import org.apache.logging.log4j.core.LoggerContext;
5453 new ConcurrentHashMap<>();
5554
5655 @Override
57 public void shutdown(final String fqcn, final ClassLoader loader, final boolean currentContext,
58 final boolean allContexts) {
59 LoggerContext ctx = null;
60 if (currentContext) {
61 ctx = ContextAnchor.THREAD_CONTEXT.get();
62 } else if (loader != null) {
63 ctx = findContext(loader);
64 } else {
65 final Class<?> clazz = StackLocatorUtil.getCallerClass(fqcn);
66 if (clazz != null) {
67 ctx = findContext(clazz.getClassLoader());
68 }
69 if (ctx == null) {
70 ctx = ContextAnchor.THREAD_CONTEXT.get();
71 }
72 }
73 if (ctx != null) {
74 ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
75 }
76 }
77
78 @Override
7956 public void contextShutdown(org.apache.logging.log4j.spi.LoggerContext loggerContext) {
8057 if (loggerContext instanceof LoggerContext) {
8158 removeContext((LoggerContext) loggerContext);
8259 }
83 }
84
85 @Override
86 public boolean hasContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
87 LoggerContext ctx;
88 if (currentContext) {
89 ctx = ContextAnchor.THREAD_CONTEXT.get();
90 } else if (loader != null) {
91 ctx = findContext(loader);
92 } else {
93 final Class<?> clazz = StackLocatorUtil.getCallerClass(fqcn);
94 if (clazz != null) {
95 ctx = findContext(clazz.getClassLoader());
96 } else {
97 ctx = ContextAnchor.THREAD_CONTEXT.get();
98 }
99 }
100 return ctx != null && ctx.isStarted();
101 }
102
103 private LoggerContext findContext(ClassLoader loaderOrNull) {
104 final ClassLoader loader = loaderOrNull != null ? loaderOrNull : ClassLoader.getSystemClassLoader();
105 final String name = toContextMapKey(loader);
106 AtomicReference<WeakReference<LoggerContext>> ref = CONTEXT_MAP.get(name);
107 if (ref != null) {
108 final WeakReference<LoggerContext> weakRef = ref.get();
109 return weakRef.get();
110 }
111 return null;
11260 }
11361
11462 @Override
11967 @Override
12068 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
12169 final URI configLocation) {
122 return getContext(fqcn, loader, null, currentContext, configLocation);
123 }
124
125 @Override
126 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Map.Entry<String, Object> entry,
127 final boolean currentContext, final URI configLocation) {
12870 if (currentContext) {
12971 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
13072 if (ctx != null) {
13274 }
13375 return getDefault();
13476 } else if (loader != null) {
135 return locateContext(loader, entry, configLocation);
77 return locateContext(loader, configLocation);
13678 } else {
13779 final Class<?> clazz = StackLocatorUtil.getCallerClass(fqcn);
13880 if (clazz != null) {
139 return locateContext(clazz.getClassLoader(), entry, configLocation);
81 return locateContext(clazz.getClassLoader(), configLocation);
14082 }
14183 final LoggerContext lc = ContextAnchor.THREAD_CONTEXT.get();
14284 if (lc != null) {
15799 }
158100
159101 @Override
160 public boolean isClassLoaderDependent() {
161 // By definition the ClassLoaderContextSelector depends on the callers class loader.
162 return true;
163 }
164
165 @Override
166102 public List<LoggerContext> getLoggerContexts() {
167103 final List<LoggerContext> list = new ArrayList<>();
168104 final Collection<AtomicReference<WeakReference<LoggerContext>>> coll = CONTEXT_MAP.values();
175111 return Collections.unmodifiableList(list);
176112 }
177113
178 private LoggerContext locateContext(final ClassLoader loaderOrNull, final Map.Entry<String, Object> entry,
179 final URI configLocation) {
114 private LoggerContext locateContext(final ClassLoader loaderOrNull, final URI configLocation) {
180115 // LOG4J2-477: class loader may be null
181116 final ClassLoader loader = loaderOrNull != null ? loaderOrNull : ClassLoader.getSystemClassLoader();
182117 final String name = toContextMapKey(loader);
215150 }
216151 }
217152 LoggerContext ctx = createContext(name, configLocation);
218 if (entry != null) {
219 ctx.putObject(entry.getKey(), entry.getValue());
220 }
221 LoggerContext newContext = CONTEXT_MAP.computeIfAbsent(name,
222 k -> new AtomicReference<>(new WeakReference<>(ctx))).get().get();
223 if (newContext == ctx) {
224 ctx.addShutdownListener(this);
225 }
226 return newContext;
153 final AtomicReference<WeakReference<LoggerContext>> r = new AtomicReference<>();
154 r.set(new WeakReference<>(ctx));
155 CONTEXT_MAP.putIfAbsent(name, r);
156 ctx = CONTEXT_MAP.get(name).get().get();
157 return ctx;
227158 }
228159 final WeakReference<LoggerContext> weakRef = ref.get();
229160 LoggerContext ctx = weakRef.get();
230161 if (ctx != null) {
231 if (entry != null && ctx.getObject(entry.getKey()) == null) {
232 ctx.putObject(entry.getKey(), entry.getValue());
233 }
234162 if (ctx.getConfigLocation() == null && configLocation != null) {
235163 LOGGER.debug("Setting configuration to {}", configLocation);
236164 ctx.setConfigLocation(configLocation);
242170 return ctx;
243171 }
244172 ctx = createContext(name, configLocation);
245 if (entry != null) {
246 ctx.putObject(entry.getKey(), entry.getValue());
247 }
248173 ref.compareAndSet(weakRef, new WeakReference<>(ctx));
249174 return ctx;
250175 }
1717
1818 import java.net.URI;
1919 import java.util.List;
20 import java.util.Map;
21 import java.util.concurrent.TimeUnit;
2220
2321 import org.apache.logging.log4j.core.LoggerContext;
2422
2624 * Interface used to locate a LoggerContext.
2725 */
2826 public interface ContextSelector {
29
30 long DEFAULT_STOP_TIMEOUT = 50;
31
32 /**
33 * Shuts down the LoggerContext.
34 * @param fqcn The fully qualified class name of the caller.
35 * @param loader The ClassLoader to use or null.
36 * @param currentContext If true returns the current Context, if false returns the Context appropriate
37 * @param allContexts if true all LoggerContexts that can be located will be shutdown.
38 * @since 2.13.0
39 */
40 default void shutdown(final String fqcn, final ClassLoader loader, final boolean currentContext,
41 final boolean allContexts) {
42 if (hasContext(fqcn, loader, currentContext)) {
43 getContext(fqcn, loader, currentContext).stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
44 }
45 }
46
47 /**
48 * Checks to see if a LoggerContext is installed. The default implementation returns false.
49 * @param fqcn The fully qualified class name of the caller.
50 * @param loader The ClassLoader to use or null.
51 * @param currentContext If true returns the current Context, if false returns the Context appropriate
52 * for the caller if a more appropriate Context can be determined.
53 * @return true if a LoggerContext has been installed, false otherwise.
54 * @since 2.13.0
55 */
56 default boolean hasContext(String fqcn, ClassLoader loader, boolean currentContext) {
57 return false;
58 }
5927
6028 /**
6129 * Returns the LoggerContext.
7139 * Returns the LoggerContext.
7240 * @param fqcn The fully qualified class name of the caller.
7341 * @param loader ClassLoader to use or null.
74 * @param entry An entry for the external Context map.
75 * @param currentContext If true returns the current Context, if false returns the Context appropriate
76 * for the caller if a more appropriate Context can be determined.
77 * @return The LoggerContext.
78 */
79 default LoggerContext getContext(String fqcn, ClassLoader loader, Map.Entry<String, Object> entry, boolean currentContext) {
80 LoggerContext lc = getContext(fqcn, loader, currentContext);
81 if (lc != null) {
82 lc.putObject(entry.getKey(), entry.getValue());
83 }
84 return lc;
85 }
86
87 /**
88 * Returns the LoggerContext.
89 * @param fqcn The fully qualified class name of the caller.
90 * @param loader ClassLoader to use or null.
9142 * @param currentContext If true returns the current Context, if false returns the Context appropriate
9243 * for the caller if a more appropriate Context can be determined.
9344 * @param configLocation The location of the configuration for the LoggerContext.
9445 * @return The LoggerContext.
9546 */
9647 LoggerContext getContext(String fqcn, ClassLoader loader, boolean currentContext, URI configLocation);
97
98 /**
99 * Returns the LoggerContext.
100 * @param fqcn The fully qualified class name of the caller.
101 * @param loader ClassLoader to use or null.
102 * @param currentContext If true returns the current Context, if false returns the Context appropriate
103 * for the caller if a more appropriate Context can be determined.
104 * @param configLocation The location of the configuration for the LoggerContext.
105 * @return The LoggerContext.
106 */
107 default LoggerContext getContext(String fqcn, ClassLoader loader, Map.Entry<String, Object> entry,
108 boolean currentContext, URI configLocation) {
109 LoggerContext lc = getContext(fqcn, loader, currentContext, configLocation);
110 if (lc != null) {
111 lc.putObject(entry.getKey(), entry.getValue());
112 }
113 return lc;
114 }
11548
11649 /**
11750 * Returns a List of all the available LoggerContexts.
12457 * @param context The context to remove.
12558 */
12659 void removeContext(LoggerContext context);
127
128 /**
129 * Determines whether or not this ContextSelector depends on the callers classloader.
130 * This method should be overridden by implementations, however a default method is provided which always
131 * returns {@code true} to preserve the old behavior.
132 *
133 * @return true if the class loader is required.
134 * @since 2.15.0
135 */
136 default boolean isClassLoaderDependent() {
137 return true;
138 }
13960 }
1616 package org.apache.logging.log4j.core.selector;
1717
1818 import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
19 import org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector;
2019
2120 public class CoreContextSelectors {
2221
23 public static final Class<?>[] CLASSES = new Class<?>[] {
24 ClassLoaderContextSelector.class,
25 BasicContextSelector.class,
26 AsyncLoggerContextSelector.class,
27 BasicAsyncLoggerContextSelector.class
28 };
22 public static final Class<?>[] CLASSES = new Class<?>[] { ClassLoaderContextSelector.class, BasicContextSelector.class, AsyncLoggerContextSelector.class };
2923
3024 }
2222 import java.util.Map;
2323 import java.util.concurrent.ConcurrentHashMap;
2424 import java.util.concurrent.ConcurrentMap;
25 import java.util.concurrent.TimeUnit;
2625 import javax.naming.NamingException;
2726
2827 import org.apache.logging.log4j.core.LoggerContext;
4039 * context to look up the value of the entry. The logging context of the web-application will depend on the value the
4140 * env-entry. The JNDI context which is looked up by this class is <code>java:comp/env/log4j/context-name</code>.
4241 *
43 * <p>For security reasons, JNDI must be enabled by setting system property <code>log4j2.enableJndiContextSelector=true</code>.</p>
4442 * <p>
4543 * Here is an example of an <code>env-entry</code>:
4644 * </p>
10098 }
10199
102100 @Override
103 public void shutdown(String fqcn, ClassLoader loader, boolean currentContext, boolean allContexts) {
104 LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
105 if (ctx == null) {
106 String loggingContextName = getContextName();
107 if (loggingContextName != null) {
108 ctx = CONTEXT_MAP.get(loggingContextName);
109 }
110 }
111 if (ctx != null) {
112 ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
113 }
114 }
115
116 @Override
117 public boolean hasContext(String fqcn, ClassLoader loader, boolean currentContext) {
118 LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
119 if (ctx == null) {
120 String loggingContextName = getContextName();
121 if (loggingContextName == null) {
122 return false;
123 }
124 ctx = CONTEXT_MAP.get(loggingContextName);
125 }
126 return ctx != null && ctx.isStarted();
127 }
128
129 @Override
130101 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
131102 return getContext(fqcn, loader, currentContext, null);
132103 }
149120 }
150121
151122 return loggingContextName == null ? CONTEXT : locateContext(loggingContextName, null, configLocation);
152 }
153
154 private String getContextName() {
155 String loggingContextName = null;
156
157 try (final JndiManager jndiManager = JndiManager.getDefaultManager()) {
158 loggingContextName = jndiManager.lookup(Constants.JNDI_CONTEXT_NAME);
159 } catch (final NamingException ne) {
160 LOGGER.error("Unable to lookup {}", Constants.JNDI_CONTEXT_NAME, ne);
161 }
162 return loggingContextName;
163123 }
164124
165125 @Override
186146 }
187147
188148 @Override
189 public boolean isClassLoaderDependent() {
190 return false;
191 }
192
193 @Override
194149 public LoggerContext removeContext(final String name) {
195150 return CONTEXT_MAP.remove(name);
196151 }
1919 import org.apache.logging.log4j.util.PerformanceSensitive;
2020
2121 import java.io.Serializable;
22 import java.time.temporal.ChronoField;
23 import java.time.temporal.TemporalAccessor;
24 import java.time.temporal.TemporalField;
25 import java.time.temporal.TemporalQueries;
26 import java.time.temporal.TemporalQuery;
27 import java.time.temporal.UnsupportedTemporalTypeException;
28 import java.time.temporal.ValueRange;
29
30 import static java.time.temporal.ChronoField.INSTANT_SECONDS;
31 import static java.time.temporal.ChronoField.MICRO_OF_SECOND;
32 import static java.time.temporal.ChronoField.MILLI_OF_SECOND;
33 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
34 import static java.time.temporal.ChronoUnit.NANOS;
3522
3623 /**
3724 * An instantaneous point on the time line, used for high-precision log event timestamps.
4431 * @since 2.11
4532 */
4633 @PerformanceSensitive("allocation")
47 public class MutableInstant implements Instant, Serializable, TemporalAccessor {
34 public class MutableInstant implements Instant, Serializable {
4835
4936 private static final int MILLIS_PER_SECOND = 1000;
5037 private static final int NANOS_PER_MILLI = 1000_000;
139126 }
140127
141128 @Override
142 public boolean isSupported(final TemporalField field) {
143 if (field instanceof ChronoField) {
144 return field == INSTANT_SECONDS ||
145 field == NANO_OF_SECOND ||
146 field == MICRO_OF_SECOND ||
147 field == MILLI_OF_SECOND;
148 }
149 return field != null && field.isSupportedBy(this);
150 }
151
152 @Override
153 public long getLong(final TemporalField field) {
154 if (field instanceof ChronoField) {
155 switch ((ChronoField) field) {
156 case NANO_OF_SECOND: return nanoOfSecond;
157 case MICRO_OF_SECOND: return nanoOfSecond / 1000;
158 case MILLI_OF_SECOND: return nanoOfSecond / 1000_000;
159 case INSTANT_SECONDS: return epochSecond;
160 }
161 throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
162 }
163 return field.getFrom(this);
164 }
165
166 @Override
167 public ValueRange range(final TemporalField field) {
168 return TemporalAccessor.super.range(field);
169 }
170
171 @Override
172 public int get(final TemporalField field) {
173 if (field instanceof ChronoField) {
174 switch ((ChronoField) field) {
175 case NANO_OF_SECOND: return nanoOfSecond;
176 case MICRO_OF_SECOND: return nanoOfSecond / 1000;
177 case MILLI_OF_SECOND: return nanoOfSecond / 1000_000;
178 case INSTANT_SECONDS: INSTANT_SECONDS.checkValidIntValue(epochSecond);
179 }
180 throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
181 }
182 return range(field).checkValidIntValue(field.getFrom(this), field);
183 }
184
185 @Override
186 public <R> R query(final TemporalQuery<R> query) {
187 if (query == TemporalQueries.precision()) {
188 return (R) NANOS;
189 }
190 // inline TemporalAccessor.super.query(query) as an optimization
191 if (query == TemporalQueries.chronology() ||
192 query == TemporalQueries.zoneId() ||
193 query == TemporalQueries.zone() ||
194 query == TemporalQueries.offset() ||
195 query == TemporalQueries.localDate() ||
196 query == TemporalQueries.localTime()) {
197 return null;
198 }
199 return query.queryFrom(this);
200 }
201
202 @Override
203129 public boolean equals(final Object object) {
204130 if (object == this) {
205131 return true;
230156 public void formatTo(final StringBuilder buffer) {
231157 buffer.append("MutableInstant[epochSecond=").append(epochSecond).append(", nano=").append(nanoOfSecond).append("]");
232158 }
233
234159 }
138138 private String commandName = Help.DEFAULT_COMMAND_NAME;
139139 private boolean overwrittenOptionsAllowed = false;
140140 private boolean unmatchedArgumentsAllowed = false;
141 private final List<String> unmatchedArguments = new ArrayList<>();
141 private final List<String> unmatchedArguments = new ArrayList<String>();
142142 private CommandLine parent;
143143 private boolean usageHelpRequested;
144144 private boolean versionHelpRequested;
145 private final List<String> versionLines = new ArrayList<>();
145 private final List<String> versionLines = new ArrayList<String>();
146146
147147 /**
148148 * Constructs a new {@code CommandLine} interpreter with the specified annotated object.
207207 * @since 0.9.7
208208 */
209209 public Map<String, CommandLine> getSubcommands() {
210 return new LinkedHashMap<>(interpreter.commands);
210 return new LinkedHashMap<String, CommandLine>(interpreter.commands);
211211 }
212212 /**
213213 * Returns the command that this is a subcommand of, or {@code null} if this is a top-level command.
562562 if (printHelpIfRequested(parsedCommands, out, ansi)) {
563563 return null;
564564 }
565 final List<Object> result = new ArrayList<>();
565 final List<Object> result = new ArrayList<Object>();
566566 for (final CommandLine parsed : parsedCommands) {
567567 result.add(execute(parsed));
568568 }
18551855 * Helper class responsible for processing command line arguments.
18561856 */
18571857 private class Interpreter {
1858 private final Map<String, CommandLine> commands = new LinkedHashMap<>();
1859 private final Map<Class<?>, ITypeConverter<?>> converterRegistry = new HashMap<>();
1860 private final Map<String, Field> optionName2Field = new HashMap<>();
1861 private final Map<Character, Field> singleCharOption2Field = new HashMap<>();
1862 private final List<Field> requiredFields = new ArrayList<>();
1863 private final List<Field> positionalParametersFields = new ArrayList<>();
1858 private final Map<String, CommandLine> commands = new LinkedHashMap<String, CommandLine>();
1859 private final Map<Class<?>, ITypeConverter<?>> converterRegistry = new HashMap<Class<?>, ITypeConverter<?>>();
1860 private final Map<String, Field> optionName2Field = new HashMap<String, Field>();
1861 private final Map<Character, Field> singleCharOption2Field = new HashMap<Character, Field>();
1862 private final List<Field> requiredFields = new ArrayList<Field>();
1863 private final List<Field> positionalParametersFields = new ArrayList<Field>();
18641864 private final Object command;
18651865 private boolean isHelpRequested;
18661866 private String separator = Help.DEFAULT_SEPARATOR;
19581958 List<CommandLine> parse(final String... args) {
19591959 Assert.notNull(args, "argument array");
19601960 if (tracer.isInfo()) {tracer.info("Parsing %d command line args %s%n", args.length, Arrays.toString(args));}
1961 final Stack<String> arguments = new Stack<>();
1961 final Stack<String> arguments = new Stack<String>();
19621962 for (int i = args.length - 1; i >= 0; i--) {
19631963 arguments.push(args[i]);
19641964 }
1965 final List<CommandLine> result = new ArrayList<>();
1965 final List<CommandLine> result = new ArrayList<CommandLine>();
19661966 parse(result, arguments, args);
19671967 return result;
19681968 }
19741974 CommandLine.this.usageHelpRequested = false;
19751975
19761976 final Class<?> cmdClass = this.command.getClass();
1977 if (tracer.isDebug()) {tracer.debug("Initializing %s: %d options, %d positional parameters, %d required, %d subcommands.%n", cmdClass.getName(), new HashSet<>(optionName2Field.values()).size(), positionalParametersFields.size(), requiredFields.size(), commands.size());}
1977 if (tracer.isDebug()) {tracer.debug("Initializing %s: %d options, %d positional parameters, %d required, %d subcommands.%n", cmdClass.getName(), new HashSet<Field>(optionName2Field.values()).size(), positionalParametersFields.size(), requiredFields.size(), commands.size());}
19781978 parsedCommands.add(CommandLine.this);
1979 final List<Field> required = new ArrayList<>(requiredFields);
1980 final Set<Field> initialized = new HashSet<>();
1979 final List<Field> required = new ArrayList<Field>(requiredFields);
1980 final Set<Field> initialized = new HashSet<Field>();
19811981 Collections.sort(required, new PositionalParametersSorter());
19821982 try {
19831983 processArguments(parsedCommands, argumentStack, required, initialized, originalArgs);
20542054 args.push(optionParam);
20552055 arg = key;
20562056 if (tracer.isDebug()) {tracer.debug("Separated '%s' option from '%s' option parameter%n", key, optionParam);}
2057 } else if (tracer.isDebug()) {tracer.debug("'%s' contains separator '%s' but '%s' is not a known option%n", arg, separator, key);}
2058 } else if (tracer.isDebug()) {tracer.debug("'%s' cannot be separated into <option>%s<option-parameter>%n", arg, separator);}
2057 } else {
2058 if (tracer.isDebug()) {tracer.debug("'%s' contains separator '%s' but '%s' is not a known option%n", arg, separator, key);}
2059 }
2060 } else {
2061 if (tracer.isDebug()) {tracer.debug("'%s' cannot be separated into <option>%s<option-parameter>%n", arg, separator);}
2062 }
20592063 if (optionName2Field.containsKey(arg)) {
20602064 processStandaloneOption(required, initialized, arg, args, paramAttachedToOption);
20612065 }
20872091 if (tracer.isDebug()) {tracer.debug("%s %s an option: %d matching prefix chars out of %d option names%n", arg, (result ? "resembles" : "doesn't resemble"), count, optionName2Field.size());}
20882092 return result;
20892093 }
2090 private void handleUnmatchedArguments(final String arg) {final Stack<String> args = new Stack<>(); args.add(arg); handleUnmatchedArguments(args);}
2094 private void handleUnmatchedArguments(final String arg) {final Stack<String> args = new Stack<String>(); args.add(arg); handleUnmatchedArguments(args);}
20912095 private void handleUnmatchedArguments(final Stack<String> args) {
20922096 while (!args.isEmpty()) { unmatchedArguments.add(args.pop()); } // addAll would give args in reverse order
20932097 }
23672371 final int length = existing == null ? 0 : Array.getLength(existing);
23682372 final Class<?> type = getTypeAttribute(field)[0];
23692373 final List<Object> converted = consumeArguments(field, annotation, arity, args, type, length, argDescription);
2370 final List<Object> newValues = new ArrayList<>();
2374 final List<Object> newValues = new ArrayList<Object>();
23712375 for (int i = 0; i < length; i++) {
23722376 newValues.add(Array.get(existing, i));
23732377 }
24182422 final Class<?> type,
24192423 final int originalSize,
24202424 final String argDescription) throws Exception {
2421 final List<Object> result = new ArrayList<>();
2425 final List<Object> result = new ArrayList<Object>();
24222426
24232427 // first do the arity.min mandatory parameters
24242428 for (int i = 0; i < arity.min; i++) {
25412545 @SuppressWarnings("unchecked")
25422546 private Collection<Object> createCollection(final Class<?> collectionClass) throws Exception {
25432547 if (collectionClass.isInterface()) {
2544 if (SortedSet.class.isAssignableFrom(collectionClass)) {
2545 return new TreeSet<>();
2548 if (List.class.isAssignableFrom(collectionClass)) {
2549 return new ArrayList<Object>();
2550 } else if (SortedSet.class.isAssignableFrom(collectionClass)) {
2551 return new TreeSet<Object>();
25462552 } else if (Set.class.isAssignableFrom(collectionClass)) {
2547 return new LinkedHashSet<>();
2553 return new LinkedHashSet<Object>();
25482554 } else if (Queue.class.isAssignableFrom(collectionClass)) {
2549 return new LinkedList<>(); // ArrayDeque is only available since 1.6
2550 }
2551 return new ArrayList<>();
2555 return new LinkedList<Object>(); // ArrayDeque is only available since 1.6
2556 }
2557 return new ArrayList<Object>();
25522558 }
25532559 // custom Collection implementation class must have default constructor
25542560 return (Collection<Object>) collectionClass.newInstance();
25572563 try { // if it is an implementation class, instantiate it
25582564 return (Map<Object, Object>) mapClass.newInstance();
25592565 } catch (final Exception ignored) {}
2560 return new LinkedHashMap<>();
2566 return new LinkedHashMap<Object, Object>();
25612567 }
25622568 private ITypeConverter<?> getTypeConverter(final Class<?> type, final Field field) {
25632569 final ITypeConverter<?> result = converterRegistry.get(type);
28162822 private final static int usageHelpWidth = 80;
28172823 private final static int optionsColumnWidth = 2 + 2 + 1 + 24;
28182824 private final Object command;
2819 private final Map<String, Help> commands = new LinkedHashMap<>();
2825 private final Map<String, Help> commands = new LinkedHashMap<String, Help>();
28202826 final ColorScheme colorScheme;
28212827
28222828 /** Immutable list of fields annotated with {@link Option}, in declaration order. */
29192925 public Help(final Object command, final ColorScheme colorScheme) {
29202926 this.command = Assert.notNull(command, "command");
29212927 this.colorScheme = Assert.notNull(colorScheme, "colorScheme").applySystemProperties();
2922 final List<Field> options = new ArrayList<>();
2923 final List<Field> operands = new ArrayList<>();
2928 final List<Field> options = new ArrayList<Field>();
2929 final List<Field> operands = new ArrayList<Field>();
29242930 Class<?> cls = command.getClass();
29252931 while (cls != null) {
29262932 for (final Field field : cls.getDeclaredFields()) {
30573063 * @return a detailed synopsis */
30583064 public String detailedSynopsis(final int synopsisHeadingLength, final Comparator<Field> optionSort, final boolean clusterBooleanOptions) {
30593065 Text optionText = ansi().new Text(0);
3060 final List<Field> fields = new ArrayList<>(optionFields); // iterate in declaration order
3066 final List<Field> fields = new ArrayList<Field>(optionFields); // iterate in declaration order
30613067 if (optionSort != null) {
30623068 Collections.sort(fields, optionSort);// iterate in specified sort order
30633069 }
30643070 if (clusterBooleanOptions) { // cluster all short boolean options into a single string
3065 final List<Field> booleanOptions = new ArrayList<>();
3071 final List<Field> booleanOptions = new ArrayList<Field>();
30663072 final StringBuilder clusteredRequired = new StringBuilder("-");
30673073 final StringBuilder clusteredOptional = new StringBuilder("-");
30683074 for (final Field field : fields) {
31193125
31203126 // right-adjust the command name by length of synopsis heading
31213127 final Text PADDING = Ansi.OFF.new Text(stringOf('X', synopsisHeadingLength));
3122 textTable.addRowValues(PADDING.append(colorScheme.commandText(commandName)), optionText);
3128 textTable.addRowValues(new Text[] {PADDING.append(colorScheme.commandText(commandName)), optionText});
31233129 return textTable.toString().substring(synopsisHeadingLength); // cut off leading synopsis heading spaces
31243130 }
31253131
31633169 * @return the fully formatted option list
31643170 */
31653171 public String optionList(final Layout layout, final Comparator<Field> optionSort, final IParamLabelRenderer valueLabelRenderer) {
3166 final List<Field> fields = new ArrayList<>(optionFields); // options are stored in order of declaration
3172 final List<Field> fields = new ArrayList<Field>(optionFields); // options are stored in order of declaration
31673173 if (optionSort != null) {
31683174 Collections.sort(fields, optionSort); // default: sort options ABC
31693175 }
33323338 return textTable.toString();
33333339 }
33343340 private static int maxLength(final Collection<String> any) {
3335 final List<String> strings = new ArrayList<>(any);
3341 final List<String> strings = new ArrayList<String>(any);
33363342 Collections.sort(strings, Collections.reverseOrder(Help.shortestFirst()));
33373343 return strings.get(0).length();
33383344 }
35453551 final Text longOptionText,
35463552 final Object defaultValue) {
35473553 final Text EMPTY = Ansi.EMPTY_TEXT;
3548 final List<Text[]> result = new ArrayList<>();
3554 final List<Text[]> result = new ArrayList<Text[]>();
35493555 Text[] descriptionFirstLines = scheme.ansi().new Text(str(option.description(), 0)).splitLines();
35503556 if (descriptionFirstLines.length == 0) {
35513557 if (showDefault) {
36283634 final Text requiredParameter = scheme.parameterText(Range.parameterArity(field).min > 0 ? requiredMarker : "");
36293635
36303636 final Text EMPTY = Ansi.EMPTY_TEXT;
3631 final List<Text[]> result = new ArrayList<>();
3637 final List<Text[]> result = new ArrayList<Text[]>();
36323638 Text[] descriptionFirstLines = scheme.ansi().new Text(str(params.description(), 0)).splitLines();
36333639 if (descriptionFirstLines.length == 0) { descriptionFirstLines = new Text[]{ EMPTY }; }
36343640 result.add(new Text[] { requiredParameter, EMPTY, EMPTY, label, descriptionFirstLines[0] });
39033909 public final Column[] columns;
39043910
39053911 /** The {@code char[]} slots of the {@code TextTable} to copy text values into. */
3906 protected final List<Text> columnValues = new ArrayList<>();
3912 protected final List<Text> columnValues = new ArrayList<Text>();
39073913
39083914 /** By default, indent wrapped lines by 2 spaces. */
39093915 public int indentWrappedLines = 2;
41504156 * @see Help#defaultColorScheme(Ansi)
41514157 */
41524158 public static class ColorScheme {
4153 public final List<IStyle> commandStyles = new ArrayList<>();
4154 public final List<IStyle> optionStyles = new ArrayList<>();
4155 public final List<IStyle> parameterStyles = new ArrayList<>();
4156 public final List<IStyle> optionParamStyles = new ArrayList<>();
4159 public final List<IStyle> commandStyles = new ArrayList<IStyle>();
4160 public final List<IStyle> optionStyles = new ArrayList<IStyle>();
4161 public final List<IStyle> parameterStyles = new ArrayList<IStyle>();
4162 public final List<IStyle> optionParamStyles = new ArrayList<IStyle>();
41574163 private final Ansi ansi;
41584164
41594165 /** Constructs a new ColorScheme with {@link Help.Ansi#AUTO}. */
44434449 private int from;
44444450 private int length;
44454451 private StringBuilder plain = new StringBuilder();
4446 private List<StyledSection> sections = new ArrayList<>();
4452 private List<StyledSection> sections = new ArrayList<StyledSection>();
44474453
44484454 /** Constructs a Text with the specified max length (for use in a TextTable Column).
44494455 * @param maxLength max length of this text */
45044510 }
45054511
45064512 public Text[] splitLines() {
4507 final List<Text> result = new ArrayList<>();
4513 final List<Text> result = new ArrayList<Text>();
45084514 boolean trailingEmptyString = false;
45094515 int start = 0, end = 0;
45104516 for (int i = 0; i < plain.length(); i++, end = i) {
45554561 final Text result = (Text) clone();
45564562 result.plain = new StringBuilder(plain.toString().substring(from, from + length));
45574563 result.from = 0;
4558 result.sections = new ArrayList<>();
4564 result.sections = new ArrayList<StyledSection>();
45594565 for (final StyledSection section : sections) {
45604566 result.sections.add(section.withStartIndex(section.startIndex - from));
45614567 }
47584764 return new MissingParameterException(cmd, "Missing required option '"
47594765 + describe(missing.iterator().next(), separator) + "'");
47604766 }
4761 final List<String> names = new ArrayList<>(missing.size());
4767 final List<String> names = new ArrayList<String>(missing.size());
47624768 for (final Field field : missing) {
47634769 names.add(describe(field, separator));
47644770 }
47954801 public static class UnmatchedArgumentException extends ParameterException {
47964802 private static final long serialVersionUID = -8700426380701452440L;
47974803 public UnmatchedArgumentException(final CommandLine commandLine, final String msg) { super(commandLine, msg); }
4798 public UnmatchedArgumentException(final CommandLine commandLine, final Stack<String> args) { this(commandLine, new ArrayList<>(reverse(args))); }
4804 public UnmatchedArgumentException(final CommandLine commandLine, final Stack<String> args) { this(commandLine, new ArrayList<String>(reverse(args))); }
47994805 public UnmatchedArgumentException(final CommandLine commandLine, final List<String> args) { this(commandLine, "Unmatched argument" + (args.size() == 1 ? " " : "s ") + args); }
48004806 }
48014807 /** Exception indicating that more values were specified for an option or parameter than its {@link Option#arity() arity} allows. */
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.io.File;
1819 import java.util.List;
1920
2021 import org.apache.logging.log4j.core.config.Configuration;
5859 return configuration;
5960 }
6061
61 @Override
6262 public abstract long getLastModified();
6363
64 @Override
6564 public abstract boolean isModified();
6665
6766 @Override
2323 */
2424 public class ArrayUtils {
2525
26 /**
27 * Checks if an array of Objects is empty or {@code null}.
28 *
29 * @param array the array to test
30 * @return {@code true} if the array is empty or {@code null}
31 * @since 2.1
32 */
33 public static boolean isEmpty(final byte[] array) {
34 return getLength(array) == 0;
35 }
36
3726 /**
3827 * <p>Returns the length of the specified array.
3928 * This method can deal with {@code Object} arrays and with primitive arrays.</p>
1616 package org.apache.logging.log4j.core.util;
1717
1818 import java.net.URLConnection;
19
1920 import org.apache.logging.log4j.Logger;
2021 import org.apache.logging.log4j.status.StatusLogger;
2122 import org.apache.logging.log4j.util.Base64Util;
2627 * Provides the Basic Authorization header to a request.
2728 */
2829 public class BasicAuthorizationProvider implements AuthorizationProvider {
29 private static final String[] PREFIXES = {"log4j2.config.", "logging.auth."};
30 private static final String AUTH_USER_NAME = "username";
31 private static final String AUTH_PASSWORD = "password";
32 private static final String AUTH_PASSWORD_DECRYPTOR = "passwordDecryptor";
30
3331 public static final String CONFIG_USER_NAME = "log4j2.configurationUserName";
3432 public static final String CONFIG_PASSWORD = "log4j2.configurationPassword";
3533 public static final String PASSWORD_DECRYPTOR = "log4j2.passwordDecryptor";
3937 private String authString = null;
4038
4139 public BasicAuthorizationProvider(PropertiesUtil props) {
42 String userName = props.getStringProperty(PREFIXES,AUTH_USER_NAME,
43 () -> props.getStringProperty(CONFIG_USER_NAME));
44 String password = props.getStringProperty(PREFIXES, AUTH_PASSWORD,
45 () -> props.getStringProperty(CONFIG_PASSWORD));
46 String decryptor = props.getStringProperty(PREFIXES, AUTH_PASSWORD_DECRYPTOR,
47 () -> props.getStringProperty(PASSWORD_DECRYPTOR));
40 String userName = props.getStringProperty(CONFIG_USER_NAME);
41 String password = props.getStringProperty(CONFIG_PASSWORD);
42 String decryptor = props.getStringProperty(PASSWORD_DECRYPTOR);
4843 if (decryptor != null) {
4944 try {
5045 Object obj = LoaderUtil.newInstanceOf(decryptor);
3333 private short count = 0;
3434
3535 private CachedClock() {
36 final Thread updater = new Log4jThread(() -> {
37 while (true) {
38 final long time = System.currentTimeMillis();
39 millis = time;
36 final Thread updater = new Log4jThread(new Runnable() {
37 @Override
38 public void run() {
39 while (true) {
40 final long time = System.currentTimeMillis();
41 millis = time;
4042
41 // avoid explicit dependency on sun.misc.Util
42 LockSupport.parkNanos(1000 * 1000);
43 // avoid explicit dependency on sun.misc.Util
44 LockSupport.parkNanos(1000 * 1000);
45 }
4346 }
4447 }, "CachedClock Updater Thread");
4548 updater.setDaemon(true);
6868
6969 private static Map<String, Supplier<Clock>> aliases() {
7070 final Map<String, Supplier<Clock>> result = new HashMap<>();
71 result.put("SystemClock", SystemClock::new);
72 result.put("SystemMillisClock", SystemMillisClock::new);
73 result.put("CachedClock", CachedClock::instance);
74 result.put("CoarseCachedClock", CoarseCachedClock::instance);
75 result.put("org.apache.logging.log4j.core.util.CachedClock", CachedClock::instance);
76 result.put("org.apache.logging.log4j.core.util.CoarseCachedClock", CoarseCachedClock::instance);
71 result.put("SystemClock", new Supplier<Clock>() { @Override public Clock get() { return new SystemClock(); } });
72 result.put("SystemMillisClock", new Supplier<Clock>() { @Override public Clock get() { return new SystemMillisClock(); } });
73 result.put("CachedClock", new Supplier<Clock>() { @Override public Clock get() { return CachedClock.instance(); } });
74 result.put("CoarseCachedClock", new Supplier<Clock>() { @Override public Clock get() { return CoarseCachedClock.instance(); } });
75 result.put("org.apache.logging.log4j.core.util.CachedClock", new Supplier<Clock>() { @Override public Clock get() { return CachedClock.instance(); } });
76 result.put("org.apache.logging.log4j.core.util.CoarseCachedClock", new Supplier<Clock>() { @Override public Clock get() { return CoarseCachedClock.instance(); } });
7777 return result;
7878 }
7979
5454 "log4j.format.msg.async", false);
5555
5656 /**
57 * LOG4J2-3198 property which used to globally opt out of lookups in pattern layout message text, however
58 * this is the default and this property is no longer read.
59 *
60 * Deprecated in 2.15.
57 * LOG4J2-2109 if {@code true}, MessagePatternConverter will always operate as though
58 * <pre>%m{nolookups}</pre> is configured.
6159 *
6260 * @since 2.10
63 * @deprecated no longer used, lookups are only used when {@code %m{lookups}} is specified
61 * @deprecated Since 2.12.2
6462 */
6563 @Deprecated
6664 public static final boolean FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS = PropertiesUtil.getProperties().getBooleanProperty(
67 "log4j2.formatMsgNoLookups", true);
65 "log4j2.formatMsgNoLookups", false);
6866
6967 /**
7068 * {@code true} if we think we are running in a web container, based on the boolean value of system property
+0
-42
log4j-core/src/main/java/org/apache/logging/log4j/core/util/ContextDataProvider.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.logging.log4j.core.util;
17
18 import org.apache.logging.log4j.core.impl.JdkMapAdapterStringMap;
19 import org.apache.logging.log4j.util.StringMap;
20
21 import java.util.Map;
22
23 /**
24 * Source of context data to be added to each log event.
25 */
26 public interface ContextDataProvider {
27
28 /**
29 * Returns a Map containing context data to be injected into the event or null if no context data is to be added.
30 * @return A Map containing the context data or null.
31 */
32 Map<String, String> supplyContextData();
33
34 /**
35 * Returns the context data as a StringMap.
36 * @return the context data in a StringMap.
37 */
38 default StringMap supplyStringMap() {
39 return new JdkMapAdapterStringMap(supplyContextData());
40 }
41 }
534534 }
535535 if (s.length() > i + 3) {
536536 c = s.charAt(i + 3);
537 switch (c) {
538 case '-':
537 if (c == '-') {
539538 i += 4;
540539 sub = s.substring(i, i + 3);
541540 eval = getDayOfWeekNumber(sub);
544543 "Invalid Day-of-Week value: '" + sub
545544 + "'", i);
546545 }
547 break;
548 case '#':
546 } else if (c == '#') {
549547 try {
550548 i += 4;
551549 nthdayOfWeek = Integer.parseInt(s.substring(i));
557555 "A numeric value between 1 and 5 must follow the '#' option",
558556 i);
559557 }
560 break;
561 case 'L':
558 } else if (c == 'L') {
562559 lastdayOfWeek = true;
563560 i++;
564 break;
565 default:
566 break;
567561 }
568562 }
569563
579573 return (i + 3);
580574 }
581575
582 switch (c) {
583 case '?':
576 if (c == '?') {
584577 i++;
585578 if ((i + 1) < s.length()
586579 && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) {
600593 i);
601594 }
602595 }
596
603597 addToSet(NO_SPEC_INT, -1, 0, type);
604598 return i;
605 case '*':
606 case '/':
599 }
600
601 if (c == '*' || c == '/') {
607602 if (c == '*' && (i + 1) >= s.length()) {
608603 addToSet(ALL_SPEC_INT, -1, incr, type);
609604 return i + 1;
641636 } else {
642637 incr = 1;
643638 }
639
644640 addToSet(ALL_SPEC_INT, -1, incr, type);
645641 return i;
646 case 'L':
642 } else if (c == 'L') {
647643 i++;
648644 if (type == DAY_OF_MONTH) {
649645 lastdayOfMonth = true;
670666 }
671667 }
672668 return i;
673 default:
674 if (c >= '0' && c <= '9') {
675 int val = Integer.parseInt(String.valueOf(c));
676 i++;
677 if (i >= s.length()) {
678 addToSet(val, -1, -1, type);
679 } else {
680 c = s.charAt(i);
681 if (c >= '0' && c <= '9') {
682 final ValueSet vs = getValue(val, s, i);
683 val = vs.value;
684 i = vs.pos;
685 }
686 i = checkNext(i, s, val, type);
687 return i;
688 }
669 } else if (c >= '0' && c <= '9') {
670 int val = Integer.parseInt(String.valueOf(c));
671 i++;
672 if (i >= s.length()) {
673 addToSet(val, -1, -1, type);
689674 } else {
690 throw new ParseException("Unexpected character: " + c, i);
691 }
692 break;
675 c = s.charAt(i);
676 if (c >= '0' && c <= '9') {
677 final ValueSet vs = getValue(val, s, i);
678 val = vs.value;
679 i = vs.pos;
680 }
681 i = checkNext(i, s, val, type);
682 return i;
683 }
684 } else {
685 throw new ParseException("Unexpected character: " + c, i);
693686 }
694687
695688 return i;
738731 return i;
739732 }
740733
741 switch (c) {
742 case '#':
734 if (c == '#') {
743735 if (type != DAY_OF_WEEK) {
744736 throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i);
745737 }
754746 "A numeric value between 1 and 5 must follow the '#' option",
755747 i);
756748 }
749
757750 final TreeSet<Integer> set = getSet(type);
758751 set.add(val);
759752 i++;
760753 return i;
761 case '-':
754 }
755
756 if (c == '-') {
762757 i++;
763758 c = s.charAt(i);
764759 final int v = Integer.parseInt(String.valueOf(c));
789784 final int v3 = vs.value;
790785 addToSet(val, end, v3, type);
791786 i = vs.pos;
787 return i;
792788 } else {
793789 addToSet(val, end, v2, type);
794 }
795 return i;
790 return i;
791 }
796792 } else {
797793 addToSet(val, end, 1, type);
798794 return i;
799795 }
800 case '/':
796 }
797
798 if (c == '/') {
801799 i++;
802800 c = s.charAt(i);
803801 final int v2 = Integer.parseInt(String.valueOf(c));
816814 } else {
817815 throw new ParseException("Unexpected character '" + c + "' after '/'", i);
818816 }
819 default:
820 break;
821817 }
822818
823819 addToSet(val, end, 0, type);
942938
943939 final TreeSet<Integer> set = getSet(type);
944940
945 switch (type) {
946 case SECOND:
947 case MINUTE:
941 if (type == SECOND || type == MINUTE) {
948942 if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) {
949943 throw new ParseException(
950944 "Minute and Second values must be between 0 and 59",
951945 -1);
952946 }
953 break;
954 case HOUR:
947 } else if (type == HOUR) {
955948 if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) {
956949 throw new ParseException(
957950 "Hour values must be between 0 and 23", -1);
958951 }
959 break;
960 case DAY_OF_MONTH:
952 } else if (type == DAY_OF_MONTH) {
961953 if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT)
962954 && (val != NO_SPEC_INT)) {
963955 throw new ParseException(
964956 "Day of month values must be between 1 and 31", -1);
965957 }
966 break;
967 case MONTH:
958 } else if (type == MONTH) {
968959 if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) {
969960 throw new ParseException(
970961 "Month values must be between 1 and 12", -1);
971962 }
972 break;
973 case DAY_OF_WEEK:
963 } else if (type == DAY_OF_WEEK) {
974964 if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT)
975965 && (val != NO_SPEC_INT)) {
976966 throw new ParseException(
977967 "Day-of-Week values must be between 1 and 7", -1);
978968 }
979 break;
980 default:
981 break;
982969 }
983970
984971 if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) {
999986 set.add(ALL_SPEC); // put in a marker, but also fill values
1000987 }
1001988
1002 switch (type) {
1003 case SECOND:
1004 case MINUTE:
989 if (type == SECOND || type == MINUTE) {
1005990 if (stopAt == -1) {
1006991 stopAt = 59;
1007992 }
1008993 if (startAt == -1 || startAt == ALL_SPEC_INT) {
1009994 startAt = 0;
1010995 }
1011 break;
1012 case HOUR:
996 } else if (type == HOUR) {
1013997 if (stopAt == -1) {
1014998 stopAt = 23;
1015999 }
10161000 if (startAt == -1 || startAt == ALL_SPEC_INT) {
10171001 startAt = 0;
10181002 }
1019 break;
1020 case DAY_OF_MONTH:
1003 } else if (type == DAY_OF_MONTH) {
10211004 if (stopAt == -1) {
10221005 stopAt = 31;
10231006 }
10241007 if (startAt == -1 || startAt == ALL_SPEC_INT) {
10251008 startAt = 1;
10261009 }
1027 break;
1028 case MONTH:
1010 } else if (type == MONTH) {
10291011 if (stopAt == -1) {
10301012 stopAt = 12;
10311013 }
10321014 if (startAt == -1 || startAt == ALL_SPEC_INT) {
10331015 startAt = 1;
10341016 }
1035 break;
1036 case DAY_OF_WEEK:
1017 } else if (type == DAY_OF_WEEK) {
10371018 if (stopAt == -1) {
10381019 stopAt = 7;
10391020 }
10401021 if (startAt == -1 || startAt == ALL_SPEC_INT) {
10411022 startAt = 1;
10421023 }
1043 break;
1044 case YEAR:
1024 } else if (type == YEAR) {
10451025 if (stopAt == -1) {
10461026 stopAt = MAX_YEAR;
10471027 }
10481028 if (startAt == -1 || startAt == ALL_SPEC_INT) {
10491029 startAt = 1970;
10501030 }
1051 break;
1052 default:
1053 break;
10541031 }
10551032
10561033 // if the end of the range is before the start, then we need to overflow into
11941171 return null;
11951172 }
11961173
1174 SortedSet<Integer> st = null;
1175 int t = 0;
1176
11971177 int sec = cl.get(Calendar.SECOND);
11981178 int min = cl.get(Calendar.MINUTE);
11991179
12001180 // get second.................................................
1201 SortedSet<Integer> st = seconds.tailSet(sec);
1181 st = seconds.tailSet(sec);
12021182 if (st != null && st.size() != 0) {
12031183 sec = st.first();
12041184 } else {
12101190
12111191 min = cl.get(Calendar.MINUTE);
12121192 int hr = cl.get(Calendar.HOUR_OF_DAY);
1213 int t = -1;
1193 t = -1;
12141194
12151195 // get minute.................................................
12161196 st = minutes.tailSet(min);
14901470 cl.set(Calendar.MONTH, mon);
14911471 // no '- 1' here because we are promoting the month
14921472 continue;
1493 } else if (daysToAdd > 0) { // are we switching days?
1473 } else if (daysToAdd > 0) { // are we swithing days?
14941474 cl.set(Calendar.SECOND, 0);
14951475 cl.set(Calendar.MINUTE, 0);
14961476 cl.set(Calendar.HOUR_OF_DAY, 0);
15911571 protected Date getTimeBefore(final Date targetDate) {
15921572 final Calendar cl = Calendar.getInstance(getTimeZone());
15931573
1594 // CronTrigger does not deal with milliseconds, so truncate target
1595 cl.setTime(targetDate);
1596 cl.set(Calendar.MILLISECOND, 0);
1597 final Date targetDateNoMs = cl.getTime();
1598
15991574 // to match this
1600 Date start = targetDateNoMs;
1575 Date start = targetDate;
16011576 final long minIncrement = findMinIncrement();
16021577 Date prevFireTime;
16031578 do {
16071582 return null;
16081583 }
16091584 start = prevCheckDate;
1610 } while (prevFireTime.compareTo(targetDateNoMs) >= 0);
1585 } while (prevFireTime.compareTo(targetDate) >= 0);
16111586 return prevFireTime;
16121587 }
16131588
4343
4444 private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED);
4545 private final ThreadFactory threadFactory;
46
47 // use references to prevent memory leaks
48 private final Collection<Reference<Cancellable>> hooks = new CopyOnWriteArrayList<>();
46 private final Collection<Cancellable> hooks = new CopyOnWriteArrayList<>();
4947 private Reference<Thread> shutdownHookRef;
5048
5149 /**
7068 @Override
7169 public void run() {
7270 if (state.compareAndSet(State.STARTED, State.STOPPING)) {
73 for (final Reference<Cancellable> hookRef : hooks) {
74 Cancellable hook = hookRef.get();
75 if (hook != null) {
71 for (final Runnable hook : hooks) {
72 try {
73 hook.run();
74 } catch (final Throwable t1) {
7675 try {
77 hook.run();
78 } catch (final Throwable t1) {
79 try {
80 LOGGER.error(SHUTDOWN_HOOK_MARKER, "Caught exception executing shutdown hook {}", hook, t1);
81 } catch (final Throwable t2) {
82 System.err.println("Caught exception " + t2.getClass() + " logging exception " + t1.getClass());
83 t1.printStackTrace();
84 }
76 LOGGER.error(SHUTDOWN_HOOK_MARKER, "Caught exception executing shutdown hook {}", hook, t1);
77 } catch (final Throwable t2) {
78 System.err.println("Caught exception " + t2.getClass() + " logging exception " + t1.getClass());
79 t1.printStackTrace();
8580 }
8681 }
8782 }
9085 }
9186
9287 private static class RegisteredCancellable implements Cancellable {
93 private Runnable callback;
94 private Collection<Reference<Cancellable>> registered;
95
96 RegisteredCancellable(final Runnable callback, final Collection<Reference<Cancellable>> registered) {
97 this.callback = callback;
88 // use a reference to prevent memory leaks
89 private final Reference<Runnable> hook;
90 private Collection<Cancellable> registered;
91
92 RegisteredCancellable(final Runnable callback, final Collection<Cancellable> registered) {
9893 this.registered = registered;
94 hook = new SoftReference<>(callback);
9995 }
10096
10197 @Override
10298 public void cancel() {
103 callback = null;
104 Collection<Reference<Cancellable>> references = registered;
105 if (references != null) {
106 registered = null;
107 references.removeIf(ref -> {
108 Cancellable value = ref.get();
109 return value == null || value == RegisteredCancellable.this;
110 });
111 }
99 hook.clear();
100 registered.remove(this);
101 registered = null;
112102 }
113103
114104 @Override
115105 public void run() {
116 final Runnable runnableHook = callback;
106 final Runnable runnableHook = this.hook.get();
117107 if (runnableHook != null) {
118108 runnableHook.run();
119 callback = null;
109 this.hook.clear();
120110 }
121111 }
122112
123113 @Override
124114 public String toString() {
125 return String.valueOf(callback);
115 return String.valueOf(hook.get());
126116 }
127117 }
128118
130120 public Cancellable addShutdownCallback(final Runnable callback) {
131121 if (isStarted()) {
132122 final Cancellable receipt = new RegisteredCancellable(callback, hooks);
133 hooks.add(new SoftReference<>(receipt));
123 hooks.add(receipt);
134124 return receipt;
135125 }
136126 throw new IllegalStateException("Cannot add new shutdown hook as this is not started. Current state: " +
1717
1818 import java.io.File;
1919 import java.io.IOException;
20 import java.io.UnsupportedEncodingException;
21 import java.net.MalformedURLException;
2022 import java.net.URI;
21 import java.net.URISyntaxException;
2223 import java.net.URL;
24 import java.net.URLDecoder;
25 import java.nio.charset.StandardCharsets;
2326 import java.nio.file.FileSystems;
2427 import java.nio.file.Files;
2528 import java.nio.file.Path;
5659 * @return the resulting file object
5760 */
5861 public static File fileFromUri(URI uri) {
59 if (uri == null) {
62 // There MUST be a better way to do this. TODO Search other ASL projects...
63 if (uri == null || (uri.getScheme() != null
64 && (!PROTOCOL_FILE.equals(uri.getScheme()) && !JBOSS_FILE.equals(uri.getScheme())))) {
6065 return null;
6166 }
62 if (uri.isAbsolute()) {
63 if (JBOSS_FILE.equals(uri.getScheme())) {
64 try {
65 // patch the scheme
66 uri = new URI(PROTOCOL_FILE, uri.getSchemeSpecificPart(), uri.getFragment());
67 } catch (URISyntaxException use) {
68 // should not happen, ignore
69 }
67 if (uri.getScheme() == null) {
68 File file = new File(uri.toString());
69 if (file.exists()) {
70 return file;
7071 }
7172 try {
72 if (PROTOCOL_FILE.equals(uri.getScheme())) {
73 return new File(uri);
74 }
75 } catch (final Exception ex) {
76 LOGGER.warn("Invalid URI {}", uri);
77 }
78 } else {
79 File file = new File(uri.toString());
80 try {
73 final String path = uri.getPath();
74 file = new File(path);
8175 if (file.exists()) {
8276 return file;
8377 }
84 final String path = uri.getPath();
85 return new File(path);
78 uri = new File(path).toURI();
8679 } catch (final Exception ex) {
8780 LOGGER.warn("Invalid URI {}", uri);
81 return null;
8882 }
83 }
84 final String charsetName = StandardCharsets.UTF_8.name();
85 try {
86 String fileName = uri.toURL().getFile();
87 if (new File(fileName).exists()) { // LOG4J2-466
88 return new File(fileName); // allow files with '+' char in name
89 }
90 fileName = URLDecoder.decode(fileName, charsetName);
91 return new File(fileName);
92 } catch (final MalformedURLException ex) {
93 LOGGER.warn("Invalid URL {}", uri, ex);
94 } catch (final UnsupportedEncodingException uee) {
95 LOGGER.warn("Invalid encoding: {}", charsetName, uee);
8996 }
9097 return null;
9198 }
104111
105112 /**
106113 * Asserts that the given directory exists and creates it if necessary.
107 *
114 *
108115 * @param dir the directory that shall exist
109116 * @param createDirectoryIfNotExisting specifies if the directory shall be created if it does not exist.
110117 * @throws java.io.IOException thrown if the directory could not be created.
123130 throw new IOException("File " + dir + " exists and is not a directory. Unable to create directory.");
124131 }
125132 }
126
133
127134 /**
128135 * Creates the parent directories for the given File.
129 *
136 *
130137 * @param file
131138 * @throws IOException
132139 */
3434 *
3535 * @param context the JNDI Context to close, may be {@code null}
3636 * @throws NamingException if a problem occurred closing the specified JNDI Context
37 * @see Context#close()
3837 */
3938 public static void close(final Context context) throws NamingException {
4039 if (context != null) {
4645 * Closes the specified {@code Context}, ignoring any exceptions thrown by the close operation.
4746 *
4847 * @param context the JNDI Context to close, may be {@code null}
49 * @return Whether closing succeeded
50 * @see Context#close()
5148 */
5249 public static boolean closeSilently(final Context context) {
5350 try {
1616
1717 package org.apache.logging.log4j.core.util;
1818
19 import java.util.Objects;
20
2119 import org.apache.logging.log4j.core.config.Node;
2220 import org.apache.logging.log4j.core.config.plugins.Plugin;
2321 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
3028 */
3129 @Plugin(name = "KeyValuePair", category = Node.CATEGORY, printObject = true)
3230 public final class KeyValuePair {
33
34 /**
35 * The empty array.
36 */
37 public static final KeyValuePair[] EMPTY_ARRAY = {};
3831
3932 private final String key;
4033 private final String value;
10295
10396 @Override
10497 public int hashCode() {
105 return Objects.hash(key, value);
98 final int prime = 31;
99 int result = 1;
100 result = prime * result + ((key == null) ? 0 : key.hashCode());
101 result = prime * result + ((value == null) ? 0 : value.hashCode());
102 return result;
106103 }
107104
108105 @Override
117114 return false;
118115 }
119116 final KeyValuePair other = (KeyValuePair) obj;
120 if (!Objects.equals(key, other.key)) {
117 if (key == null) {
118 if (other.key != null) {
119 return false;
120 }
121 } else if (!key.equals(other.key)) {
121122 return false;
122123 }
123 if (!Objects.equals(value, other.value)) {
124 if (value == null) {
125 if (other.value != null) {
126 return false;
127 }
128 } else if (!value.equals(other.value)) {
124129 return false;
125130 }
126131 return true;
7676 * <li>Search for {@code resource} using the thread context
7777 * class loader under Java2. If that fails, search for
7878 * {@code resource} using the class loader that loaded this
79 * class ({@code Loader}). Under JDK 1.1, only the class
79 * class ({@code Loader}). Under JDK 1.1, only the the class
8080 * loader that loaded this class ({@code Loader}) is used.</li>
8181 * <li>Try one last time with
8282 * {@code ClassLoader.getSystemResource(resource)}, that is is
138138 * <li>Search for {@code resource} using the thread context
139139 * class loader under Java2. If that fails, search for
140140 * {@code resource} using the class loader that loaded this
141 * class ({@code Loader}). Under JDK 1.1, only the class
141 * class ({@code Loader}). Under JDK 1.1, only the the class
142142 * loader that loaded this class ({@code Loader}) is used.</li>
143143 * <li>Try one last time with
144144 * {@code ClassLoader.getSystemResource(resource)}, that is is
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.security.MessageDigest;
19
1820 import org.apache.logging.log4j.util.Strings;
19
20 import java.nio.charset.Charset;
21 import java.security.MessageDigest;
22 import java.security.NoSuchAlgorithmException;
23 import java.util.Objects;
2421
2522 /**
2623 *
2724 */
2825 public final class NameUtil {
2926
30 private NameUtil() {}
27 private static final int MASK = 0xff;
28
29 private NameUtil() {
30 }
3131
3232 public static String getSubName(final String name) {
3333 if (Strings.isEmpty(name)) {
3737 return i > 0 ? name.substring(0, i) : Strings.EMPTY;
3838 }
3939
40 /**
41 * Calculates the <a href="https://en.wikipedia.org/wiki/MD5">MD5</a> hash
42 * of the given input string encoded using the default platform
43 * {@link Charset charset}.
44 * <p>
45 * <b>MD5 has severe vulnerabilities and should not be used for sharing any
46 * sensitive information.</b> This function should only be used to create
47 * unique identifiers, e.g., configuration element names.
48 *
49 * @param input string to be hashed
50 * @return string composed of 32 hexadecimal digits of the calculated hash
51 */
52 public static String md5(final String input) {
53 Objects.requireNonNull(input, "input");
40 public static String md5(final String string) {
5441 try {
55 final byte[] inputBytes = input.getBytes();
5642 final MessageDigest digest = MessageDigest.getInstance("MD5");
57 final byte[] bytes = digest.digest(inputBytes);
58 final StringBuilder md5 = new StringBuilder(bytes.length * 2);
43 digest.update(string.getBytes());
44 final byte[] bytes = digest.digest();
45 final StringBuilder md5 = new StringBuilder();
5946 for (final byte b : bytes) {
60 final String hex = Integer.toHexString(0xFF & b);
47 final String hex = Integer.toHexString(MASK & b);
6148 if (hex.length() == 1) {
6249 md5.append('0');
6350 }
6451 md5.append(hex);
6552 }
6653 return md5.toString();
67 }
68 // Every implementation of the Java platform is required to support MD5.
69 // Hence, this catch block should be unreachable.
70 // See https://docs.oracle.com/javase/8/docs/api/java/security/MessageDigest.html
71 // for details.
72 catch (final NoSuchAlgorithmException error) {
73 throw new RuntimeException(error);
54 } catch (final Exception ex) {
55 return string;
7456 }
7557 }
76
7758 }
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.
5651 public static String getLocalHostname() {
5752 try {
5853 final InetAddress addr = InetAddress.getLocalHost();
59 return addr == null ? UNKNOWN_LOCALHOST : addr.getHostName();
54 return addr.getHostName();
6055 } catch (final UnknownHostException uhe) {
6156 try {
6257 final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
63 if (interfaces != null) {
64 while (interfaces.hasMoreElements()) {
65 final NetworkInterface nic = interfaces.nextElement();
66 final Enumeration<InetAddress> addresses = nic.getInetAddresses();
67 while (addresses.hasMoreElements()) {
68 final InetAddress address = addresses.nextElement();
69 if (!address.isLoopbackAddress()) {
70 final String hostname = address.getHostName();
71 if (hostname != null) {
72 return hostname;
73 }
58 while (interfaces.hasMoreElements()) {
59 final NetworkInterface nic = interfaces.nextElement();
60 final Enumeration<InetAddress> addresses = nic.getInetAddresses();
61 while (addresses.hasMoreElements()) {
62 final InetAddress address = addresses.nextElement();
63 if (!address.isLoopbackAddress()) {
64 final String hostname = address.getHostName();
65 if (hostname != null) {
66 return hostname;
7467 }
7568 }
7669 }
7770 }
7871 } catch (final SocketException se) {
79 // ignore and log below.
72 LOGGER.error("Could not determine local host name", uhe);
73 return UNKNOWN_LOCALHOST;
8074 }
8175 LOGGER.error("Could not determine local host name", uhe);
8276 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 }
12677 }
12778 }
12879
14394 }
14495 if (mac == null) {
14596 final Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
146 if (networkInterfaces != null) {
147 while (networkInterfaces.hasMoreElements() && mac == null) {
148 final NetworkInterface nic = networkInterfaces.nextElement();
149 if (isUpAndNotLoopback(nic)) {
150 mac = nic.getHardwareAddress();
151 }
97 while (networkInterfaces.hasMoreElements() && mac == null) {
98 final NetworkInterface nic = networkInterfaces.nextElement();
99 if (isUpAndNotLoopback(nic)) {
100 mac = nic.getHardwareAddress();
152101 }
153102 }
154103 }
155104 } catch (final SocketException e) {
156105 LOGGER.catching(e);
157106 }
158 if (ArrayUtils.isEmpty(mac) && localHost != null) {
159 // Emulate a MAC address with an IP v4 or v6
107 if (mac == null || mac.length == 0) {
108 // Emulate a mac address with an IP v4 or v6
160109 final byte[] address = localHost.getAddress();
161110 // Take only 6 bytes if the address is an IPv6 otherwise will pad with two zero bytes
162111 mac = Arrays.copyOf(address, 6);
173122 */
174123 public static String getMacAddressString() {
175124 final byte[] macAddr = getMacAddress();
176 if (!ArrayUtils.isEmpty(macAddr)) {
125 if (macAddr != null && macAddr.length > 0) {
177126 StringBuilder sb = new StringBuilder(String.format("%02x", macAddr[0]));
178127 for (int i = 1; i < macAddr.length; ++i) {
179128 sb.append(":").append(String.format("%02x", macAddr[i]));
8080 * @throws NullPointerException if <code>array</code> is <code>null</code>
8181 */
8282 public ObjectArrayIterator(final E array[], final int start, final int end) {
83 super();
8384 if (start < 0) {
8485 throw new ArrayIndexOutOfBoundsException("Start index must not be less than zero");
8586 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.io.InterruptedIOException;
1918 import java.util.Locale;
2019 import java.util.Properties;
2120
22 import org.apache.logging.log4j.Level;
2321 import org.apache.logging.log4j.Logger;
2422 import org.apache.logging.log4j.status.StatusLogger;
2523 import org.apache.logging.log4j.util.PropertiesUtil;
153151 }
154152 }
155153 return defaultValue;
156 }
157
158 public static Level toLevel(String value, Level defaultValue) {
159 if(value == null) {
160 return defaultValue;
161 }
162
163 value = value.trim();
164
165 int hashIndex = value.indexOf('#');
166 if (hashIndex == -1) {
167 if("NULL".equalsIgnoreCase(value)) {
168 return null;
169 } else {
170 // no class name specified : use standard Level class
171 return Level.toLevel(value, defaultValue);
172 }
173 }
174
175 Level result = defaultValue;
176
177 String clazz = value.substring(hashIndex+1);
178 String levelName = value.substring(0, hashIndex);
179
180 // This is degenerate case but you never know.
181 if("NULL".equalsIgnoreCase(levelName)) {
182 return null;
183 }
184
185 LOGGER.debug("toLevel" + ":class=[" + clazz + "]"
186 + ":pri=[" + levelName + "]");
187
188 try {
189 Class<?> customLevel = Loader.loadClass(clazz);
190
191 // get a ref to the specified class' static method
192 // toLevel(String, org.apache.log4j.Level)
193 Class<?>[] paramTypes = new Class[] { String.class, Level.class };
194 java.lang.reflect.Method toLevelMethod =
195 customLevel.getMethod("toLevel", paramTypes);
196
197 // now call the toLevel method, passing level string + default
198 Object[] params = new Object[] {levelName, defaultValue};
199 Object o = toLevelMethod.invoke(null, params);
200
201 result = (Level) o;
202 } catch(ClassNotFoundException e) {
203 LOGGER.warn("custom level class [" + clazz + "] not found.");
204 } catch(NoSuchMethodException e) {
205 LOGGER.warn("custom level class [" + clazz + "]"
206 + " does not have a class function toLevel(String, Level)", e);
207 } catch(java.lang.reflect.InvocationTargetException e) {
208 if (e.getTargetException() instanceof InterruptedException
209 || e.getTargetException() instanceof InterruptedIOException) {
210 Thread.currentThread().interrupt();
211 }
212 LOGGER.warn("custom level class [" + clazz + "]" + " could not be instantiated", e);
213 } catch(ClassCastException e) {
214 LOGGER.warn("class [" + clazz + "] is not a subclass of org.apache.log4j.Level", e);
215 } catch(IllegalAccessException e) {
216 LOGGER.warn("class ["+clazz+ "] cannot be instantiated due to access restrictions", e);
217 } catch(RuntimeException e) {
218 LOGGER.warn("class ["+clazz+"], level [" + levelName + "] conversion failed.", e);
219 }
220 return result;
221154 }
222155
223156 /**
296229 LOGGER.error("A \"{}\" object is not assignable to a \"{}\" variable.", className,
297230 superClass.getName());
298231 LOGGER.error("The class \"{}\" was loaded by [{}] whereas object of type [{}] was loaded by [{}].",
299 superClass.getName(), superClass.getClassLoader(), classObj.getTypeName(), classObj.getName());
232 superClass.getName(), superClass.getClassLoader(), classObj.getName());
300233 return defaultValue;
301234 }
302235 return classObj.newInstance();
179179 * @throws IllegalArgumentException if the given class is abstract, an interface, an array class, a primitive type,
180180 * or void
181181 * @throws IllegalStateException if access is denied to the constructor, or there are no default constructors
182 * @throws InternalException wrapper of the underlying exception if checked
183182 */
184183 public static <T> T instantiate(final Class<T> clazz) {
185184 Objects.requireNonNull(clazz, "No class provided");
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 java.util.HashSet;
19 import java.util.Set;
20
21 /**
22 * Set-related convenience methods.
23 */
24 public final class SetUtils {
25 private SetUtils() {
26 }
27
28 /**
29 * Extracts the Strings from a Set that start with a given prefix.
30 *
31 * @param set a Set of Strings (assumed to all be non-{@code null})
32 * @param prefix the prefix to look for in the string set
33 * @return an array of the matching strings from the given set
34 */
35 public static String[] prefixSet(final Set<String> set, final String prefix) {
36 final Set<String> prefixSet = new HashSet<>();
37 for (final String str : set) {
38 if (str.startsWith(prefix)) {
39 prefixSet.add(str);
40 }
41 }
42 return prefixSet.toArray(new String[prefixSet.size()]);
43 }
44 }
4646 /**
4747 * Adds a Runnable shutdown callback to this class.
4848 *
49 * Note: The returned {@code Cancellable} must be retained on heap by caller
50 * to avoid premature garbage-collection of the registered callback (and to ensure
51 * the callback runs on shutdown).
52 *
5349 * @param callback the shutdown callback to be executed upon shutdown.
5450 * @return a Cancellable wrapper of the provided callback or {@code null} if the shutdown hook is disabled and
5551 * cannot be added.
1616
1717 package org.apache.logging.log4j.core.util;
1818
19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream;
1921 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.MalformedURLException;
2027 import java.net.URI;
28 import java.net.URISyntaxException;
29 import java.net.URL;
2130 import java.util.Objects;
2231
32 import org.apache.logging.log4j.Level;
33 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2334 import org.apache.logging.log4j.core.config.ConfigurationSource;
35 import org.apache.logging.log4j.util.LoaderUtil;
2436
2537 /**
2638 * Represents the source for the logging configuration.
117129
118130 @Override
119131 public int hashCode() {
120 return 31 + Objects.hashCode(location);
132 return Objects.hash(location);
121133 }
122134 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.io.UnsupportedEncodingException;
1819 import java.nio.charset.Charset;
20 import java.nio.charset.StandardCharsets;
1921
2022 /**
2123 * Encodes Strings to bytes.
3638 */
3739 public static byte[] toBytes(final String str, final Charset charset) {
3840 if (str != null) {
39 return str.getBytes(charset != null ? charset : Charset.defaultCharset());
41 if (StandardCharsets.ISO_8859_1.equals(charset)) {
42 return encodeSingleByteChars(str);
43 }
44 final Charset actual = charset != null ? charset : Charset.defaultCharset();
45 try { // LOG4J2-935: String.getBytes(String) gives better performance
46 return str.getBytes(actual.name());
47 } catch (final UnsupportedEncodingException e) {
48 return str.getBytes(actual);
49 }
4050 }
4151 return null;
4252 }
4353
4454 /**
45 * Prefer standard {@link String#getBytes(Charset)} which performs better in Java 8 and beyond.
4655 * Encodes the specified char sequence by casting each character to a byte.
4756 *
4857 * @param s the char sequence to encode
4958 * @return the encoded String
5059 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-1151">LOG4J2-1151</a>
51 * @deprecated No longer necessary given better performance in Java 8
5260 */
53 @Deprecated
5461 public static byte[] encodeSingleByteChars(final CharSequence s) {
5562 final int length = s.length();
5663 final byte[] result = new byte[length];
5966 }
6067
6168 // LOG4J2-1151
62 /**
63 * Prefer standard {@link String#getBytes(Charset)} which performs better in Java 8 and beyond.
64 *
69 /*
6570 * Implementation note: this is the fast path. If the char array contains only ISO-8859-1 characters, all the work
6671 * will be done here.
67 *
68 * @deprecated No longer necessary given better performance in Java 8
6972 */
70 @Deprecated
7173 public static int encodeIsoChars(final CharSequence charArray, int charIndex, final byte[] byteArray, int byteIndex, final int length) {
7274 int i = 0;
7375 for (; i < length; i++) {
8183 }
8284
8385 // LOG4J2-1151
84
85 /**
86 * Prefer standard {@link String#getBytes(Charset)} which performs better in Java 8 and beyond.
87 * @deprecated No longer necessary given better performance in Java 8
88 */
89 @Deprecated
9086 public static int encodeString(final CharSequence charArray, int charOffset, int charLength, final byte[] byteArray) {
9187 int byteOffset = 0;
9288 int length = Math.min(charLength, byteArray.length);
3939 * @return the deepest throwable or the given throwable
4040 */
4141 public static Throwable getRootCause(final Throwable throwable) {
42
43 // Keep a second pointer that slowly walks the causal chain. If the fast
44 // pointer ever catches the slower pointer, then there's a loop.
45 Throwable slowPointer = throwable;
46 boolean advanceSlowPointer = false;
47
48 Throwable parent = throwable;
4942 Throwable cause;
50 while ((cause = parent.getCause()) != null) {
51 parent = cause;
52 if (parent == slowPointer) {
53 throw new IllegalArgumentException("loop in causal chain");
54 }
55 if (advanceSlowPointer) {
56 slowPointer = slowPointer.getCause();
57 }
58 advanceSlowPointer = !advanceSlowPointer; // only advance every other iteration
43 Throwable root = throwable;
44 while ((cause = root.getCause()) != null) {
45 root = cause;
5946 }
60 return parent;
61
47 return root;
6248 }
6349
6450 /**
6363 final char ch = input.charAt(i);
6464 if (ch > '>') {
6565 buf.append(ch);
66 } else
67 switch (ch) {
68 case '<':
69 buf.append("&lt;");
70 break;
71 case '>':
72 buf.append("&gt;");
73 break;
74 case '&':
75 buf.append("&amp;");
76 break;
77 case '"':
78 buf.append("&quot;");
79 break;
80 default:
81 buf.append(ch);
82 break;
83 }
66 } else if (ch == '<') {
67 buf.append("&lt;");
68 } else if (ch == '>') {
69 buf.append("&gt;");
70 } else if (ch == '&') {
71 buf.append("&amp;");
72 } else if (ch == '"') {
73 buf.append("&quot;");
74 } else {
75 buf.append(ch);
76 }
8477 }
8578 return buf.toString();
8679 }
2121 import java.lang.reflect.Type;
2222 import java.lang.reflect.WildcardType;
2323 import java.util.ArrayList;
24 import java.util.Collections;
2524 import java.util.List;
2625 import java.util.Objects;
2726
5352 public static List<Field> getAllDeclaredFields(Class<?> cls) {
5453 final List<Field> fields = new ArrayList<>();
5554 while (cls != null) {
56 Collections.addAll(fields, cls.getDeclaredFields());
55 for (final Field field : cls.getDeclaredFields()) {
56 fields.add(field);
57 }
5758 cls = cls.getSuperclass();
5859 }
5960 return fields;
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.net.InetAddress;
19 import java.net.NetworkInterface;
20 import java.net.SocketException;
21 import java.net.UnknownHostException;
1822 import java.nio.ByteBuffer;
1923 import java.security.SecureRandom;
24 import java.util.Enumeration;
2025 import java.util.Random;
2126 import java.util.UUID;
2227 import java.util.concurrent.atomic.AtomicInteger;
3035 * less than 10,000 IDs are generated per millisecond on the same device (as identified by its MAC address).
3136 */
3237 public final class UuidUtil {
33
34 private static final long[] EMPTY_LONG_ARRAY = {};
35
3638 /**
3739 * System property that may be used to seed the UUID generation with an integer value.
3840 */
4951 private static final long NUM_100NS_INTERVALS_SINCE_UUID_EPOCH = 0x01b21dd213814000L;
5052 private static final long INITIAL_UUID_SEQNO = PropertiesUtil.getProperties().getLongProperty(UUID_SEQUENCE, 0);
5153
54 private static final long LEAST;
55
5256 private static final long LOW_MASK = 0xffffffffL;
5357 private static final long MID_MASK = 0xffff00000000L;
5458 private static final long HIGH_MASK = 0xfff000000000000L;
5862 private static final int SHIFT_6 = 48;
5963 private static final int HUNDRED_NANOS_PER_MILLI = 10000;
6064
61 private static final long LEAST = initialize(NetUtils.getMacAddress());
62
63 /* This class cannot be instantiated */
64 private UuidUtil() {
65 }
66
67 /**
68 * Initializes this class
69 *
70 * @param mac MAC address
71 * @return Least
72 */
73 static long initialize(byte[] mac) {
65 static {
66 byte[] mac = NetUtils.getMacAddress();
7467 final Random randomGenerator = new SecureRandom();
7568 if (mac == null || mac.length == 0) {
7669 mac = new byte[6];
8477 for (int i = 2; i < NODE_SIZE; ++i) {
8578 node[i] = 0;
8679 }
87 System.arraycopy(mac, index, node, 2, length);
80 System.arraycopy(mac, index, node, index + 2, length);
8881 final ByteBuffer buf = ByteBuffer.wrap(node);
8982 long rand = INITIAL_UUID_SEQNO;
9083 String assigned = PropertiesUtil.getProperties().getStringProperty(ASSIGNED_SEQUENCES);
9184 long[] sequences;
9285 if (assigned == null) {
93 sequences = EMPTY_LONG_ARRAY;
86 sequences = new long[0];
9487 } else {
9588 final String[] array = assigned.split(Patterns.COMMA_SEPARATOR);
9689 sequences = new long[array.length];
120113 assigned = assigned == null ? Long.toString(rand) : assigned + ',' + Long.toString(rand);
121114 System.setProperty(ASSIGNED_SEQUENCES, assigned);
122115
123 return buf.getLong() | rand << SHIFT_6;
116 LEAST = buf.getLong() | rand << SHIFT_6;
117 }
118
119
120 /* This class cannot be instantiated */
121 private UuidUtil() {
124122 }
125123
126124 /**
2121 import java.util.HashMap;
2222 import java.util.List;
2323 import java.util.Map;
24 import java.util.Objects;
2524 import java.util.ServiceLoader;
2625 import java.util.UUID;
2726 import java.util.concurrent.ConcurrentHashMap;
2827 import java.util.concurrent.ConcurrentMap;
2928 import java.util.concurrent.ScheduledFuture;
3029 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.atomic.AtomicInteger;
3230
3331 import org.apache.logging.log4j.Logger;
3432 import org.apache.logging.log4j.core.AbstractLifeCycle;
4543 */
4644 public class WatchManager extends AbstractLifeCycle {
4745
48 private final class ConfigurationMonitor {
49 private final Watcher watcher;
50 private volatile long lastModifiedMillis;
51
52 public ConfigurationMonitor(final long lastModifiedMillis, final Watcher watcher) {
53 this.watcher = watcher;
54 this.lastModifiedMillis = lastModifiedMillis;
55 }
56
57 public Watcher getWatcher() {
58 return watcher;
59 }
60
61 private void setLastModifiedMillis(final long lastModifiedMillis) {
62 this.lastModifiedMillis = lastModifiedMillis;
63 }
64
65 @Override
66 public String toString() {
67 return "ConfigurationMonitor [watcher=" + watcher + ", lastModifiedMillis=" + lastModifiedMillis + "]";
68 }
69 }
70
71 private static class LocalUUID {
72 private static final long LOW_MASK = 0xffffffffL;
73 private static final long MID_MASK = 0xffff00000000L;
74 private static final long HIGH_MASK = 0xfff000000000000L;
75 private static final int NODE_SIZE = 8;
76 private static final int SHIFT_2 = 16;
77 private static final int SHIFT_4 = 32;
78 private static final int SHIFT_6 = 48;
79 private static final int HUNDRED_NANOS_PER_MILLI = 10000;
80 private static final long NUM_100NS_INTERVALS_SINCE_UUID_EPOCH = 0x01b21dd213814000L;
81 private static final AtomicInteger COUNT = new AtomicInteger(0);
82 private static final long TYPE1 = 0x1000L;
83 private static final byte VARIANT = (byte) 0x80;
84 private static final int SEQUENCE_MASK = 0x3FFF;
85
86
87 public static UUID get() {
88 final long time = ((System.currentTimeMillis() * HUNDRED_NANOS_PER_MILLI) +
89 NUM_100NS_INTERVALS_SINCE_UUID_EPOCH) + (COUNT.incrementAndGet() % HUNDRED_NANOS_PER_MILLI);
90 final long timeLow = (time & LOW_MASK) << SHIFT_4;
91 final long timeMid = (time & MID_MASK) >> SHIFT_2;
92 final long timeHi = (time & HIGH_MASK) >> SHIFT_6;
93 final long most = timeLow | timeMid | TYPE1 | timeHi;
94 return new UUID(most, COUNT.incrementAndGet());
95 }
96 }
46 private static Logger logger = StatusLogger.getLogger();
47 private final ConcurrentMap<Source, ConfigurationMonitor> watchers = new ConcurrentHashMap<>();
48 private int intervalSeconds = 0;
49 private ScheduledFuture<?> future;
50 private final ConfigurationScheduler scheduler;
51 private final List<WatchEventService> eventServiceList;
52 private final UUID id = UuidUtil.getTimeBasedUuid();
53
54 public WatchManager(final ConfigurationScheduler scheduler) {
55 this.scheduler = scheduler;
56 eventServiceList = getEventServices();
57 }
58
59 public UUID getId() {
60 return this.id;
61 }
62
63 public boolean hasEventListeners() {
64 return eventServiceList.size() > 0;
65 }
66
67 /**
68 * Resets all file monitors to their current last modified time. If this manager does not watch any file, nothing
69 * happens.
70 * <p>
71 * This allows you to start, stop, reset and start again a manager, without triggering file modified events if the a
72 * watched file has changed during the period of time when the manager was stopped.
73 * </p>
74 *
75 * @since 2.11.0
76 */
77 public void reset() {
78 logger.debug("Resetting {}", this);
79 for (final Source source : watchers.keySet()) {
80 reset(source);
81 }
82 }
83
84 /**
85 * Resets the file monitor for the given file being watched to its current last modified time. If this manager does
86 * not watch the given file, nothing happens.
87 * <p>
88 * This allows you to start, stop, reset and start again a manager, without triggering file modified events if the
89 * given watched file has changed during the period of time when the manager was stopped.
90 * </p>
91 *
92 * @param file the file for the monitor to reset.
93 * @since 2.11.0
94 */
95 public void reset(final File file) {
96 if (file == null) {
97 return;
98 }
99 Source source = new Source(file);
100 reset(source);
101 }
102
103 /**
104 * Resets the configuration monitor for the given file being watched to its current last modified time. If this
105 * manager does not watch the given configuration, nothing happens.
106 * <p>
107 * This allows you to start, stop, reset and start again a manager, without triggering file modified events if the
108 * given watched configuration has changed during the period of time when the manager was stopped.
109 * </p>
110 *
111 * @param source the Source for the monitor to reset.
112 * @since 2.12.0
113 */
114 public void reset(final Source source) {
115 if (source == null) {
116 return;
117 }
118 final ConfigurationMonitor monitor = watchers.get(source);
119 if (monitor != null) {
120 Watcher watcher = monitor.getWatcher();
121 if (watcher.isModified()) {
122 final long lastModifiedMillis = watcher.getLastModified();
123 if (logger.isDebugEnabled()) {
124 logger.debug("Resetting file monitor for '{}' from {} ({}) to {} ({})", source.getLocation(),
125 millisToString(monitor.lastModifiedMillis), monitor.lastModifiedMillis,
126 millisToString(lastModifiedMillis), lastModifiedMillis);
127 }
128 monitor.setLastModifiedMillis(lastModifiedMillis);
129 }
130 }
131 }
132
133 public void setIntervalSeconds(final int intervalSeconds) {
134 if (!isStarted()) {
135 if (this.intervalSeconds > 0 && intervalSeconds == 0) {
136 scheduler.decrementScheduledItems();
137 } else {
138 if (this.intervalSeconds == 0 && intervalSeconds > 0) {
139 scheduler.incrementScheduledItems();
140 }
141 }
142 this.intervalSeconds = intervalSeconds;
143 }
144 }
145
146 /**
147 * Gets how often this manager checks for file modifications.
148 *
149 * @return how often, in seconds, this manager checks for file modifications.
150 */
151 public int getIntervalSeconds() {
152 return this.intervalSeconds;
153 }
154
155 @Override
156 public void start() {
157 super.start();
158
159 if (intervalSeconds > 0) {
160 future = scheduler
161 .scheduleWithFixedDelay(new WatchRunnable(), intervalSeconds, intervalSeconds, TimeUnit.SECONDS);
162 }
163 for (WatchEventService service : eventServiceList) {
164 service.subscribe(this);
165 }
166 }
167
168 @Override
169 public boolean stop(final long timeout, final TimeUnit timeUnit) {
170 setStopping();
171 for (WatchEventService service : eventServiceList) {
172 service.unsubscribe(this);
173 }
174 final boolean stopped = stop(future);
175 setStopped();
176 return stopped;
177 }
178
179 /**
180 * Unwatches the given file.
181 *
182 * @param file the file to stop watching.
183 * @since 2.11.0
184 */
185 public void unwatchFile(final File file) {
186 Source source = new Source(file);
187 unwatch(source);
188 }
189
190 /**
191 * Unwatches the given file.
192 *
193 * @param source the Source to stop watching.
194 * the file to stop watching.
195 * @since 2.12.0
196 */
197 public void unwatch(final Source source) {
198 logger.debug("Unwatching configuration {}", source);
199 watchers.remove(source);
200 }
201
202 public void checkFiles() {
203 new WatchRunnable().run();
204 }
205
206 /**
207 * Watches the given file.
208 *
209 * @param file the file to watch.
210 * @param fileWatcher the watcher to notify of file changes.
211 */
212 public void watchFile(final File file, final FileWatcher fileWatcher) {
213 Watcher watcher;
214 if (fileWatcher instanceof Watcher) {
215 watcher = (Watcher) fileWatcher;
216 } else {
217 watcher = new WrappedFileWatcher(fileWatcher);
218 }
219 Source source = new Source(file);
220 watch(source, watcher);
221 }
222
223 /**
224 * Watches the given file.
225 *
226 * @param source the source to watch.
227 * @param watcher the watcher to notify of file changes.
228 */
229 public void watch(final Source source, final Watcher watcher) {
230 watcher.watching(source);
231 final long lastModified = watcher.getLastModified();
232 if (logger.isDebugEnabled()) {
233 logger.debug("Watching configuration '{}' for lastModified {} ({})", source, millisToString(lastModified),
234 lastModified);
235 }
236 watchers.put(source, new ConfigurationMonitor(lastModified, watcher));
237 }
238
239 /**
240 * Returns a Map of the file watchers.
241 *
242 * @return A Map of the file watchers.
243 * @deprecated use getConfigurationWatchers.
244 */
245 public Map<File, FileWatcher> getWatchers() {
246 final Map<File, FileWatcher> map = new HashMap<>(watchers.size());
247 for (Map.Entry<Source, ConfigurationMonitor> entry : watchers.entrySet()) {
248 if (entry.getValue().getWatcher() instanceof ConfigurationFileWatcher) {
249 map.put(entry.getKey().getFile(), (FileWatcher) entry.getValue().getWatcher());
250 } else {
251 map.put(entry.getKey().getFile(), new WrappedFileWatcher((FileWatcher) entry.getValue().getWatcher()));
252 }
253 }
254 return map;
255 }
256
257 /**
258 * Return the ConfigurationWaatchers.
259 *
260 * @return the ConfigurationWatchers.
261 * @since 2.11.2
262 */
263 public Map<Source, Watcher> getConfigurationWatchers() {
264 final Map<Source, Watcher> map = new HashMap<>(watchers.size());
265 for (final Map.Entry<Source, ConfigurationMonitor> entry : watchers.entrySet()) {
266 map.put(entry.getKey(), entry.getValue().getWatcher());
267 }
268 return map;
269 }
270
271 private String millisToString(final long millis) {
272 return new Date(millis).toString();
273 }
274
275 private List<WatchEventService> getEventServices() {
276 List<WatchEventService> list = new ArrayList<>();
277 for (final ClassLoader classLoader : LoaderUtil.getClassLoaders()) {
278 try {
279 final ServiceLoader<WatchEventService> serviceLoader = ServiceLoader
280 .load(WatchEventService.class, classLoader);
281 for (final WatchEventService service : serviceLoader) {
282 list.add(service);
283 }
284 } catch (final Throwable ex) {
285 LOGGER.debug("Unable to retrieve WatchEventService from ClassLoader {}", classLoader, ex);
286 }
287 }
288 return list;
289 }
290
97291 private final class WatchRunnable implements Runnable {
98292
99293 // Use a hard class reference here in case a refactoring changes the class name.
119313 logger.trace("{} run ended.", SIMPLE_NAME);
120314 }
121315 }
122 private static Logger logger = StatusLogger.getLogger();
123 private final ConcurrentMap<Source, ConfigurationMonitor> watchers = new ConcurrentHashMap<>();
124 private int intervalSeconds = 0;
125 private ScheduledFuture<?> future;
126
127 private final ConfigurationScheduler scheduler;
128
129 private final List<WatchEventService> eventServiceList;
130
131 // This just needs to be a unique key within the WatchEventManager.
132 private final UUID id = LocalUUID.get();
133
134 public WatchManager(final ConfigurationScheduler scheduler) {
135 this.scheduler = Objects.requireNonNull(scheduler, "scheduler");
136 eventServiceList = getEventServices();
137 }
138
139 public void checkFiles() {
140 new WatchRunnable().run();
141 }
142
143 /**
144 * Return the ConfigurationWaatchers.
145 *
146 * @return the ConfigurationWatchers.
147 * @since 2.11.2
148 */
149 public Map<Source, Watcher> getConfigurationWatchers() {
150 final Map<Source, Watcher> map = new HashMap<>(watchers.size());
151 for (final Map.Entry<Source, ConfigurationMonitor> entry : watchers.entrySet()) {
152 map.put(entry.getKey(), entry.getValue().getWatcher());
153 }
154 return map;
155 }
156
157 private List<WatchEventService> getEventServices() {
158 List<WatchEventService> list = new ArrayList<>();
159 for (final ClassLoader classLoader : LoaderUtil.getClassLoaders()) {
160 try {
161 final ServiceLoader<WatchEventService> serviceLoader = ServiceLoader
162 .load(WatchEventService.class, classLoader);
163 for (final WatchEventService service : serviceLoader) {
164 list.add(service);
165 }
166 } catch (final Throwable ex) {
167 LOGGER.debug("Unable to retrieve WatchEventService from ClassLoader {}", classLoader, ex);
168 }
169 }
170 return list;
171 }
172
173 public UUID getId() {
174 return this.id;
175 }
176
177 /**
178 * Gets how often this manager checks for file modifications.
179 *
180 * @return how often, in seconds, this manager checks for file modifications.
181 */
182 public int getIntervalSeconds() {
183 return this.intervalSeconds;
184 }
185
186 /**
187 * Returns a Map of the file watchers.
188 *
189 * @return A Map of the file watchers.
190 * @deprecated use getConfigurationWatchers.
191 */
192 @Deprecated
193 public Map<File, FileWatcher> getWatchers() {
194 final Map<File, FileWatcher> map = new HashMap<>(watchers.size());
195 for (Map.Entry<Source, ConfigurationMonitor> entry : watchers.entrySet()) {
196 if (entry.getValue().getWatcher() instanceof ConfigurationFileWatcher) {
197 map.put(entry.getKey().getFile(), (FileWatcher) entry.getValue().getWatcher());
198 } else {
199 map.put(entry.getKey().getFile(), new WrappedFileWatcher((FileWatcher) entry.getValue().getWatcher()));
200 }
201 }
202 return map;
203 }
204
205 public boolean hasEventListeners() {
206 return eventServiceList.size() > 0;
207 }
208
209 private String millisToString(final long millis) {
210 return new Date(millis).toString();
211 }
212
213 /**
214 * Resets all file monitors to their current last modified time. If this manager does not watch any file, nothing
215 * happens.
216 * <p>
217 * This allows you to start, stop, reset and start again a manager, without triggering file modified events if the a
218 * watched file has changed during the period of time when the manager was stopped.
219 * </p>
220 *
221 * @since 2.11.0
222 */
223 public void reset() {
224 logger.debug("Resetting {}", this);
225 for (final Source source : watchers.keySet()) {
226 reset(source);
227 }
228 }
229
230 /**
231 * Resets the file monitor for the given file being watched to its current last modified time. If this manager does
232 * not watch the given file, nothing happens.
233 * <p>
234 * This allows you to start, stop, reset and start again a manager, without triggering file modified events if the
235 * given watched file has changed during the period of time when the manager was stopped.
236 * </p>
237 *
238 * @param file the file for the monitor to reset.
239 * @since 2.11.0
240 */
241 public void reset(final File file) {
242 if (file == null) {
243 return;
244 }
245 Source source = new Source(file);
246 reset(source);
247 }
248
249 /**
250 * Resets the configuration monitor for the given file being watched to its current last modified time. If this
251 * manager does not watch the given configuration, nothing happens.
252 * <p>
253 * This allows you to start, stop, reset and start again a manager, without triggering file modified events if the
254 * given watched configuration has changed during the period of time when the manager was stopped.
255 * </p>
256 *
257 * @param source the Source for the monitor to reset.
258 * @since 2.12.0
259 */
260 public void reset(final Source source) {
261 if (source == null) {
262 return;
263 }
264 final ConfigurationMonitor monitor = watchers.get(source);
265 if (monitor != null) {
266 Watcher watcher = monitor.getWatcher();
267 if (watcher.isModified()) {
268 final long lastModifiedMillis = watcher.getLastModified();
269 if (logger.isDebugEnabled()) {
270 logger.debug("Resetting file monitor for '{}' from {} ({}) to {} ({})", source.getLocation(),
271 millisToString(monitor.lastModifiedMillis), monitor.lastModifiedMillis,
272 millisToString(lastModifiedMillis), lastModifiedMillis);
273 }
274 monitor.setLastModifiedMillis(lastModifiedMillis);
275 }
276 }
277 }
278
279 public void setIntervalSeconds(final int intervalSeconds) {
280 if (!isStarted()) {
281 if (this.intervalSeconds > 0 && intervalSeconds == 0) {
282 scheduler.decrementScheduledItems();
283 } else if (this.intervalSeconds == 0 && intervalSeconds > 0) {
284 scheduler.incrementScheduledItems();
285 }
286 this.intervalSeconds = intervalSeconds;
287 }
288 }
289
290 @Override
291 public void start() {
292 super.start();
293
294 if (intervalSeconds > 0) {
295 future = scheduler
296 .scheduleWithFixedDelay(new WatchRunnable(), intervalSeconds, intervalSeconds, TimeUnit.SECONDS);
297 }
298 for (WatchEventService service : eventServiceList) {
299 service.subscribe(this);
300 }
301 }
302
303 @Override
304 public boolean stop(final long timeout, final TimeUnit timeUnit) {
305 setStopping();
306 for (WatchEventService service : eventServiceList) {
307 service.unsubscribe(this);
308 }
309 final boolean stopped = stop(future);
310 setStopped();
311 return stopped;
316
317 private final class ConfigurationMonitor {
318 private final Watcher watcher;
319 private volatile long lastModifiedMillis;
320
321 public Watcher getWatcher() {
322 return watcher;
323 }
324
325 public ConfigurationMonitor(final long lastModifiedMillis, final Watcher watcher) {
326 this.watcher = watcher;
327 this.lastModifiedMillis = lastModifiedMillis;
328 }
329
330 private void setLastModifiedMillis(final long lastModifiedMillis) {
331 this.lastModifiedMillis = lastModifiedMillis;
332 }
333
334 @Override
335 public String toString() {
336 return "ConfigurationMonitor [watcher=" + watcher + ", lastModifiedMillis=" + lastModifiedMillis + "]";
337 }
338
312339 }
313340
314341 @Override
316343 return "WatchManager [intervalSeconds=" + intervalSeconds + ", watchers=" + watchers + ", scheduler="
317344 + scheduler + ", future=" + future + "]";
318345 }
319
320 /**
321 * Unwatches the given file.
322 *
323 * @param source the Source to stop watching.
324 * the file to stop watching.
325 * @since 2.12.0
326 */
327 public void unwatch(final Source source) {
328 logger.debug("Unwatching configuration {}", source);
329 watchers.remove(source);
330 }
331
332 /**
333 * Unwatches the given file.
334 *
335 * @param file the file to stop watching.
336 * @since 2.11.0
337 */
338 public void unwatchFile(final File file) {
339 Source source = new Source(file);
340 unwatch(source);
341 }
342
343 /**
344 * Watches the given file.
345 *
346 * @param source the source to watch.
347 * @param watcher the watcher to notify of file changes.
348 */
349 public void watch(final Source source, final Watcher watcher) {
350 watcher.watching(source);
351 final long lastModified = watcher.getLastModified();
352 if (logger.isDebugEnabled()) {
353 logger.debug("Watching configuration '{}' for lastModified {} ({})", source, millisToString(lastModified),
354 lastModified);
355 }
356 watchers.put(source, new ConfigurationMonitor(lastModified, watcher));
357 }
358
359 /**
360 * Watches the given file.
361 *
362 * @param file the file to watch.
363 * @param fileWatcher the watcher to notify of file changes.
364 */
365 public void watchFile(final File file, final FileWatcher fileWatcher) {
366 Watcher watcher;
367 if (fileWatcher instanceof Watcher) {
368 watcher = (Watcher) fileWatcher;
369 } else {
370 watcher = new WrappedFileWatcher(fileWatcher);
371 }
372 Source source = new Source(file);
373 watch(source, watcher);
374 }
375346 }
1717
1818 import java.util.List;
1919
20 import org.apache.logging.log4j.core.config.Configuration;
2021 import org.apache.logging.log4j.core.config.ConfigurationListener;
2122 import org.apache.logging.log4j.core.config.Reconfigurable;
2223
3839
3940 /**
4041 * Called when the configuration has been modified.
42 * @param source The location of the configuration that was modified.
4143 */
4244 void modified();
4345
4951
5052 /**
5153 * Returns the time the source was last modified or 0 if it is not available.
52 * @return the time the source was last modified.
54 * @return the time the soruce was last modified.
5355 */
5456 long getLastModified();
5557
3838 private static Logger LOGGER = StatusLogger.getLogger();
3939 private static PluginManager pluginManager = new PluginManager(Watcher.CATEGORY);
4040
41 private static volatile WatcherFactory factory;
41 private static volatile WatcherFactory factory = null;
4242
4343 private final Map<String, PluginType<?>> plugins;
4444
4545 this.watcher = watcher;
4646 }
4747
48 @Override
4948 public long getLastModified() {
5049 return lastModifiedMillis;
5150 }
9797 // comparator used to sort regex alternatives
9898 // alternatives should be ordered longer first, and shorter last. ('february' before 'feb')
9999 // all entries must be lowercase by locale.
100 private static final Comparator<String> LONGER_FIRST_LOWERCASE = (left, right) -> right.compareTo(left);
100 private static final Comparator<String> LONGER_FIRST_LOWERCASE = new Comparator<String>() {
101 @Override
102 public int compare(final String left, final String right) {
103 return right.compareTo(left);
104 }
105 };
101106
102107 /**
103108 * <p>Constructs a new FastDateParser.</p>
933933 *
934934 */
935935 UnpaddedMonthField() {
936 super();
936937 }
937938
938939 /**
10651066 * Constructs an instance of {@code TwoDigitYearField}.
10661067 */
10671068 TwoDigitYearField() {
1069 super();
10681070 }
10691071
10701072 /**
11021104 * Constructs an instance of {@code TwoDigitMonthField}.
11031105 */
11041106 TwoDigitMonthField() {
1107 super();
11051108 }
11061109
11071110 /**
133133 /**
134134 * ISO8601 time format: {@code "yyyy-MM-dd'T'HH:mm:ss.SSS"}.
135135 */
136 ISO8601_PERIOD("yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'", 2, ':', 1, '.', 1, 3, null),
137
138 /**
139 * ISO8601 time format with support for microsecond precision: {@code "yyyy-MM-dd'T'HH:mm:ss.nnnnnn"}.
140 */
141 ISO8601_PERIOD_MICROS("yyyy-MM-dd'T'HH:mm:ss.nnnnnn", "yyyy-MM-dd'T'", 2, ':', 1, '.', 1, 6, null),
142
143 /**
144 * American date/time format with 2-digit year: {@code "dd/MM/yy HH:mm:ss.SSS"}.
145 */
146 US_MONTH_DAY_YEAR2_TIME("dd/MM/yy HH:mm:ss.SSS", "dd/MM/yy ", 0, ':', 1, '.', 1, 3, null),
147
148 /**
149 * American date/time format with 4-digit year: {@code "dd/MM/yyyy HH:mm:ss.SSS"}.
150 */
151 US_MONTH_DAY_YEAR4_TIME("dd/MM/yyyy HH:mm:ss.SSS", "dd/MM/yyyy ", 0, ':', 1, '.', 1, 3, null);
136 ISO8601_PERIOD("yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'", 2, ':', 1, '.', 1, 3, null);
152137
153138 private static final String DEFAULT_SECOND_FRACTION_PATTERN = "SSS";
154139 private static final int MILLI_FRACTION_DIGITS = DEFAULT_SECOND_FRACTION_PATTERN.length();
397382 private final int millisSeparatorLength;
398383 private final FixedTimeZoneFormat fixedTimeZoneFormat;
399384
400 private volatile long midnightToday;
401 private volatile long midnightTomorrow;
385 private volatile long midnightToday = 0;
386 private volatile long midnightTomorrow = 0;
402387 private final int[] dstOffsets = new int[25];
403388
404389 // cachedDate does not need to be volatile because
461446 }
462447
463448 final String option0 = options[0];
464 final FixedFormat withoutNanos = FixedFormat.lookupIgnoringNanos(option0);
465 if (withoutNanos != null) {
449 final FixedFormat withNanos = FixedFormat.lookupIgnoringNanos(option0);
450 if (withNanos != null) {
466451 final int[] nanoRange = FixedFormat.nanoRange(option0);
467452 final int nanoStart = nanoRange[0];
468453 final int nanoEnd = nanoRange[1];
469454 final int secondFractionDigits = nanoEnd - nanoStart;
470 return new FixedDateFormat(withoutNanos, tz, secondFractionDigits);
455 return new FixedDateFormat(withNanos, tz, secondFractionDigits);
471456 }
472457 final FixedFormat type = FixedFormat.lookup(option0);
473458 return type == null ? null : new FixedDateFormat(type, tz);
708693 private int daylightSavingTime(final int hourOfDay) {
709694 return hourOfDay > 23 ? dstOffsets[23] : dstOffsets[hourOfDay];
710695 }
711
712 /**
713 * Returns {@code true} if the old and new date values will result in the same formatted output, {@code false}
714 * if results <i>may</i> differ.
715 */
716 public boolean isEquivalent(long oldEpochSecond, int oldNanoOfSecond, long epochSecond, int nanoOfSecond) {
717 if (oldEpochSecond == epochSecond) {
718 if (secondFractionDigits <= 3) {
719 // Convert nanos to milliseconds for comparison if the format only requires milliseconds.
720 return (oldNanoOfSecond / 1000_000L) == (nanoOfSecond / 1000_000L);
721 }
722 return oldNanoOfSecond == nanoOfSecond;
723 }
724 return false;
725 }
726696 }
+0
-1
log4j-core/src/main/resources/META-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider less more
0 org.apache.logging.log4j.core.impl.ThreadContextDataProvider
2121 import java.util.List;
2222 import java.util.Map;
2323 import java.util.Set;
24
25 import org.apache.logging.log4j.util.Strings;
2624
2725 /**
2826 * Container for a complete SMTP message - headers and message body.
8583 public String[] getHeaderValues(final String name) {
8684 final List<String> values = headers.get(name);
8785 if (values == null) {
88 return Strings.EMPTY_ARRAY;
86 return new String[0];
8987 }
9088 return values.toArray(new String[values.size()]);
9189 }
9090 } else {
9191 response = new SmtpResponse(500, "Command not recognized", this.state);
9292 }
93 // Stateful commands
94 } else if (SmtpActionType.CONNECT == action) {
95 if (SmtpState.CONNECT == state) {
96 response = new SmtpResponse(220, "localhost Dumbster SMTP service ready", SmtpState.GREET);
97 } else {
98 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
99 }
100 } else if (SmtpActionType.EHLO == action) {
101 if (SmtpState.GREET == state) {
102 response = new SmtpResponse(250, "OK", SmtpState.MAIL);
103 } else {
104 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
105 }
106 } else if (SmtpActionType.MAIL == action) {
107 if (SmtpState.MAIL == state || SmtpState.QUIT == state) {
108 response = new SmtpResponse(250, "OK", SmtpState.RCPT);
109 } else {
110 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
111 }
112 } else if (SmtpActionType.RCPT == action) {
113 if (SmtpState.RCPT == state) {
114 response = new SmtpResponse(250, "OK", this.state);
115 } else {
116 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
117 }
118 } else if (SmtpActionType.DATA == action) {
119 if (SmtpState.RCPT == state) {
120 response = new SmtpResponse(354, "Start mail input; end with <CRLF>.<CRLF>", SmtpState.DATA_HDR);
121 } else {
122 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
123 }
124 } else if (SmtpActionType.UNRECOG == action) {
125 if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
126 response = new SmtpResponse(-1, Strings.EMPTY, this.state);
93 } else { // Stateful commands
94 if (SmtpActionType.CONNECT == action) {
95 if (SmtpState.CONNECT == state) {
96 response = new SmtpResponse(220, "localhost Dumbster SMTP service ready", SmtpState.GREET);
97 } else {
98 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
99 }
100 } else if (SmtpActionType.EHLO == action) {
101 if (SmtpState.GREET == state) {
102 response = new SmtpResponse(250, "OK", SmtpState.MAIL);
103 } else {
104 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
105 }
106 } else if (SmtpActionType.MAIL == action) {
107 if (SmtpState.MAIL == state || SmtpState.QUIT == state) {
108 response = new SmtpResponse(250, "OK", SmtpState.RCPT);
109 } else {
110 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
111 }
112 } else if (SmtpActionType.RCPT == action) {
113 if (SmtpState.RCPT == state) {
114 response = new SmtpResponse(250, "OK", this.state);
115 } else {
116 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
117 }
118 } else if (SmtpActionType.DATA == action) {
119 if (SmtpState.RCPT == state) {
120 response = new SmtpResponse(354, "Start mail input; end with <CRLF>.<CRLF>", SmtpState.DATA_HDR);
121 } else {
122 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
123 }
124 } else if (SmtpActionType.UNRECOG == action) {
125 if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
126 response = new SmtpResponse(-1, Strings.EMPTY, this.state);
127 } else {
128 response = new SmtpResponse(500, "Command not recognized", this.state);
129 }
130 } else if (SmtpActionType.DATA_END == action) {
131 if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
132 response = new SmtpResponse(250, "OK", SmtpState.QUIT);
133 } else {
134 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
135 }
136 } else if (SmtpActionType.BLANK_LINE == action) {
137 if (SmtpState.DATA_HDR == state) {
138 response = new SmtpResponse(-1, Strings.EMPTY, SmtpState.DATA_BODY);
139 } else if (SmtpState.DATA_BODY == state) {
140 response = new SmtpResponse(-1, Strings.EMPTY, this.state);
141 } else {
142 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
143 }
144 } else if (SmtpActionType.QUIT == action) {
145 if (SmtpState.QUIT == state) {
146 response = new SmtpResponse(221, "localhost Dumbster service closing transmission channel",
147 SmtpState.CONNECT);
148 } else {
149 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
150 }
127151 } else {
128152 response = new SmtpResponse(500, "Command not recognized", this.state);
129153 }
130 } else if (SmtpActionType.DATA_END == action) {
131 if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
132 response = new SmtpResponse(250, "OK", SmtpState.QUIT);
133 } else {
134 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
135 }
136 } else if (SmtpActionType.BLANK_LINE == action) {
137 if (SmtpState.DATA_HDR == state) {
138 response = new SmtpResponse(-1, Strings.EMPTY, SmtpState.DATA_BODY);
139 } else if (SmtpState.DATA_BODY == state) {
140 response = new SmtpResponse(-1, Strings.EMPTY, this.state);
141 } else {
142 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
143 }
144 } else if (SmtpActionType.QUIT == action) {
145 if (SmtpState.QUIT == state) {
146 response = new SmtpResponse(221, "localhost Dumbster service closing transmission channel",
147 SmtpState.CONNECT);
148 } else {
149 response = new SmtpResponse(503, "Bad sequence of commands: " + action, this.state);
150 }
151 } else {
152 response = new SmtpResponse(500, "Command not recognized", this.state);
153154 }
154155 return response;
155156 }
1717
1818 import org.apache.logging.log4j.Marker;
1919 import org.apache.logging.log4j.MarkerManager;
20 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextSource;
20 import org.apache.logging.log4j.categories.Configurations;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2222 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Tag;
24 import org.junit.jupiter.api.Test;
23 import org.junit.Before;
24 import org.junit.ClassRule;
25 import org.junit.Test;
26 import org.junit.experimental.categories.Category;
2527
26 import static org.hamcrest.MatcherAssert.*;
2728 import static org.hamcrest.Matchers.hasSize;
29 import static org.junit.Assert.*;
2830
29 @Tag("json")
30 @LoggerContextSource("log4j-reference-level.json")
31 /**
32 *
33 */
34 @Category(Configurations.Json.class)
3135 public class AppenderRefLevelJsonTest {
3236
33 private final ListAppender app1;
34 private final ListAppender app2;
37 private static final String CONFIG = "log4j-reference-level.json";
38 private ListAppender app1;
39 private ListAppender app2;
3540
36 org.apache.logging.log4j.Logger logger1;
37 org.apache.logging.log4j.Logger logger2;
38 org.apache.logging.log4j.Logger logger3;
41 @ClassRule
42 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
43
44 org.apache.logging.log4j.Logger logger1 = context.getLogger("org.apache.logging.log4j.test1");
45 org.apache.logging.log4j.Logger logger2 = context.getLogger("org.apache.logging.log4j.test2");
46 org.apache.logging.log4j.Logger logger3 = context.getLogger("org.apache.logging.log4j.test3");
3947 Marker testMarker = MarkerManager.getMarker("TEST");
4048
41 public AppenderRefLevelJsonTest(final LoggerContext context, @Named("LIST1") final ListAppender first, @Named("LIST2") final ListAppender second) {
42 logger1 = context.getLogger("org.apache.logging.log4j.test1");
43 logger2 = context.getLogger("org.apache.logging.log4j.test2");
44 logger3 = context.getLogger("org.apache.logging.log4j.test3");
45 app1 = first.clear();
46 app2 = second.clear();
49 @Before
50 public void before() {
51 app1 = context.getListAppender("LIST1").clear();
52 app2 = context.getListAppender("LIST2").clear();
4753 }
4854
4955 @Test
1919
2020 import org.apache.logging.log4j.Marker;
2121 import org.apache.logging.log4j.MarkerManager;
22 import org.apache.logging.log4j.junit.Named;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2423 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.ClassRule;
26 import org.junit.Test;
2627
27 import static org.junit.jupiter.api.Assertions.*;
28 import static org.junit.Assert.*;
2829
29 @LoggerContextSource("log4j-reference-level.xml")
30 /**
31 *
32 */
3033 public class AppenderRefLevelTest {
3134
32 private final ListAppender app1;
33 private final ListAppender app2;
35 private static final String CONFIG = "log4j-reference-level.xml";
36 private ListAppender app1;
37 private ListAppender app2;
3438
35 public AppenderRefLevelTest(final LoggerContext context, @Named("LIST1") final ListAppender first, @Named("LIST2") final ListAppender second) {
36 logger1 = context.getLogger("org.apache.logging.log4j.test1");
37 logger2 = context.getLogger("org.apache.logging.log4j.test2");
38 logger3 = context.getLogger("org.apache.logging.log4j.test3");
39 app1 = first.clear();
40 app2 = second.clear();
39 @ClassRule
40 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
41
42 org.apache.logging.log4j.Logger logger1 = context.getLogger("org.apache.logging.log4j.test1");
43 org.apache.logging.log4j.Logger logger2 = context.getLogger("org.apache.logging.log4j.test2");
44 org.apache.logging.log4j.Logger logger3 = context.getLogger("org.apache.logging.log4j.test3");
45 Marker testMarker = MarkerManager.getMarker("TEST");
46
47 @Before
48 public void before() {
49 app1 = context.getListAppender("LIST1").clear();
50 app2 = context.getListAppender("LIST2").clear();
4151 }
42
43 org.apache.logging.log4j.Logger logger1;
44 org.apache.logging.log4j.Logger logger2;
45 org.apache.logging.log4j.Logger logger3;
46 Marker testMarker = MarkerManager.getMarker("TEST");
4752
4853 @Test
4954 public void logger1() {
5459 logger1.warn("warn Message");
5560 logger1.traceExit();
5661 List<LogEvent> events = app1.getEvents();
57 assertEquals(6, events.size(), "Incorrect number of events. Expected 6, actual " + events.size());
62 assertEquals("Incorrect number of events. Expected 6, actual " + events.size(), 6, events.size());
5863 events = app2.getEvents();
59 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
64 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
6065 }
6166
6267 @Test
6873 logger2.warn("warn Message");
6974 logger2.traceExit();
7075 List<LogEvent> events = app1.getEvents();
71 assertEquals(events.size(), 2, "Incorrect number of events. Expected 2, actual " + events.size());
76 assertEquals("Incorrect number of events. Expected 2, actual " + events.size(), events.size(), 2);
7277 events = app2.getEvents();
73 assertEquals(events.size(), 4, "Incorrect number of events. Expected 4, actual " + events.size());
78 assertEquals("Incorrect number of events. Expected 4, actual " + events.size(), events.size(), 4);
7479 }
7580
7681 @Test
8287 logger3.warn("warn Message");
8388 logger3.traceExit();
8489 final List<LogEvent> events = app1.getEvents();
85 assertEquals(4, events.size(), "Incorrect number of events. Expected 4, actual " + events.size());
90 assertEquals("Incorrect number of events. Expected 4, actual " + events.size(), 4, events.size());
8691 }
8792 }
8893
1717
1818 import org.apache.logging.log4j.LogManager;
1919 import org.apache.logging.log4j.Logger;
20 import org.junit.jupiter.api.Tag;
21 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2221
23 @Tag("smoke")
22 /**
23 *
24 */
2425 public class BasicLoggingTest {
2526
2627 @Test
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.junit.LoggerContextSource;
20 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.message.StringMapMessage;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Disabled;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.parallel.ResourceAccessMode;
26 import org.junit.jupiter.api.parallel.ResourceLock;
27 import org.junit.jupiter.api.parallel.Resources;
28
2918 import java.net.NetworkInterface;
3019 import java.net.SocketException;
3120 import java.nio.charset.Charset;
3221 import java.util.HashMap;
3322 import java.util.Map;
3423
35 @LoggerContextSource("log4j-collectionLogging.xml")
36 @Disabled("Work in progress")
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
26 import org.apache.logging.log4j.message.StringMapMessage;
27 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.Before;
29 import org.junit.ClassRule;
30 import org.junit.Test;
31
32 /**
33 * TODO: Work in progress.
34 */
3735 public class CollectionLoggingTest {
3836
39 private final ListAppender app;
37 private static final String CONFIG = "log4j-collectionLogging.xml";
38 private ListAppender app;
4039
41 public CollectionLoggingTest(@Named("List") final ListAppender app) {
42 this.app = app.clear();
40 @ClassRule
41 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
42
43 @Before
44 public void before() {
45 app = context.getListAppender("List").clear();
4346 }
4447
4548 @Test
46 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
47 public void testSystemProperties(final LoggerContext context) {
49 public void testSystemProperties() {
4850 final Logger logger = context.getLogger(CollectionLoggingTest.class.getName());
4951 logger.error(System.getProperties());
5052 // logger.error(new MapMessage(System.getProperties()));
5254 }
5355
5456 @Test
55 @ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
56 public void testSimpleMap(final LoggerContext context) {
57 public void testSimpleMap() {
5758 final Logger logger = context.getLogger(CollectionLoggingTest.class.getName());
5859 logger.error(System.getProperties());
5960 final Map<String, String> map = new HashMap<>();
6566 }
6667
6768 @Test
68 public void testNetworkInterfaces(final LoggerContext context) throws SocketException {
69 public void testNetworkInterfaces() throws SocketException {
6970 final Logger logger = context.getLogger(CollectionLoggingTest.class.getName());
7071 logger.error(NetworkInterface.getNetworkInterfaces());
7172 // TODO: some assertions
7273 }
7374
7475 @Test
75 public void testAvailableCharsets(final LoggerContext context) {
76 public void testAvailableCharsets() throws SocketException {
7677 final Logger logger = context.getLogger(CollectionLoggingTest.class.getName());
7778 logger.error(Charset.availableCharsets());
7879 // TODO: some assertions
3636 }
3737 } catch (final Exception e) {
3838 //e.printStackTrace();
39 logger.error("Exception general", e);
39 logger.error("Excepcion general", e);
4040 }
4141 }
4242 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import static org.hamcrest.MatcherAssert.*;
1918 import static org.hamcrest.Matchers.hasSize;
20 import static org.junit.jupiter.api.Assertions.*;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotEquals;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertThat;
2123
2224 import org.apache.logging.log4j.Level;
23 import org.apache.logging.log4j.junit.Named;
24 import org.apache.logging.log4j.junit.LoggerContextSource;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
2526 import org.apache.logging.log4j.test.appender.ListAppender;
26 import org.junit.jupiter.api.Test;
27 import org.junit.Before;
28 import org.junit.ClassRule;
29 import org.junit.Test;
2730
28 @LoggerContextSource("log4j-customLevels.xml")
2931 public class CustomLevelsOverrideTest {
3032
31 private final ListAppender listAppender;
32 private final Level warnLevel;
33 private final Level infoLevel;
34 private final Level debugLevel;
35 private final Logger logger;
33 private static final String CONFIG = "log4j-customLevels.xml";
3634
37 public CustomLevelsOverrideTest(final LoggerContext context, @Named("List1") final ListAppender appender) {
35 @ClassRule
36 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
37
38 private ListAppender listAppender;
39 private Level warnLevel;
40 private Level infoLevel;
41 private Level debugLevel;
42
43 @Before
44 public void before() {
3845 warnLevel = Level.getLevel("WARN");
3946 infoLevel = Level.getLevel("INFO");
4047 debugLevel = Level.getLevel("DEBUG");
41 listAppender = appender.clear();
42 logger = context.getLogger(getClass().getName());
48 listAppender = context.getListAppender("List1").clear();
4349 }
4450
4551 @Test
6874
6975 @Test
7076 public void testLog() {
77 final Logger logger = context.getLogger();
7178 assertThat(listAppender.getEvents(), hasSize(0));
7279 logger.debug("Hello, {}", "World");
7380 assertThat(listAppender.getEvents(), hasSize(1));
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import static org.hamcrest.MatcherAssert.*;
1918 import static org.hamcrest.Matchers.hasSize;
20 import static org.junit.jupiter.api.Assertions.*;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertThat;
2122
2223 import org.apache.logging.log4j.Level;
23 import org.apache.logging.log4j.junit.Named;
24 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.LoggerContextRule;
2525 import org.apache.logging.log4j.test.appender.ListAppender;
26 import org.junit.jupiter.api.Test;
26 import org.junit.Before;
27 import org.junit.ClassRule;
28 import org.junit.Test;
2729
28 @LoggerContextSource("log4j-customLevels.xml")
2930 public class CustomLevelsTest {
3031
31 private final ListAppender listAppender;
32 private final Level diagLevel;
33 private final Level noticeLevel;
34 private final Level verboseLevel;
35 private final Logger logger;
32 private static final String CONFIG = "log4j-customLevels.xml";
3633
37 public CustomLevelsTest(final LoggerContext context, @Named("List1") final ListAppender appender) {
34 @ClassRule
35 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
36
37 private ListAppender listAppender;
38 private Level diagLevel;
39 private Level noticeLevel;
40 private Level verboseLevel;
41
42 @Before
43 public void before() {
3844 diagLevel = Level.getLevel("DIAG");
3945 noticeLevel = Level.getLevel("NOTICE");
4046 verboseLevel = Level.getLevel("VERBOSE");
41 listAppender = appender.clear();
42 logger = context.getLogger(getClass().getName());
47 listAppender = context.getListAppender("List1").clear();
4348 }
4449
4550 @Test
5863
5964 @Test
6065 public void testLog() {
66 final Logger logger = context.getLogger();
6167 assertThat(listAppender.getEvents(), hasSize(0));
6268 logger.debug("Hello, {}", "World");
6369 assertThat(listAppender.getEvents(), hasSize(1));
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.core.appender.FileAppender;
2023 import org.apache.logging.log4j.core.config.Configuration;
2124 import org.apache.logging.log4j.core.filter.CompositeFilter;
2225 import org.apache.logging.log4j.core.filter.ThresholdFilter;
23 import org.apache.logging.log4j.junit.Named;
24 import org.apache.logging.log4j.junit.LoggerContextSource;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.Assert;
28 import org.junit.Before;
29 import org.junit.ClassRule;
30 import org.junit.Test;
2731
28 import static org.junit.jupiter.api.Assertions.*;
32 /**
33 *
34 */
35 public class CustomLevelsWithFiltersTest {
2936
30 @LoggerContextSource("log4j-customLevelsWithFilters.xml")
31 public class CustomLevelsWithFiltersTest {
37 private static final String CONFIG = "log4j-customLevelsWithFilters.xml";
38
39 @ClassRule
40 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
3241
3342 private Level infom1Level;
3443 private Level infop1Level;
3544
36 @BeforeEach
45 @Before
3746 public void before() {
3847 infom1Level = Level.getLevel("INFOM1");
3948 infop1Level = Level.getLevel("INFOP1");
4049 }
4150
4251 @Test
43 public void testConfiguration(final Configuration configuration, @Named("info") final FileAppender appender) {
52 public void testConfiguration() {
53 final Configuration configuration = context.getConfiguration();
4454 assertNotNull(configuration);
55 final FileAppender appender = configuration.getAppender("info");
4556 assertNotNull(appender);
4657 final CompositeFilter compFilter = (CompositeFilter) appender.getFilter();
4758 assertNotNull(compFilter);
5566 break;
5667 }
5768 }
58 assertTrue(foundLevel, "Level not found: " + infom1Level);
69 Assert.assertTrue("Level not found: " + infom1Level, foundLevel);
5970 }
6071
6172 @Test
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.junit.LoggerContextSource;
19 import org.junit.jupiter.api.Tag;
20 import org.junit.jupiter.api.Test;
18 import org.apache.logging.log4j.junit.LoggerContextRule;
19 import org.junit.ClassRule;
20 import org.junit.Test;
2121
22 @LoggerContextSource("log4j-deadlock.xml")
23 @Tag("concurrency")
22 /**
23 *
24 */
2425 public class DeadlockTest {
2526
27 private static final String CONFIG = "log4j-deadlock.xml";
28
29 @ClassRule
30 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
31
2632 @Test
27 public void deadlockOnReconfigure(final LoggerContext context) {
28 context.reconfigure();
33 public void deadlockOnReconfigure() {
34 context.getLoggerContext().reconfigure();
2935 }
3036 }
1818 import org.apache.logging.log4j.LogManager;
1919 import org.apache.logging.log4j.Logger;
2020 import org.apache.logging.log4j.core.config.ConfigurationFactory;
21 import org.junit.jupiter.api.BeforeAll;
22 import org.junit.jupiter.api.Tag;
23 import org.junit.jupiter.api.Test;
21 import org.junit.BeforeClass;
22 import org.junit.Test;
2423
2524 import java.io.BufferedReader;
2625 import java.io.File;
3029
3130 import static org.hamcrest.MatcherAssert.assertThat;
3231 import static org.hamcrest.Matchers.containsString;
33 import static org.junit.jupiter.api.Assertions.*;
32 import static org.junit.Assert.assertNull;
33 import static org.junit.Assert.assertTrue;
3434
35 @Tag("functional")
3635 public class EventParameterMemoryLeakTest {
3736
38 @BeforeAll
37 @BeforeClass
3938 public static void beforeClass() {
4039 System.setProperty("log4j2.enable.threadlocals", "true");
4140 System.setProperty("log4j2.enable.direct.encoders", "true");
4746 @SuppressWarnings("UnusedAssignment") // parameter set to null to allow garbage collection
4847 public void testParametersAreNotLeaked() throws Exception {
4948 final File file = new File("target", "EventParameterMemoryLeakTest.log");
50 assertTrue(!file.exists() || file.delete(), "Deleted old file before test");
49 assertTrue("Deleted old file before test", !file.exists() || file.delete());
5150
5251 final Logger log = LogManager.getLogger("com.foo.Bar");
53 CountDownLatch latch = new CountDownLatch(1);
52 final CountDownLatch latch = new CountDownLatch(1);
5453 Object parameter = new ParameterObject("paramValue", latch);
5554 log.info("Message with parameter {}", parameter);
5655 log.info(parameter);
7069 assertThat(line2, containsString("paramValue"));
7170 assertThat(line3, containsString("paramValue"));
7271 assertThat(line4, containsString("paramValue"));
73 assertNull(line5, "Expected only three lines");
74 GarbageCollectionHelper gcHelper = new GarbageCollectionHelper();
72 assertNull("Expected only three lines", line5);
73 final GarbageCollectionHelper gcHelper = new GarbageCollectionHelper();
7574 gcHelper.run();
7675 try {
77 assertTrue(latch.await(30, TimeUnit.SECONDS), "Parameter should have been garbage collected");
76 assertTrue("Parameter should have been garbage collected", latch.await(30, TimeUnit.SECONDS));
7877 } finally {
7978 gcHelper.close();
8079 }
8382 private static final class ParameterObject {
8483 private final String value;
8584 private final CountDownLatch latch;
86 ParameterObject(String value, CountDownLatch latch) {
85 ParameterObject(final String value, final CountDownLatch latch) {
8786 this.value = value;
8887 this.latch = latch;
8988 }
103102 private static final class ObjectThrowable extends RuntimeException {
104103 private final Object object;
105104
106 ObjectThrowable(Object object) {
105 ObjectThrowable(final Object object) {
107106 super(String.valueOf(object));
108107 this.object = object;
109108 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import java.util.List;
19
1820 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.junit.Named;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2122 import org.apache.logging.log4j.test.ExtendedLevels;
2223 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.ClassRule;
26 import org.junit.Test;
2427
25 import java.util.List;
28 import static org.hamcrest.Matchers.hasSize;
29 import static org.junit.Assert.*;
2630
27 import static org.hamcrest.MatcherAssert.*;
28 import static org.hamcrest.Matchers.hasSize;
29 import static org.junit.jupiter.api.Assertions.*;
30
31 @LoggerContextSource("log4j-customLevel.xml")
31 /**
32 *
33 */
3234 public class ExtendedLevelTest {
3335
34 private final ListAppender list1;
35 private final ListAppender list2;
36 private static final String CONFIG = "log4j-customLevel.xml";
37 private ListAppender list1;
38 private ListAppender list2;
3639
37 public ExtendedLevelTest(@Named("List1") final ListAppender list1, @Named("List2") final ListAppender list2) {
38 this.list1 = list1.clear();
39 this.list2 = list2.clear();
40 @ClassRule
41 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
42
43 @Before
44 public void before() {
45 list1 = context.getListAppender("List1").clear();
46 list2 = context.getListAppender("List2").clear();
4047 }
4148
4249 @Test
43 public void testLevelLogging(final LoggerContext context) {
50 public void testLevelLogging() {
4451 org.apache.logging.log4j.Logger logger = context.getLogger("org.apache.logging.log4j.test1");
4552 logger.log(ExtendedLevels.DETAIL, "Detail message");
4653 logger.log(Level.DEBUG, "Debug message");
4754 List<LogEvent> events = list1.getEvents();
48 assertNotNull(events, "No events");
55 assertNotNull("No events", events);
4956 assertThat(events, hasSize(1));
5057 LogEvent event = events.get(0);
51 assertEquals("DETAIL", event.getLevel().name(), "Expected level DETAIL, got" + event.getLevel());
58 assertEquals("Expected level DETAIL, got" + event.getLevel(), "DETAIL", event.getLevel().name());
5259 logger = context.getLogger("org.apache.logging.log4j.test2");
5360 logger.log(ExtendedLevels.NOTE, "Note message");
5461 logger.log(Level.INFO, "Info message");
5562 events = list2.getEvents();
56 assertNotNull(events, "No events");
63 assertNotNull("No events", events);
5764 assertThat(events, hasSize(1));
5865 event = events.get(0);
59 assertEquals("NOTE", event.getLevel().name(), "Expected level NOTE, got" + event.getLevel());
66 assertEquals("Expected level NOTE, got" + event.getLevel(), "NOTE", event.getLevel().name());
6067 }
6168 }
2626
2727 import static org.junit.Assert.assertTrue;
2828
29 public final class GarbageCollectionHelper implements Closeable, Runnable {
29 final class GarbageCollectionHelper implements Closeable, Runnable {
3030 private static final OutputStream sink = ByteStreams.nullOutputStream();
31 private final AtomicBoolean running = new AtomicBoolean();
31 public final AtomicBoolean running = new AtomicBoolean();
3232 private final CountDownLatch latch = new CountDownLatch(1);
33 private final Thread gcThread = new Thread(() -> {
34 try {
35 while (running.get()) {
36 // Allocate data to help suggest a GC
37 try {
38 // 1mb of heap
39 sink.write(new byte[1024 * 1024]);
40 } catch (final IOException ignored) {
33 private final Thread gcThread = new Thread(new Runnable() {
34 @Override
35 public void run() {
36 try {
37 while (running.get()) {
38 // Allocate data to help suggest a GC
39 try {
40 // 1mb of heap
41 sink.write(new byte[1024 * 1024]);
42 } catch (final IOException ignored) {
43 }
44 // May no-op depending on the jvm configuration
45 System.gc();
4146 }
42 // May no-op depending on the JVM configuration
43 System.gc();
47 } finally {
48 latch.countDown();
4449 }
45 } finally {
46 latch.countDown();
4750 }
4851 });
4952
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.categories.AsyncLoggers;
1819 import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
19 import org.junit.jupiter.api.Tag;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
21 import org.junit.experimental.categories.Category;
2122
2223 /**
2324 * Verifies steady state logging is GC-free.
2425 *
2526 * @see <a href="https://github.com/google/allocation-instrumenter">https://github.com/google/allocation-instrumenter</a>
2627 */
27 @Tag("allocation")
28 @Tag("functional")
28 @Category(AsyncLoggers.class)
2929 public class GcFreeAsynchronousLoggingTest {
3030
3131 @Test
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
19 import com.google.monitoring.runtime.instrumentation.Sampler;
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21
22 import java.io.File;
23 import java.net.URL;
24 import java.nio.charset.Charset;
25 import java.nio.file.Files;
26 import java.util.List;
27 import java.util.concurrent.atomic.AtomicBoolean;
28
2029 import org.apache.logging.log4j.LogManager;
2130 import org.apache.logging.log4j.Marker;
2231 import org.apache.logging.log4j.MarkerManager;
2332 import org.apache.logging.log4j.ThreadContext;
2433 import org.apache.logging.log4j.core.util.Constants;
2534 import org.apache.logging.log4j.message.StringMapMessage;
35 import org.apache.logging.log4j.util.Strings;
2636
27 import java.io.File;
28 import java.net.URL;
29 import java.nio.charset.Charset;
30 import java.nio.file.Files;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 import java.util.concurrent.atomic.AtomicInteger;
33 import java.util.regex.Pattern;
34
35 import static org.junit.jupiter.api.Assertions.assertFalse;
36 import static org.junit.jupiter.api.Assertions.assertTrue;
37 import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
38 import com.google.monitoring.runtime.instrumentation.Sampler;
3739
3840 /**
39 * Utility methods for the GC-free logging tests.
41 * Utily methods for the GC-free logging tests.s.
4042 */
41 public enum GcFreeLoggingTestUtil {;
43 public class GcFreeLoggingTestUtil {
4244
4345 public static void executeLogging(final String configurationFile,
44 final Class<?> testClass) throws Exception {
46 final Class<?> testClass) throws Exception {
4547
4648 System.setProperty("log4j2.enable.threadlocals", "true");
4749 System.setProperty("log4j2.enable.direct.encoders", "true");
4850 System.setProperty("log4j2.is.webapp", "false");
4951 System.setProperty("log4j.configurationFile", configurationFile);
5052
51 assertTrue(Constants.ENABLE_THREADLOCALS, "Constants.ENABLE_THREADLOCALS");
52 assertTrue(Constants.ENABLE_DIRECT_ENCODERS, "Constants.ENABLE_DIRECT_ENCODERS");
53 assertFalse(Constants.IS_WEB_APP, "Constants.IS_WEB_APP");
53 assertTrue("Constants.ENABLE_THREADLOCALS", Constants.ENABLE_THREADLOCALS);
54 assertTrue("Constants.ENABLE_DIRECT_ENCODERS", Constants.ENABLE_DIRECT_ENCODERS);
55 assertFalse("Constants.IS_WEB_APP", Constants.IS_WEB_APP);
5456
5557 final MyCharSeq myCharSeq = new MyCharSeq();
5658 final Marker testGrandParent = MarkerManager.getMarker("testGrandParent");
8082 "com/google/monitoring/runtime/instrumentation/Sampler", //
8183 };
8284 final AtomicBoolean samplingEnabled = new AtomicBoolean(true);
83 final Sampler sampler = (count, desc, newObj, size) -> {
84 if (!samplingEnabled.get()) {
85 return;
85 final Sampler sampler = new Sampler() {
86 @Override
87 public void sampleAllocation(final int count, final String desc, final Object newObj, final long size) {
88 if (!samplingEnabled.get()) {
89 return;
90 }
91 for (int i = 0; i < exclude.length; i++) {
92 if (exclude[i].equals(desc)) {
93 return; // exclude
94 }
95 }
96 System.err.println("I just allocated the object " + newObj +
97 " of type " + desc + " whose size is " + size);
98 if (count != -1) {
99 System.err.println("It's an array of size " + count);
100 }
101
102 // show a stack trace to see which line caused allocation
103 new RuntimeException().printStackTrace();
86104 }
87 for (int i = 0; i < exclude.length; i++) {
88 if (exclude[i].equals(desc)) {
89 return; // exclude
90 }
91 }
92 System.err.println("I just allocated the object " + newObj +
93 " of type " + desc + " whose size is " + size);
94 if (count != -1) {
95 System.err.println("It's an array of size " + count);
96 }
97
98 // show a stack trace to see which line caused allocation
99 new RuntimeException().printStackTrace();
100105 };
101106 Thread.sleep(500);
102107 final StringMapMessage mapMessage = new StringMapMessage().with("eventId", "Login");
142147 process.waitFor();
143148 process.exitValue();
144149
145 final AtomicInteger lineCounter = new AtomicInteger(0);
146 Files.lines(tempFile.toPath(), Charset.defaultCharset()).forEach(line -> {
150 final String text = new String(Files.readAllBytes(tempFile.toPath()));
151 final List<String> lines = Files.readAllLines(tempFile.toPath(), Charset.defaultCharset());
152 final String className = cls.getSimpleName();
153 assertEquals(text, "FATAL o.a.l.l.c." + className + " [main] value1 {aKey=value1, key2=value2, prop1=value1, prop2=value2} This message is logged to the console",
154 lines.get(0));
147155
148 // Trim the line.
149 line = line.trim();
150
151 // Check the first line.
152 final int lineNumber = lineCounter.incrementAndGet();
153 if (lineNumber == 1) {
154 final String className = cls.getSimpleName();
155 final String firstLinePattern = String.format(
156 "^FATAL .*\\.%s %s",
157 className,
158 Pattern.quote("[main] value1 {aKey=value1, " +
159 "key2=value2, prop1=value1, prop2=value2} " +
160 "This message is logged to the console"));
161 assertTrue(
162 line.matches(firstLinePattern),
163 "pattern mismatch at line 1: " + line);
164 }
165
166 // Check the rest of the lines.
167 else {
168 assertFalse(
169 line.contains("allocated") || line.contains("array"),
170 "(allocated|array) pattern matches at line " + lineNumber + ": " + line);
171 }
172
173 });
174
156 for (int i = 1; i < lines.size(); i++) {
157 final String line = lines.get(i);
158 assertFalse(i + ": " + line + Strings.LINE_SEPARATOR + text, line.contains("allocated") || line.contains("array"));
159 }
175160 }
176161
177162 private static File agentJar() {
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.junit.jupiter.api.Tag;
19 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
2019
2120 /**
2221 * Verifies steady state mixed synchronous and asynchronous logging is GC-free.
2322 *
2423 * @see <a href="https://github.com/google/allocation-instrumenter">https://github.com/google/allocation-instrumenter</a>
2524 */
26 @Tag("allocation")
27 @Tag("functional")
2825 public class GcFreeMixedSyncAyncLoggingTest {
2926
3027 @Test
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.junit.jupiter.api.Tag;
19 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
2019
2120 /**
2221 * Verifies steady state synchronous logging is GC-free.
2322 *
2423 * @see <a href="https://github.com/google/allocation-instrumenter">https://github.com/google/allocation-instrumenter</a>
2524 */
26 @Tag("allocation")
27 @Tag("functional")
2825 public class GcFreeSynchronousLoggingTest {
2926
3027 @Test
1919
2020 import org.apache.logging.log4j.core.appender.RollingFileAppender;
2121 import org.apache.logging.log4j.core.util.NetUtils;
22 import org.apache.logging.log4j.junit.Named;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2423 import org.apache.logging.log4j.test.appender.ListAppender;
2524 import org.apache.logging.log4j.util.Strings;
26 import org.junit.jupiter.api.Test;
25 import org.junit.Before;
26 import org.junit.ClassRule;
27 import org.junit.Test;
2728
28 import static org.hamcrest.MatcherAssert.*;
2929 import static org.hamcrest.Matchers.endsWith;
3030 import static org.hamcrest.Matchers.hasSize;
31 import static org.junit.jupiter.api.Assertions.*;
31 import static org.junit.Assert.*;
3232
33 @LoggerContextSource("log4j-test2.xml")
33 /**
34 *
35 */
3436 public class HostNameTest {
3537
36 private final ListAppender host;
37 private final RollingFileAppender hostFile;
38 private static final String CONFIG = "log4j-test2.xml";
39 private ListAppender host;
40 private RollingFileAppender hostFile;
3841
39 public HostNameTest(@Named("HostTest") final ListAppender list, @Named("HostFile") final RollingFileAppender rolling) {
40 host = list.clear();
41 hostFile = rolling;
42 @ClassRule
43 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
44
45 @Before
46 public void before() {
47 host = context.getListAppender("HostTest").clear();
48 hostFile = context.getRequiredAppender("HostFile", RollingFileAppender.class);
4249 }
4350
4451 @Test
45 public void testHostname(final LoggerContext context) {
52 public void testHostname() {
4653 final org.apache.logging.log4j.Logger testLogger = context.getLogger("org.apache.logging.log4j.hosttest");
4754 testLogger.debug("Hello, {}", "World");
4855 final List<String> msgs = host.getMessages();
4956 assertThat(msgs, hasSize(1));
5057 String expected = NetUtils.getLocalHostname() + Strings.LINE_SEPARATOR;
5158 assertThat(msgs.get(0), endsWith(expected));
52 assertNotNull(hostFile.getFileName(), "No Host FileAppender file name");
59 assertNotNull("No Host FileAppender file name", hostFile.getFileName());
5360 expected = "target/" + NetUtils.getLocalHostname() + ".log";
5461 String name = hostFile.getFileName();
55 assertEquals(name,
56 expected, "Incorrect HostFile FileAppender file name - expected " + expected + " actual - " + name);
62 assertEquals("Incorrect HostFile FileAppender file name - expected " + expected + " actual - " + name, name,
63 expected);
5764 name = hostFile.getFilePattern();
58 assertNotNull(name, "No file pattern");
65 assertNotNull("No file pattern", name);
5966 expected = "target/" + NetUtils.getLocalHostname() + "-%d{MM-dd-yyyy}-%i.log";
60 assertEquals(name,
61 expected, "Incorrect HostFile FileAppender file pattern - expected " + expected + " actual - " + name);
67 assertEquals("Incorrect HostFile FileAppender file pattern - expected " + expected + " actual - " + name, name,
68 expected);
6269
6370 }
6471 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
1821 import java.io.File;
1922
2023 import org.apache.logging.log4j.core.config.Configuration;
2225 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2326 import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
2427 import org.apache.logging.log4j.status.StatusLogger;
25 import org.junit.jupiter.api.AfterAll;
26 import org.junit.jupiter.api.BeforeAll;
27 import org.junit.jupiter.api.Tag;
28 import org.junit.jupiter.api.Test;
28 import org.junit.AfterClass;
29 import org.junit.BeforeClass;
30 import org.junit.Test;
2931
30 import static org.junit.jupiter.api.Assertions.*;
31
32 @Tag("functional")
32 /**
33 *
34 */
3335 public class LateConfigTest {
3436
3537 private static final String CONFIG = "target/test-classes/log4j-test1.xml";
3638 private static LoggerContext context;
3739
38 @BeforeAll
40 @BeforeClass
3941 public static void setupClass() {
4042 context = LoggerContext.getContext(false);
4143 }
4244
43 @AfterAll
45 @AfterClass
4446 public static void tearDownClass() {
4547 Configurator.shutdown(context);
4648 StatusLogger.getLogger().reset();
4951 @Test
5052 public void testReconfiguration() throws Exception {
5153 final Configuration cfg = context.getConfiguration();
52 assertNotNull(cfg, "No configuration");
53 assertTrue(cfg instanceof DefaultConfiguration, "Not set to default configuration");
54 assertNotNull("No configuration", cfg);
55 assertTrue("Not set to default configuration", cfg instanceof DefaultConfiguration);
5456 final File file = new File(CONFIG);
5557 final LoggerContext loggerContext = LoggerContext.getContext(null, false, file.toURI());
56 assertNotNull(loggerContext, "No Logger Context");
58 assertNotNull("No Logger Context", loggerContext);
5759 final Configuration newConfig = loggerContext.getConfiguration();
58 assertNotSame(cfg, newConfig, "Configuration not reset");
59 assertTrue(newConfig instanceof XmlConfiguration, "Reconfiguration failed");
60 assertTrue("Configuration not reset", cfg != newConfig);
61 assertTrue("Reconfiguration failed", newConfig instanceof XmlConfiguration);
6062 context = LoggerContext.getContext(false);
6163 final Configuration sameConfig = context.getConfiguration();
62 assertSame(newConfig, sameConfig, "Configuration should not have been reset");
64 assertTrue("Configuration should not have been reset", newConfig == sameConfig);
6365 }
6466 }
6567
2121 import org.apache.logging.log4j.Logger;
2222 import org.apache.logging.log4j.Marker;
2323 import org.apache.logging.log4j.MarkerManager;
24 import org.apache.logging.log4j.junit.Named;
25 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.LoggerContextRule;
2625 import org.apache.logging.log4j.message.Message;
2726 import org.apache.logging.log4j.message.ObjectMessage;
2827 import org.apache.logging.log4j.test.appender.ListAppender;
29 import org.junit.jupiter.api.Test;
28 import org.junit.Before;
29 import org.junit.ClassRule;
30 import org.junit.Test;
3031
31 import static org.hamcrest.MatcherAssert.*;
3232 import static org.hamcrest.Matchers.*;
33 import static org.junit.jupiter.api.Assertions.*;
33 import static org.junit.Assert.*;
3434
35 @LoggerContextSource("log4j-Level.xml")
35 /**
36 *
37 */
3638 public class LevelTest {
3739
38 private final ListAppender listAll;
39 private final ListAppender listTrace;
40 private final ListAppender listDebug;
41 private final ListAppender listInfo;
42 private final ListAppender listWarn;
43 private final ListAppender listError;
44 private final ListAppender listFatal;
40 private static final String CONFIG = "log4j-Level.xml";
41 private ListAppender listAll;
42 private ListAppender listTrace;
43 private ListAppender listDebug;
44 private ListAppender listInfo;
45 private ListAppender listWarn;
46 private ListAppender listError;
47 private ListAppender listFatal;
4548
46 public LevelTest(@Named("ListAll") final ListAppender listAll, @Named("ListTrace") final ListAppender listTrace,
47 @Named("ListDebug") final ListAppender listDebug, @Named("ListInfo") final ListAppender listInfo,
48 @Named("ListWarn") final ListAppender listWarn, @Named("ListError") final ListAppender listError,
49 @Named("ListFatal") final ListAppender listFatal) {
50 this.listAll = listAll.clear();
51 this.listTrace = listTrace.clear();
52 this.listDebug = listDebug.clear();
53 this.listInfo = listInfo.clear();
54 this.listWarn = listWarn.clear();
55 this.listError = listError.clear();
56 this.listFatal = listFatal.clear();
49 @ClassRule
50 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
51
52 @Before
53 public void before() {
54 listAll = context.getListAppender("ListAll").clear();
55 listTrace = context.getListAppender("ListTrace").clear();
56 listDebug = context.getListAppender("ListDebug").clear();
57 listInfo = context.getListAppender("ListInfo").clear();
58 listWarn = context.getListAppender("ListWarn").clear();
59 listError = context.getListAppender("ListError").clear();
60 listFatal = context.getListAppender("ListFatal").clear();
5761 }
5862
5963 // Helper class
7276 }
7377
7478 @Test
75 public void testLevelLogging(final LoggerContext context) {
79 public void testLevelLogging() {
7680 final Marker marker = MarkerManager.getMarker("marker");
7781 final Message msg = new ObjectMessage("msg");
7882 final Throwable t = new Throwable("test");
114118 for (final Expected expected : expectedResults) {
115119 final String description = expected.description;
116120 final List<LogEvent> events = expected.appender.getEvents();
117 assertNotNull(events, description + ": No events");
121 assertNotNull(description + ": No events", events);
118122 assertThat(events, hasSize(expected.expectedEventCount));
119123 final LogEvent event = events.get(0);
120124 assertEquals(
121 event.getLevel().name(), expected.expectedInitialEventLevel,
122 description + ": Expected level " + expected.expectedInitialEventLevel + ", got" + event.getLevel());
125 description + ": Expected level " + expected.expectedInitialEventLevel + ", got" + event.getLevel(),
126 event.getLevel().name(), expected.expectedInitialEventLevel);
123127 }
124128 }
125129 }
1818 import org.apache.logging.log4j.LogManager;
1919 import org.apache.logging.log4j.Logger;
2020 import org.apache.logging.log4j.TestLogger;
21 import org.junit.jupiter.api.Tag;
22 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2322
2423 import static org.junit.Assert.assertTrue;
2524
2625 /**
2726 * Tests logging during shutdown.
2827 */
29 @Tag("functional")
3028 public class Log4j1222Test
3129 {
3230
5351 private void trigger() {
5452 Holder.LOGGER.info("Attempt to trigger");
5553 assertTrue("Logger is of type " + Holder.LOGGER.getClass().getName(), Holder.LOGGER instanceof TestLogger);
56 if (((TestLogger) Holder.LOGGER).getEntries().isEmpty()) {
54 if (((TestLogger) Holder.LOGGER).getEntries().size() == 0) {
5755 System.out.println("Logger contains no messages");
5856 }
5957 for (final String msg : ((TestLogger) Holder.LOGGER).getEntries()) {
3838 import org.junit.ClassRule;
3939 import org.junit.Test;
4040 import org.junit.rules.RuleChain;
41 import org.junit.rules.TestRule;
42 import org.junit.runner.Description;
4143 import org.junit.runners.model.Statement;
4244
4345 /**
5254
5355 // this would look so cool using lambdas
5456 @ClassRule
55 public static RuleChain chain = RuleChain.outerRule((base, description) -> new Statement() {
57 public static RuleChain chain = RuleChain.outerRule(new TestRule() {
5658 @Override
57 public void evaluate() throws Throwable {
58 System.setProperty(Constants.LOG4J_LOG_EVENT_FACTORY, TestLogEventFactory.class.getName());
59 resetLogEventFactory(new TestLogEventFactory());
60 try {
61 base.evaluate();
62 } finally {
63 System.clearProperty(Constants.LOG4J_LOG_EVENT_FACTORY);
64 resetLogEventFactory(new DefaultLogEventFactory());
65 }
66 }
59 public Statement apply(final Statement base, final Description description) {
60 return new Statement() {
61 @Override
62 public void evaluate() throws Throwable {
63 System.setProperty(Constants.LOG4J_LOG_EVENT_FACTORY, TestLogEventFactory.class.getName());
64 resetLogEventFactory(new TestLogEventFactory());
65 try {
66 base.evaluate();
67 } finally {
68 System.clearProperty(Constants.LOG4J_LOG_EVENT_FACTORY);
69 resetLogEventFactory(new DefaultLogEventFactory());
70 }
71 }
6772
68 private void resetLogEventFactory(final LogEventFactory logEventFactory) throws IllegalAccessException {
69 final Field field = FieldUtils.getField(LoggerConfig.class, "LOG_EVENT_FACTORY", true);
70 FieldUtils.removeFinalModifier(field);
71 FieldUtils.writeStaticField(field, logEventFactory, false);
73 private void resetLogEventFactory(final LogEventFactory logEventFactory) throws IllegalAccessException {
74 final Field field = FieldUtils.getField(LoggerConfig.class, "LOG_EVENT_FACTORY", true);
75 FieldUtils.removeFinalModifier(field, true);
76 FieldUtils.writeStaticField(field, logEventFactory, false);
77 }
78 };
7279 }
7380 }).around(context);
7481
2727 import org.apache.logging.log4j.message.Message;
2828 import org.apache.logging.log4j.message.SimpleMessage;
2929 import org.apache.logging.log4j.util.FilteredObjectInputStream;
30 import org.junit.jupiter.api.Disabled;
31 import org.junit.jupiter.api.Test;
30 import org.junit.Ignore;
31 import org.junit.Test;
3232
33 import static org.junit.jupiter.api.Assertions.*;
33 import static org.junit.Assert.*;
3434
3535 /**
3636 *
9797 final ObjectInputStream ois = new FilteredObjectInputStream(bais);
9898
9999 final LogEvent actual = (LogEvent) ois.readObject();
100 assertNotEquals(copy, actual, "Different event: nanoTime");
101 assertNotEquals(copy.getNanoTime(), actual.getNanoTime(), "Different nanoTime");
102 assertEquals(0, actual.getNanoTime(), "deserialized nanoTime is zero");
100 assertNotEquals("Different event: nanoTime", copy, actual);
101 assertNotEquals("Different nanoTime", copy.getNanoTime(), actual.getNanoTime());
102 assertEquals("deserialized nanoTime is zero", 0, actual.getNanoTime());
103103 }
104104
105105 @Test
124124 final ObjectInputStream ois = new FilteredObjectInputStream(bais);
125125
126126 final LogEvent actual = (LogEvent) ois.readObject();
127 assertEquals(event2, actual, "both zero nanoTime");
127 assertEquals("both zero nanoTime", event2, actual);
128128 }
129129
130130 @Test
131 @Disabled
131 @Ignore
132132 public void testEquals() {
133133 final LogEvent event1 = Log4jLogEvent.newBuilder() //
134134 .setLoggerName(this.getClass().getName()) //
148148 .setLevel(Level.INFO) //
149149 .setMessage(new SimpleMessage("Hello, world!")) //
150150 .build();
151 assertNotEquals(event1, event2, "Events should not be equal");
152 assertEquals(event2, event3, "Events should be equal");
151 assertNotEquals("Events should not be equal", event1, event2);
152 assertEquals("Events should be equal", event2, event3);
153153 }
154154
155155 @Test
156156 public void testLocation() {
157157 final StackTraceElement ste = TESTER.getEventSource(this.getClass().getName());
158 assertNotNull(ste, "No StackTraceElement");
159 assertEquals(this.getClass().getName(), ste.getClassName(), "Incorrect event");
158 assertNotNull("No StackTraceElement", ste);
159 assertEquals("Incorrect event", this.getClass().getName(), ste.getClassName());
160160 }
161161
162162 private static class TestClass {
1818 import java.util.Calendar;
1919
2020 import org.apache.logging.log4j.core.appender.FileAppender;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.junit.jupiter.api.Test;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.junit.Before;
23 import org.junit.ClassRule;
24 import org.junit.Test;
2425
25 import static org.junit.jupiter.api.Assertions.*;
26 import static org.junit.Assert.*;
2627
27 @LoggerContextSource("log4j-date.xml")
28 /**
29 *
30 */
2831 public class LoggerDateTest {
2932
30 private final FileAppender fileApp;
33 private static final String CONFIG = "log4j-date.xml";
34 private FileAppender fileApp;
3135
32 public LoggerDateTest(@Named("File") final FileAppender fileApp) {
33 this.fileApp = fileApp;
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
38
39 @Before
40 public void before() {
41 fileApp = context.getRequiredAppender("File", FileAppender.class);
3442 }
3543
3644 @Test
3745 public void testFileName() {
3846 final String name = fileApp.getFileName();
3947 final int year = Calendar.getInstance().get(Calendar.YEAR);
40 assertTrue(name.contains(Integer.toString(year)), "Date was not substituted: " + name);
48 assertTrue("Date was not substituted: " + name, name.contains(Integer.toString(year)));
4149 }
4250 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Marker;
21 import org.apache.logging.log4j.MarkerManager;
22 import org.apache.logging.log4j.ThreadContext;
23 import org.apache.logging.log4j.core.config.Configuration;
24 import org.apache.logging.log4j.core.config.Configurator;
25 import org.apache.logging.log4j.core.config.LoggerConfig;
26 import org.apache.logging.log4j.junit.LoggerContextSource;
27 import org.apache.logging.log4j.junit.Named;
28 import org.apache.logging.log4j.junit.ReconfigurationPolicy;
29 import org.apache.logging.log4j.message.Message;
30 import org.apache.logging.log4j.message.MessageFactory;
31 import org.apache.logging.log4j.message.ParameterizedMessageFactory;
32 import org.apache.logging.log4j.message.SimpleMessage;
33 import org.apache.logging.log4j.message.StringFormatterMessageFactory;
34 import org.apache.logging.log4j.message.StructuredDataMessage;
35 import org.apache.logging.log4j.spi.AbstractLogger;
36 import org.apache.logging.log4j.spi.MessageFactory2Adapter;
37 import org.apache.logging.log4j.test.appender.ListAppender;
38 import org.hamcrest.MatcherAssert;
39 import org.junit.jupiter.api.Test;
40 import org.junit.jupiter.api.TestInfo;
18 import static org.junit.Assert.assertArrayEquals;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertNotSame;
22 import static org.junit.Assert.assertTrue;
4123
4224 import java.io.File;
43 import java.lang.reflect.Method;
4425 import java.util.Date;
4526 import java.util.HashMap;
4627 import java.util.List;
4829 import java.util.Map;
4930 import java.util.concurrent.TimeUnit;
5031
51 import static org.hamcrest.CoreMatchers.equalTo;
52 import static org.junit.jupiter.api.Assertions.*;
53
54 @LoggerContextSource(value = LoggerTest.CONFIG, reconfigure = ReconfigurationPolicy.AFTER_EACH)
32 import org.apache.logging.log4j.Level;
33 import org.apache.logging.log4j.LogManager;
34 import org.apache.logging.log4j.MarkerManager;
35 import org.apache.logging.log4j.ThreadContext;
36 import org.apache.logging.log4j.core.config.Configuration;
37 import org.apache.logging.log4j.core.config.Configurator;
38 import org.apache.logging.log4j.core.config.LoggerConfig;
39 import org.apache.logging.log4j.junit.LoggerContextRule;
40 import org.apache.logging.log4j.message.Message;
41 import org.apache.logging.log4j.message.MessageFactory;
42 import org.apache.logging.log4j.message.ParameterizedMessageFactory;
43 import org.apache.logging.log4j.message.StringFormatterMessageFactory;
44 import org.apache.logging.log4j.message.StructuredDataMessage;
45 import org.apache.logging.log4j.spi.AbstractLogger;
46 import org.apache.logging.log4j.spi.MessageFactory2Adapter;
47 import org.apache.logging.log4j.test.appender.ListAppender;
48 import org.junit.Before;
49 import org.junit.Rule;
50 import org.junit.Test;
51 import org.junit.rules.TestName;
52
5553 public class LoggerTest {
5654
57 static final String CONFIG = "log4j-test2.xml";
55 private static final String CONFIG = "log4j-test2.xml";
56
57 @Rule
58 public final TestName testName = new TestName();
59 private ListAppender app;
60 private ListAppender host;
61 private ListAppender noThrown;
62
63 @Rule
64 public LoggerContextRule context = new LoggerContextRule(CONFIG);
65
66 private void assertEventCount(final List<LogEvent> events, final int expected) {
67 assertEquals("Incorrect number of events.", expected, events.size());
68 }
69
70 @Before
71 public void before() {
72 logger = context.getLogger("LoggerTest");
73 loggerChild = context.getLogger("LoggerTest.child");
74 loggerGrandchild = context.getLogger("LoggerTest.child.grand");
75 //
76 app = context.getListAppender("List").clear();
77 host = context.getListAppender("HostTest").clear();
78 noThrown = context.getListAppender("NoThrowable").clear();
79 }
80
5881 org.apache.logging.log4j.Logger logger;
5982 org.apache.logging.log4j.Logger loggerChild;
6083 org.apache.logging.log4j.Logger loggerGrandchild;
61 private final ListAppender app;
62 private final ListAppender host;
63 private final ListAppender noThrown;
64
65 public LoggerTest(final LoggerContext context, @Named("List") final ListAppender app, @Named("HostTest") final ListAppender host, @Named("NoThrowable") final ListAppender noThrown) {
66 logger = context.getLogger("LoggerTest");
67 loggerChild = context.getLogger("LoggerTest.child");
68 loggerGrandchild = context.getLogger("LoggerTest.child.grand");
69 this.app = app.clear();
70 this.host = host.clear();
71 this.noThrown = noThrown.clear();
72 }
73
74 private void assertEventCount(final List<LogEvent> events, final int expected) {
75 assertEquals(expected, events.size(), "Incorrect number of events.");
76 }
77
78 @Test
79 public void builder() {
80 logger.atDebug().withLocation().log("Hello");
81 Marker marker = MarkerManager.getMarker("test");
82 logger.atError().withMarker(marker).log("Hello {}", "John");
83 logger.atWarn().withThrowable(new Throwable("This is a test")).log((Message) new SimpleMessage("Log4j rocks!"));
84 final List<LogEvent> events = app.getEvents();
85 assertEventCount(events, 3);
86 assertEquals(
87 "org.apache.logging.log4j.core.LoggerTest.builder(LoggerTest.java:81)", events.get(0).getSource().toString(),
88 "Incorrect location");
89 assertEquals(Level.DEBUG, events.get(0).getLevel(), "Incorrect Level");
90 MatcherAssert.assertThat("Incorrect message", events.get(1).getMessage().getFormattedMessage(), equalTo("Hello John"));
91 assertNotNull(events.get(2).getThrown(), "Missing Throwable");
92 }
9384
9485 @Test
9586 public void basicFlow() {
191182 }
192183
193184 @Test
194 public void debugChangeLevelsChildLoggers(final LoggerContext context) {
185 public void debugChangeLevelsChildLoggers() {
195186 final org.apache.logging.log4j.Logger loggerChild = context.getLogger(logger.getName() + ".child");
196187 // Use logger AND loggerChild
197188 logger.debug("Debug message 1");
261252 }
262253
263254 @Test
264 public void getLogger_String_MessageFactoryMismatch(final TestInfo testInfo) {
265 final Logger testLogger = testMessageFactoryMismatch(testInfo.getTestMethod().map(Method::getName).orElseThrow(AssertionError::new),
255 public void getLogger_String_MessageFactoryMismatch() {
256 final Logger testLogger = testMessageFactoryMismatch(testName.getMethodName(),
266257 StringFormatterMessageFactory.INSTANCE, ParameterizedMessageFactory.INSTANCE);
267258 testLogger.debug("%,d", Integer.MAX_VALUE);
268259 final List<LogEvent> events = app.getEvents();
271262 }
272263
273264 @Test
274 public void getLogger_String_MessageFactoryMismatchNull(final TestInfo testInfo) {
275 final Logger testLogger = testMessageFactoryMismatch(testInfo.getTestMethod().map(Method::getName).orElseThrow(AssertionError::new), StringFormatterMessageFactory.INSTANCE, null);
265 public void getLogger_String_MessageFactoryMismatchNull() {
266 final Logger testLogger = testMessageFactoryMismatch(testName.getMethodName(), StringFormatterMessageFactory.INSTANCE, null);
276267 testLogger.debug("%,d", Integer.MAX_VALUE);
277268 final List<LogEvent> events = app.getEvents();
278269 assertEventCount(events, 1);
318309 }
319310
320311 @Test
321 public void testImpliedThrowable(final LoggerContext context) {
312 public void testImpliedThrowable() {
322313 final org.apache.logging.log4j.Logger testLogger = context.getLogger("org.apache.logging.log4j.hosttest");
323314 testLogger.debug("This is a test", new Throwable("Testing"));
324315 final List<String> msgs = host.getMessages();
325 assertEquals(1, msgs.size(), "Incorrect number of messages. Expected 1, actual " + msgs.size());
316 assertEquals("Incorrect number of messages. Expected 1, actual " + msgs.size(), 1, msgs.size());
326317 final String expected = "java.lang.Throwable: Testing";
327 assertTrue(msgs.get(0).contains(expected), "Incorrect message data");
328 }
329
330
331 @Test
332 public void testSuppressedThrowable(final LoggerContext context) {
318 assertTrue("Incorrect message data", msgs.get(0).contains(expected));
319 }
320
321
322 @Test
323 public void testSuppressedThrowable() {
333324 final org.apache.logging.log4j.Logger testLogger = context.getLogger("org.apache.logging.log4j.nothrown");
334325 testLogger.debug("This is a test", new Throwable("Testing"));
335326 final List<String> msgs = noThrown.getMessages();
336 assertEquals(1, msgs.size(), "Incorrect number of messages. Expected 1, actual " + msgs.size());
327 assertEquals("Incorrect number of messages. Expected 1, actual " + msgs.size(), 1, msgs.size());
337328 final String suppressed = "java.lang.Throwable: Testing";
338 assertFalse(msgs.get(0).contains(suppressed), "Incorrect message data");
329 assertTrue("Incorrect message data", !msgs.get(0).contains(suppressed));
339330 }
340331
341332
365356 }
366357
367358 @Test
368 public void testReconfiguration(final LoggerContext context) throws Exception {
359 public void testReconfiguration() throws Exception {
369360 final Configuration oldConfig = context.getConfiguration();
370361 final int MONITOR_INTERVAL_SECONDS = 5;
371362 final File file = new File("target/test-classes/" + CONFIG);
372363 final long orig = file.lastModified();
373364 final long newTime = orig + 10000;
374 assertTrue(file.setLastModified(newTime), "setLastModified should have succeeded.");
365 assertTrue("setLastModified should have succeeded.", file.setLastModified(newTime));
375366 TimeUnit.SECONDS.sleep(MONITOR_INTERVAL_SECONDS + 1);
376367 for (int i = 0; i < 17; ++i) {
377368 logger.debug("Reconfigure");
384375 Thread.sleep(50);
385376 }
386377 final Configuration newConfig = context.getConfiguration();
387 assertNotNull(newConfig, "No configuration");
388 assertNotSame(newConfig, oldConfig, "Reconfiguration failed");
389 }
390
391 @Test
392 public void testAdditivity(final LoggerContext context) throws Exception {
378 assertNotNull("No configuration", newConfig);
379 assertNotSame("Reconfiguration failed", newConfig, oldConfig);
380 }
381
382 @Test
383 public void testAdditivity() throws Exception {
393384 final Logger localLogger = context.getLogger("org.apache.test");
394385 localLogger.error("Test parent additivity");
395386 final List<LogEvent> events = app.getEvents();
397388 }
398389
399390 @Test
400 public void testLevelInheritance(final LoggerContext context) throws Exception {
391 public void testLevelInheritence() throws Exception {
401392 final Configuration config = context.getConfiguration();
402393 final LoggerConfig loggerConfig = config.getLoggerConfig("org.apache.logging.log4j.core.LoggerTest");
403394 assertNotNull(loggerConfig);
404395 assertEquals(loggerConfig.getName(), "org.apache.logging.log4j.core.LoggerTest");
405396 assertEquals(loggerConfig.getLevel(), Level.DEBUG);
406397 final Logger localLogger = context.getLogger("org.apache.logging.log4j.core.LoggerTest");
407 assertSame(localLogger.getLevel(), Level.DEBUG, "Incorrect level - expected DEBUG, actual " + localLogger.getLevel());
398 assertTrue("Incorrect level - expected DEBUG, actual " + localLogger.getLevel(), localLogger.getLevel() == Level.DEBUG);
408399 }
409400
410401 @Test
411402 public void paramWithExceptionTest() throws Exception {
412403 logger.error("Throwing with parameters {}", "TestParam", new NullPointerException("Test Exception"));
413404 final List<LogEvent> events = app.getEvents();
414 assertNotNull(events, "Log event list not returned");
415 assertEquals(1, events.size(), "Incorrect number of log events");
405 assertNotNull("Log event list not returned", events);
406 assertEquals("Incorrect number of log events", 1, events.size());
416407 final LogEvent event = events.get(0);
417408 final Throwable thrown = event.getThrown();
418 assertNotNull(thrown, "No throwable present in log event");
409 assertNotNull("No throwable present in log event", thrown);
419410 final Message msg = event.getMessage();
420411 assertEquals("Throwing with parameters {}", msg.getFormat());
421412 assertEquals("Throwing with parameters TestParam", msg.getFormattedMessage());
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
18 import java.beans.PropertyChangeEvent;
19 import java.beans.PropertyChangeListener;
20 import java.util.List;
21
22 import org.apache.logging.log4j.*;
2023 import org.apache.logging.log4j.core.config.Configuration;
2124 import org.apache.logging.log4j.core.config.LoggerConfig;
22 import org.apache.logging.log4j.junit.Named;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
2426 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.Test;
27 import org.junit.Before;
28 import org.junit.ClassRule;
29 import org.junit.Test;
2630
27 import java.util.List;
31 import static org.junit.Assert.*;
2832
29 import static org.junit.jupiter.api.Assertions.assertEquals;
30 import static org.junit.jupiter.api.Assertions.assertSame;
31
32 @LoggerContextSource("log4j-test2.xml")
33 /**
34 *
35 */
3336 public class LoggerUpdateTest {
3437
35 private final ListAppender app;
38 private static final String CONFIG = "log4j-test2.xml";
39 private ListAppender app;
3640
37 public LoggerUpdateTest(@Named("List") final ListAppender app) {
38 this.app = app.clear();
41 @ClassRule
42 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
43
44 @Before
45 public void before() {
46 app = context.getListAppender("List").clear();
3947 }
4048
4149 @Test
42 public void resetLevel(final LoggerContext context) {
50 public void resetLevel() {
4351 final org.apache.logging.log4j.Logger logger = context.getLogger("com.apache.test");
4452 logger.traceEntry();
4553 List<LogEvent> events = app.getEvents();
46 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
54 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
4755 app.clear();
4856 final LoggerContext ctx = LoggerContext.getContext(false);
4957 final Configuration config = ctx.getConfiguration();
5563 ctx.updateLoggers(); // This causes all Loggers to refetch information from their LoggerConfig.
5664 logger.traceEntry();
5765 events = app.getEvents();
58 assertEquals(0, events.size(), "Incorrect number of events. Expected 0, actual " + events.size());
66 assertEquals("Incorrect number of events. Expected 0, actual " + events.size(), 0, events.size());
5967 }
6068
6169 @Test
62 public void testUpdateLoggersPropertyListeners(final LoggerContext context) throws Exception {
63 context.addPropertyChangeListener(evt -> {
64 assertEquals(LoggerContext.PROPERTY_CONFIG, evt.getPropertyName());
65 assertSame(context, evt.getSource());
70 public void testUpdateLoggersPropertyListeners() throws Exception {
71 final LoggerContext ctx = context.getLoggerContext();
72 ctx.addPropertyChangeListener(new PropertyChangeListener() {
73 @Override
74 public void propertyChange(final PropertyChangeEvent evt) {
75 assertEquals(LoggerContext.PROPERTY_CONFIG, evt.getPropertyName());
76 assertSame(ctx, evt.getSource());
77 }
6678 });
67 context.updateLoggers();
79 ctx.updateLoggers();
6880 }
6981 }
7082
1717
1818 import org.apache.logging.log4j.core.appender.ConsoleAppender;
1919 import org.apache.logging.log4j.core.layout.PatternLayout;
20 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.junit.jupiter.api.Test;
20 import org.apache.logging.log4j.junit.LoggerContextRule;
21 import org.junit.ClassRule;
22 import org.junit.Test;
2323
24 import static org.junit.jupiter.api.Assertions.*;
24 import static org.junit.Assert.*;
2525
26 @LoggerContextSource("log4j-lookup.xml")
26 /**
27 *
28 */
2729 public class LookupTest {
2830
31 private static final String CONFIG = "log4j-lookup.xml";
32
33 @ClassRule
34 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
35
2936 @Test
30 public void testHostname(@Named final ConsoleAppender console) {
31 final Layout<?> layout = console.getLayout();
32 assertNotNull(layout, "No Layout");
33 assertTrue(layout instanceof PatternLayout, "Layout is not a PatternLayout");
37 public void testHostname() {
38 final ConsoleAppender app = context.getRequiredAppender("console", ConsoleAppender.class);
39 final Layout<?> layout = app.getLayout();
40 assertNotNull("No Layout", layout);
41 assertTrue("Layout is not a PatternLayout", layout instanceof PatternLayout);
3442 final String pattern = ((PatternLayout) layout).getConversionPattern();
35 assertNotNull(pattern, "No conversion pattern");
36 assertTrue(pattern.contains("org.junit,org.apache.maven,org.eclipse,sun.reflect,java.lang.reflect"),
37 "No filters");
43 assertNotNull("No conversion pattern", pattern);
44 assertTrue("No filters", pattern.contains("org.junit,org.apache.maven,org.eclipse,sun.reflect,java.lang.reflect"));
3845 }
3946 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.MarkerManager;
1819 import org.apache.logging.log4j.ThreadContext;
1920 import org.apache.logging.log4j.junit.LoggerContextRule;
2021 import org.apache.logging.log4j.test.appender.ListAppender;
2425
2526 import java.util.List;
2627
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.junit.Assert.assertTrue;
29 import static org.junit.Assert.assertEquals;
2930
3031 public class PatternResolverDoesNotEvaluateThreadContextTest {
3132
4647 @Test
4748 public void testNoUserSet() {
4849 Logger logger = context.getLogger(getClass());
49 logger.info("This is a test");
50 logger.info(MarkerManager.getMarker("This is a test"), "msg");
5051 List<String> messages = listAppender.getMessages();
51 assertTrue(messages != null && messages.size() > 0, "No messages returned");
52 assertTrue("No messages returned", messages != null && messages.size() > 0);
5253 String message = messages.get(0);
5354 assertEquals("INFO org.apache.logging.log4j.core." +
5455 "PatternResolverDoesNotEvaluateThreadContextTest ${ctx:user} This is a test", message);
5758 @Test
5859 public void testMessageIsNotLookedUp() {
5960 Logger logger = context.getLogger(getClass());
60 logger.info("This is a ${upper:test}");
61 logger.info(MarkerManager.getMarker("This is a ${upper:test}"), "msg");
6162 List<String> messages = listAppender.getMessages();
62 assertTrue(messages != null && messages.size() > 0, "No messages returned");
63 assertTrue("No messages returned", messages != null && messages.size() > 0);
6364 String message = messages.get(0);
6465 assertEquals("INFO org.apache.logging.log4j.core." +
6566 "PatternResolverDoesNotEvaluateThreadContextTest ${ctx:user} This is a ${upper:test}", message);
7071 Logger logger = context.getLogger(getClass());
7172 ThreadContext.put(PARAMETER, "123");
7273 try {
73 logger.info("This is a test");
74 logger.info(MarkerManager.getMarker("This is a test"), "msg");
7475 } finally {
7576 ThreadContext.remove(PARAMETER);
7677 }
7778 List<String> messages = listAppender.getMessages();
78 assertTrue(messages != null && messages.size() > 0, "No messages returned");
79 assertTrue("No messages returned", messages != null && messages.size() > 0);
7980 String message = messages.get(0);
8081 assertEquals("INFO org.apache.logging.log4j.core." +
8182 "PatternResolverDoesNotEvaluateThreadContextTest 123 This is a test", message);
8687 Logger logger = context.getLogger(getClass());
8788 ThreadContext.put(PARAMETER, "${java:version}");
8889 try {
89 logger.info("This is a test");
90 logger.info(MarkerManager.getMarker("This is a test"), "msg");
9091 } finally {
9192 ThreadContext.remove(PARAMETER);
9293 }
9394 List<String> messages = listAppender.getMessages();
94 assertTrue(messages != null && messages.size() > 0, "No messages returned");
95 assertTrue("No messages returned", messages != null && messages.size() > 0);
9596 String message = messages.get(0);
9697 assertEquals("INFO org.apache.logging.log4j.core." +
9798 "PatternResolverDoesNotEvaluateThreadContextTest ${java:version} This is a test", message);
102103 Logger logger = context.getLogger(getClass());
103104 ThreadContext.put(PARAMETER, "user${java:version}name");
104105 try {
105 logger.info("This is a test");
106 logger.info(MarkerManager.getMarker("This is a test"), "msg");
106107 } finally {
107108 ThreadContext.remove(PARAMETER);
108109 }
109110 List<String> messages = listAppender.getMessages();
110 assertTrue(messages != null && messages.size() > 0, "No messages returned");
111 assertTrue("No messages returned",messages != null && messages.size() > 0);
111112 String message = messages.get(0);
112113 assertEquals("INFO org.apache.logging.log4j.core." +
113114 "PatternResolverDoesNotEvaluateThreadContextTest user${java:version}name This is a test", message);
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2322 import org.apache.logging.log4j.test.appender.ListAppender;
2423 import org.apache.logging.log4j.util.Strings;
25 import org.junit.jupiter.api.Test;
24 import org.junit.ClassRule;
25 import org.junit.Test;
2626
27 import static org.junit.jupiter.api.Assertions.*;
28
29 @LoggerContextSource("log4j-patternSelector.xml")
27 import static org.junit.Assert.*;
28 /**
29 *
30 */
3031 public class PatternSelectorTest {
3132
33
34 private static final String CONFIG = "log4j-patternSelector.xml";
35
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
38
3239 @Test
33 public void testMarkerPatternSelector(@Named("List") final ListAppender app) {
40 public void testMarkerPatternSelector() throws Exception {
3441 final org.apache.logging.log4j.Logger logger = LogManager.getLogger("TestMarkerPatternSelector");
3542 logger.traceEntry();
3643 logger.info("Hello World");
3744 logger.traceExit();
45 final ListAppender app = (ListAppender) context.getRequiredAppender("List");
46 assertNotNull("No ListAppender", app);
3847 final List<String> messages = app.getMessages();
39 assertNotNull(messages, "No Messages");
40 assertEquals(3, messages.size(),
41 "Incorrect number of messages. Expected 3, Actual " + messages.size() + ": " + messages);
48 assertNotNull("No Messages", messages);
49 assertTrue("Incorrect number of messages. Expected 3, Actual " + messages.size() + ": " + messages, messages.size() == 3);
4250 final String expect = String.format("[TRACE] TestMarkerPatternSelector ====== "
43 + "o.a.l.l.c.PatternSelectorTest.testMarkerPatternSelector:36 Enter ======%n");
51 + "o.a.l.l.c.PatternSelectorTest.testMarkerPatternSelector:43 Enter ======%n");
4452 assertEquals(expect, messages.get(0));
4553 assertEquals("[INFO ] TestMarkerPatternSelector Hello World" + Strings.LINE_SEPARATOR, messages.get(1));
4654 app.clear();
4755 }
4856
4957 @Test
50 public void testScriptPatternSelector(@Named("List2") final ListAppender app) {
58 public void testScriptPatternSelector() throws Exception {
5159 final org.apache.logging.log4j.Logger logger = LogManager.getLogger("TestScriptPatternSelector");
5260 final org.apache.logging.log4j.Logger logger2 = LogManager.getLogger("NoLocation");
5361 logger.traceEntry();
5462 logger.info("Hello World");
5563 logger2.info("No location information");
5664 logger.traceExit();
65 final ListAppender app = (ListAppender) context.getRequiredAppender("List2");
66 assertNotNull("No ListAppender", app);
5767 final List<String> messages = app.getMessages();
58 assertNotNull(messages, "No Messages");
59 assertEquals(4, messages.size(),
60 "Incorrect number of messages. Expected 4, Actual " + messages.size() + ": " + messages);
68 assertNotNull("No Messages", messages);
69 assertTrue("Incorrect number of messages. Expected 4, Actual " + messages.size() + ": " + messages, messages.size() == 4);
6170 String expect = "[TRACE] TestScriptPatternSelector ====== " +
62 "o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector:54 Enter ======" + Strings.LINE_SEPARATOR;
71 "o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector:62 Enter ======" + Strings.LINE_SEPARATOR;
6372 assertEquals(expect, messages.get(0));
64 expect = "[INFO ] TestScriptPatternSelector o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector.55 " +
73 expect = "[INFO ] TestScriptPatternSelector o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector.63 " +
6574 "Hello World" + Strings.LINE_SEPARATOR;
6675 assertEquals(expect, messages.get(1));
6776 assertEquals("[INFO ] NoLocation No location information" + Strings.LINE_SEPARATOR, messages.get(2));
6978 }
7079
7180 @Test
72 public void testJavaScriptPatternSelector(@Named("List3") final ListAppender app) {
81 public void testJavaScriptPatternSelector() throws Exception {
7382 final org.apache.logging.log4j.Logger logger = LogManager.getLogger("TestJavaScriptPatternSelector");
7483 final org.apache.logging.log4j.Logger logger2 = LogManager.getLogger("JavascriptNoLocation");
7584 logger.traceEntry();
7685 logger.info("Hello World");
7786 logger2.info("No location information");
7887 logger.traceExit();
88 final ListAppender app = (ListAppender) context.getRequiredAppender("List3");
89 assertNotNull("No ListAppender", app);
7990 final List<String> messages = app.getMessages();
80 assertNotNull(messages, "No Messages");
81 assertEquals(4, messages.size(),
82 "Incorrect number of messages. Expected 4, Actual " + messages.size() + ": " + messages);
91 assertNotNull("No Messages", messages);
92 assertTrue("Incorrect number of messages. Expected 4, Actual " + messages.size() + ": " + messages, messages.size() == 4);
8393 String expect = "[TRACE] TestJavaScriptPatternSelector ====== " +
84 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector:76 Enter ======" + Strings.LINE_SEPARATOR;
94 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector:85 Enter ======" + Strings.LINE_SEPARATOR;
8595 assertEquals(expect, messages.get(0));
8696 expect = "[INFO ] TestJavaScriptPatternSelector " +
87 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector.77 Hello World" + Strings.LINE_SEPARATOR;
97 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector.86 Hello World" + Strings.LINE_SEPARATOR;
8898 assertEquals(expect, messages.get(1));
8999 assertEquals("[INFO ] JavascriptNoLocation No location information" + Strings.LINE_SEPARATOR, messages.get(2));
90100 app.clear();
+0
-55
log4j-core/src/test/java/org/apache/logging/log4j/core/PatternVariableResolverTest.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.logging.log4j.core;
17
18 import org.apache.logging.log4j.junit.LoggerContextRule;
19 import org.apache.logging.log4j.test.appender.ListAppender;
20 import org.junit.Before;
21 import org.junit.ClassRule;
22 import org.junit.Test;
23
24 import java.util.List;
25
26 import static org.junit.Assert.assertTrue;
27
28 /**
29 * Class Description goes here.
30 */
31 public class PatternVariableResolverTest {
32
33
34 private static final String CONFIG = "log4j2-pattern-layout.xml";
35 private ListAppender listAppender;
36
37 @ClassRule
38 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
39
40 @Before
41 public void before() {
42 listAppender = context.getRequiredAppender("list", ListAppender.class);
43 }
44
45 @Test
46 public void testFileName() {
47 Logger logger = context.getLogger(PatternVariableResolverTest.class);
48 logger.info("This is a test");
49 List<String> messages = listAppender.getMessages();
50 assertTrue("No messages returned", messages != null && messages.size() > 0);
51 String message = messages.get(0);
52 System.out.println(message);
53 }
54 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.core.config.Configuration;
19 import org.apache.logging.log4j.junit.Named;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.test.appender.ListAppender;
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.Test;
18 import static org.junit.Assert.assertNotSame;
19 import static org.junit.Assert.assertTrue;
2420
2521 import java.io.File;
2622 import java.util.concurrent.TimeUnit;
2723
28 import static org.junit.jupiter.api.Assertions.assertNotSame;
29 import static org.junit.jupiter.api.Assertions.assertTrue;
24 import org.apache.logging.log4j.core.config.Configuration;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
26 import org.junit.Before;
27 import org.junit.ClassRule;
28 import org.junit.Test;
3029
31 @LoggerContextSource("log4j-test2.properties")
30 /**
31 *
32 */
3233 public class PropertiesFileConfigTest {
3334
3435 private static final String CONFIG = "target/test-classes/log4j-test2.properties";
3536
36 private final org.apache.logging.log4j.Logger logger;
37 @ClassRule
38 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
3739
38 public PropertiesFileConfigTest(final LoggerContext context) {
39 logger = context.getLogger("LoggerTest");
40 }
40 private final org.apache.logging.log4j.Logger logger = context.getLogger("LoggerTest");
4141
42 @BeforeEach
43 void clear(@Named("List") final ListAppender appender) {
44 appender.clear();
42 @Before
43 public void before() {
44 context.getListAppender("List").clear();
4545 }
4646
4747 @Test
48 public void testReconfiguration(final LoggerContext context) throws Exception {
48 public void testReconfiguration() throws Exception {
4949 final Configuration oldConfig = context.getConfiguration();
5050 final int MONITOR_INTERVAL_SECONDS = 5;
5151 final File file = new File(CONFIG);
5252 final long orig = file.lastModified();
5353 final long newTime = orig + 10000;
54 assertTrue(file.setLastModified(newTime), "setLastModified should have succeeded.");
54 assertTrue("setLastModified should have succeeded.", file.setLastModified(newTime));
5555 TimeUnit.SECONDS.sleep(MONITOR_INTERVAL_SECONDS + 1);
5656 for (int i = 0; i < 17; ++i) {
5757 logger.info("Reconfigure");
6262 Thread.sleep(100);
6363 newConfig = context.getConfiguration();
6464 } while (newConfig == oldConfig && loopCount++ < 5);
65 assertNotSame(newConfig, oldConfig, "Reconfiguration failed");
65 assertNotSame("Reconfiguration failed", newConfig, oldConfig);
6666 }
6767 }
6868
1717
1818 import org.apache.logging.log4j.message.ReusableMessage;
1919 import org.apache.logging.log4j.message.ReusableMessageFactory;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
2222 import java.util.concurrent.CountDownLatch;
2323 import java.util.concurrent.TimeUnit;
2424
25 import static org.junit.jupiter.api.Assertions.assertTrue;
25 import static org.junit.Assert.assertTrue;
2626
2727 public class ReusableParameterizedMessageMemoryLeakTest {
2828
2929 @Test
30 @SuppressWarnings("UnusedAssignment") // parameter set to null to allow garbage collection
3031 public void testParametersAreNotLeaked() throws Exception {
3132 final CountDownLatch latch = new CountDownLatch(1);
3233 final ReusableMessage message = (ReusableMessage) ReusableMessageFactory.INSTANCE.newMessage(
3637 final GarbageCollectionHelper gcHelper = new GarbageCollectionHelper();
3738 gcHelper.run();
3839 try {
39 assertTrue(latch.await(30, TimeUnit.SECONDS), "Parameter should have been garbage collected");
40 assertTrue("Parameter should have been garbage collected", latch.await(30, TimeUnit.SECONDS));
4041 } finally {
4142 gcHelper.close();
4243 }
1616 package org.apache.logging.log4j.core;
1717
1818 import org.apache.logging.log4j.core.config.Configuration;
19 import org.apache.logging.log4j.junit.LoggerContextSource;
20 import org.junit.jupiter.api.Test;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.junit.ClassRule;
21 import org.junit.Test;
2122
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.Assert.*;
2324
24 @LoggerContextSource("log4j-test3.xml")
25 /**
26 *
27 */
2528 public class ShutdownDisabledTest {
2629
30 private static final String CONFIG = "log4j-test3.xml";
31
32 @ClassRule
33 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
34
2735 @Test
28 public void testShutdownFlag(final Configuration config) {
29 assertFalse(config.isShutdownHookEnabled(), "Shutdown hook is enabled");
36 public void testShutdownFlag() {
37 final Configuration config = context.getConfiguration();
38 assertNotNull("No configuration", config);
39 assertFalse("Shutdown hook is enabled", config.isShutdownHookEnabled());
3040 }
3141
3242 }
1616 package org.apache.logging.log4j.core;
1717
1818 import org.apache.logging.log4j.core.config.Configuration;
19 import org.apache.logging.log4j.junit.LoggerContextSource;
20 import org.junit.jupiter.api.Test;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.junit.ClassRule;
21 import org.junit.Test;
2122
22 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2324
24 @LoggerContextSource("log4j-test-shutdownTimeout.xml")
25 /**
26 *
27 */
2528 public class ShutdownTimeoutConfigurationTest {
2629
30 private static final String CONFIG = "log4j-test-shutdownTimeout.xml";
31
32 @ClassRule
33 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
34
2735 @Test
28 public void testShutdownFlag(final Configuration config) {
36 public void testShutdownFlag() {
37 final Configuration config = context.getConfiguration();
38 assertNotNull("No configuration", config);
2939 assertEquals(5000, config.getShutdownTimeoutMillis());
3040 }
3141
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import org.apache.logging.log4j.MarkerManager;
19 import org.apache.logging.log4j.ThreadContext;
20 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.message.EntryMessage;
23 import org.apache.logging.log4j.message.StructuredDataMessage;
24 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.Test;
26
2718 import java.util.Date;
2819 import java.util.List;
2920 import java.util.Locale;
3021
31 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import org.apache.logging.log4j.MarkerManager;
23 import org.apache.logging.log4j.ThreadContext;
24 import org.apache.logging.log4j.junit.LoggerContextRule;
25 import org.apache.logging.log4j.message.EntryMessage;
26 import org.apache.logging.log4j.message.StructuredDataMessage;
27 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.Before;
29 import org.junit.ClassRule;
30 import org.junit.Test;
3231
33 @LoggerContextSource("log4j-strict1.xml")
32 import static org.junit.Assert.*;
33
34 /**
35 *
36 */
3437 public class StrictXmlConfigTest {
3538
36 org.apache.logging.log4j.Logger logger;
39 private static final String CONFIG = "log4j-strict1.xml";
3740 private ListAppender app;
3841
39 public StrictXmlConfigTest(final LoggerContext context, @Named("List") final ListAppender app) {
40 logger = context.getLogger("LoggerTest");
41 this.app = app.clear();
42 @ClassRule
43 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
44
45 @Before
46 public void setUp() throws Exception {
47 app = context.getListAppender("List").clear();
4248 }
49
50 org.apache.logging.log4j.Logger logger = context.getLogger("LoggerTest");
4351
4452 @Test
4553 public void basicFlow() {
4654 final EntryMessage entry = logger.traceEntry();
4755 logger.traceExit(entry);
4856 final List<LogEvent> events = app.getEvents();
49 assertEquals(2, events.size(), "Incorrect number of events. Expected 2, actual " + events.size());
57 assertEquals("Incorrect number of events. Expected 2, actual " + events.size(), 2, events.size());
5058 }
5159
5260 @Test
5462 logger.traceEntry();
5563 logger.traceExit();
5664 final List<LogEvent> events = app.getEvents();
57 assertEquals(2, events.size(), "Incorrect number of events. Expected 2, actual " + events.size());
65 assertEquals("Incorrect number of events. Expected 2, actual " + events.size(), 2, events.size());
5866 }
5967
6068 @Test
6169 public void simpleFlow() {
62 logger.traceEntry();
63 logger.traceExit(0);
70 logger.entry(CONFIG);
71 logger.exit(0);
6472 final List<LogEvent> events = app.getEvents();
65 assertEquals(2, events.size(), "Incorrect number of events. Expected 2, actual " + events.size());
73 assertEquals("Incorrect number of events. Expected 2, actual " + events.size(), 2, events.size());
6674 }
6775
6876 @Test
6977 public void throwing() {
7078 logger.throwing(new IllegalArgumentException("Test Exception"));
7179 final List<LogEvent> events = app.getEvents();
72 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
80 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
7381 }
7482
7583 @Test
8088 logger.catching(e);
8189 }
8290 final List<LogEvent> events = app.getEvents();
83 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
91 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
8492 }
8593
8694 @Test
8795 public void debug() {
8896 logger.debug("Debug message");
8997 final List<LogEvent> events = app.getEvents();
90 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
98 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
9199 }
92100
93101 @Test
94102 public void debugObject() {
95103 logger.debug(new Date());
96104 final List<LogEvent> events = app.getEvents();
97 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
105 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
98106 }
99107
100108 @Test
101109 public void debugWithParms() {
102110 logger.debug("Hello, {}", "World");
103111 final List<LogEvent> events = app.getEvents();
104 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
112 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
105113 }
106114
107115 @Test
111119 ThreadContext.clearMap();
112120 logger.debug("Debug message");
113121 final List<LogEvent> events = app.getEvents();
114 assertEquals(2, events.size(), "Incorrect number of events. Expected 2, actual " + events.size());
122 assertEquals("Incorrect number of events. Expected 2, actual " + events.size(), 2, events.size());
115123 }
116124
117125 @Test
126134 logger.info(MarkerManager.getMarker("EVENT"), msg);
127135 ThreadContext.clearMap();
128136 final List<LogEvent> events = app.getEvents();
129 assertEquals(1, events.size(), "Incorrect number of events. Expected 1, actual " + events.size());
137 assertEquals("Incorrect number of events. Expected 1, actual " + events.size(), 1, events.size());
130138 }
131139 }
132140
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import java.util.List;
19
1820 import org.apache.logging.log4j.Logger;
1921 import org.apache.logging.log4j.core.util.Clock;
2022 import org.apache.logging.log4j.core.util.ClockFactory;
2123 import org.apache.logging.log4j.core.util.ClockFactoryTest;
2224 import org.apache.logging.log4j.core.util.Constants;
23 import org.apache.logging.log4j.junit.Named;
24 import org.apache.logging.log4j.junit.LoggerContextSource;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
2526 import org.apache.logging.log4j.message.Message;
2627 import org.apache.logging.log4j.message.SimpleMessage;
2728 import org.apache.logging.log4j.message.TimestampMessage;
2829 import org.apache.logging.log4j.test.appender.ListAppender;
2930 import org.apache.logging.log4j.util.Strings;
30 import org.junit.jupiter.api.AfterAll;
31 import org.junit.jupiter.api.BeforeAll;
32 import org.junit.jupiter.api.Test;
31 import org.junit.AfterClass;
32 import org.junit.Before;
33 import org.junit.BeforeClass;
34 import org.junit.ClassRule;
35 import org.junit.Test;
3336
34 import java.util.List;
35
36 import static org.junit.jupiter.api.Assertions.assertEquals;
37 import static org.junit.jupiter.api.Assertions.assertNotNull;
37 import static org.junit.Assert.*;
3838
3939 /**
4040 * Confirms that if you log a {@link TimestampMessage} then there are no unnecessary calls to {@link Clock}.
4242 * See LOG4J2-744.
4343 * </p>
4444 */
45 @LoggerContextSource("log4j2-744.xml")
4645 public class TimestampMessageTest {
4746 private ListAppender app;
4847
49 public TimestampMessageTest(@Named("List") final ListAppender app) {
50 this.app = app.clear();
51 }
48 @ClassRule
49 public static LoggerContextRule context = new LoggerContextRule("log4j2-744.xml");
5250
53 @BeforeAll
51 @BeforeClass
5452 public static void beforeClass() {
5553 System.setProperty(ClockFactory.PROPERTY_NAME, PoisonClock.class.getName());
5654 }
5755
58 @AfterAll
56 @Before
57 public void setUp() throws Exception {
58 this.app = context.getListAppender("List").clear();
59 }
60
61 @AfterClass
5962 public static void afterClass() throws IllegalAccessException {
6063 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, Strings.EMPTY);
6164 ClockFactoryTest.resetClocks();
6265 }
6366
6467 @Test
65 public void testTimestampMessage(final LoggerContext context) {
68 public void testTimestampMessage() {
6669 final Logger log = context.getLogger("TimestampMessageTest");
6770 log.info((Message) new TimeMsg("Message with embedded timestamp", 123456789000L));
6871 final List<String> msgs = app.getMessages();
7477
7578 public static class PoisonClock implements Clock {
7679 public PoisonClock() {
80 super();
7781 // Breakpoint here for debuging.
7882 }
7983
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import java.util.Locale;
19
1820 import org.apache.logging.log4j.EventLogger;
1921 import org.apache.logging.log4j.ThreadContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2123 import org.apache.logging.log4j.message.AsynchronouslyFormattable;
2224 import org.apache.logging.log4j.message.StructuredDataMessage;
23 import org.junit.jupiter.api.Disabled;
24 import org.junit.jupiter.api.Test;
25 import org.junit.ClassRule;
26 import org.junit.Test;
2527
26 import java.util.Locale;
28 /**
29 *
30 */
31 public class XmlEvents {
2732
28 @LoggerContextSource("xml-events.xml")
29 @Disabled("TODO")
30 public class XmlEvents {
33 private static final String CONFIG = "xml-events.xml";
34
35 @ClassRule
36 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
3137
3238 @Test
3339 public void testEvents() {
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;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.junit.After;
25 import org.junit.Before;
26 import org.junit.ClassRule;
27 import org.junit.Test;
28
29 import static org.junit.Assert.*;
30
31 /**
32 *
33 */
34 public class AsyncAppenderNoLocationTest {
35 private ListAppender app;
36
37 @ClassRule
38 public static LoggerContextRule init = null;
39
40 static {
41 try {
42 init = new LoggerContextRule("log4j-asynch-no-location.xml");
43 } catch (final Exception ex) {
44 ex.printStackTrace();
45 }
46 }
47
48 @Before
49 public void setUp() throws Exception {
50 try {
51 this.app = (ListAppender) init.getAppender("List");
52 assertNotNull("No List appender found", app);
53 } catch (final Exception ex) {
54 System.out.println("init = " + init == null ? "null" : init);
55
56 }
57
58 }
59
60 @After
61 public void after() {
62 if (app != null) {
63 app.clear();
64 }
65 }
66
67 @Test
68 public void testNoLocation() throws Exception {
69 final Logger logger = LogManager.getLogger(AsyncAppender.class);
70 logger.error("This is a test");
71 logger.warn("Hello world!");
72 Thread.sleep(100);
73 System.out.println("app = " + app == null ? "null" : app);
74 final List<String> list = app.getMessages();
75 assertNotNull("No events generated", list);
76 assertEquals("Incorrect number of events. Expected 2, got " + list.size(), list.size(), 2);
77 String msg = list.get(0);
78 String expected = "? This is a test";
79 assertEquals("Expected " + expected + ", Actual " + msg, expected, msg);
80 msg = list.get(1);
81 expected = "? Hello world!";
82 assertEquals("Expected " + expected + ", Actual " + msg, expected, msg);
83 }
84 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import java.lang.reflect.Field;
19 import java.util.concurrent.atomic.AtomicLong;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.LogManager;
2023 import org.apache.logging.log4j.Logger;
2124 import org.apache.logging.log4j.core.async.DefaultAsyncQueueFullPolicy;
2225 import org.apache.logging.log4j.core.async.EventRoute;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.Named;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
2527 import org.apache.logging.log4j.test.appender.BlockingAppender;
26 import org.junit.jupiter.api.AfterEach;
27 import org.junit.jupiter.api.Test;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.ClassRule;
31 import org.junit.Test;
2832
29 import java.lang.reflect.Field;
30 import java.util.concurrent.atomic.AtomicLong;
31
32 import static org.junit.jupiter.api.Assertions.assertEquals;
33 import static org.junit.Assert.*;
3334
3435 /**
3536 * Tests the AsyncAppender (LOG4J2-1080) event routing logic:
4142 * else queue.add(event) // blocking call
4243 * </pre>
4344 */
44 @LoggerContextSource("log4j-asynch-queue-full.xml")
4545 public class AsyncAppenderQueueFullPolicyTest {
46 private static final String CONFIG = "log4j-asynch-queue-full.xml";
4647
47 private final BlockingAppender blockingAppender;
48 private final AsyncAppender asyncAppender;
49 private final CountingAsyncQueueFullPolicy policy;
48 @ClassRule
49 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
5050
51 public AsyncAppenderQueueFullPolicyTest(
52 @Named("Block") final BlockingAppender blockingAppender, @Named("Async") final AsyncAppender asyncAppender)
53 throws Exception {
54 this.blockingAppender = blockingAppender;
55 this.asyncAppender = asyncAppender;
51 private BlockingAppender blockingAppender;
52 private AsyncAppender asyncAppender;
53 private CountingAsyncQueueFullPolicy policy;
54
55 @Before
56 public void before() throws Exception {
57 blockingAppender = context.getAppender("Block", BlockingAppender.class);
58 asyncAppender = context.getAppender("Async", AsyncAppender.class);
59
5660 final Field field = AsyncAppender.class.getDeclaredField("asyncQueueFullPolicy");
5761 field.setAccessible(true);
5862 policy = new CountingAsyncQueueFullPolicy();
6064 policy.queueFull.set(0L);
6165 }
6266
63 @AfterEach
67 @After
6468 public void after() {
6569 blockingAppender.running = false;
6670 policy.queueFull.set(0L);
7983 Thread.yield(); // wait until background thread takes one element off the queue
8084 }
8185 logger.info("event 5 - now the queue is full");
82 assertEquals(0, asyncAppender.getQueueRemainingCapacity(), "queue remaining capacity");
83 assertEquals(0, policy.queueFull.get(), "EventRouter invocations");
86 assertEquals("queue remaining capacity", 0, asyncAppender.getQueueRemainingCapacity());
87 assertEquals("EventRouter invocations", 0, policy.queueFull.get());
8488
8589 final Thread release = new Thread("AsyncAppenderReleaser") {
8690 @Override
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;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.junit.ClassRule;
23 import org.junit.Test;
24
25 /**
26 *
27 */
28 public class AsyncAppenderShutdownTimeoutTest {
29
30 @ClassRule
31 public static LoggerContextRule init = new LoggerContextRule("log4j-asynch-shutdownTimeout.xml");
32
33 @Test(timeout = 5000)
34 public void shutdownTest() throws Exception {
35 final LoggerContext ctx = (LoggerContext)LogManager.getContext(false);
36 final Logger logger = ctx.getLogger("Logger");
37 logger.info("This is a test");
38 ctx.stop();
39 }
40
41 }
1313 * See the license for the specific language governing permissions and
1414 * limitations under the license.
1515 */
16
1716 package org.apache.logging.log4j.core.appender;
18
19 import org.apache.logging.log4j.LoggingException;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.junit.Named;
23 import org.apache.logging.log4j.spi.ExtendedLogger;
24 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.Tag;
26 import org.junit.jupiter.api.Test;
27 import org.junit.jupiter.api.Timeout;
2817
2918 import java.util.List;
3019 import java.util.concurrent.TimeUnit;
31 import java.util.stream.Collectors;
3220
33 import static org.junit.jupiter.api.Assertions.*;
21 import org.apache.logging.log4j.LogManager;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.LoggingException;
24 import org.apache.logging.log4j.categories.Appenders;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
26 import org.apache.logging.log4j.test.appender.ListAppender;
27 import org.junit.After;
28 import org.junit.Before;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.experimental.categories.Category;
32 import org.junit.runner.RunWith;
33 import org.junit.runners.Parameterized;
3434
35 class AsyncAppenderTest {
35 import static org.junit.Assert.*;
3636
37 static void rewriteTest(final LoggerContext context) throws InterruptedException {
38 final ExtendedLogger logger = context.getLogger(AsyncAppender.class);
37 /**
38 *
39 */
40 @RunWith(Parameterized.class)
41 @Category({Appenders.AsyncConversant.class, Appenders.AsyncJcTools.class})
42 public class AsyncAppenderTest {
43
44 private static final long TIMEOUT_MILLIS = 2000;
45
46 @Parameterized.Parameters(name = "{0}")
47 public static Object[] data() {
48 return new String[]{
49 // default async config uses array blocking queue
50 "log4j-asynch.xml",
51 // override default blocking queue implementations
52 "BlockingQueueFactory-ArrayBlockingQueue.xml",
53 "BlockingQueueFactory-DisruptorBlockingQueue.xml",
54 "BlockingQueueFactory-JCToolsBlockingQueue.xml",
55 "BlockingQueueFactory-LinkedTransferQueue.xml"
56 };
57 }
58
59 public AsyncAppenderTest(final String configFileName) {
60 context = new LoggerContextRule(configFileName);
61 }
62
63 @Rule
64 public LoggerContextRule context;
65
66 private ListAppender listAppender;
67
68 @Before
69 public void before() throws Exception {
70 listAppender = context.getListAppender("List");
71 }
72
73 @After
74 public void after() {
75 listAppender.clear();
76 }
77
78 @Test
79 public void rewriteTest() throws Exception {
80 final Logger logger = LogManager.getLogger(AsyncAppender.class);
3981 logger.error("This is a test");
4082 logger.warn("Hello world!");
41 final ListAppender appender = context.getConfiguration().getAppender("List");
42 final List<String> messages;
43 try {
44 messages = appender.getMessages(2, 2, TimeUnit.SECONDS);
45 } finally {
46 appender.clear();
47 }
48 assertNotNull(messages);
49 assertEquals(2, messages.size());
50 final String messagePrefix = AsyncAppenderTest.class.getName() + " rewriteTest ";
51 assertEquals(messagePrefix + "This is a test", messages.get(0));
52 assertEquals(messagePrefix + "Hello world!", messages.get(1));
83 final long timeoutMillis = TIMEOUT_MILLIS;
84 final TimeUnit timeUnit = TimeUnit.MILLISECONDS;
85 final List<String> list = listAppender.getMessages(2, timeoutMillis, timeUnit);
86 assertNotNull("No events generated", list);
87 assertTrue("Incorrect number of events after " + timeoutMillis + " " + timeUnit + ". Expected 2, got "
88 + list.size(), list.size() == 2);
89 String msg = list.get(0);
90 String expected = AsyncAppenderTest.class.getName() + " rewriteTest This is a test";
91 assertTrue("Expected " + expected + ", Actual " + msg, expected.equals(msg));
92 msg = list.get(1);
93 expected = AsyncAppenderTest.class.getName() + " rewriteTest Hello world!";
94 assertTrue("Expected " + expected + ", Actual " + msg, expected.equals(msg));
5395 }
5496
55 static void exceptionTest(final LoggerContext context) throws InterruptedException {
56 final ExtendedLogger logger = context.getLogger(AsyncAppender.class);
97 @Test
98 public void testException() throws Exception {
99 final Logger logger = LogManager.getLogger(AsyncAppender.class);
57100 final Exception parent = new IllegalStateException("Test");
58101 final Throwable child = new LoggingException("This is a test", parent);
59102 logger.error("This is a test", child);
60 final ListAppender appender = context.getConfiguration().getAppender("List");
61 final List<String> messages;
62 try {
63 messages = appender.getMessages(1, 2, TimeUnit.SECONDS);
64 } finally {
65 appender.clear();
66 }
67 assertNotNull(messages);
68 assertEquals(1, messages.size());
69 assertTrue(messages.get(0).contains(parent.getClass().getName()));
70 }
71
72 @Test
73 @LoggerContextSource("log4j-asynch.xml")
74 void defaultAsyncAppenderConfig(final LoggerContext context) throws InterruptedException {
75 rewriteTest(context);
76 exceptionTest(context);
77
78 List<Thread> backgroundThreads = Thread.getAllStackTraces().keySet().stream()
79 .filter(AsyncAppenderEventDispatcher.class::isInstance)
80 .collect(Collectors.toList());
81 assertFalse(backgroundThreads.isEmpty(), "Failed to locate background thread");
82 for (Thread thread : backgroundThreads) {
83 assertTrue(thread.isDaemon(), "AsyncAppender should use daemon threads");
84 }
85 }
86
87 @Test
88 @LoggerContextSource("BlockingQueueFactory-ArrayBlockingQueue.xml")
89 void arrayBlockingQueue(final LoggerContext context) throws InterruptedException {
90 rewriteTest(context);
91 exceptionTest(context);
92 }
93
94 @Test
95 @Tag("disruptor")
96 @LoggerContextSource("BlockingQueueFactory-DisruptorBlockingQueue.xml")
97 void disruptorBlockingQueue(final LoggerContext context) throws InterruptedException {
98 rewriteTest(context);
99 exceptionTest(context);
100 }
101
102 @Test
103 @Tag("jctools")
104 @LoggerContextSource("BlockingQueueFactory-JCToolsBlockingQueue.xml")
105 void jcToolsBlockingQueue(final LoggerContext context) throws InterruptedException {
106 rewriteTest(context);
107 exceptionTest(context);
108 }
109
110 @Test
111 @LoggerContextSource("BlockingQueueFactory-LinkedTransferQueue.xml")
112 void linkedTransferQueue(final LoggerContext context) throws InterruptedException {
113 rewriteTest(context);
114 exceptionTest(context);
115 }
116
117 @Test
118 @Timeout(5)
119 @LoggerContextSource("log4j-asynch-shutdownTimeout.xml")
120 void shutdownTimeout(final LoggerContext context) {
121 context.getLogger("Logger").info("This is a test");
122 context.stop();
123 }
124
125 @Test
126 @LoggerContextSource("log4j-asynch-no-location.xml")
127 void noLocationInformation(final LoggerContext context, @Named("List") final ListAppender appender) throws InterruptedException {
128 final ExtendedLogger logger = context.getLogger(getClass());
129 logger.error("This is a test");
130 logger.warn("Hello world!");
131 final List<String> messages;
132 try {
133 messages = appender.getMessages(2, 2, TimeUnit.SECONDS);
134 } finally {
135 appender.clear();
136 }
137 assertNotNull(messages);
138 assertEquals(2, messages.size());
139 assertEquals("? This is a test", messages.get(0));
140 assertEquals("? Hello world!", messages.get(1));
103 final long timeoutMillis = TIMEOUT_MILLIS;
104 final TimeUnit timeUnit = TimeUnit.MILLISECONDS;
105 final List<String> list = listAppender.getMessages(1, timeoutMillis, timeUnit);
106 assertNotNull("No events generated", list);
107 assertTrue("Incorrect number of events after " + timeoutMillis + " " + timeUnit + ". Expected 1, got "
108 + list.size(), list.size() == 1);
109 final String msg = list.get(0);
110 assertTrue("No parent exception", msg.contains("java.lang.IllegalStateException"));
141111 }
142112 }
1919
2020 import org.apache.logging.log4j.core.ErrorHandler;
2121 import org.apache.logging.log4j.core.layout.PatternLayout;
22 import org.junit.jupiter.api.Test;
23
24 import static org.junit.jupiter.api.Assertions.*;
22 import org.junit.Assert;
23 import org.junit.Test;
2524
2625 public class ConsoleAppenderBuilderTest {
2726
3029 */
3130 @Test
3231 public void testDefaultImmediateFlush() {
33 assertTrue(ConsoleAppender.newBuilder().isImmediateFlush());
32 Assert.assertTrue(ConsoleAppender.newBuilder().isImmediateFlush());
3433 }
3534
3635 /**
3736 * Tests https://issues.apache.org/jira/browse/LOG4J2-1636
38 *
37 *
3938 * Tested with Oracle 7 and 8 and IBM Java 8.
4039 */
4140 @Test
4443 final PatternLayout layout = (PatternLayout) appender.getLayout();
4544 final String charsetName = System.getProperty("sun.stdout.encoding");
4645 final String expectedName = charsetName != null ? charsetName : Charset.defaultCharset().name();
47 assertEquals(expectedName, layout.getCharset().name());
46 Assert.assertEquals(expectedName, layout.getCharset().name());
4847 }
4948
5049 /**
5352 @Test
5453 public void testSetNullErrorHandlerIsNotAllowed() {
5554 final ConsoleAppender appender = ConsoleAppender.newBuilder().setName("test").build();
56 ErrorHandler handler = appender.getHandler();
57 assertNotNull(handler);
55 final ErrorHandler handler = appender.getHandler();
56 Assert.assertNotNull(handler);
5857 // This could likely be allowed to throw, but we're just testing that
5958 // setting null does not actually set a null handler.
6059 appender.setHandler(null);
61 assertSame(handler, appender.getHandler());
60 Assert.assertSame(handler, appender.getHandler());
6261 }
6362 }
2828 import org.apache.logging.log4j.core.config.Configurator;
2929 import org.junit.Test;
3030 import org.junit.experimental.categories.Category;
31 import org.junit.jupiter.api.parallel.ResourceLock;
32 import org.junit.jupiter.api.parallel.Resources;
3331
3432 /**
3533 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
6058 * This is a @Test method to make it easy to run from a command line with {@code mvn -Dtest=FQCN test}
6159 */
6260 @Test
63 @ResourceLock(Resources.SYSTEM_PROPERTIES)
6461 public void test() {
6562 test(null);
6663 }
2626 import org.apache.logging.log4j.core.layout.PatternLayout;
2727 import org.apache.logging.log4j.message.SimpleMessage;
2828 import org.apache.logging.log4j.util.Strings;
29 import org.junit.jupiter.api.AfterAll;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
33 import org.junit.jupiter.api.extension.ExtendWith;
29 import org.junit.AfterClass;
30 import org.junit.Assert;
31 import org.junit.Before;
32 import org.junit.BeforeClass;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
3435 import org.mockito.Mock;
35 import org.mockito.junit.jupiter.MockitoExtension;
36 import org.mockito.runners.MockitoJUnitRunner;
3637
37 import static org.junit.jupiter.api.Assertions.*;
38 import static org.junit.Assert.*;
3839 import static org.mockito.ArgumentMatchers.any;
3940 import static org.mockito.ArgumentMatchers.anyInt;
4041 import static org.mockito.BDDMockito.then;
4142 import static org.mockito.Mockito.atLeastOnce;
4243
43 @ExtendWith(MockitoExtension.class)
44 /**
45 *
46 */
47 @RunWith(MockitoJUnitRunner.class)
4448 public class ConsoleAppenderTest {
4549
4650 private static final String LOG4J_SKIP_JANSI = "log4j.skipJansi";
4751
48 @AfterAll
52 @AfterClass
4953 public static void afterClass() {
5054 System.clearProperty(LOG4J_SKIP_JANSI);
5155 }
5256
53 @BeforeAll
57 @BeforeClass
5458 public static void beforeClass() {
5559 System.setProperty(LOG4J_SKIP_JANSI, "true");
5660 }
6064 @Mock
6165 PrintStream psMock;
6266
63 @BeforeEach
67 @Before
6468 public void before() {
6569 System.setProperty(LOG4J_SKIP_JANSI, "true");
6670 baos = new ByteArrayOutputStream();
8993 final Layout<String> layout = PatternLayout.newBuilder().withAlwaysWriteExceptions(true).build();
9094 final ConsoleAppender app = ConsoleAppender.newBuilder().setLayout(layout).setTarget(targetName).setName("Console").setIgnoreExceptions(false).build();
9195 app.start();
92 assertTrue(app.isStarted(), "Appender did not start");
96 assertTrue("Appender did not start", app.isStarted());
9397
9498 final LogEvent event = Log4jLogEvent.newBuilder() //
9599 .setLoggerName("TestLogger") //
100104 app.append(event);
101105
102106 app.stop();
103 assertFalse(app.isStarted(), "Appender did not stop");
107 assertFalse("Appender did not stop", app.isStarted());
104108 } finally {
105109 systemSetter.systemSet(ps);
106110 }
120124
121125 private void testFollowSystemPrintStream(final PrintStream ps, final Target target, final SystemSetter systemSetter) {
122126 final ConsoleAppender app = ConsoleAppender.newBuilder().setTarget(target).setFollow(true).setIgnoreExceptions(false).setName("test").build();
123 assertEquals(target, app.getTarget());
127 Assert.assertEquals(target, app.getTarget());
124128 app.start();
125129 try {
126130 final LogEvent event = Log4jLogEvent.newBuilder() //
130134 .setMessage(new SimpleMessage("Test")) //
131135 .build();
132136
133 assertTrue(app.isStarted(), "Appender did not start");
137 assertTrue("Appender did not start", app.isStarted());
134138 systemSetter.systemSet(new PrintStream(baos));
135139 try {
136140 app.append(event);
138142 systemSetter.systemSet(ps);
139143 }
140144 final String msg = baos.toString();
141 assertNotNull(msg, "No message");
142 assertTrue(msg.endsWith("Test" + Strings.LINE_SEPARATOR), "Incorrect message: \"" + msg + "\"");
145 assertNotNull("No message", msg);
146 assertTrue("Incorrect message: \"" + msg + "\"", msg.endsWith("Test" + Strings.LINE_SEPARATOR));
143147 } finally {
144148 app.stop();
145149 }
146 assertFalse(app.isStarted(), "Appender did not stop");
150 assertFalse("Appender did not stop", app.isStarted());
147151 }
148152
149153 @Test
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import java.util.List;
19
1820 import org.apache.logging.log4j.Logger;
1921 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2323 import org.apache.logging.log4j.test.appender.FailOnceAppender;
2424 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.AfterEach;
26 import org.junit.jupiter.api.Test;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.ClassRule;
28 import org.junit.Test;
2729
28 import java.util.List;
30 import static org.junit.Assert.*;
2931
30 import static org.junit.jupiter.api.Assertions.assertEquals;
31 import static org.junit.jupiter.api.Assertions.assertNotNull;
32 /**
33 *
34 */
35 public class FailoverAppenderTest {
36 private ListAppender app;
37 private FailOnceAppender foApp;
38 private Logger logger;
39 private Logger onceLogger;
3240
33 @LoggerContextSource("log4j-failover.xml")
34 public class FailoverAppenderTest {
35 private final ListAppender app;
36 private final FailOnceAppender foApp;
37 private final Logger logger;
38 private final Logger onceLogger;
41 @ClassRule
42 public static LoggerContextRule init = new LoggerContextRule("log4j-failover.xml");
3943
40 public FailoverAppenderTest(
41 final LoggerContext context, @Named("List") final ListAppender app, @Named("Once") final FailOnceAppender foApp) {
42 this.app = app;
43 this.foApp = foApp;
44 logger = context.getLogger("LoggerTest");
45 onceLogger = context.getLogger("Once");
44 @Before
45 public void setUp() throws Exception {
46 app = init.getListAppender("List");
47 foApp = (FailOnceAppender) init.getAppender("Once");
48 logger = init.getLogger("LoggerTest");
49 onceLogger = init.getLogger("Once");
4650 }
4751
48 @AfterEach
52 @After
4953 public void tearDown() throws Exception {
50 app.clear();
54 if (app != null) {
55 app.clear();
56 }
5157 }
5258
5359 @Test
5561 logger.error("This is a test");
5662 List<LogEvent> events = app.getEvents();
5763 assertNotNull(events);
58 assertEquals(events.size(), 1, "Incorrect number of events. Should be 1 is " + events.size());
64 assertEquals("Incorrect number of events. Should be 1 is " + events.size(), events.size(), 1);
5965 app.clear();
6066 logger.error("This is a test");
6167 events = app.getEvents();
6268 assertNotNull(events);
63 assertEquals(events.size(), 1, "Incorrect number of events. Should be 1 is " + events.size());
69 assertEquals("Incorrect number of events. Should be 1 is " + events.size(), events.size(), 1);
6470 }
6571
6672 @Test
6975 onceLogger.error("Fail again");
7076 List<LogEvent> events = app.getEvents();
7177 assertNotNull(events);
72 assertEquals(events.size(), 2, "Incorrect number of events. Should be 2 is " + events.size());
78 assertEquals("Incorrect number of events. Should be 2 is " + events.size(), events.size(), 2);
7379 app.clear();
7480 Thread.sleep(1100);
7581 onceLogger.error("Fail after recovery interval");
7682 onceLogger.error("Second log message");
7783 events = app.getEvents();
78 assertEquals(events.size(), 0, "Did not recover");
79 events = foApp.drainEvents();
80 assertEquals(events.size(), 2, "Incorrect number of events in primary appender");
84 assertEquals("Did not recover", events.size(), 0);
85 events = foApp.getEvents();
86 assertEquals("Incorrect number of events in primary appender", events.size(), 2);
8187 }
8288 }
+0
-90
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FailoverFailedPrimaryAppenderTest.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.logging.log4j.core.appender;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.test.appender.FailOnceAppender;
24 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29
30 import static org.junit.Assert.assertEquals;
31 import static org.junit.Assert.assertNotNull;
32
33 /**
34 *
35 */
36 public class FailoverFailedPrimaryAppenderTest {
37 private ListAppender app;
38 private FailOnceAppender foApp;
39 private Logger logger;
40 private Logger onceLogger;
41
42 @ClassRule
43 public static LoggerContextRule init = new LoggerContextRule("log4j-failover.xml");
44
45 @Before
46 public void setUp() throws Exception {
47 app = init.getListAppender("List");
48 foApp = (FailOnceAppender) init.getAppender("Once");
49 logger = init.getLogger("LoggerTest");
50 onceLogger = init.getLogger("Once");
51 }
52
53 @After
54 public void tearDown() throws Exception {
55 if (app != null) {
56 app.clear();
57 }
58 }
59
60 @Test
61 public void testFailover() {
62 logger.error("This is a test");
63 List<LogEvent> events = app.getEvents();
64 assertNotNull(events);
65 assertEquals("Incorrect number of events. Should be 1 is " + events.size(), events.size(), 1);
66 app.clear();
67 logger.error("This is a test");
68 events = app.getEvents();
69 assertNotNull(events);
70 assertEquals("Incorrect number of events. Should be 1 is " + events.size(), events.size(), 1);
71 }
72
73 @Test
74 public void testRecovery() throws Exception {
75 onceLogger.error("Fail once");
76 onceLogger.error("Fail again");
77 List<LogEvent> events = app.getEvents();
78 assertNotNull(events);
79 assertEquals("Incorrect number of events. Should be 2 is " + events.size(), events.size(), 2);
80 app.clear();
81 Thread.sleep(1100);
82 onceLogger.error("Fail after recovery interval");
83 onceLogger.error("Second log message");
84 events = app.getEvents();
85 assertEquals("Did not recover", events.size(), 0);
86 events = foApp.drainEvents();
87 assertEquals("Incorrect number of events in primary appender", events.size(), 2);
88 }
89 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import org.junit.jupiter.api.Test;
19
20 import static org.junit.jupiter.api.Assertions.assertTrue;
18 import org.junit.Assert;
19 import org.junit.Test;
2120
2221 public class FileAppenderBuilderTest {
2322
2625 */
2726 @Test
2827 public void testDefaultImmediateFlush() {
29 assertTrue(FileAppender.newBuilder().isImmediateFlush());
28 Assert.assertTrue(FileAppender.newBuilder().isImmediateFlush());
3029 }
3130 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.nio.charset.Charset;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.attribute.PosixFileAttributes;
30 import java.nio.file.attribute.PosixFilePermissions;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.List;
34
1835 import org.apache.commons.lang3.SystemUtils;
1936 import org.apache.logging.log4j.Level;
2037 import org.apache.logging.log4j.core.Layout;
2138 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.LoggerContext;
2339 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2440 import org.apache.logging.log4j.core.layout.PatternLayout;
2541 import org.apache.logging.log4j.core.util.FileUtils;
26 import org.apache.logging.log4j.junit.CleanUpDirectories;
27 import org.apache.logging.log4j.junit.LoggerContextSource;
2842 import org.apache.logging.log4j.message.SimpleMessage;
29 import org.apache.logging.log4j.spi.ExtendedLogger;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.params.ParameterizedTest;
33 import org.junit.jupiter.params.provider.CsvSource;
34
35 import java.io.File;
36 import java.io.IOException;
37 import java.nio.file.Files;
38 import java.nio.file.Path;
39 import java.nio.file.Paths;
40 import java.nio.file.attribute.PosixFileAttributes;
41 import java.nio.file.attribute.PosixFilePermissions;
42 import java.util.stream.Stream;
43
44 import static org.apache.logging.log4j.util.Unbox.box;
45 import static org.junit.jupiter.api.Assertions.*;
46 import static org.junit.jupiter.api.Assumptions.assumeTrue;
43 import org.junit.Assert;
44 import org.junit.Assume;
45 import org.junit.BeforeClass;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.junit.runners.Parameterized;
4749
4850 /**
4951 * Tests {@link FileAppender}.
5052 */
51 @CleanUpDirectories(FileAppenderPermissionsTest.DIR)
53 @RunWith(Parameterized.class)
5254 public class FileAppenderPermissionsTest {
5355
54 static final String DIR = "target/permissions1";
55
56 @BeforeAll
56 private static final String DIR = "target/permissions1";
57
58 @Parameterized.Parameters(name = "{0} {1} {2}")
59 public static Collection<Object[]> data() throws IOException {
60 return Arrays.asList(new Object[][] { //
61 // @formatter:off
62 {"rwxrwxrwx", true, 2},
63 {"rw-r--r--", false, 3},
64 {"rw-------", true, 4},
65 {"rw-rw----", false, 5},
66 });
67 // @formatter:on
68 }
69
70 private final boolean createOnDemand;
71 private final String filePermissions;
72 private final int fileIndex;
73
74 public FileAppenderPermissionsTest(final String filePermissions, final boolean createOnDemand, final int fileIndex) {
75 this.filePermissions = filePermissions;
76 this.createOnDemand = createOnDemand;
77 this.fileIndex = fileIndex;
78 }
79
80 @BeforeClass
5781 public static void beforeClass() {
5882 System.setProperty("log4j2.debug", "true");
59 assumeTrue(FileUtils.isFilePosixAttributeViewSupported());
60 }
61
62 @ParameterizedTest
63 @CsvSource({ "rwxrwxrwx,true,2", "rw-r--r--,false,3", "rw-------,true,4", "rw-rw----,false,5" })
64 public void testFilePermissionsAPI(final String filePermissions, final boolean createOnDemand, final int fileIndex)
65 throws Exception {
83 Assume.assumeTrue(FileUtils.isFilePosixAttributeViewSupported());
84 }
85
86 @Test
87 public void testFilePermissionsAPI() throws Exception {
6688 final File file = new File(DIR, "AppenderTest-" + fileIndex + ".log");
6789 final Path path = file.toPath();
6890 final Layout<String> layout = PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN)
6991 .build();
7092 // @formatter:off
7193 final FileAppender appender = FileAppender.newBuilder()
72 .withFileName(file.getAbsolutePath())
73 .setName("test")
74 .withImmediateFlush(false)
75 .setIgnoreExceptions(false)
94 .withFileName(file.getAbsolutePath()).setName("test")
95 .withImmediateFlush(false).setIgnoreExceptions(false)
7696 .withBufferedIo(false)
77 .withBufferSize(1)
78 .setLayout(layout)
97 .withBufferSize(1).setLayout(layout)
7998 .withCreateOnDemand(createOnDemand)
8099 .withFilePermissions(filePermissions)
81100 .build();
82101 // @formatter:on
83102 try {
84103 appender.start();
85 assertTrue(appender.isStarted(), "Appender did not start");
86 assertNotEquals(createOnDemand, Files.exists(path));
104 assertTrue("Appender did not start", appender.isStarted());
105 Assert.assertNotEquals(createOnDemand, Files.exists(path));
87106 long curLen = file.length();
88107 long prevLen = curLen;
89 assertEquals(curLen, 0, "File length: " + curLen);
108 assertTrue("File length: " + curLen, curLen == 0);
90109 for (int i = 0; i < 100; ++i) {
91110 final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") //
92111 .setLoggerFqcn(FileAppenderPermissionsTest.class.getName()).setLevel(Level.INFO) //
95114 try {
96115 appender.append(event);
97116 curLen = file.length();
98 assertTrue(curLen > prevLen, "File length: " + curLen);
117 assertTrue("File length: " + curLen, curLen > prevLen);
99118 // Give up control long enough for another thread/process to occasionally do something.
100119 Thread.sleep(25);
101120 } catch (final Exception ex) {
106125 assertEquals(filePermissions, PosixFilePermissions.toString(Files.getPosixFilePermissions(path)));
107126 } finally {
108127 appender.stop();
109 }
110 assertFalse(appender.isStarted(), "Appender did not stop");
111 }
112
113 @ParameterizedTest
114 @CsvSource({ "rwxrwxrwx,2", "rw-r--r--,3", "rw-------,4", "rw-rw----,5" })
115 public void testFileUserGroupAPI(final String filePermissions, final int fileIndex)
116 throws Exception {
128 Files.deleteIfExists(path);
129 }
130 assertFalse("Appender did not stop", appender.isStarted());
131 }
132
133 @Test
134 public void testFileUserGroupAPI() throws Exception {
117135 final File file = new File(DIR, "AppenderTest-" + (1000 + fileIndex) + ".log");
118136 final Path path = file.toPath();
119137 final String user = findAUser();
125143 .build();
126144 // @formatter:off
127145 final FileAppender appender = FileAppender.newBuilder()
128 .withFileName(file.getAbsolutePath())
129 .setName("test")
130 .withImmediateFlush(true)
131 .setIgnoreExceptions(false)
146 .withFileName(file.getAbsolutePath()).setName("test")
147 .withImmediateFlush(true).setIgnoreExceptions(false)
132148 .withBufferedIo(false)
133 .withBufferSize(1)
134 .setLayout(layout)
149 .withBufferSize(1).setLayout(layout)
135150 .withFilePermissions(filePermissions)
136151 .withFileOwner(user)
137152 .withFileGroup(group)
139154 // @formatter:on
140155 try {
141156 appender.start();
142 assertTrue(appender.isStarted(), "Appender did not start");
157 assertTrue("Appender did not start", appender.isStarted());
143158 long curLen = file.length();
144159 long prevLen = curLen;
145 assertEquals(curLen, 0, file + " File length: " + curLen);
160 assertTrue(file + " File length: " + curLen, curLen == 0);
146161 for (int i = 0; i < 100; ++i) {
147162 final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") //
148163 .setLoggerFqcn(FileAppenderPermissionsTest.class.getName()).setLevel(Level.INFO) //
151166 try {
152167 appender.append(event);
153168 curLen = file.length();
154 assertTrue(curLen > prevLen, "File length: " + curLen);
169 assertTrue("File length: " + curLen, curLen > prevLen);
155170 // Give up control long enough for another thread/process to occasionally do something.
156171 Thread.sleep(25);
157172 } catch (final Exception ex) {
164179 assertEquals(group, Files.readAttributes(path, PosixFileAttributes.class).group().getName());
165180 } finally {
166181 appender.stop();
167 }
168 assertFalse(appender.isStarted(), "Appender did not stop");
169 }
170
171 @Test
172 @LoggerContextSource(value = "log4j-posix.xml", timeout = 10)
173 void testFilePermissions(final LoggerContext context) throws IOException {
174 final ExtendedLogger logger = context.getLogger(getClass());
175 for (int i = 0; i < 1000; i++) {
176 logger.debug("This is test message number {}", box(i));
177 }
178 final String permissions = PosixFilePermissions.toString(
179 Files.getPosixFilePermissions(Paths.get("target/permissions1/AppenderTest-1.log")));
180 assertEquals("rw-------", permissions);
182 Files.deleteIfExists(path);
183 }
184 assertFalse("Appender did not stop", appender.isStarted());
181185 }
182186
183187 public static String findAGroup(final String user) throws IOException {
184188 if (SystemUtils.IS_OS_MAC_OSX) {
185189 return "staff";
186190 }
187 try (final Stream<String> lines = Files.lines(Paths.get("/etc/group"))) {
188 return lines.filter(group -> !group.startsWith(user) && group.contains(user))
189 .map(group -> group.substring(0, group.indexOf(':')))
190 .findAny()
191 .orElse(user);
192 }
191 String group = user;
192 try (FileInputStream fis = new FileInputStream("/etc/group")) {
193 final List<String> groups = org.apache.commons.io.IOUtils.readLines(fis, Charset.defaultCharset());
194 for (int i = 0; i < groups.size(); i++) {
195 final String aGroup = groups.get(i);
196 if (!aGroup.startsWith(user) && aGroup.contains(user)) {
197 group = aGroup.split(":")[0];
198 break;
199 }
200 }
201 }
202 return group;
193203 }
194204
195205 private static String findAUser() throws IOException {
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
17 package org.apache.logging.log4j.core.appender;
18
19 import static org.junit.Assert.assertEquals;
20
21 import java.nio.file.Files;
22 import java.nio.file.Paths;
23 import java.nio.file.attribute.PosixFilePermissions;
24
25 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.util.FileUtils;
27 import org.apache.logging.log4j.junit.LoggerContextRule;
28 import org.junit.Assume;
29 import org.junit.BeforeClass;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.rules.RuleChain;
33
34 /**
35 * Tests {@link FileAppender}.
36 */
37 public class FileAppenderPermissionsXmlConfigTest {
38
39 private static final String DIR = "target/permissions1";
40
41 private static final String CONFIG = "log4j-posix.xml";
42
43 public static LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
44
45 @Rule
46 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
47
48 @BeforeClass
49 public static void beforeClass() {
50 Assume.assumeTrue(FileUtils.isFilePosixAttributeViewSupported());
51 }
52
53 @Test
54 public void testFilePermissions() throws Exception {
55 final Logger logger = loggerContextRule.getLogger(FileAppenderPermissionsTest.class);
56 for (int i = 0; i < 1000; ++i) {
57 final String message = "This is test message number " + i;
58 logger.debug(message);
59 }
60 assertEquals("rw-------", PosixFilePermissions.toString(
61 Files.getPosixFilePermissions(Paths.get("target/permissions1/AppenderTest-1.log"))));
62 }
63
64
65 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import static org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertTrue;
20
1821 import java.io.BufferedReader;
1922 import java.io.File;
2023 import java.io.FileInputStream;
3437 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3538 import org.apache.logging.log4j.core.layout.PatternLayout;
3639 import org.apache.logging.log4j.core.util.Throwables;
37 import org.apache.logging.log4j.junit.CleanUpFiles;
40 import org.apache.logging.log4j.junit.CleanFiles;
3841 import org.apache.logging.log4j.message.SimpleMessage;
39 import org.junit.jupiter.api.AfterAll;
40 import org.junit.jupiter.api.Disabled;
41 import org.junit.jupiter.params.ParameterizedTest;
42 import org.junit.jupiter.params.provider.ValueSource;
43
44 import static org.junit.jupiter.api.Assertions.*;
42 import org.apache.logging.log4j.util.Strings;
43 import org.junit.AfterClass;
44 import org.junit.Assert;
45 import org.junit.Ignore;
46 import org.junit.Rule;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 import org.junit.runners.Parameterized;
50 import org.junit.runners.Parameterized.Parameters;
4551
4652 /**
4753 * Tests {@link FileAppender}.
4854 */
49 @CleanUpFiles(FileAppenderTest.FILE_NAME)
55 @RunWith(Parameterized.class)
5056 public class FileAppenderTest {
5157
52 static final String FILE_NAME = "target/fileAppenderTest.log";
58 @Parameters(name = "createOnDemand = {0}")
59 public static Boolean[] getParameters() {
60 return new Boolean[] { false, true };
61 }
62
63 private static final String FILE_NAME = "target/fileAppenderTest.log";
5364 private static final Path PATH = Paths.get(FILE_NAME);
5465 private static final int THREADS = 2;
5566
56 @AfterAll
67 public FileAppenderTest(final boolean createOnDemand) {
68 super();
69 this.createOnDemand = createOnDemand;
70 }
71
72 private final boolean createOnDemand;
73 private final int threadCount = THREADS;
74
75 @Rule
76 public CleanFiles files = new CleanFiles(PATH);
77
78 @AfterClass
5779 public static void cleanupClass() {
58 assertFalse(AbstractManager.hasManager(FILE_NAME), "Manager for " + FILE_NAME + " not removed");
59 }
60
61 @ParameterizedTest
62 @ValueSource(booleans = { false, true })
63 public void testAppender(final boolean createOnDemand) throws Exception {
80 assertTrue("Manager for " + FILE_NAME + " not removed", !AbstractManager.hasManager(FILE_NAME));
81 }
82
83 @Test
84 public void testAppender() throws Exception {
6485 final int logEventCount = 1;
6586 writer(false, logEventCount, "test", createOnDemand, false);
6687 verifyFile(logEventCount);
6788 }
6889
69 @ParameterizedTest
70 @ValueSource(booleans = { false, true })
71 public void testLazyCreate(final boolean createOnDemand) throws Exception {
90 @Test
91 public void testLazyCreate() throws Exception {
7292 final Layout<String> layout = createPatternLayout();
7393 // @formatter:off
7494 final FileAppender appender = FileAppender.newBuilder()
7999 .withCreateOnDemand(createOnDemand)
80100 .build();
81101 // @formatter:on
82 assertEquals(createOnDemand, appender.getManager().isCreateOnDemand());
102 Assert.assertEquals(createOnDemand, appender.getManager().isCreateOnDemand());
83103 try {
84 assertNotEquals(createOnDemand, Files.exists(PATH));
104 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
85105 appender.start();
86 assertNotEquals(createOnDemand, Files.exists(PATH));
106 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
87107 } finally {
88108 appender.stop();
89109 }
90 assertNotEquals(createOnDemand, Files.exists(PATH));
110 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
91111 }
92112
93113 private static PatternLayout createPatternLayout() {
95115 .build();
96116 }
97117
98 @ParameterizedTest
99 @ValueSource(booleans = { false, true })
100 public void testSmallestBufferSize(final boolean createOnDemand) throws Exception {
118 @Test
119 public void testSmallestBufferSize() throws Exception {
101120 final Layout<String> layout = createPatternLayout();
102121 // @formatter:off
103122 final FileAppender appender = FileAppender.newBuilder()
111130 try {
112131 appender.start();
113132 final File file = new File(FILE_NAME);
114 assertTrue(appender.isStarted(), "Appender did not start");
115 assertNotEquals(createOnDemand, Files.exists(PATH));
133 assertTrue("Appender did not start", appender.isStarted());
134 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
116135 long curLen = file.length();
117136 long prevLen = curLen;
118 assertEquals(0, curLen, "File length: " + curLen);
137 assertTrue("File length: " + curLen, curLen == 0);
119138 for (int i = 0; i < 100; ++i) {
120139 final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") //
121140 .setLoggerFqcn(FileAppenderTest.class.getName()).setLevel(Level.INFO) //
122141 .setMessage(new SimpleMessage("Test")).setThreadName(this.getClass().getSimpleName()) //
123142 .setTimeMillis(System.currentTimeMillis()).build();
124 appender.append(event);
125 curLen = file.length();
126 assertTrue(curLen > prevLen, "File length: " + curLen);
127 // Give up control long enough for another thread/process to occasionally do something.
128 Thread.sleep(25);
143 try {
144 appender.append(event);
145 curLen = file.length();
146 assertTrue("File length: " + curLen, curLen > prevLen);
147 // Give up control long enough for another thread/process to occasionally do something.
148 Thread.sleep(25);
149 } catch (final Exception ex) {
150 throw ex;
151 }
129152 prevLen = curLen;
130153 }
131154 } finally {
132155 appender.stop();
133156 }
134 assertFalse(appender.isStarted(), "Appender did not stop");
135 }
136
137 @ParameterizedTest
138 @ValueSource(booleans = { false, true })
139 public void testLockingAppender(final boolean createOnDemand) throws Exception {
157 assertFalse("Appender did not stop", appender.isStarted());
158 }
159
160 @Test
161 public void testLockingAppender() throws Exception {
140162 final int logEventCount = 1;
141163 writer(true, logEventCount, "test", createOnDemand, false);
142164 verifyFile(logEventCount);
143165 }
144166
145 @ParameterizedTest
146 @ValueSource(booleans = { false, true })
147 public void testMultipleAppenderThreads(final boolean createOnDemand) throws Exception {
148 testMultipleLockingAppenderThreads(false, THREADS, createOnDemand);
149 }
150
151 private void testMultipleLockingAppenderThreads(final boolean lock, final int threadCount, boolean createOnDemand)
167 @Test
168 public void testMultipleAppenderThreads() throws Exception {
169 testMultipleLockingAppenderThreads(false, threadCount);
170 }
171
172 private void testMultipleLockingAppenderThreads(final boolean lock, final int threadCount)
152173 throws InterruptedException, Exception {
153174 final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
154175 final Exception[] exceptionRef = new Exception[1];
155176 final int logEventCount = 100;
156 final Runnable runnable = new FileWriterRunnable(createOnDemand, lock, logEventCount, exceptionRef);
177 final Runnable runnable = new FileWriterRunnable(lock, logEventCount, exceptionRef);
157178 for (int i = 0; i < threadCount; ++i) {
158179 threadPool.execute(runnable);
159180 }
160181 threadPool.shutdown();
161 assertTrue(
162 threadPool.awaitTermination(10, TimeUnit.SECONDS), "The thread pool has not shutdown: " + threadPool);
182 Assert.assertTrue("The thread pool has not shutdown: " + threadPool,
183 threadPool.awaitTermination(10, TimeUnit.SECONDS));
163184 if (exceptionRef[0] != null) {
164185 throw exceptionRef[0];
165186 }
166187 verifyFile(threadCount * logEventCount);
167188 }
168189
169 @ParameterizedTest
170 @ValueSource(booleans = { false, true })
171 public void testMultipleLockingAppenders(final boolean createOnDemand) throws Exception {
172 testMultipleLockingAppenderThreads(true, THREADS, createOnDemand);
173 }
174
175 @ParameterizedTest
176 @ValueSource(booleans = { false, true })
177 @Disabled
178 public void testMultipleVMs(final boolean createOnDemand) throws Exception {
190 @Test
191 public void testMultipleLockingAppenders() throws Exception {
192 testMultipleLockingAppenderThreads(true, threadCount);
193 }
194
195 @Test
196 @Ignore
197 public void testMultipleVMs() throws Exception {
179198 final String classPath = System.getProperty("java.class.path");
180 final int logEventCount = 10;
199 final Integer logEventCount = 10;
181200 final int processCount = 3;
182201 final Process[] processes = new Process[processCount];
183202 final ProcessBuilder[] builders = new ProcessBuilder[processCount];
184203 for (int index = 0; index < processCount; ++index) {
185204 builders[index] = new ProcessBuilder("java", "-cp", classPath, ProcessTest.class.getName(),
186 "Process " + index, Integer.toString(logEventCount), "true", Boolean.toString(createOnDemand));
205 "Process " + index, logEventCount.toString(), "true", Boolean.toString(createOnDemand));
187206 }
188207 for (int index = 0; index < processCount; ++index) {
189208 processes[index] = builders[index].start();
214233 .withCreateOnDemand(createOnDemand)
215234 .build();
216235 // @formatter:on
217 assertEquals(createOnDemand, appender.getManager().isCreateOnDemand());
236 Assert.assertEquals(createOnDemand, appender.getManager().isCreateOnDemand());
218237 try {
219238 appender.start();
220 assertTrue(appender.isStarted(), "Appender did not start");
239 assertTrue("Appender did not start", appender.isStarted());
221240 final boolean exists = Files.exists(PATH);
222241 final String msg = String.format("concurrent = %s, createOnDemand = %s, file exists = %s", concurrent, createOnDemand,
223242 exists);
225244 // Can't really test createOnDemand && concurrent.
226245 final boolean expectFileCreated = !createOnDemand;
227246 if (concurrent && expectFileCreated) {
228 assertTrue(exists, msg);
247 Assert.assertTrue(msg, exists);
229248 } else if (expectFileCreated) {
230 assertNotEquals(createOnDemand, exists, msg);
249 Assert.assertNotEquals(msg, createOnDemand, exists);
231250 }
232251 for (int i = 0; i < logEventCount; ++i) {
233252 final LogEvent logEvent = Log4jLogEvent.newBuilder().setLoggerName("TestLogger")
234253 .setLoggerFqcn(FileAppenderTest.class.getName()).setLevel(Level.INFO)
235254 .setMessage(new SimpleMessage("Test")).setThreadName(name)
236255 .setTimeMillis(System.currentTimeMillis()).build();
237 appender.append(logEvent);
238 Thread.sleep(25); // Give up control long enough for another thread/process to occasionally do something.
256 try {
257 appender.append(logEvent);
258 Thread.sleep(25); // Give up control long enough for another thread/process to occasionally do
259 // something.
260 } catch (final Exception ex) {
261 throw ex;
262 }
239263 }
240264 } finally {
241265 appender.stop();
242266 }
243 assertFalse(appender.isStarted(), "Appender did not stop");
267 assertFalse("Appender did not stop", appender.isStarted());
244268 }
245269
246270 private void verifyFile(final int count) throws Exception {
249273 final Pattern pattern = Pattern.compile(expected);
250274 int lines = 0;
251275 try (final BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(FILE_NAME)))) {
252 String str;
276 String str = Strings.EMPTY;
253277 while (is.ready()) {
254278 str = is.readLine();
255279 // System.out.println(str);
256280 ++lines;
257281 final Matcher matcher = pattern.matcher(str);
258 assertTrue(matcher.matches(), "Unexpected data: " + str);
259 }
260 }
261 assertEquals(count, lines);
262 }
263
264 public static class FileWriterRunnable implements Runnable {
265 private final boolean createOnDemand;
282 assertTrue("Unexpected data: " + str, matcher.matches());
283 }
284 }
285 Assert.assertEquals(count, lines);
286 }
287
288 public class FileWriterRunnable implements Runnable {
266289 private final boolean lock;
267290 private final int logEventCount;
268291 private final Exception[] exceptionRef;
269292
270 public FileWriterRunnable(
271 boolean createOnDemand, final boolean lock, final int logEventCount, final Exception[] exceptionRef) {
272 this.createOnDemand = createOnDemand;
293 public FileWriterRunnable(final boolean lock, final int logEventCount, final Exception[] exceptionRef) {
273294 this.lock = lock;
274295 this.logEventCount = logEventCount;
275296 this.exceptionRef = exceptionRef;
3131 import java.io.Serializable;
3232 import java.net.URL;
3333
34 import org.apache.commons.lang3.SystemUtils;
3534 import org.apache.logging.log4j.Level;
3635 import org.apache.logging.log4j.core.Appender;
3736 import org.apache.logging.log4j.core.Layout;
4847 import org.apache.logging.log4j.status.StatusData;
4948 import org.apache.logging.log4j.status.StatusListener;
5049 import org.apache.logging.log4j.status.StatusLogger;
51 import org.junit.Assume;
52 import org.junit.BeforeClass;
50 import org.junit.Ignore;
5351 import org.junit.Rule;
5452 import org.junit.Test;
5553
5654 import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
5755 import com.github.tomakehurst.wiremock.junit.WireMockRule;
56
57 @Ignore("Fails often on Windows")
5858
5959 /* Fails often on Windows, for example:
6060 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.20.1:test (default-test) on project log4j-core: There are test failures.
130130
131131 private static final String LOG_MESSAGE = "Hello, world!";
132132
133 @BeforeClass
134 public static void setupClass() {
135 Assume.assumeFalse(SystemUtils.IS_OS_WINDOWS);
136 }
137
138133 private static Log4jLogEvent createLogEvent() {
139134 return Log4jLogEvent.newBuilder()
140135 .setLoggerName(HttpAppenderTest.class.getName())
2323 import org.apache.logging.log4j.message.SimpleMessage;
2424 import org.apache.logging.log4j.test.appender.InMemoryAppender;
2525 import org.apache.logging.log4j.util.Strings;
26 import org.junit.jupiter.api.Test;
26 import org.junit.Test;
2727
28 import static org.junit.jupiter.api.Assertions.*;
28 import static org.junit.Assert.*;
2929
30 /**
31 *
32 */
3033 public class InMemoryAppenderTest {
3134
3235 @Test
6467 .setMessage(new SimpleMessage("Test")) //
6568 .build();
6669 app.start();
67 assertTrue(app.isStarted(), "Appender did not start");
70 assertTrue("Appender did not start", app.isStarted());
6871 app.append(event);
6972 app.append(event);
7073 final String msg = app.toString();
71 assertNotNull(msg, "No message");
74 assertNotNull("No message", msg);
7275 final String expectedHeader = header == null ? "" : header;
7376 final String expected = expectedHeader + "Test" + Strings.LINE_SEPARATOR + "Test" + Strings.LINE_SEPARATOR;
74 assertEquals(expected, msg, "Incorrect message: " + msg);
77 assertTrue("Incorrect message: " + msg, msg.equals(expected));
7578 app.stop();
76 assertFalse(app.isStarted(), "Appender did not stop");
79 assertFalse("Appender did not stop", app.isStarted());
7780 }
7881 }
8888 final String[] expected = {
8989 "[", // equals
9090 "{", // equals
91 " \"instant\" : {", //
92 " \"epochSecond\" : 1234567,", //
93 " \"nanoOfSecond\" : 890000000", //
94 " },", //
9591 " \"thread\" : \"main\",", //
9692 " \"level\" : \"INFO\",", //
9793 " \"loggerName\" : \"com.foo.Bar\",", //
9894 " \"message\" : \"Message flushed with immediate flush=true\",", //
9995 " \"endOfBatch\" : false,", //
10096 " \"loggerFqcn\" : \"org.apache.logging.log4j.spi.AbstractLogger\",", //
97 " \"instant\" : {", //
98 " \"epochSecond\" : 1234567,", //
99 " \"nanoOfSecond\" : 890000000", //
100 " },", //
101101 };
102102 for (int i = 0; i < expected.length; i++) {
103103 final String line = lines.get(i);
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;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileReader;
21
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
24 import org.apache.logging.log4j.core.CoreLoggerContexts;
25 import org.apache.logging.log4j.core.config.ConfigurationFactory;
26 import org.apache.logging.log4j.core.util.Integers;
27 import org.junit.Before;
28 import org.junit.Test;
29
30 import static org.hamcrest.CoreMatchers.*;
31
32 import static org.junit.Assert.*;
33
34 /**
35 * Tests that logged strings and their location appear in the file,
36 * that the file size is the next power of two of the specified mapped region length
37 * and that the file is shrunk to its actual usage when done.
38 *
39 * @since 2.1
40 */
41 public class MemoryMappedFileAppenderLocationTest {
42
43 final String LOGFILE = "target/MemoryMappedFileAppenderLocationTest.log";
44
45 @Before
46 public void before() {
47 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
48 "MemoryMappedFileAppenderLocationTest.xml");
49 }
50
51 @Test
52 public void testMemMapLocation() throws Exception {
53 final File f = new File(LOGFILE);
54 if (f.exists()) {
55 assertTrue("deleted ok", f.delete());
56 }
57 assertTrue(!f.exists());
58
59 final int expectedFileLength = Integers.ceilingNextPowerOfTwo(32000);
60 assertEquals(32768, expectedFileLength);
61
62 final Logger log = LogManager.getLogger();
63 try {
64 log.warn("Test log1");
65 assertTrue(f.exists());
66 assertEquals("initial length", expectedFileLength, f.length());
67
68 log.warn("Test log2");
69 assertEquals("not grown", expectedFileLength, f.length());
70 } finally {
71 CoreLoggerContexts.stopLoggerContext(false);
72 }
73 final int LINESEP = System.lineSeparator().length();
74 assertEquals("Shrunk to actual used size", 474 + 2 * LINESEP, f.length());
75
76 String line1, line2, line3;
77 try (final BufferedReader reader = new BufferedReader(new FileReader(LOGFILE))) {
78 line1 = reader.readLine();
79 line2 = reader.readLine();
80 line3 = reader.readLine();
81 }
82 assertNotNull(line1);
83 assertThat(line1, containsString("Test log1"));
84 final String location1 = "org.apache.logging.log4j.core.appender.MemoryMappedFileAppenderLocationTest.testMemMapLocation(MemoryMappedFileAppenderLocationTest.java:65)";
85 assertThat(line1, containsString(location1));
86
87 assertNotNull(line2);
88 assertThat(line2, containsString("Test log2"));
89 final String location2 = "org.apache.logging.log4j.core.appender.MemoryMappedFileAppenderLocationTest.testMemMapLocation(MemoryMappedFileAppenderLocationTest.java:69)";
90 assertThat(line2, containsString(location2));
91
92 assertNull("only two lines were logged", line3);
93 }
94 }
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;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileReader;
21 import java.util.Arrays;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.CoreLoggerContexts;
26 import org.apache.logging.log4j.core.config.ConfigurationFactory;
27 import org.junit.Before;
28 import org.junit.Test;
29
30 import static org.hamcrest.CoreMatchers.*;
31
32 import static org.junit.Assert.*;
33
34 /**
35 * Tests that logged strings appear in the file, that the initial file size is the specified specified region length,
36 * that the file is extended by region length when necessary, and that the file is shrunk to its actual usage when done.
37 *
38 * @since 2.1
39 */
40 public class MemoryMappedFileAppenderRemapTest {
41
42 final String LOGFILE = "target/MemoryMappedFileAppenderRemapTest.log";
43
44 @Before
45 public void before() {
46 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "MemoryMappedFileAppenderRemapTest.xml");
47 }
48
49 @Test
50 public void testMemMapExtendsIfNeeded() throws Exception {
51 final File f = new File(LOGFILE);
52 if (f.exists()) {
53 assertTrue(f.delete());
54 }
55 assertTrue(!f.exists());
56
57 final Logger log = LogManager.getLogger();
58 final char[] text = new char[200];
59 Arrays.fill(text, 'A');
60 try {
61 log.warn("Test log1");
62 assertTrue(f.exists());
63 assertEquals("initial length", 256, f.length());
64
65 log.warn(new String(text));
66 assertEquals("grown", 256 * 2, f.length());
67
68 log.warn(new String(text));
69 assertEquals("grown again", 256 * 3, f.length());
70 } finally {
71 CoreLoggerContexts.stopLoggerContext(false);
72 }
73 final int LINESEP = System.lineSeparator().length();
74 assertEquals("Shrunk to actual used size", 658 + 3 * LINESEP, f.length());
75
76 String line1, line2, line3, line4;
77 try (final BufferedReader reader = new BufferedReader(new FileReader(LOGFILE))) {
78 line1 = reader.readLine();
79 line2 = reader.readLine();
80 line3 = reader.readLine();
81 line4 = reader.readLine();
82 }
83 assertNotNull(line1);
84 assertThat(line1, containsString("Test log1"));
85
86 assertNotNull(line2);
87 assertThat(line2, containsString(new String(text)));
88
89 assertNotNull(line3);
90 assertThat(line3, containsString(new String(text)));
91
92 assertNull("only three lines were logged", line4);
93 }
94 }
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;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileReader;
21
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
24 import org.apache.logging.log4j.core.CoreLoggerContexts;
25 import org.apache.logging.log4j.core.config.ConfigurationFactory;
26 import org.junit.Before;
27 import org.junit.Test;
28
29 import static org.hamcrest.CoreMatchers.*;
30
31 import static org.junit.Assert.*;
32
33 /**
34 * Tests that logged strings appear in the file,
35 * that the default file size is used if not specified
36 * and that the file is shrunk to its actual usage when done.
37 *
38 * @since 2.1
39 */
40 public class MemoryMappedFileAppenderSimpleTest {
41
42 final String LOGFILE = "target/MemoryMappedFileAppenderTest.log";
43
44 @Before
45 public void before() {
46 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "MemoryMappedFileAppenderTest.xml");
47 }
48
49 @Test
50 public void testMemMapBasics() throws Exception {
51 final File f = new File(LOGFILE);
52 if (f.exists()) {
53 assertTrue(f.delete());
54 }
55 assertTrue(!f.exists());
56
57 final Logger log = LogManager.getLogger();
58 try {
59 log.warn("Test log1");
60 assertTrue(f.exists());
61 assertEquals("initial length", MemoryMappedFileManager.DEFAULT_REGION_LENGTH, f.length());
62
63 log.warn("Test log2");
64 assertEquals("not grown", MemoryMappedFileManager.DEFAULT_REGION_LENGTH, f.length());
65 } finally {
66 CoreLoggerContexts.stopLoggerContext(false);
67 }
68 final int LINESEP = System.lineSeparator().length();
69 assertEquals("Shrunk to actual used size", 186 + 2 * LINESEP, f.length());
70
71 String line1, line2, line3;
72 try (final BufferedReader reader = new BufferedReader(new FileReader(LOGFILE))) {
73 line1 = reader.readLine();
74 line2 = reader.readLine();
75 line3 = reader.readLine();
76 }
77 assertNotNull(line1);
78 assertThat(line1, containsString("Test log1"));
79
80 assertNotNull(line2);
81 assertThat(line2, containsString("Test log2"));
82
83 assertNull("only two lines were logged", line3);
84 }
85 }
+0
-120
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/MemoryMappedFileAppenderTest.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.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.util.Integers;
21 import org.apache.logging.log4j.junit.CleanUpFiles;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.junit.jupiter.api.Test;
24
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.util.Arrays;
29 import java.util.List;
30
31 import static org.hamcrest.MatcherAssert.assertThat;
32 import static org.hamcrest.Matchers.*;
33 import static org.junit.jupiter.api.Assertions.assertEquals;
34 import static org.junit.jupiter.api.Assertions.assertTrue;
35
36 /**
37 * Tests that logged strings appear in the file, that the initial file size is the specified specified region length,
38 * that the file is extended by region length when necessary, and that the file is shrunk to its actual usage when done.
39 *
40 * @since 2.1
41 */
42 @CleanUpFiles({
43 "target/MemoryMappedFileAppenderTest.log",
44 "target/MemoryMappedFileAppenderRemapTest.log",
45 "target/MemoryMappedFileAppenderLocationTest.log"
46 })
47 public class MemoryMappedFileAppenderTest {
48
49 @Test
50 @LoggerContextSource("MemoryMappedFileAppenderTest.xml")
51 public void testMemMapBasics(final LoggerContext context) throws Exception {
52 final Logger log = context.getLogger(getClass());
53 final Path logFile = Paths.get("target", "MemoryMappedFileAppenderTest.log");
54 try {
55 log.warn("Test log1");
56 assertTrue(Files.exists(logFile));
57 assertEquals(MemoryMappedFileManager.DEFAULT_REGION_LENGTH, Files.size(logFile));
58 log.warn("Test log2");
59 assertEquals(MemoryMappedFileManager.DEFAULT_REGION_LENGTH, Files.size(logFile));
60 } finally {
61 context.stop();
62 }
63 final int LINESEP = System.lineSeparator().length();
64 assertEquals(18 + 2 * LINESEP, Files.size(logFile));
65
66 final List<String> lines = Files.readAllLines(logFile);
67 assertThat(lines, both(hasSize(2)).and(contains("Test log1", "Test log2")));
68 }
69
70 @Test
71 @LoggerContextSource("MemoryMappedFileAppenderRemapTest.xml")
72 public void testMemMapExtendsIfNeeded(final LoggerContext context) throws Exception {
73 final Logger log = context.getLogger(getClass());
74 final Path logFile = Paths.get("target", "MemoryMappedFileAppenderRemapTest.log");
75 final char[] text = new char[256];
76 Arrays.fill(text, 'A');
77 final String str = new String(text);
78 try {
79 log.warn("Test log1");
80 assertTrue(Files.exists(logFile));
81 assertEquals(256, Files.size(logFile));
82 log.warn(str);
83 assertEquals(2 * 256, Files.size(logFile));
84 log.warn(str);
85 assertEquals(3 * 256, Files.size(logFile));
86 } finally {
87 context.stop();
88 }
89 assertEquals(521 + 3 * System.lineSeparator().length(), Files.size(logFile), "Expected file size to shrink");
90
91 final List<String> lines = Files.readAllLines(logFile);
92 assertThat(lines, both(hasSize(3)).and(contains("Test log1", str, str)));
93 }
94
95 @Test
96 @LoggerContextSource("MemoryMappedFileAppenderLocationTest.xml")
97 void testMemMapLocation(final LoggerContext context) throws Exception {
98 final Logger log = context.getLogger(getClass());
99 final Path logFile = Paths.get("target", "MemoryMappedFileAppenderLocationTest.log");
100 final int expectedFileLength = Integers.ceilingNextPowerOfTwo(32000);
101 assertEquals(32768, expectedFileLength);
102 try {
103 log.warn("Test log1");
104 assertTrue(Files.exists(logFile));
105 assertEquals(expectedFileLength, Files.size(logFile));
106 log.warn("Test log2");
107 assertEquals(expectedFileLength, Files.size(logFile));
108 } finally {
109 context.stop();
110 }
111 assertEquals(272 + 2 * System.lineSeparator().length(), Files.size(logFile), "Expected file size to shrink");
112
113 final List<String> lines = Files.readAllLines(logFile);
114 assertThat(lines, both(hasSize(2)).and(contains(
115 "org.apache.logging.log4j.core.appender.MemoryMappedFileAppenderTest.testMemMapLocation(MemoryMappedFileAppenderTest.java:104): Test log1",
116 "org.apache.logging.log4j.core.appender.MemoryMappedFileAppenderTest.testMemMapLocation(MemoryMappedFileAppenderTest.java:107): Test log2"
117 )));
118 }
119 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
1822 import java.io.BufferedReader;
1923 import java.io.File;
2024 import java.io.FileOutputStream;
2125 import java.io.FileReader;
2226 import java.io.IOException;
2327
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.io.TempDir;
26
27 import static org.junit.jupiter.api.Assertions.*;
28 import org.junit.Test;
2829
2930 /**
3031 * Tests the MemoryMappedFileManager class.
3334 */
3435 public class MemoryMappedFileManagerTest {
3536
36 @TempDir
37 File tempDir;
38
3937 @Test
4038 public void testRemapAfterInitialMapSizeExceeded() throws IOException {
4139 final int mapSize = 64; // very small, on purpose
42 final File file = new File(tempDir, "memory-mapped-file.bin");
40 final File file = File.createTempFile("log4j2", "test");
41 file.deleteOnExit();
42 assertEquals(0, file.length());
4343
4444 final boolean append = false;
4545 final boolean immediateFlush = false;
5656 try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
5757 String line = reader.readLine();
5858 for (int i = 0; i < 1000; i++) {
59 assertNotNull(line, "line");
60 assertTrue(line.contains("Message " + i), "line incorrect");
59 assertNotNull("line", line);
60 assertTrue("line incorrect", line.contains("Message " + i));
6161 line = reader.readLine();
6262 }
6363 }
6565
6666 @Test
6767 public void testAppendDoesNotOverwriteExistingFile() throws IOException {
68 final File file = new File(tempDir, "memory-mapped-file.bin");
68 final File file = File.createTempFile("log4j2", "test");
69 file.deleteOnExit();
70 assertEquals(0, file.length());
6971
7072 final int initialLength = 4 * 1024;
7173
7476 fos.write(new byte[initialLength], 0, initialLength);
7577 fos.flush();
7678 }
77 assertEquals(initialLength, file.length(), "all flushed to disk");
79 assertEquals("all flushed to disk", initialLength, file.length());
7880
7981 final boolean isAppend = true;
8082 final boolean immediateFlush = false;
8385 manager.writeBytes(new byte[initialLength], 0, initialLength);
8486 }
8587 final int expected = initialLength * 2;
86 assertEquals(expected, file.length(), "appended, not overwritten");
88 assertEquals("appended, not overwritten", expected, file.length());
8789 }
8890 }
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;
17
18 import java.io.BufferedOutputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.OutputStream;
21 import java.sql.SQLException;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.Appender;
26 import org.apache.logging.log4j.core.LoggerContext;
27 import org.apache.logging.log4j.core.config.Configuration;
28 import org.apache.logging.log4j.core.filter.NoMarkerFilter;
29 import org.apache.logging.log4j.core.layout.PatternLayout;
30 import org.junit.Assert;
31 import org.junit.Rule;
32 import org.junit.Test;
33 import org.junit.rules.TestName;
34
35 /**
36 * Tests {@link OutputStreamAppender}.
37 */
38 public class OutputStreamAppenderTest {
39
40 private static final String TEST_MSG = "FOO ERROR";
41
42 @Rule
43 public TestName testName = new TestName();
44
45 private String getName(final OutputStream out) {
46 return out.getClass().getSimpleName() + "." + testName.getMethodName();
47 }
48
49 /**
50 * Tests that you can add an output stream appender dynamically.
51 */
52 private void addAppender(final OutputStream outputStream, final String outputStreamName) {
53 final LoggerContext context = LoggerContext.getContext(false);
54 final Configuration config = context.getConfiguration();
55 final PatternLayout layout = PatternLayout.createDefaultLayout(config);
56 final Appender appender = OutputStreamAppender.createAppender(layout, null, outputStream, outputStreamName, false, true);
57 appender.start();
58 config.addAppender(appender);
59 ConfigurationTestUtils.updateLoggers(appender, config);
60 }
61
62 @Test
63 public void testBuildFilter() {
64 final NoMarkerFilter filter = NoMarkerFilter.newBuilder().build();
65 // @formatter:off
66 final OutputStreamAppender.Builder builder = OutputStreamAppender.newBuilder()
67 .setName("test")
68 .setFilter(filter);
69 // @formatter:on
70 Assert.assertEquals(filter, builder.getFilter());
71 final OutputStreamAppender appender = builder.build();
72 Assert.assertEquals(filter, appender.getFilter());
73 }
74
75 @Test
76 public void testOutputStreamAppenderToBufferedOutputStream() throws SQLException {
77 final ByteArrayOutputStream out = new ByteArrayOutputStream();
78 final OutputStream os = new BufferedOutputStream(out);
79 final String name = getName(out);
80 final Logger logger = LogManager.getLogger(name);
81 addAppender(os, name);
82 logger.error(TEST_MSG);
83 final String actual = out.toString();
84 Assert.assertTrue(actual, actual.contains(TEST_MSG));
85 }
86
87 @Test
88 public void testOutputStreamAppenderToByteArrayOutputStream() throws SQLException {
89 final OutputStream out = new ByteArrayOutputStream();
90 final String name = getName(out);
91 final Logger logger = LogManager.getLogger(name);
92 addAppender(out, name);
93 logger.error(TEST_MSG);
94 final String actual = out.toString();
95 Assert.assertTrue(actual, actual.contains(TEST_MSG));
96 }
97
98 /**
99 * Validates that the code pattern we use to add an appender on the fly
100 * works with a basic appender that is not the new OutputStream appender or
101 * new Writer appender.
102 */
103 @Test
104 public void testUpdatePatternWithFileAppender() {
105 final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
106 final Configuration config = ctx.getConfiguration();
107 // @formatter:off
108 final Appender appender = FileAppender.newBuilder()
109 .withFileName("target/" + getClass().getName() + ".log")
110 .withAppend(false).setName("File").setIgnoreExceptions(false)
111 .withBufferedIo(false)
112 .withBufferSize(4000)
113 .setConfiguration(config)
114 .build();
115 // @formatter:on
116 appender.start();
117 config.addAppender(appender);
118 ConfigurationTestUtils.updateLoggers(appender, config);
119 LogManager.getLogger().error("FOO MSG");
120 }
121 }
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;
17
18 import java.io.BufferedOutputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.OutputStream;
21 import java.sql.SQLException;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.Appender;
26 import org.apache.logging.log4j.core.LoggerContext;
27 import org.apache.logging.log4j.core.config.Configuration;
28 import org.apache.logging.log4j.core.layout.PatternLayout;
29 import org.junit.Assert;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.rules.TestName;
33
34 /**
35 * Tests {@link OutputStreamAppender}.
36 */
37 public class OutputStreamAppenderTest {
38
39 private static final String TEST_MSG = "FOO ERROR";
40
41 @Rule
42 public TestName testName = new TestName();
43
44 private String getName(final OutputStream out) {
45 return out.getClass().getSimpleName() + "." + testName.getMethodName();
46 }
47
48 /**
49 * Tests that you can add an output stream appender dynamically.
50 */
51 private void addAppender(final OutputStream outputStream, final String outputStreamName) {
52 final LoggerContext context = LoggerContext.getContext(false);
53 final Configuration config = context.getConfiguration();
54 final PatternLayout layout = PatternLayout.createDefaultLayout(config);
55 final Appender appender = OutputStreamAppender.createAppender(layout, null, outputStream, outputStreamName, false, true);
56 appender.start();
57 config.addAppender(appender);
58 ConfigurationTestUtils.updateLoggers(appender, config);
59 }
60
61 @Test
62 public void testOutputStreamAppenderToBufferedOutputStream() throws SQLException {
63 final ByteArrayOutputStream out = new ByteArrayOutputStream();
64 final OutputStream os = new BufferedOutputStream(out);
65 final String name = getName(out);
66 final Logger logger = LogManager.getLogger(name);
67 addAppender(os, name);
68 logger.error(TEST_MSG);
69 final String actual = out.toString();
70 Assert.assertTrue(actual, actual.contains(TEST_MSG));
71 }
72
73 @Test
74 public void testOutputStreamAppenderToByteArrayOutputStream() throws SQLException {
75 final OutputStream out = new ByteArrayOutputStream();
76 final String name = getName(out);
77 final Logger logger = LogManager.getLogger(name);
78 addAppender(out, name);
79 logger.error(TEST_MSG);
80 final String actual = out.toString();
81 Assert.assertTrue(actual, actual.contains(TEST_MSG));
82 }
83
84 /**
85 * Validates that the code pattern we use to add an appender on the fly
86 * works with a basic appender that is not the new OutputStream appender or
87 * new Writer appender.
88 */
89 @Test
90 public void testUpdatePatternWithFileAppender() {
91 final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
92 final Configuration config = ctx.getConfiguration();
93 // @formatter:off
94 final Appender appender = FileAppender.newBuilder()
95 .withFileName("target/" + getClass().getName() + ".log")
96 .withAppend(false).setName("File").setIgnoreExceptions(false)
97 .withBufferedIo(false)
98 .withBufferSize(4000)
99 .setConfiguration(config)
100 .build();
101 // @formatter:on
102 appender.start();
103 config.addAppender(appender);
104 ConfigurationTestUtils.updateLoggers(appender, config);
105 LogManager.getLogger().error("FOO MSG");
106 }
107 }
1616
1717 package org.apache.logging.log4j.core.appender;
1818
19 import java.io.IOException;
20 import java.io.OutputStream;
2119 import java.util.List;
2220
2321 import org.apache.logging.log4j.Level;
22 import org.apache.logging.log4j.LogManager;
2423 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.LoggerContext;
26 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.LoggerContextRule;
2725 import org.apache.logging.log4j.status.StatusData;
2826 import org.apache.logging.log4j.status.StatusLogger;
29 import org.junit.jupiter.api.Test;
27 import org.junit.ClassRule;
28 import org.junit.Test;
3029
31 import static org.junit.jupiter.api.Assertions.*;
30 import static org.junit.Assert.*;
3231
3332 /**
3433 * OutputStreamManager Tests.
3534 */
3635 public class OutputStreamManagerTest {
36 private static final String CONFIG = "multipleIncompatibleAppendersTest.xml";
37
38 @ClassRule
39 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
3740
3841 @Test
39 @LoggerContextSource("multipleIncompatibleAppendersTest.xml")
40 public void narrow(final LoggerContext context) {
41 final Logger logger = context.getLogger(OutputStreamManagerTest.class);
42 public void narrow() throws Exception {
43 final Logger logger = LogManager.getLogger(OutputStreamManagerTest.class);
4244 logger.info("test");
4345 final List<StatusData> statusData = StatusLogger.getLogger().getStatusData();
4446 StatusData data = statusData.get(0);
5254 data.getThrowable().toString());
5355 }
5456
55
56 @Test
57 public void testOutputStreamAppenderFlushClearsBufferOnException() {
58 IOException exception = new IOException();
59 final OutputStream throwingOutputStream = new OutputStream() {
60 @Override
61 public void write(int b) throws IOException {
62 throw exception;
63 }
64 };
65
66 final int bufferSize = 3;
67 OutputStreamManager outputStreamManager = new OutputStreamManager(throwingOutputStream, "test", null, false, bufferSize);
68
69 for (int i = 0; i < bufferSize - 1; i++) {
70 outputStreamManager.getByteBuffer().put((byte) 0);
71 }
72
73 assertEquals(outputStreamManager.getByteBuffer().remaining(), 1);
74
75 AppenderLoggingException appenderLoggingException = assertThrows(AppenderLoggingException.class, () -> outputStreamManager.flushBuffer(outputStreamManager.getByteBuffer()));
76 assertEquals(appenderLoggingException.getCause(), exception);
77
78 assertEquals(outputStreamManager.getByteBuffer().limit(), outputStreamManager.getByteBuffer().capacity());
79 }
8057 }
2222 import java.io.RandomAccessFile;
2323
2424 import org.apache.logging.log4j.core.util.NullOutputStream;
25 import org.junit.jupiter.api.Test;
26 import org.junit.jupiter.api.io.TempDir;
25 import org.junit.ClassRule;
26 import org.junit.Test;
27 import org.junit.rules.TemporaryFolder;
2728
28 import static org.junit.jupiter.api.Assertions.*;
29 import static org.junit.Assert.*;
2930
3031 /**
3132 * Tests the RandomAccessFileManager class.
3233 */
3334 public class RandomAccessFileManagerTest {
3435
35 @TempDir
36 File tempDir;
36 @ClassRule
37 public static TemporaryFolder folder = new TemporaryFolder();
3738
3839 /**
3940 * Test method for
40 * {@link org.apache.logging.log4j.core.appender.RandomAccessFileManager#writeBytes(byte[], int, int)}.
41 * {@link org.apache.logging.log4j.core.appender.RandomAccessFileManager#writeBytes(byte[], int, int)}
42 * .
4143 */
4244 @Test
4345 public void testWrite_multiplesOfBufferSize() throws IOException {
44 final File file = new File(tempDir, "testWrite_multiplesOfBufferSize.bin");
46 final File file = folder.newFile();
4547 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
4648 final OutputStream os = NullOutputStream.getInstance();
4749 final RandomAccessFileManager manager = new RandomAccessFileManager(null, raf, file.getName(),
5355
5456 // all data is written if exceeds buffer size
5557 assertEquals(RandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3, raf.length());
56 }
57 }
58 }}
5859
5960 /**
6061 * Test method for
6364 */
6465 @Test
6566 public void testWrite_dataExceedingBufferSize() throws IOException {
66 final File file = new File(tempDir, "testWrite_dataExceedingBufferSize.bin");
67 final File file = folder.newFile();
6768 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
6869 final OutputStream os = NullOutputStream.getInstance();
6970 final RandomAccessFileManager manager = new RandomAccessFileManager(null, raf, file.getName(),
7778
7879 manager.flush();
7980 assertEquals(size, raf.length()); // all data written to file now
80 }
81 }
81 }}
8282
8383 @Test
8484 public void testConfigurableBufferSize() throws IOException {
85 final File file = new File(tempDir, "testConfigurableBufferSize.bin");
85 final File file = folder.newFile();
8686 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
8787 final OutputStream os = NullOutputStream.getInstance();
8888 final int bufferSize = 4 * 1024;
9393
9494 // check the resulting buffer size is what was requested
9595 assertEquals(bufferSize, manager.getBufferSize());
96 }
97 }
96 }}
9897
9998 @Test
10099 public void testWrite_dataExceedingMinBufferSize() throws IOException {
101 final File file = new File(tempDir, "testWrite_dataExceedingMinBufferSize.bin");
100 final File file = folder.newFile();
102101 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
103102 final OutputStream os = NullOutputStream.getInstance();
104103 final int bufferSize = 1;
113112
114113 manager.flush();
115114 assertEquals(size, raf.length()); // all data written to file now
116 }
117 }
115 }}
118116
119117 @Test
120118 public void testAppendDoesNotOverwriteExistingFile() throws IOException {
121119 final boolean isAppend = true;
122 final File file = new File(tempDir, "testAppendDoesNotOverwriteExistingFile.bin");
120 final File file = folder.newFile();
123121 assertEquals(0, file.length());
124122
125123 final byte[] bytes = new byte[4 * 1024];
129127 fos.write(bytes, 0, bytes.length);
130128 fos.flush();
131129 }
132 assertEquals(bytes.length, file.length(), "all flushed to disk");
130 assertEquals("all flushed to disk", bytes.length, file.length());
133131
134 try (final RandomAccessFileManager manager = RandomAccessFileManager.getFileManager(file.getAbsolutePath(),
135 isAppend, true, RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null, null)) {
136 manager.write(bytes, 0, bytes.length, true);
137 final int expected = bytes.length * 2;
138 assertEquals(expected, file.length(), "appended, not overwritten");
139 }
132 final RandomAccessFileManager manager = RandomAccessFileManager.getFileManager(
133 file.getAbsolutePath(), isAppend, true, RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null, null);
134 manager.write(bytes, 0, bytes.length, true);
135 final int expected = bytes.length * 2;
136 assertEquals("appended, not overwritten", expected, file.length());
140137 }
141138 }
3131 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
3232 import org.apache.logging.log4j.core.layout.PatternLayout;
3333 import org.apache.logging.log4j.core.util.Builder;
34 import org.junit.jupiter.api.Test;
34 import org.junit.Test;
3535
36 /**
37 * Class Description goes here.
38 * Created by rgoers on 2019-02-02
39 */
3640 public class ReconfigureAppenderTest {
3741 private RollingFileAppender appender;
3842
138142 ConfigurationBuilderFactory.newConfigurationBuilder();
139143
140144 // All loggers must have a root logger. The default root logger logs ERRORs to the console.
141 // Override this with a root logger that does not log anywhere as we leave it up the
145 // Override this with a root logger that does not log anywhere as we leave it up the the
142146 // appenders on the logger.
143147 config_builder.add(config_builder.newRootLogger(Level.INFO));
144148
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import org.apache.logging.log4j.Marker;
1819 import org.apache.logging.log4j.MarkerManager;
19 import org.apache.logging.log4j.core.config.Configuration;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.spi.ExtendedLogger;
20 import org.apache.logging.log4j.categories.Scripts;
21 import org.apache.logging.log4j.core.Logger;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2223 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Test;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.experimental.categories.Category;
27 import org.junit.runner.RunWith;
28 import org.junit.runners.Parameterized;
2429
25 import static org.hamcrest.MatcherAssert.assertThat;
26 import static org.hamcrest.Matchers.hasSize;
27 import static org.junit.jupiter.api.Assertions.assertNotNull;
28 import static org.junit.jupiter.api.Assertions.assertNull;
30 import static org.junit.Assert.*;
2931
32 @RunWith(Parameterized.class)
33 @Category(Scripts.Groovy.class)
3034 public class ScriptAppenderSelectorTest {
3135
32 @Test
33 @LoggerContextSource("log4j-appender-selector-javascript.xml")
34 void testJavaScriptSelector(final Configuration config) {
35 verify(config);
36 @Parameterized.Parameters(name = "{0}")
37 public static Object[][] getParameters() {
38 // @formatter:off
39 return new Object[][] {
40 { "log4j-appender-selector-groovy.xml" },
41 { "log4j-appender-selector-javascript.xml" },
42 };
43 // @formatter:on
44 }
45
46 @Rule
47 public final LoggerContextRule loggerContextRule;
48
49 public ScriptAppenderSelectorTest(final String configLocation) {
50 this.loggerContextRule = new LoggerContextRule(configLocation);
51 }
52
53 private ListAppender getListAppender() {
54 return loggerContextRule.getListAppender("SelectIt");
55 }
56
57 private void logAndCheck() {
58 final Marker marker = MarkerManager.getMarker("HEXDUMP");
59 final Logger logger = loggerContextRule.getLogger(ScriptAppenderSelectorTest.class);
60 logger.error("Hello");
61 final ListAppender listAppender = getListAppender();
62 assertEquals("Incorrect number of events", 1, listAppender.getEvents().size());
63 logger.error("World");
64 assertEquals("Incorrect number of events", 2, listAppender.getEvents().size());
65 logger.error(marker, "DEADBEEF");
66 assertEquals("Incorrect number of events", 3, listAppender.getEvents().size());
67 }
68
69 @Test(expected = AssertionError.class)
70 public void testAppender1Absence() {
71 loggerContextRule.getListAppender("List1");
72 }
73
74 @Test(expected = AssertionError.class)
75 public void testAppender2Absence() {
76 loggerContextRule.getListAppender("List2");
3677 }
3778
3879 @Test
39 @LoggerContextSource("log4j-appender-selector-groovy.xml")
40 void testGroovySelector(final Configuration config) {
41 verify(config);
80 public void testAppenderPresence() {
81 getListAppender();
4282 }
4383
44 static void verify(final Configuration config) {
45 assertNull(config.getAppender("List1"), "List1 appender should not be initialized");
46 assertNull(config.getAppender("List2"), "List2 appender should not be initialized");
47 final ListAppender listAppender = config.getAppender("SelectIt");
48 assertNotNull(listAppender);
49 final ExtendedLogger logger = config.getLoggerContext().getLogger(ScriptAppenderSelectorTest.class);
50 logger.error("Hello");
51 assertThat(listAppender.getEvents(), hasSize(1));
52 logger.error("World");
53 assertThat(listAppender.getEvents(), hasSize(2));
54 logger.error(MarkerManager.getMarker("HEXDUMP"), "DEADBEEF");
55 assertThat(listAppender.getEvents(), hasSize(3));
84 @Test
85 public void testLogging1() {
86 logAndCheck();
5687 }
5788
89 @Test
90 public void testLogging2() {
91 logAndCheck();
92 }
5893 }
119119 .setBcc("bcc@example.com")
120120 .setFrom("from@example.com")
121121 .setReplyTo("replyTo@example.com")
122 .setSubject("Subject Pattern %X{" + subjectKey + "} %maxLen{%m}{10}")
122 .setSubject("Subject Pattern %X{" + subjectKey + "}")
123123 .setSmtpHost(HOST)
124124 .setSmtpPort(smtpPort)
125125 .setBufferSize(3)
152152 // can't be tested with Dumpster 1.6
153153 assertEquals("from@example.com", email.getHeaderValue("From"));
154154 assertEquals("replyTo@example.com", email.getHeaderValue("Reply-To"));
155 assertEquals("Subject Pattern " + subjectValue +" Error with", email.getHeaderValue("Subject"));
155 final String headerValue = email.getHeaderValue("Subject");
156 assertEquals(headerValue, "Subject Pattern " + subjectValue);
156157
157158 final String body = email.getBody();
158159 assertFalse(body.contains("Debug message #1"));
165166 assertFalse(body.contains("Error message #2"));
166167
167168 final SmtpMessage email2 = messages.next();
168
169 assertEquals("Subject Pattern " + subjectValue +" Error mess", email2.getHeaderValue("Subject"));
170
171169 final String body2 = email2.getBody();
172170 assertFalse(body2.contains("Debug message #4"));
173171 assertFalse(body2.contains("Error with exception"));
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import org.junit.jupiter.api.Test;
19
20 import static org.junit.jupiter.api.Assertions.assertTrue;
18 import org.apache.logging.log4j.core.appender.SocketAppender;
19 import org.junit.Assert;
20 import org.junit.Test;
2121
2222 public class SocketAppenderBuilderTest {
2323
2626 */
2727 @Test
2828 public void testDefaultImmediateFlush() {
29 assertTrue(SocketAppender.newBuilder().isImmediateFlush(),
30 "Regression of LOG4J2-1620: default value for immediateFlush should be true");
29 Assert.assertTrue(SocketAppender.newBuilder().isImmediateFlush());
3130 }
3231 }
115115 protected Builder newSyslogAppenderBuilder(final String protocol, final String format, final boolean newLine) {
116116 // @formatter:off
117117 return SyslogAppender.newSyslogAppenderBuilder()
118 .withPort(PORTNUM)
119 .withProtocol(EnglishEnums.valueOf(Protocol.class, protocol))
120 .withReconnectDelayMillis(-1).setName("TestApp").setIgnoreExceptions(false)
121 .setId("Audit")
122 .setEnterpriseNumber(18060)
123 .setMdcId("RequestContext")
124 .setNewLine(newLine)
125 .setAppName("TestApp")
126 .setMsgId("Test")
127 .setFormat(format);
118 .withPort(PORTNUM)
119 .withProtocol(EnglishEnums.valueOf(Protocol.class, protocol))
120 .withReconnectDelayMillis(-1).setName("TestApp").setIgnoreExceptions(false)
121 .setId("Audit")
122 .setEnterpriseNumber(18060)
123 .setMdcId("RequestContext")
124 .setNewLine(newLine)
125 .setAppName("TestApp")
126 .setMsgId("Test")
127 .setFormat(format);
128128 // @formatter:on
129129 }
130130 }
1818 import java.nio.charset.StandardCharsets;
1919
2020 import org.apache.logging.log4j.util.Chars;
21 import org.junit.jupiter.api.Test;
22
23 import static org.junit.jupiter.api.Assertions.assertEquals;
24 import static org.junit.jupiter.api.Assertions.assertNotEquals;
21 import org.junit.Assert;
22 import org.junit.Test;
2523
2624 public class TlsSyslogFrameTest {
2725 private static final String TEST_MESSAGE = "The quick brown fox jumps over the lazy dog";
3028 public void equals() {
3129 final TlsSyslogFrame first = new TlsSyslogFrame(TEST_MESSAGE);
3230 final TlsSyslogFrame second = new TlsSyslogFrame(TEST_MESSAGE);
33 assertEquals(first, second);
34 assertEquals(first.hashCode(), second.hashCode());
31 Assert.assertEquals(first, second);
32 Assert.assertEquals(first.hashCode(), second.hashCode());
3533 }
3634
3735 @Test
3836 public void notEquals() {
3937 final TlsSyslogFrame first = new TlsSyslogFrame("A message");
4038 final TlsSyslogFrame second = new TlsSyslogFrame("B message");
41 assertNotEquals(first, second);
42 assertNotEquals(first.hashCode(), second.hashCode());
39 Assert.assertNotEquals(first, second);
40 Assert.assertNotEquals(first.hashCode(), second.hashCode());
4341 }
4442
4543 @Test
4745 final TlsSyslogFrame frame = new TlsSyslogFrame(TEST_MESSAGE);
4846 final int length = TEST_MESSAGE.getBytes(StandardCharsets.UTF_8).length;
4947 final String expected = Integer.toString(length) + Chars.SPACE + TEST_MESSAGE;
50 assertEquals(expected, frame.toString());
48 Assert.assertEquals(expected, frame.toString());
5149 }
5250 }
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;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.CharArrayWriter;
20 import java.io.OutputStreamWriter;
21 import java.io.PrintWriter;
22 import java.io.StringWriter;
23 import java.io.Writer;
24 import java.lang.reflect.Method;
25
26 import org.apache.logging.log4j.LogManager;
27 import org.apache.logging.log4j.Logger;
28 import org.apache.logging.log4j.core.Appender;
29 import org.apache.logging.log4j.core.LoggerContext;
30 import org.apache.logging.log4j.core.config.Configuration;
31 import org.apache.logging.log4j.core.layout.PatternLayout;
32 import org.junit.jupiter.api.BeforeEach;
33 import org.junit.jupiter.api.Test;
34 import org.junit.jupiter.api.TestInfo;
35
36 import static org.hamcrest.MatcherAssert.assertThat;
37 import static org.hamcrest.Matchers.containsString;
38
39 /**
40 * Tests {@link WriterAppender}.
41 */
42 public class WriterAppenderTest {
43
44 private static final String TEST_MSG = "FOO ERROR";
45
46 private String testMethodName;
47
48 @BeforeEach
49 void setUp(final TestInfo testInfo) {
50 testMethodName = testInfo.getTestMethod().map(Method::getName).orElseGet(testInfo::getDisplayName);
51 }
52
53 private String getName(final Writer writer) {
54 return writer.getClass().getSimpleName() + "." + testMethodName;
55 }
56
57 private void test(final ByteArrayOutputStream out, final Writer writer) {
58 final String name = getName(writer);
59 addAppender(writer, name);
60 final Logger logger = LogManager.getLogger(name);
61 logger.error(TEST_MSG);
62 final String actual = out.toString();
63 assertThat(actual, containsString(TEST_MSG));
64 }
65
66 private void test(final Writer writer) {
67 final String name = getName(writer);
68 addAppender(writer, name);
69 final Logger logger = LogManager.getLogger(name);
70 logger.error(TEST_MSG);
71 final String actual = writer.toString();
72 assertThat(actual, containsString(TEST_MSG));
73 }
74
75 private void addAppender(final Writer writer, final String writerName) {
76 final LoggerContext context = LoggerContext.getContext(false);
77 final Configuration config = context.getConfiguration();
78 final PatternLayout layout = PatternLayout.createDefaultLayout(config);
79 final Appender appender = WriterAppender.createAppender(layout, null, writer, writerName, false, true);
80 appender.start();
81 config.addAppender(appender);
82 ConfigurationTestUtils.updateLoggers(appender, config);
83 }
84
85 @Test
86 public void testWriterAppenderToCharArrayWriter() {
87 test(new CharArrayWriter());
88 }
89
90 @Test
91 public void testWriterAppenderToOutputStreamWriter() {
92 final ByteArrayOutputStream out = new ByteArrayOutputStream();
93 final Writer writer = new OutputStreamWriter(out);
94 test(out, writer);
95 }
96
97 @Test
98 public void testWriterAppenderToPrintWriter() {
99 final ByteArrayOutputStream out = new ByteArrayOutputStream();
100 final Writer writer = new PrintWriter(out);
101 test(out, writer);
102 }
103
104 @Test
105 public void testWriterAppenderToStringWriter() {
106 test(new StringWriter());
107 }
108
109 @Test
110 public void testBuilder() {
111 // This should compile
112 WriterAppender.newBuilder().setTarget(new StringWriter()).setName("testWriterAppender").build();
113 }
114 }
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;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.CharArrayWriter;
20 import java.io.OutputStreamWriter;
21 import java.io.PrintWriter;
22 import java.io.StringWriter;
23 import java.io.Writer;
24 import java.sql.SQLException;
25
26 import org.apache.logging.log4j.LogManager;
27 import org.apache.logging.log4j.Logger;
28 import org.apache.logging.log4j.core.Appender;
29 import org.apache.logging.log4j.core.LoggerContext;
30 import org.apache.logging.log4j.core.config.Configuration;
31 import org.apache.logging.log4j.core.layout.PatternLayout;
32 import org.junit.Assert;
33 import org.junit.Rule;
34 import org.junit.Test;
35 import org.junit.rules.TestName;
36
37 /**
38 * Tests {@link WriterAppender}.
39 */
40 public class WriterAppenderTest {
41
42 private static final String TEST_MSG = "FOO ERROR";
43
44 @Rule
45 public TestName testName = new TestName();
46
47 private String getName(final Writer writer) {
48 return writer.getClass().getSimpleName() + "." + testName.getMethodName();
49 }
50
51 private void test(final ByteArrayOutputStream out, final Writer writer) throws SQLException {
52 final String name = getName(writer);
53 addAppender(writer, name);
54 final Logger logger = LogManager.getLogger(name);
55 logger.error(TEST_MSG);
56 final String actual = out.toString();
57 Assert.assertTrue(actual, actual.contains(TEST_MSG));
58 }
59
60 private void test(final Writer writer) throws SQLException {
61 final String name = getName(writer);
62 addAppender(writer, name);
63 final Logger logger = LogManager.getLogger(name);
64 logger.error(TEST_MSG);
65 final String actual = writer.toString();
66 Assert.assertTrue(actual, actual.contains(TEST_MSG));
67 }
68
69 private void addAppender(final Writer writer, final String writerName) {
70 final LoggerContext context = LoggerContext.getContext(false);
71 final Configuration config = context.getConfiguration();
72 final PatternLayout layout = PatternLayout.createDefaultLayout(config);
73 final Appender appender = WriterAppender.createAppender(layout, null, writer, writerName, false, true);
74 appender.start();
75 config.addAppender(appender);
76 ConfigurationTestUtils.updateLoggers(appender, config);
77 }
78
79 @Test
80 public void testWriterAppenderToCharArrayWriter() throws SQLException {
81 test(new CharArrayWriter());
82 }
83
84 @Test
85 public void testWriterAppenderToOutputStreamWriter() throws SQLException {
86 final ByteArrayOutputStream out = new ByteArrayOutputStream();
87 final Writer writer = new OutputStreamWriter(out);
88 test(out, writer);
89 }
90
91 @Test
92 public void testWriterAppenderToPrintWriter() throws SQLException {
93 final ByteArrayOutputStream out = new ByteArrayOutputStream();
94 final Writer writer = new PrintWriter(out);
95 test(out, writer);
96 }
97
98 @Test
99 public void testWriterAppenderToStringWriter() throws SQLException {
100 test(new StringWriter());
101 }
102
103 @Test
104 public void testBuilder() {
105 // This should compile
106 WriterAppender.newBuilder().setTarget(new StringWriter()).setName("testWriterAppender").build();
107 }
108 }
3333 import org.junit.Rule;
3434 import org.junit.Test;
3535 import org.junit.rules.RuleChain;
36 import org.mockito.invocation.InvocationOnMock;
37 import org.mockito.stubbing.Answer;
3638
3739 import static org.junit.Assert.*;
3840 import static org.mockito.BDDMockito.given;
5961 private DataSource createMockDataSource() {
6062 try {
6163 final DataSource dataSource = mock(DataSource.class);
62 given(dataSource.getConnection()).willAnswer(invocation -> jdbcRule.getConnectionSource().getConnection());
64 given(dataSource.getConnection()).willAnswer(new Answer<Connection>() {
65 @Override
66 public Connection answer(final InvocationOnMock invocation) throws Throwable {
67 return jdbcRule.getConnectionSource().getConnection();
68 }
69 });
6370 return dataSource;
6471 } catch (final SQLException e) {
6572 Throwables.rethrow(e);
4141 import org.junit.Rule;
4242 import org.junit.Test;
4343 import org.junit.rules.RuleChain;
44 import org.mockito.invocation.InvocationOnMock;
45 import org.mockito.stubbing.Answer;
4446
4547 /**
4648 * Unit tests {@link MapMessage}s for JdbcAppender using a {@link DataSource} configuration.
7274 private DataSource createMockDataSource() {
7375 try {
7476 final DataSource dataSource = mock(DataSource.class);
75 given(dataSource.getConnection()).willAnswer(invocation -> jdbcRule.getConnectionSource().getConnection());
77 given(dataSource.getConnection()).willAnswer(new Answer<Connection>() {
78 @Override
79 public Connection answer(final InvocationOnMock invocation) throws Throwable {
80 return jdbcRule.getConnectionSource().getConnection();
81 }
82 });
7683 return dataSource;
7784 } catch (final SQLException e) {
7885 Throwables.rethrow(e);
2727 private static final String KEY = "Test.TableName";
2828
2929 public JdbcAppenderStringSubstitutionTest() {
30 super();
3031 System.setProperty(KEY, VALUE);
3132 }
3233
9292 appender.resetSendRcs();
9393 final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(nThreads);
9494 for (int i = 0; i < 10.; i++) {
95 fixedThreadPool.submit(() -> {
96 logger.info("Hello");
97 logger.info("Again");
95 fixedThreadPool.submit(new Runnable() {
96 @Override
97 public void run() {
98 logger.info("Hello");
99 logger.info("Again");
100 }
98101 });
99102 }
100103 final List<String> list = future.get();
2020 import java.util.List;
2121 import java.util.concurrent.Callable;
2222
23 import org.apache.logging.log4j.util.Constants;
2423 import org.zeromq.ZMQ;
2524
2625 class JeroMqTestClient implements Callable<List<String>> {
3231 private final int receiveCount;
3332
3433 JeroMqTestClient(final ZMQ.Context context, final String endpoint, final int receiveCount) {
34 super();
3535 this.context = context;
3636 this.endpoint = endpoint;
3737 this.receiveCount = receiveCount;
4242 public List<String> call() throws Exception {
4343 try (ZMQ.Socket subscriber = context.socket(ZMQ.SUB)) {
4444 subscriber.connect(endpoint);
45 subscriber.subscribe(Constants.EMPTY_BYTE_ARRAY);
45 subscriber.subscribe(new byte[0]);
4646 for (int messageNum = 0; messageNum < receiveCount
4747 && !Thread.currentThread().isInterrupted(); messageNum++) {
4848 // Use trim to remove the tailing '0' character
1616
1717 package org.apache.logging.log4j.core.appender.mom.kafka;
1818
19 import java.util.Properties;
1920 import java.util.concurrent.TimeUnit;
2021
2122 import org.apache.kafka.clients.producer.MockProducer;
23 import org.apache.kafka.clients.producer.Producer;
2224 import org.apache.logging.log4j.categories.Appenders;
2325 import org.apache.logging.log4j.core.Appender;
2426 import org.apache.logging.log4j.junit.LoggerContextRule;
5153
5254 @BeforeClass
5355 public static void setUpClass() throws Exception {
54 KafkaManager.producerFactory = config -> kafka;
56 KafkaManager.producerFactory = new KafkaProducerFactory() {
57 @Override
58 public Producer<byte[], byte[]> newKafkaProducer(final Properties config) {
59 return kafka;
60 }
61 };
5562 }
5663
5764 @Rule
1616
1717 package org.apache.logging.log4j.core.appender.mom.kafka;
1818
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23
2419 import java.io.ByteArrayInputStream;
2520 import java.io.IOException;
2621 import java.io.ObjectInput;
2823 import java.text.SimpleDateFormat;
2924 import java.util.Date;
3025 import java.util.List;
31 import java.util.concurrent.Future;
26 import java.util.Properties;
3227 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.TimeoutException;
3428
3529 import org.apache.kafka.clients.producer.MockProducer;
30 import org.apache.kafka.clients.producer.Producer;
3631 import org.apache.kafka.clients.producer.ProducerRecord;
37 import org.apache.kafka.clients.producer.RecordMetadata;
38 import org.apache.log4j.MDC;
3932 import org.apache.logging.log4j.Level;
4033 import org.apache.logging.log4j.categories.Appenders;
4134 import org.apache.logging.log4j.core.Appender;
5043 import org.junit.Test;
5144 import org.junit.experimental.categories.Category;
5245
46 import static org.junit.Assert.*;
47
5348 @Category(Appenders.Kafka.class)
5449 public class KafkaAppenderTest {
5550
56 private static final MockProducer<byte[], byte[]> kafka = new MockProducer<byte[], byte[]>(true, null, null) {
51 private static final MockProducer<byte[], byte[]> kafka = new MockProducer<byte[], byte[]>(true, null, null) {
5752
58 @Override
59 public synchronized Future<RecordMetadata> send(ProducerRecord<byte[], byte[]> record) {
53 @Override
54 public void close(final long timeout, final TimeUnit timeUnit) {
55 }
6056
61 Future<RecordMetadata> retVal = super.send(record);
57 };
6258
63 boolean isRetryTest = "true".equals(MDC.get("KafkaAppenderWithRetryCount"));
64 if (isRetryTest) {
65 try {
66 throw new TimeoutException();
67 } catch (TimeoutException e) {
68 // TODO Auto-generated catch block
69 throw new RuntimeException(e);
70 }
71 }
59 private static final String LOG_MESSAGE = "Hello, world!";
60 private static final String TOPIC_NAME = "kafka-topic";
7261
73 return retVal;
74 };
62 private static Log4jLogEvent createLogEvent() {
63 return Log4jLogEvent.newBuilder()
64 .setLoggerName(KafkaAppenderTest.class.getName())
65 .setLoggerFqcn(KafkaAppenderTest.class.getName())
66 .setLevel(Level.INFO)
67 .setMessage(new SimpleMessage(LOG_MESSAGE))
68 .build();
69 }
7570
76 @Override
77 public void close(final long timeout, final TimeUnit timeUnit) {
78 }
71 @BeforeClass
72 public static void setUpClass() throws Exception {
73 KafkaManager.producerFactory = new KafkaProducerFactory() {
74 @Override
75 public Producer<byte[], byte[]> newKafkaProducer(final Properties config) {
76 return kafka;
77 }
78 };
79 }
7980
80 };
81 @Rule
82 public LoggerContextRule ctx = new LoggerContextRule("KafkaAppenderTest.xml");
8183
82 private static final String LOG_MESSAGE = "Hello, world!";
83 private static final String TOPIC_NAME = "kafka-topic";
84 private static final int RETRY_COUNT = 3;
84 @Before
85 public void setUp() throws Exception {
86 kafka.clear();
87 }
8588
86 private static Log4jLogEvent createLogEvent() {
87 return Log4jLogEvent.newBuilder().setLoggerName(KafkaAppenderTest.class.getName())
88 .setLoggerFqcn(KafkaAppenderTest.class.getName()).setLevel(Level.INFO)
89 .setMessage(new SimpleMessage(LOG_MESSAGE)).build();
90 }
89 @Test
90 public void testAppendWithLayout() throws Exception {
91 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithLayout");
92 appender.append(createLogEvent());
93 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
94 assertEquals(1, history.size());
95 final ProducerRecord<byte[], byte[]> item = history.get(0);
96 assertNotNull(item);
97 assertEquals(TOPIC_NAME, item.topic());
98 assertNull(item.key());
99 assertEquals("[" + LOG_MESSAGE + "]", new String(item.value(), StandardCharsets.UTF_8));
100 }
91101
92 @BeforeClass
93 public static void setUpClass() throws Exception {
94 KafkaManager.producerFactory = config -> kafka;
95 }
102 @Test
103 public void testAppendWithSerializedLayout() throws Exception {
104 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithSerializedLayout");
105 final LogEvent logEvent = createLogEvent();
106 appender.append(logEvent);
107 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
108 assertEquals(1, history.size());
109 final ProducerRecord<byte[], byte[]> item = history.get(0);
110 assertNotNull(item);
111 assertEquals(TOPIC_NAME, item.topic());
112 assertNull(item.key());
113 assertEquals(LOG_MESSAGE, deserializeLogEvent(item.value()).getMessage().getFormattedMessage());
114 }
96115
97 @Rule
98 public LoggerContextRule ctx = new LoggerContextRule("KafkaAppenderTest.xml");
116 @Test
117 public void testAsyncAppend() throws Exception {
118 final Appender appender = ctx.getRequiredAppender("AsyncKafkaAppender");
119 appender.append(createLogEvent());
120 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
121 assertEquals(1, history.size());
122 final ProducerRecord<byte[], byte[]> item = history.get(0);
123 assertNotNull(item);
124 assertEquals(TOPIC_NAME, item.topic());
125 assertNull(item.key());
126 assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
127 }
99128
100 @Before
101 public void setUp() throws Exception {
102 kafka.clear();
103 }
129 @Test
130 public void testAppendWithKey() throws Exception {
131 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithKey");
132 final LogEvent logEvent = createLogEvent();
133 appender.append(logEvent);
134 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
135 assertEquals(1, history.size());
136 final ProducerRecord<byte[], byte[]> item = history.get(0);
137 assertNotNull(item);
138 assertEquals(TOPIC_NAME, item.topic());
139 final String msgKey = item.key().toString();
140 final byte[] keyValue = "key".getBytes(StandardCharsets.UTF_8);
141 assertArrayEquals(item.key(), keyValue);
142 assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
143 }
104144
105 @Test
106 public void testAppendWithLayout() throws Exception {
107 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithLayout");
108 appender.append(createLogEvent());
109 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
110 assertEquals(1, history.size());
111 final ProducerRecord<byte[], byte[]> item = history.get(0);
112 assertNotNull(item);
113 assertEquals(TOPIC_NAME, item.topic());
114 assertNull(item.key());
115 assertEquals("[" + LOG_MESSAGE + "]", new String(item.value(), StandardCharsets.UTF_8));
116 }
145 @Test
146 public void testAppendWithKeyLookup() throws Exception {
147 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithKeyLookup");
148 final LogEvent logEvent = createLogEvent();
149 final Date date = new Date();
150 final SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
151 appender.append(logEvent);
152 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
153 assertEquals(1, history.size());
154 final ProducerRecord<byte[], byte[]> item = history.get(0);
155 assertNotNull(item);
156 assertEquals(TOPIC_NAME, item.topic());
157 final byte[] keyValue = format.format(date).getBytes(StandardCharsets.UTF_8);
158 assertArrayEquals(item.key(), keyValue);
159 assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
160 }
117161
118 @Test
119 public void testAppendWithSerializedLayout() throws Exception {
120 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithSerializedLayout");
121 final LogEvent logEvent = createLogEvent();
122 appender.append(logEvent);
123 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
124 assertEquals(1, history.size());
125 final ProducerRecord<byte[], byte[]> item = history.get(0);
126 assertNotNull(item);
127 assertEquals(TOPIC_NAME, item.topic());
128 assertNull(item.key());
129 assertEquals(LOG_MESSAGE, deserializeLogEvent(item.value()).getMessage().getFormattedMessage());
130 }
131162
132 @Test
133 public void testAsyncAppend() throws Exception {
134 final Appender appender = ctx.getRequiredAppender("AsyncKafkaAppender");
135 appender.append(createLogEvent());
136 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
137 assertEquals(1, history.size());
138 final ProducerRecord<byte[], byte[]> item = history.get(0);
139 assertNotNull(item);
140 assertEquals(TOPIC_NAME, item.topic());
141 assertNull(item.key());
142 assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
143 }
144
145 @Test
146 public void testAppendWithKey() throws Exception {
147 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithKey");
148 final LogEvent logEvent = createLogEvent();
149 appender.append(logEvent);
150 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
151 assertEquals(1, history.size());
152 final ProducerRecord<byte[], byte[]> item = history.get(0);
153 assertNotNull(item);
154 assertEquals(TOPIC_NAME, item.topic());
155 final String msgKey = item.key().toString();
156 final byte[] keyValue = "key".getBytes(StandardCharsets.UTF_8);
157 assertArrayEquals(item.key(), keyValue);
158 assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
159 }
160
161 @Test
162 public void testAppendWithKeyLookup() throws Exception {
163 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithKeyLookup");
164 final LogEvent logEvent = createLogEvent();
165 final Date date = new Date();
166 final SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
167 appender.append(logEvent);
168 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
169 assertEquals(1, history.size());
170 final ProducerRecord<byte[], byte[]> item = history.get(0);
171 assertNotNull(item);
172 assertEquals(TOPIC_NAME, item.topic());
173 final byte[] keyValue = format.format(date).getBytes(StandardCharsets.UTF_8);
174 assertArrayEquals(item.key(), keyValue);
175 assertEquals(LOG_MESSAGE, new String(item.value(), StandardCharsets.UTF_8));
176 }
177
178 @Test
179 public void testAppendWithRetryCount() {
180 try {
181 MDC.put("KafkaAppenderWithRetryCount", "true");
182 final Appender appender = ctx.getRequiredAppender("KafkaAppenderWithRetryCount");
183 final LogEvent logEvent = createLogEvent();
184 appender.append(logEvent);
185
186 final List<ProducerRecord<byte[], byte[]>> history = kafka.history();
187 assertEquals(RETRY_COUNT + 1, history.size());
188 } catch (Exception e) {
189 e.printStackTrace();
190 } finally {
191 MDC.clear();
192 }
193
194 }
195
196 private LogEvent deserializeLogEvent(final byte[] data) throws IOException, ClassNotFoundException {
197 final ByteArrayInputStream bis = new ByteArrayInputStream(data);
198 try (ObjectInput ois = new FilteredObjectInputStream(bis)) {
199 return (LogEvent) ois.readObject();
200 }
201 }
202
203 // public void shouldRetryWhenTimeoutExceptionOccursOnSend() throws Exception {
204 // final AtomicInteger attempt = new AtomicInteger(0);
205 // final RecordCollectorImpl collector = new RecordCollectorImpl(
206 // new MockProducer(cluster, true, new DefaultPartitioner(), byteArraySerializer, byteArraySerializer) {
207 // @Override
208 // public synchronized Future<RecordMetadata> send(final ProducerRecord record, final Callback callback) {
209 // if (attempt.getAndIncrement() == 0) {
210 // throw new TimeoutException();
211 // }
212 // return super.send(record, callback);
213 // }
214 // },
215 // "test");
216 //
217 // collector.send("topic1", "3", "0", null, stringSerializer, stringSerializer, streamPartitioner);
218 // final Long offset = collector.offsets().get(new TopicPartition("topic1", 0));
219 // assertEquals(Long.valueOf(0L), offset);
220 // }
163 private LogEvent deserializeLogEvent(final byte[] data) throws IOException, ClassNotFoundException {
164 final ByteArrayInputStream bis = new ByteArrayInputStream(data);
165 try (ObjectInput ois = new FilteredObjectInputStream(bis)) {
166 return (LogEvent) ois.readObject();
167 }
168 }
221169
222170 }
+0
-66
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/mom/kafka/KafkaManagerProducerThreadLeakTest.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
17 package org.apache.logging.log4j.core.appender.mom.kafka;
18
19 import org.apache.logging.log4j.categories.Appenders;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.junit.experimental.categories.Category;
23 import org.junit.jupiter.api.Test;
24
25 import static org.junit.Assert.assertEquals;
26
27 /**
28 * Verifies that restarting the {@link LoggerContext} doesn't cause
29 * {@link KafkaManager} to leak threads.
30 *
31 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-2916">LOG4J2-2916</a>
32 */
33 @Category(Appenders.Kafka.class)
34 @LoggerContextSource("KafkaManagerProducerThreadLeakTest.xml")
35 class KafkaManagerProducerThreadLeakTest {
36
37 @Test
38 void context_restart_shouldnt_leak_producer_threads(final LoggerContext context) {
39
40 // Determine the initial number of threads.
41 final int initialThreadCount = kafkaProducerThreadCount();
42
43 // Perform context restarts.
44 final int contextRestartCount = 3;
45 for (int i = 0; i < contextRestartCount; i++) {
46 context.reconfigure();
47 }
48
49 // Verify the final thread count.
50 final int lastThreadCount = kafkaProducerThreadCount();
51 assertEquals(initialThreadCount, lastThreadCount);
52
53 }
54
55 private static int kafkaProducerThreadCount() {
56 final long threadCount = Thread
57 .getAllStackTraces()
58 .keySet()
59 .stream()
60 .filter(thread -> thread.getName().startsWith("kafka-producer"))
61 .count();
62 return Math.toIntExact(threadCount);
63 }
64
65 }
4040 import org.mockito.ArgumentCaptor;
4141 import org.mockito.Captor;
4242 import org.mockito.Mock;
43 import org.mockito.invocation.InvocationOnMock;
4344 import org.mockito.runners.MockitoJUnitRunner;
45 import org.mockito.stubbing.Answer;
4446
4547 import static org.junit.Assert.*;
4648 import static org.mockito.ArgumentMatchers.anyInt;
6769 @Before
6870 public void setUp() {
6971 given(provider.getConnection()).willReturn(connection);
70 given(connection.createObject()).willAnswer(invocation -> new DefaultNoSqlObject());
71 given(connection.createList(anyInt())).willAnswer(invocation -> new DefaultNoSqlObject[invocation.<Integer>getArgument(0)]);
72 given(connection.createObject()).willAnswer(new Answer<DefaultNoSqlObject>() {
73 @Override
74 public DefaultNoSqlObject answer(final InvocationOnMock invocation) throws Throwable {
75 return new DefaultNoSqlObject();
76 }
77 });
78 given(connection.createList(anyInt())).willAnswer(new Answer<DefaultNoSqlObject[]>() {
79 @Override
80 public DefaultNoSqlObject[] answer(final InvocationOnMock invocation) throws Throwable {
81 return new DefaultNoSqlObject[invocation.<Integer>getArgument(0)];
82 }
83 });
7284 }
7385
7486 @Test
2020 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2121 import org.apache.logging.log4j.core.util.KeyValuePair;
2222 import org.apache.logging.log4j.message.SimpleMessage;
23 import org.junit.jupiter.api.Test;
24
25 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import org.junit.Assert;
24 import org.junit.Test;
2625
2726 /**
2827 * Tests {@link LoggerNameLevelRewritePolicy}.
4443 final LoggerNameLevelRewritePolicy updatePolicy = LoggerNameLevelRewritePolicy.createPolicy(loggerNameRewrite,
4544 rewrite);
4645 LogEvent rewritten = updatePolicy.rewrite(logEvent);
47 assertEquals(Level.DEBUG, rewritten.getLevel());
46 Assert.assertEquals(Level.DEBUG, rewritten.getLevel());
4847 logEvent = Log4jLogEvent.newBuilder().setLoggerName(loggerNameRewrite)
4948 .setLoggerFqcn("LoggerNameLevelRewritePolicyTest.testUpdate()").setLevel(Level.WARN)
5049 .setMessage(new SimpleMessage("Test")).setThrown(new RuntimeException("test")).setThreadName("none")
5150 .setTimeMillis(1).build();
5251 rewritten = updatePolicy.rewrite(logEvent);
53 assertEquals(Level.INFO, rewritten.getLevel());
52 Assert.assertEquals(Level.INFO, rewritten.getLevel());
5453 final String loggerNameReadOnly = "com.nochange";
5554 logEvent = Log4jLogEvent.newBuilder().setLoggerName(loggerNameReadOnly)
5655 .setLoggerFqcn("LoggerNameLevelRewritePolicyTest.testUpdate()").setLevel(Level.INFO)
5756 .setMessage(new SimpleMessage("Test")).setThrown(new RuntimeException("test")).setThreadName("none")
5857 .setTimeMillis(1).build();
5958 rewritten = updatePolicy.rewrite(logEvent);
60 assertEquals(Level.INFO, rewritten.getLevel());
59 Assert.assertEquals(Level.INFO, rewritten.getLevel());
6160 logEvent = Log4jLogEvent.newBuilder().setLoggerName(loggerNameReadOnly)
6261 .setLoggerFqcn("LoggerNameLevelRewritePolicyTest.testUpdate()").setLevel(Level.WARN)
6362 .setMessage(new SimpleMessage("Test")).setThrown(new RuntimeException("test")).setThreadName("none")
6463 .setTimeMillis(1).build();
6564 rewritten = updatePolicy.rewrite(logEvent);
66 assertEquals(Level.WARN, rewritten.getLevel());
65 Assert.assertEquals(Level.WARN, rewritten.getLevel());
6766 }
6867
6968 }
1515 */
1616 package org.apache.logging.log4j.core.appender.rewrite;
1717
18 import static org.apache.logging.log4j.hamcrest.MapMatchers.hasSize;
19 import static org.hamcrest.Matchers.hasEntry;
20 import static org.junit.Assert.assertArrayEquals;
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertThat;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Map;
27
1828 import org.apache.logging.log4j.Level;
1929 import org.apache.logging.log4j.MarkerManager;
2030 import org.apache.logging.log4j.core.LogEvent;
2737 import org.apache.logging.log4j.spi.MutableThreadContextStack;
2838 import org.apache.logging.log4j.spi.ThreadContextStack;
2939 import org.apache.logging.log4j.util.StringMap;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.Test;
32
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.Map;
36
37 import static org.apache.logging.log4j.hamcrest.MapMatchers.hasSize;
38 import static org.hamcrest.MatcherAssert.assertThat;
39 import static org.hamcrest.Matchers.hasEntry;
40 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
41 import static org.junit.jupiter.api.Assertions.assertEquals;
40 import org.junit.BeforeClass;
41 import org.junit.Test;
4242
4343
4444 public class MapRewritePolicyTest {
4747 private static KeyValuePair[] rewrite;
4848 private static LogEvent logEvent0, logEvent1, logEvent2, logEvent3;
4949
50 @BeforeAll
50 @BeforeClass
5151 public static void setupClass() {
5252 stringMap.putValue("test1", "one");
5353 stringMap.putValue("test2", "two");
54 map = stringMap.toMap();
54 map = stringMap.toMap();
5555 logEvent0 = Log4jLogEvent.newBuilder() //
5656 .setLoggerName("test") //
5757 .setContextData(stringMap) //
9292 final MapRewritePolicy addPolicy = MapRewritePolicy.createPolicy("Add", rewrite);
9393 LogEvent rewritten = addPolicy.rewrite(logEvent0);
9494 compareLogEvents(logEvent0, rewritten);
95 assertEquals(logEvent0.getMessage(), rewritten.getMessage(), "Simple log message changed");
95 assertEquals("Simple log message changed", logEvent0.getMessage(), rewritten.getMessage());
9696
9797 rewritten = addPolicy.rewrite(logEvent1);
9898 compareLogEvents(logEvent1, rewritten);
112112 final MapRewritePolicy updatePolicy = MapRewritePolicy.createPolicy("Update", rewrite);
113113 LogEvent rewritten = updatePolicy.rewrite(logEvent0);
114114 compareLogEvents(logEvent0, rewritten);
115 assertEquals(logEvent0.getMessage(), rewritten.getMessage(), "Simple log message changed");
115 assertEquals("Simple log message changed", logEvent0.getMessage(), rewritten.getMessage());
116116
117117 rewritten = updatePolicy.rewrite(logEvent1);
118118 compareLogEvents(logEvent1, rewritten);
132132 final MapRewritePolicy addPolicy = MapRewritePolicy.createPolicy(null, rewrite);
133133 LogEvent rewritten = addPolicy.rewrite(logEvent0);
134134 compareLogEvents(logEvent0, rewritten);
135 assertEquals(logEvent0.getMessage(), rewritten.getMessage(), "Simple log message changed");
135 assertEquals("Simple log message changed", logEvent0.getMessage(), rewritten.getMessage());
136136
137137 rewritten = addPolicy.rewrite(logEvent1);
138138 compareLogEvents(logEvent1, rewritten);
163163 @SuppressWarnings("deprecation")
164164 private void compareLogEvents(final LogEvent orig, final LogEvent changed) {
165165 // Ensure that everything but the Mapped Data is still the same
166 assertEquals(orig.getLoggerName(), changed.getLoggerName(), "LoggerName changed");
167 assertEquals(orig.getMarker(), changed.getMarker(), "Marker changed");
168 assertEquals(orig.getLoggerFqcn(), changed.getLoggerFqcn(), "FQCN changed");
169 assertEquals(orig.getLevel(), changed.getLevel(), "Level changed");
170 assertArrayEquals(
171 orig.getThrown() == null ? null : orig.getThrownProxy().getExtendedStackTrace(),
172 changed.getThrown() == null ? null : changed.getThrownProxy().getExtendedStackTrace(),
173 "Throwable changed");
174 assertEquals(orig.getContextData(), changed.getContextData(), "ContextData changed");
175 assertEquals(orig.getContextStack(), changed.getContextStack(), "ContextStack changed");
176 assertEquals(orig.getThreadName(), changed.getThreadName(), "ThreadName changed");
177 assertEquals(orig.getSource(), changed.getSource(), "Source changed");
178 assertEquals(orig.getTimeMillis(), changed.getTimeMillis(), "Millis changed");
166 assertEquals("LoggerName changed", orig.getLoggerName(), changed.getLoggerName());
167 assertEquals("Marker changed", orig.getMarker(), changed.getMarker());
168 assertEquals("FQCN changed", orig.getLoggerFqcn(), changed.getLoggerFqcn());
169 assertEquals("Level changed", orig.getLevel(), changed.getLevel());
170 assertArrayEquals("Throwable changed",
171 orig.getThrown() == null ? null : orig.getThrownProxy().getExtendedStackTrace(),
172 changed.getThrown() == null ? null : changed.getThrownProxy().getExtendedStackTrace()
173 );
174 assertEquals("ContextMap changed", orig.getContextMap(), changed.getContextMap());
175 assertEquals("ContextData changed", orig.getContextData(), changed.getContextData());
176 assertEquals("ContextStack changed", orig.getContextStack(), changed.getContextStack());
177 assertEquals("ThreadName changed", orig.getThreadName(), changed.getThreadName());
178 assertEquals("Source changed", orig.getSource(), changed.getSource());
179 assertEquals("Millis changed", orig.getTimeMillis(), changed.getTimeMillis());
179180 }
180181 }
1515 */
1616 package org.apache.logging.log4j.core.appender.rewrite;
1717
18 import org.apache.logging.log4j.EventLogger;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.hamcrest.MapMatchers;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.Named;
25 import org.apache.logging.log4j.message.Message;
26 import org.apache.logging.log4j.message.StructuredDataMessage;
27 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.jupiter.api.Test;
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
2922
3023 import java.util.List;
3124 import java.util.Map;
3225
33 import static org.hamcrest.MatcherAssert.assertThat;
34 import static org.hamcrest.Matchers.*;
35 import static org.junit.jupiter.api.Assertions.*;
26 import org.apache.logging.log4j.EventLogger;
27 import org.apache.logging.log4j.LogManager;
28 import org.apache.logging.log4j.Logger;
29 import org.apache.logging.log4j.core.LogEvent;
30 import org.apache.logging.log4j.junit.LoggerContextRule;
31 import org.apache.logging.log4j.message.Message;
32 import org.apache.logging.log4j.message.StructuredDataMessage;
33 import org.apache.logging.log4j.test.appender.ListAppender;
34 import org.junit.After;
35 import org.junit.Before;
36 import org.junit.ClassRule;
37 import org.junit.Test;
3638
37 @LoggerContextSource("log4j-rewrite.xml")
39 /**
40 *
41 */
3842 public class RewriteAppenderTest {
39 private final ListAppender app;
40 private final ListAppender app2;
43 private ListAppender app;
44 private ListAppender app2;
4145
42 public RewriteAppenderTest(@Named("List") final ListAppender app, @Named("List2") final ListAppender app2) {
43 this.app = app.clear();
44 this.app2 = app2.clear();
46 @ClassRule
47 public static LoggerContextRule init = new LoggerContextRule("log4j-rewrite.xml");
48
49 @Before
50 public void setUp() throws Exception {
51 app = init.getListAppender("List");
52 app2 = init.getListAppender("List2");
53 }
54
55 @After
56 public void tearDown() throws Exception {
57 if (app != null) {
58 app.clear();
59 }
60 if (app2 != null) {
61 app2.clear();
62 }
4563 }
4664
4765 @Test
5169 msg.put("Key2", "Value2");
5270 EventLogger.logEvent(msg);
5371 final List<LogEvent> list = app.getEvents();
54 assertThat(list, hasSize(1));
72 assertNotNull("No events generated", list);
73 assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
5574 final LogEvent event = list.get(0);
5675 final Message m = event.getMessage();
57 assertThat(m, instanceOf(StructuredDataMessage.class));
76 assertTrue("Message is not a StringMapMessage: " + m.getClass(), m instanceof StructuredDataMessage);
5877 final StructuredDataMessage message = (StructuredDataMessage) m;
5978 final Map<String, String> map = message.getData();
60 assertNotNull(map, "No Map");
61 assertThat(map, MapMatchers.hasSize(3));
79 assertNotNull("No Map", map);
80 assertTrue("Incorrect number of map entries, expected 3 got " + map.size(), map.size() == 3);
6281 final String value = map.get("Key1");
6382 assertEquals("Apache", value);
6483 }
6584
6685
6786 @Test
68 public void testProperties(final LoggerContext context) {
69 final Logger logger = context.getLogger(RewriteAppenderTest.class);
87 public void testProperties() {
88 final Logger logger = LogManager.getLogger(RewriteAppenderTest.class);
7089 logger.debug("Test properties rewrite");
7190 final List<String> list = app2.getMessages();
72 assertThat(list, hasSize(1));
73 assertThat(list.get(0), not(containsString("{user.dir}")));
74 assertNotNull(list, "No events generated");
75 assertEquals(list.size(), 1, "Incorrect number of events. Expected 1, got " + list.size());
76 assertFalse(list.get(0).contains("{user."), "Did not resolve user name");
91 assertNotNull("No events generated", list);
92 assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
93 assertFalse("Did not resolve user name", list.get(0).contains("{user.dir}"));
7794 }
7895
7996
8097 @Test
81 public void testFilter(final LoggerContext context) {
98 public void testFilter() {
8299 StructuredDataMessage msg = new StructuredDataMessage("Test", "This is a test", "Service");
83100 msg.put("Key1", "Value2");
84101 msg.put("Key2", "Value1");
85 final Logger logger = context.getLogger("org.apache.logging.log4j.core.Logging");
102 final Logger logger = LogManager.getLogger("org.apache.logging.log4j.core.Logging");
86103 logger.debug(msg);
87104 msg = new StructuredDataMessage("Test", "This is a test", "Service");
88105 msg.put("Key1", "Value1");
89106 msg.put("Key2", "Value2");
90107 logger.trace(msg);
91108
92 assertThat(app.getEvents(), empty());
109 final List<LogEvent> list = app.getEvents();
110 assertTrue("Events were generated", list == null || list.isEmpty());
93111 }
94112 }
2121 import org.apache.logging.log4j.core.config.Configurator;
2222 import org.apache.logging.log4j.core.config.NullConfiguration;
2323 import org.apache.logging.log4j.core.layout.PatternLayout;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import org.junit.Assert;
25 import org.junit.Before;
26 import org.junit.Test;
2827
2928 public class CronTriggeringPolicyTest {
3029
3635 //@Rule
3736 //public CleanFiles cleanFiles = new CleanFiles("testcmd1.log", "testcmd2.log", "testcmd3.log");
3837
39 @BeforeEach
38 @Before
4039 public void before() {
4140 configuration = new NullConfiguration();
4241 }
5958 .setConfiguration(configuration)
6059 .build();
6160 // @formatter:on
62 assertNotNull(raf);
61 Assert.assertNotNull(raf);
6362 }
6463
6564 /**
1919 import java.util.Map;
2020
2121 import org.apache.logging.log4j.core.pattern.NotANumber;
22 import org.junit.jupiter.api.Test;
22 import org.junit.Test;
2323
24 import static org.junit.jupiter.api.Assertions.*;
24 import static org.junit.Assert.*;
2525
2626 /**
2727 * Test getEligibleFiles method.
3333 final String path = "target/test-classes/rolloverPath/log4j.txt.20170112_09-" + NotANumber.VALUE + ".gz";
3434 final TestRolloverStrategy strategy = new TestRolloverStrategy();
3535 final Map<Integer, Path> files = strategy.findFilesInPath(path);
36 assertTrue(files.size() > 0, "No files found");
37 assertEquals(30, files.size(), "Incorrect number of files found. Should be 30, was " + files.size());
36 assertTrue("No files found", files.size() > 0);
37 assertTrue("Incorrect number of files found. Should be 30, was " + files.size(), files.size() == 30);
3838 }
3939
40 @Test
41 public void runTestWithPlusCharacter() throws Exception {
42 final String path = "target/test-classes/rolloverPath/log4j.20211028T194500+0200." + NotANumber.VALUE + ".log.gz";
43 final TestRolloverStrategy strategy = new TestRolloverStrategy();
44 final Map<Integer, Path> files = strategy.findFilesWithPlusInPath(path);
45 assertTrue(files.size() > 0, "No files found");
46 assertEquals(30, files.size(), "Incorrect number of files found. Should be 30, was " + files.size());
47 }
48
49 private static class TestRolloverStrategy extends AbstractRolloverStrategy {
40 private class TestRolloverStrategy extends AbstractRolloverStrategy {
5041
5142 public TestRolloverStrategy() {
5243 super(null);
6051 public Map<Integer, Path> findFilesInPath(final String path) {
6152 return getEligibleFiles(path, "log4j.txt.%d{yyyyMMdd}-%i.gz");
6253 }
63
64 public Map<Integer, Path> findFilesWithPlusInPath(final String path) {
65 // timezone might expand to "+0200", because of '+' we have to be careful when working with regex
66 return getEligibleFiles(path, "log4j.txt.%d{yyyyMMdd'T'HHmmssZ}.%i.log.gz");
67 }
6854 }
6955 }
1515 */
1616 package org.apache.logging.log4j.core.appender.rolling;
1717
18 import org.junit.jupiter.api.Test;
19 import org.junit.jupiter.params.ParameterizedTest;
20 import org.junit.jupiter.params.provider.CsvSource;
21
22 import static org.junit.jupiter.api.Assertions.*;
18 import org.junit.Test;
19 import static org.junit.Assert.*;
2320
2421 /**
2522 * Tests {@link FileSize}.
2926 private final static long EXPECTED = 10 * 1024;
3027
3128 @Test
32 public void testFileSize() {
29 public void testFileSize() throws Exception {
3330 long value = FileSize.parse("10KB", 0);
34 assertEquals(EXPECTED, value, "unexpected value " + value);
31 assertTrue("unexpected value " + value, value == EXPECTED);
3532 value = FileSize.parse("10 KB", 0);
36 assertEquals(EXPECTED, value, "unexpected value " + value);
37 }
38
39 @ParameterizedTest(name = "[{index}] \"{0}\" -> {1}")
40 @CsvSource(delimiter = ':', value = {
41 "10:10",
42 "10KB:10240",
43 "10 KB:10240",
44 "10 kb:10240",
45 " 10 kb :10240",
46 "0.1 MB:104857",
47 "1 MB:1048576",
48 "10 MB:10485760",
49 "10.45 MB:10957619",
50 "10.75 MB:11272192",
51 "1,000 KB:1024000",
52 "1 GB:1073741824",
53 "0.51 GB:547608330"
54 })
55 void testValidFileSizes(String expr, long expected) {
56 assertEquals(expected, FileSize.parse(expr, 0));
33 assertTrue("unexpected value " + value, value == EXPECTED);
5734 }
5835 }
1515 */
1616 package org.apache.logging.log4j.core.appender.rolling;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertTrue;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.File;
23 import java.io.InputStream;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.nio.file.StandardCopyOption;
28 import java.nio.file.attribute.BasicFileAttributeView;
29 import java.nio.file.attribute.FileTime;
30 import java.util.Arrays;
31
1832 import org.apache.logging.log4j.core.config.Configuration;
1933 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2034 import org.apache.logging.log4j.core.layout.PatternLayout;
2135 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
22 import org.junit.jupiter.api.Test;
23 import org.junit.jupiter.api.io.TempDir;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.InputStream;
27 import java.nio.charset.StandardCharsets;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.nio.file.StandardCopyOption;
31 import java.nio.file.attribute.BasicFileAttributeView;
32 import java.nio.file.attribute.FileTime;
33 import java.time.Duration;
34 import java.time.Instant;
35 import java.util.stream.Collectors;
36 import java.util.stream.Stream;
37
38 import static org.junit.jupiter.api.Assertions.assertEquals;
39 import static org.junit.jupiter.api.Assertions.assertTrue;
36 import org.apache.logging.log4j.junit.CleanFolders;
37 import org.junit.Assert;
38 import org.junit.Rule;
39 import org.junit.Test;
4040
4141 /**
4242 * Tests {@link OnStartupTriggeringPolicy}.
4343 */
44 //@Ignore
4445 public class OnStartupTriggeringPolicyTest {
4546
46 private static final String TARGET_PATTERN = "/test1-%d{MM-dd-yyyy}-%i.log";
47 private static final String TARGET_FOLDER = "target/rollOnStartup";
48 private static final String TARGET_FILE = TARGET_FOLDER + "/testfile";
49 private static final String TARGET_PATTERN = TARGET_FOLDER + "/test1-%d{MM-dd-yyyy}-%i.log";
50 private static final String ROLLED_FILE_PREFIX = TARGET_FOLDER + "/test1-";
51 private static final String ROLLED_FILE_SUFFIX = "-1.log";
4752 private static final String TEST_DATA = "Hello world!";
4853 private static final FastDateFormat formatter = FastDateFormat.getInstance("MM-dd-yyyy");
4954
50 @TempDir
51 Path tempDir;
55 @Rule
56 public CleanFolders rule = new CleanFolders(TARGET_FOLDER);
5257
5358 @Test
5459 public void testPolicy() throws Exception {
60 //System.setProperty("log4j2.debug", "true");
61 //System.setProperty("log4j2.StatusLogger.level", "trace");
5562 final Configuration configuration = new DefaultConfiguration();
56 final Path target = tempDir.resolve("testfile");
57 final long timeStamp = Instant.now().minus(Duration.ofDays(1)).toEpochMilli();
63 final Path target = Paths.get(TARGET_FILE);
64 Assert.assertFalse(Files.exists(target));
65 target.toFile().getParentFile().mkdirs();
66 final long timeStamp = System.currentTimeMillis() - (1000 * 60 * 60 * 24);
5867 final String expectedDate = formatter.format(timeStamp);
59 final Path rolled = tempDir.resolve("test1-" + expectedDate + "-1.log");
68 final String rolledFileName = ROLLED_FILE_PREFIX + expectedDate + ROLLED_FILE_SUFFIX;
69 final Path rolled = Paths.get(rolledFileName);
6070 final long copied;
61 try (final InputStream is = new ByteArrayInputStream(TEST_DATA.getBytes(StandardCharsets.UTF_8))) {
71 try (final InputStream is = new ByteArrayInputStream(TEST_DATA.getBytes("UTF-8"))) {
6272 copied = Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
6373 }
6474 final long size = Files.size(target);
6878 final FileTime fileTime = FileTime.fromMillis(timeStamp);
6979 final BasicFileAttributeView attrs = Files.getFileAttributeView(target, BasicFileAttributeView.class);
7080 attrs.setTimes(fileTime, fileTime, fileTime);
81
7182 final PatternLayout layout = PatternLayout.newBuilder().withPattern("%msg").withConfiguration(configuration)
7283 .build();
73 final RolloverStrategy strategy = DefaultRolloverStrategy.newBuilder().withCompressionLevelStr("0")
74 .withStopCustomActionsOnError(true).withConfig(configuration).build();
84 final RolloverStrategy strategy = DefaultRolloverStrategy.createStrategy(null, null, null, "0", null, true,
85 configuration);
7586 final OnStartupTriggeringPolicy policy = OnStartupTriggeringPolicy.createPolicy(1);
76
77 try (final RollingFileManager manager = RollingFileManager.getFileManager(target.toString(), tempDir.toString() + TARGET_PATTERN, true,
78 false, policy, strategy, null, layout, 8192, true, false, null, null, null, configuration)) {
87 try (final RollingFileManager manager = RollingFileManager.getFileManager(TARGET_FILE, TARGET_PATTERN, true, false,
88 policy, strategy, null, layout, 8192, true, false, null, null, null, configuration)) {
7989 manager.initialize();
80 final String files;
81 try (Stream<Path> contents = Files.list(tempDir)) {
82 files = contents.map(Path::toString).collect(Collectors.joining(", ", "[", "]"));
83 }
84 assertTrue(Files.exists(target), target.toString() + ", files = " + files);
85 assertEquals(0, Files.size(target), target.toString());
86 assertTrue(Files.exists(rolled), "Missing: " + rolled.toString() + ", files on disk = " + files);
87 assertEquals(size, Files.size(rolled), rolled.toString());
90 final String files = Arrays.toString(new File(TARGET_FOLDER).listFiles());
91 assertTrue(target.toString() + ", files = " + files, Files.exists(target));
92 assertEquals(target.toString(), 0, Files.size(target));
93 assertTrue("Missing: " + rolled.toString() + ", files on disk = " + files, Files.exists(rolled));
94 assertEquals(rolled.toString(), size, Files.size(rolled));
8895 }
8996 }
9097
2121 import java.util.Date;
2222 import java.util.Locale;
2323
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.parallel.ResourceAccessMode;
26 import org.junit.jupiter.api.parallel.ResourceLock;
27 import org.junit.jupiter.api.parallel.Resources;
28
29 import static org.junit.jupiter.api.Assertions.*;
24 import org.junit.Test;
25
26 import static org.junit.Assert.*;
3027
3128 /**
3229 * Tests the PatternProcessor class.
3835 }
3936
4037 @Test
41 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
4238 public void testDontInterpretBackslashAsEscape() {
4339 final PatternProcessor pp = new PatternProcessor("c:\\test\\new/app-%d{HH-mm-ss}.log");
4440 final Calendar cal = Calendar.getInstance();
4541 cal.set(Calendar.HOUR_OF_DAY, 16);
46 cal.set(Calendar.MINUTE, 2);
42 cal.set(Calendar.MINUTE, 02);
4743 cal.set(Calendar.SECOND, 15);
4844
4945 final StringBuilder buf = new StringBuilder();
5248 }
5349
5450 @Test
55 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
5651 public void testGetNextTimeHourlyReturnsFirstMinuteOfNextHour() {
5752 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM-dd-HH}.log.gz");
5853 final Calendar initial = Calendar.getInstance();
6156
6257 // expect Wed, March 4, 2014, 11:00
6358 final Calendar expected = Calendar.getInstance();
64 expected.set(2014, Calendar.MARCH, 4, 11, 0, 0);
65 expected.set(Calendar.MILLISECOND, 0);
66 assertEquals(format(expected.getTimeInMillis()), format(actual));
67 }
68
69 @Test
70 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
59 expected.set(2014, Calendar.MARCH, 4, 11, 00, 00);
60 expected.set(Calendar.MILLISECOND, 0);
61 assertEquals(format(expected.getTimeInMillis()), format(actual));
62 }
63
64 @Test
7165 public void testGetNextTimeHourlyReturnsFirstMinuteOfNextHour2() {
7266 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM-dd-HH}.log.gz");
7367 final Calendar initial = Calendar.getInstance();
7670
7771 // expect Wed, March 5, 2014, 00:00
7872 final Calendar expected = Calendar.getInstance();
79 expected.set(2014, Calendar.MARCH, 5, 0, 0, 0);
80 expected.set(Calendar.MILLISECOND, 0);
81 assertEquals(format(expected.getTimeInMillis()), format(actual));
82 }
83
84 @Test
85 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
73 expected.set(2014, Calendar.MARCH, 5, 00, 00, 00);
74 expected.set(Calendar.MILLISECOND, 0);
75 assertEquals(format(expected.getTimeInMillis()), format(actual));
76 }
77
78 @Test
8679 public void testGetNextTimeHourlyReturnsFirstMinuteOfNextYear() {
8780 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM-dd-HH}.log.gz");
8881 final Calendar initial = Calendar.getInstance();
9689 }
9790
9891 @Test
99 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
10092 public void testGetNextTimeMillisecondlyReturnsNextMillisec() {
10193 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM-dd-HH-mm-ss.SSS}.log.gz");
10294 final Calendar initial = Calendar.getInstance();
113105 }
114106
115107 @Test
116 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
117108 public void testGetNextTimeMinutelyReturnsFirstSecondOfNextMinute() {
118109 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM-dd-HH-mm}.log.gz");
119110 final Calendar initial = Calendar.getInstance();
124115
125116 // expect Tue, March 4, 2014, 10:32
126117 final Calendar expected = Calendar.getInstance();
127 expected.set(2014, Calendar.MARCH, 4, 10, 32, 0);
128 expected.set(Calendar.MILLISECOND, 0);
129 assertEquals(format(expected.getTimeInMillis()), format(actual));
130 }
131
132 @Test
133 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
118 expected.set(2014, Calendar.MARCH, 4, 10, 32, 00);
119 expected.set(Calendar.MILLISECOND, 0);
120 assertEquals(format(expected.getTimeInMillis()), format(actual));
121 }
122
123 @Test
134124 public void testGetNextTimeMonthlyReturnsFirstDayOfNextMonth() {
135125 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM}.log.gz");
136126 final Calendar initial = Calendar.getInstance();
139129
140130 // We expect 1st day of next month
141131 final Calendar expected = Calendar.getInstance();
142 expected.set(2014, Calendar.NOVEMBER, 1, 0, 0, 0);
143 expected.set(Calendar.MILLISECOND, 0);
144 assertEquals(format(expected.getTimeInMillis()), format(actual));
145 }
146
147 @Test
148 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
132 expected.set(2014, Calendar.NOVEMBER, 1, 00, 00, 00);
133 expected.set(Calendar.MILLISECOND, 0);
134 assertEquals(format(expected.getTimeInMillis()), format(actual));
135 }
136
137 @Test
149138 public void testGetNextTimeMonthlyReturnsFirstDayOfNextMonth2() {
150139 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM}.log.gz");
151140 final Calendar initial = Calendar.getInstance();
154143
155144 // Expect 1st of next month: 2014 Feb 1st
156145 final Calendar expected = Calendar.getInstance();
157 expected.set(2014, Calendar.FEBRUARY, 1, 0, 0, 0);
158 expected.set(Calendar.MILLISECOND, 0);
159 assertEquals(format(expected.getTimeInMillis()), format(actual));
160 }
161
162 @Test
163 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
146 expected.set(2014, Calendar.FEBRUARY, 1, 00, 00, 00);
147 expected.set(Calendar.MILLISECOND, 0);
148 assertEquals(format(expected.getTimeInMillis()), format(actual));
149 }
150
151 @Test
164152 public void testGetNextTimeMonthlyReturnsFirstDayOfNextMonth3() {
165153 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM}.log.gz");
166154 final Calendar initial = Calendar.getInstance();
169157
170158 // Expect 1st of next month: 2015 Jan 1st
171159 final Calendar expected = Calendar.getInstance();
172 expected.set(2015, Calendar.JANUARY, 1, 0, 0, 0);
173 expected.set(Calendar.MILLISECOND, 0);
174 assertEquals(format(expected.getTimeInMillis()), format(actual));
175 }
176
177 @Test
178 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
160 expected.set(2015, Calendar.JANUARY, 1, 00, 00, 00);
161 expected.set(Calendar.MILLISECOND, 0);
162 assertEquals(format(expected.getTimeInMillis()), format(actual));
163 }
164
165 @Test
179166 public void testGetNextTimeMonthlyReturnsFirstDayOfNextYear() {
180167 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM}.log.gz");
181168 final Calendar initial = Calendar.getInstance();
184171
185172 // We expect 1st day of next month
186173 final Calendar expected = Calendar.getInstance();
187 expected.set(2016, Calendar.JANUARY, 1, 0, 0, 0);
188 expected.set(Calendar.MILLISECOND, 0);
189 assertEquals(format(expected.getTimeInMillis()), format(actual));
190 }
191
192 @Test
193 @ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
174 expected.set(2016, Calendar.JANUARY, 1, 00, 00, 00);
175 expected.set(Calendar.MILLISECOND, 0);
176 assertEquals(format(expected.getTimeInMillis()), format(actual));
177 }
178
179 @Test
194180 public void testGetNextTimeSecondlyReturnsFirstMillisecOfNextSecond() {
195181 final PatternProcessor pp = new PatternProcessor("logs/app-%d{yyyy-MM-dd-HH-mm-ss}.log.gz");
196182 final Calendar initial = Calendar.getInstance();
207193 }
208194
209195 @Test
210 @ResourceLock(Resources.LOCALE)
211196 public void testGetNextTimeWeeklyReturnsFirstDayOfNextWeek_FRANCE() {
212197 final Locale old = Locale.getDefault();
213198 Locale.setDefault(Locale.FRANCE); // force 1st day of the week to be Monday
220205
221206 // expect Monday, March 10, 2014
222207 final Calendar expected = Calendar.getInstance();
223 expected.set(2014, Calendar.MARCH, 10, 0, 0, 0);
208 expected.set(2014, Calendar.MARCH, 10, 00, 00, 00);
224209 expected.set(Calendar.MILLISECOND, 0);
225210 assertEquals(format(expected.getTimeInMillis()), format(actual));
226211 } finally {
229214 }
230215
231216 @Test
232 @ResourceLock(Resources.LOCALE)
233217 public void testGetNextTimeWeeklyReturnsFirstDayOfNextWeek_US() {
234218 final Locale old = Locale.getDefault();
235219 Locale.setDefault(Locale.US); // force 1st day of the week to be Sunday
242226
243227 // expect Sunday, March 9, 2014
244228 final Calendar expected = Calendar.getInstance();
245 expected.set(2014, Calendar.MARCH, 9, 0, 0, 0);
229 expected.set(2014, Calendar.MARCH, 9, 00, 00, 00);
246230 expected.set(Calendar.MILLISECOND, 0);
247231 assertEquals(format(expected.getTimeInMillis()), format(actual));
248232 } finally {
254238 * Tests https://issues.apache.org/jira/browse/LOG4J2-1232
255239 */
256240 @Test
257 @ResourceLock(Resources.LOCALE)
258241 public void testGetNextTimeWeeklyReturnsFirstWeekInYear_US() {
259242 final Locale old = Locale.getDefault();
260243 Locale.setDefault(Locale.US); // force 1st day of the week to be Sunday
261244 try {
262245 final PatternProcessor pp = new PatternProcessor("logs/market_data_msg.log-%d{yyyy-MM-'W'W}");
263246 final Calendar initial = Calendar.getInstance();
264 initial.set(2015, Calendar.DECEMBER, 28, 0, 0, 0); // Monday, December 28, 2015
247 initial.set(2015, Calendar.DECEMBER, 28, 00, 00, 00); // Monday, December 28, 2015
265248 final long actual = pp.getNextTime(initial.getTimeInMillis(), 1, false);
266249
267250 // expect Sunday January 3, 2016
268251 final Calendar expected = Calendar.getInstance();
269 expected.set(2016, Calendar.JANUARY, 3, 0, 0, 0);
252 expected.set(2016, Calendar.JANUARY, 3, 00, 00, 00);
270253 expected.set(Calendar.MILLISECOND, 0);
271254 assertEquals(format(expected.getTimeInMillis()), format(actual));
272255 } finally {
+0
-101
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderCountTest.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.logging.log4j.core.appender.rolling;
17
18 import org.apache.commons.lang3.RandomStringUtils;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.junit.LoggerContextRule;
21 import org.junit.AfterClass;
22 import org.junit.Before;
23 import org.junit.BeforeClass;
24 import org.junit.Rule;
25 import org.junit.Test;
26
27 import java.io.File;
28 import java.nio.file.DirectoryStream;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.nio.file.StandardCopyOption;
33 import java.util.Objects;
34
35 import static org.junit.Assert.assertEquals;
36
37 /**
38 * Validate rolling with a file pattern that contains leading zeros for the increment.
39 */
40 public class RollingAppenderCountTest {
41
42 private static final String SOURCE = "src/test/resources/__files";
43 private static final String DIR = "target/rolling_count";
44 private static final String CONFIG = "log4j-rolling-count.xml";
45 private static final String FILENAME = "onStartup.log";
46 private static final String TARGET = "rolling_test.log.";
47
48 private Logger logger;
49
50 @Rule
51 public LoggerContextRule loggerContextRule;
52
53 public RollingAppenderCountTest() {
54 this.loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
55 }
56
57 @Before
58 public void setUp() throws Exception {
59 this.logger = this.loggerContextRule.getLogger("LogTest");
60 }
61
62 @BeforeClass
63 public static void beforeClass() throws Exception {
64 if (Files.exists(Paths.get(DIR))) {
65 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(DIR))) {
66 for (final Path path : directoryStream) {
67 Files.delete(path);
68 }
69 Files.delete(Paths.get(DIR));
70 }
71 }
72 File dir = new File(DIR);
73 if (!dir.exists()) {
74 Files.createDirectory(new File(DIR).toPath());
75 }
76 Path target = Paths.get(DIR, TARGET + System.currentTimeMillis());
77 Files.copy(Paths.get(SOURCE, FILENAME), target, StandardCopyOption.COPY_ATTRIBUTES);
78 }
79
80 @AfterClass
81 public static void afterClass() throws Exception {
82 int count = Objects.requireNonNull(new File(DIR).listFiles()).length;
83 assertEquals("Expected 17 files, got " + count, 17, count);
84 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(DIR))) {
85 for (final Path path : directoryStream) {
86 Files.delete(path);
87 }
88 }
89 Files.delete(Paths.get(DIR));
90 }
91
92 @Test
93 public void testLog() throws Exception {
94 for (long i = 0; i < 60; ++i) {
95 logger.info("Sequence: " + i);
96 logger.debug(RandomStringUtils.randomAscii(128, 512));
97 Thread.sleep(250);
98 }
99 }
100 }
3434 import static org.junit.Assert.assertNotNull;
3535 import static org.junit.Assert.assertThat;
3636 import static org.junit.Assert.assertTrue;
37 import static org.junit.Assert.fail;
3738
3839 /**
3940 * LOG4J2-1804.
+0
-107
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderCronOnStartupTest.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.logging.log4j.core.appender.rolling;
17
18 import java.io.File;
19 import java.io.FileOutputStream;
20 import java.io.PrintStream;
21 import java.nio.file.Files;
22 import java.time.LocalDate;
23 import java.time.format.DateTimeFormatter;
24 import java.util.Arrays;
25 import java.util.List;
26
27 import org.apache.logging.log4j.Logger;
28 import org.apache.logging.log4j.core.LoggerContext;
29 import org.apache.logging.log4j.core.config.Configurator;
30 import org.junit.Test;
31 import org.junit.jupiter.api.AfterAll;
32 import org.junit.jupiter.api.AfterEach;
33
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertNotNull;
36 import static org.junit.Assert.assertTrue;
37
38 /**
39 *
40 */
41 public class RollingAppenderCronOnStartupTest {
42
43 private static final String CONFIG = "log4j-rolling-cron-onStartup.xml";
44 private static final String DIR = "target/rolling-cron-onStartup";
45 private static final String FILE = "target/rolling-cron-onStartup/rollingtest.log";
46 private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
47
48 private LoggerContext context;
49
50 @AfterAll
51 public static void after() {
52 File dir = new File(DIR);
53 if (dir.exists()) {
54 cleanDir(dir);
55 dir.delete();
56 }
57
58 }
59
60 @AfterEach
61 public void afterEach() {
62 if (context != null) {
63 context.stop();
64 }
65 }
66
67 @Test
68 public void testAppender() throws Exception {
69 final File dir = new File(DIR);
70 if (dir.exists()) {
71 cleanDir(dir);
72 } else {
73 dir.mkdirs();
74 }
75 final File file = new File(FILE);
76 String today = formatter.format(LocalDate.now());
77 final File rolled = new File(DIR + "/test1-" + today + ".log");
78 PrintStream ps = new PrintStream(new FileOutputStream(file));
79 ps.println("This is a line2");
80 ps.close();
81 ps = new PrintStream(new FileOutputStream(rolled));
82 ps.println("This is a line 1");
83 ps.close();
84 assertTrue("Log file does not exist", file.exists());
85 assertTrue("Log file does not exist", rolled.exists());
86 LoggerContext lc = Configurator.initialize("Test", CONFIG);
87 final Logger logger = lc.getLogger(RollingAppenderCronOnStartupTest.class);
88 logger.info("This is line 3");
89 File[] files = dir.listFiles();
90 assertNotNull("No files", files);
91 assertEquals("Unexpected number of files. Expected 2 but found " + files.length, 2,
92 files.length);
93 List<String> lines = Files.readAllLines(file.toPath());
94 assertEquals("Unexpected number of lines. Expected 2: Actual: " + lines.size(), 2, lines.size());
95 lines = Files.readAllLines(rolled.toPath());
96 assertEquals("Unexpected number of lines. Expected 1: Actual: " + lines.size(), 1, lines.size());
97 }
98
99 private static void cleanDir(File dir) {
100 File[] files = dir.listFiles();
101 if (files != null) {
102 Arrays.stream(files).forEach(File::delete);
103 }
104 }
105
106 }
+0
-118
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderDirectWriteWithHtmlLayoutTest.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.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.core.appender.RollingFileAppender;
19 import org.apache.logging.log4j.core.config.Configuration;
20 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
21 import org.apache.logging.log4j.core.layout.HtmlLayout;
22 import org.apache.logging.log4j.core.util.IOUtils;
23 import org.apache.logging.log4j.junit.LoggerContextRule;
24 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.hamcrest.Matchers;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.junit.rules.RuleChain;
29
30 import java.io.*;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 import static org.apache.logging.log4j.hamcrest.Descriptors.that;
35 import static org.apache.logging.log4j.hamcrest.FileMatchers.hasName;
36 import static org.hamcrest.Matchers.endsWith;
37 import static org.hamcrest.Matchers.hasItemInArray;
38 import static org.junit.Assert.*;
39
40 /**
41 * Tests for LOG4J2-2760
42 */
43 public class RollingAppenderDirectWriteWithHtmlLayoutTest {
44
45 private static final String DIR = "target/rolling-direct-htmlLayout";
46
47 public static LoggerContextRule loggerContextRule = new LoggerContextRule();
48
49 @Rule
50 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
51
52
53 @Test
54 public void testRollingFileAppenderWithHtmlLayout() throws Exception {
55 checkAppenderWithHtmlLayout(true);
56 }
57
58 @Test
59 public void testRollingFileAppenderWithHtmlLayoutNoAppend() throws Exception {
60 checkAppenderWithHtmlLayout(false);
61 }
62
63 private void checkAppenderWithHtmlLayout(boolean append) throws InterruptedException, IOException {
64 String prefix = "testHtml_" + (append ? "append_" : "noAppend_");
65 Configuration config = loggerContextRule.getConfiguration();
66 RollingFileAppender appender = RollingFileAppender.newBuilder()
67 .setName("RollingHtml")
68 .withFilePattern(DIR + "/" + prefix + "_-%d{MM-dd-yy-HH-mm}-%i.html")
69 .withPolicy(new SizeBasedTriggeringPolicy(500))
70 .withStrategy(DirectWriteRolloverStrategy.newBuilder().withConfig(config).build())
71 .setLayout(HtmlLayout.createDefaultLayout())
72 .withAppend(append)
73 .build();
74 boolean stopped = false;
75 try {
76 int count = 100;
77 for (int i = 0; i < count; ++i) {
78 appender.append(Log4jLogEvent.newBuilder()
79 .setMessage(new SimpleMessage("This is test message number " + i))
80 .build()
81 );
82 }
83 appender.getManager().flush();
84 appender.stop();
85 stopped = true;
86 Thread.sleep(50);
87 final File dir = new File(DIR);
88 assertTrue("Directory not created", dir.exists());
89 final File[] files = dir.listFiles();
90 assertNotNull(files);
91 assertThat(files, hasItemInArray(that(hasName(that(endsWith(".html"))))));
92
93 int foundEvents = 0;
94 final Pattern eventMatcher = Pattern.compile("title=\"Message\"");
95 for (File file : files) {
96 if (!file.getName().startsWith(prefix)) {
97 continue;
98 }
99 try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
100 String data = IOUtils.toString(reader).trim();
101 // check that every file starts with the header
102 assertThat("header in file " + file, data, Matchers.startsWith("<!DOCTYPE"));
103 assertThat("footer in file " + file, data, Matchers.endsWith("</html>"));
104 final Matcher matcher = eventMatcher.matcher(data);
105 while (matcher.find()) {
106 foundEvents++;
107 }
108 }
109 }
110 assertEquals("Incorrect number of events read.", count, foundEvents);
111 } finally {
112 if (!stopped) {
113 appender.stop();
114 }
115 }
116 }
117 }
2424 import java.nio.file.StandardCopyOption;
2525 import java.nio.file.attribute.BasicFileAttributeView;
2626 import java.nio.file.attribute.FileTime;
27 import java.util.Arrays;
28 import java.util.Collection;
29
2730 import org.apache.logging.log4j.LogManager;
2831 import org.apache.logging.log4j.Logger;
2932 import org.apache.logging.log4j.core.config.Configuration;
3033 import org.apache.logging.log4j.core.config.DefaultConfiguration;
3134 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
35 import org.apache.logging.log4j.junit.LoggerContextRule;
3236 import org.junit.AfterClass;
3337 import org.junit.Assert;
38 import org.junit.Before;
3439 import org.junit.BeforeClass;
40 import org.junit.Rule;
3541 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.junit.runners.Parameterized;
44
3645 import static org.junit.Assert.assertEquals;
3746 import static org.junit.Assert.assertTrue;
3847
+0
-109
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderOnStartupDirectTest.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.logging.log4j.core.appender.rolling;
17
18 import java.io.File;
19 import java.nio.file.DirectoryStream;
20 import java.nio.file.Files;
21 import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import java.nio.file.StandardCopyOption;
24 import java.nio.file.attribute.BasicFileAttributeView;
25 import java.nio.file.attribute.FileTime;
26 import java.time.Instant;
27 import java.time.LocalDate;
28 import java.time.format.DateTimeFormatter;
29 import java.time.temporal.ChronoUnit;
30 import java.util.List;
31
32 import org.apache.logging.log4j.Logger;
33 import org.apache.logging.log4j.core.LoggerContext;
34 import org.apache.logging.log4j.core.config.Configurator;
35 import org.junit.AfterClass;
36 import org.junit.BeforeClass;
37 import org.junit.Test;
38
39 import static org.junit.Assert.assertEquals;
40 import static org.junit.Assert.assertTrue;
41
42 /**
43 *
44 */
45 public class RollingAppenderOnStartupDirectTest {
46
47 private static final String SOURCE = "src/test/resources/__files";
48 private static final String DIR = "target/onStartup";
49 private static final String CONFIG = "log4j-rollOnStartupDirect.xml";
50 private static final String FILENAME = "onStartup.log";
51 private static final String PREFIX = "This is test message number ";
52 private static final String ROLLED = "onStartup-";
53 private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy");
54
55 private static LoggerContext loggerContext;
56
57 @BeforeClass
58 public static void beforeClass() throws Exception {
59 if (Files.exists(Paths.get("target/onStartup"))) {
60 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(DIR))) {
61 for (final Path path : directoryStream) {
62 Files.delete(path);
63 }
64 Files.delete(Paths.get(DIR));
65 }
66 }
67 Files.createDirectory(new File(DIR).toPath());
68 String fileName = ROLLED + formatter.format(LocalDate.now()) + "-1.log";
69 Path target = Paths.get(DIR, fileName);
70 Files.copy(Paths.get(SOURCE, FILENAME), target, StandardCopyOption.COPY_ATTRIBUTES);
71 FileTime newTime = FileTime.from(Instant.now().minus(1, ChronoUnit.DAYS));
72 Files.getFileAttributeView(target, BasicFileAttributeView.class).setTimes(newTime, newTime, newTime);
73 }
74
75 @Test
76 public void performTest() throws Exception {
77 loggerContext = Configurator.initialize("Test", CONFIG);
78 final Logger logger = loggerContext.getLogger(RollingAppenderOnStartupDirectTest.class);
79 for (int i = 3; i < 10; ++i) {
80 logger.debug(PREFIX + i);
81 }
82 int fileCount = 0;
83 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(DIR))) {
84 for (final Path path : directoryStream) {
85 ++fileCount;
86 if (path.toFile().getName().startsWith(ROLLED)) {
87 List<String> lines = Files.readAllLines(path);
88 assertTrue("No messages in " + path.toFile().getName(), lines.size() > 0);
89 assertTrue("Missing message for " + path.toFile().getName(),
90 lines.get(0).startsWith(PREFIX));
91 }
92 }
93 }
94 assertEquals("File did not roll", 2, fileCount);
95 }
96
97 @AfterClass
98 public static void afterClass() throws Exception {
99 Configurator.shutdown(loggerContext);
100 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(DIR))) {
101 for (final Path path : directoryStream) {
102 Files.delete(path);
103 }
104 }
105 Files.delete(Paths.get(DIR));
106 }
107
108 }
1515 */
1616 package org.apache.logging.log4j.core.appender.rolling;
1717
18 import java.io.File;
1918 import java.nio.file.DirectoryStream;
2019 import java.nio.file.Files;
2120 import java.nio.file.Path;
2221 import java.nio.file.Paths;
23 import java.nio.file.StandardCopyOption;
24 import java.nio.file.attribute.BasicFileAttributeView;
25 import java.nio.file.attribute.FileTime;
26 import java.time.Instant;
27 import java.time.temporal.ChronoUnit;
28 import java.util.List;
22 import java.util.Arrays;
23 import java.util.Collection;
2924 import org.apache.logging.log4j.Logger;
30 import org.apache.logging.log4j.core.LoggerContext;
31 import org.apache.logging.log4j.core.config.Configurator;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
3226 import org.junit.AfterClass;
27 import org.junit.Before;
3328 import org.junit.BeforeClass;
29 import org.junit.Rule;
3430 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.Parameterized;
3533
3634 import static org.junit.Assert.assertTrue;
3735
3836 /**
3937 *
4038 */
39 @RunWith(Parameterized.class)
4140 public class RollingAppenderOnStartupTest {
4241
43 private static final String SOURCE = "src/test/resources/__files";
4442 private static final String DIR = "target/onStartup";
45 private static final String CONFIG = "log4j-rollOnStartup.xml";
46 private static final String FILENAME = "onStartup.log";
47 private static final String PREFIX = "This is test message number ";
48 private static final String ROLLED = "onStartup-";
4943
50 private static LoggerContext loggerContext;
44 private Logger logger;
45
46 @Parameterized.Parameters(name = "{0} \u2192 {1}")
47 public static Collection<Object[]> data() {
48 return Arrays.asList(new Object[][] { //
49 // @formatter:off
50 {"log4j-test4.xml"},
51 {"log4j-test4.xml"},});
52 // @formatter:on
53 }
54
55 @Rule
56 public LoggerContextRule loggerContextRule;
57
58 public RollingAppenderOnStartupTest(final String configFile) {
59 this.loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(configFile);
60 }
61
62 @Before
63 public void setUp() throws Exception {
64 this.logger = this.loggerContextRule.getLogger(RollingAppenderOnStartupTest.class.getName());
65 }
5166
5267 @BeforeClass
5368 public static void beforeClass() throws Exception {
5974 Files.delete(Paths.get(DIR));
6075 }
6176 }
62 Files.createDirectory(new File(DIR).toPath());
63 Path target = Paths.get(DIR, FILENAME);
64 Files.copy(Paths.get(SOURCE, FILENAME), target, StandardCopyOption.COPY_ATTRIBUTES);
65 FileTime newTime = FileTime.from(Instant.now().minus(1, ChronoUnit.DAYS));
66 Files.getFileAttributeView(target, BasicFileAttributeView.class).setTimes(newTime, newTime, newTime);
67 }
68
69 @Test
70 public void performTest() throws Exception {
71 boolean rolled = false;
72 loggerContext = Configurator.initialize("Test", CONFIG);
73 final Logger logger = loggerContext.getLogger(RollingAppenderOnStartupTest.class);
74 for (int i = 3; i < 10; ++i) {
75 logger.debug(PREFIX + i);
76 }
77 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(DIR))) {
78 for (final Path path : directoryStream) {
79 if (path.toFile().getName().startsWith(ROLLED)) {
80 rolled = true;
81 List<String> lines = Files.readAllLines(path);
82 assertTrue("No messages in " + path.toFile().getName(), lines.size() > 0);
83 assertTrue("Missing message for " + path.toFile().getName(),
84 lines.get(0).startsWith(PREFIX + "1"));
85 }
86 }
87 }
88 assertTrue("File did not roll", rolled);
8977 }
9078
9179 @AfterClass
9280 public static void afterClass() throws Exception {
93 Configurator.shutdown(loggerContext);
81 long size = 0;
9482 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(DIR))) {
9583 for (final Path path : directoryStream) {
84 if (size == 0) {
85 size = Files.size(path);
86 } else {
87 final long fileSize = Files.size(path);
88 assertTrue("Expected size: " + size + " Size of " + path.getFileName() + ": " + fileSize,
89 size == fileSize);
90 }
9691 Files.delete(path);
9792 }
93 Files.delete(Paths.get("target/onStartup"));
9894 }
99 Files.delete(Paths.get(DIR));
10095 }
10196
97 @Test
98 public void testAppender() throws Exception {
99 for (int i = 0; i < 100; ++i) {
100 logger.debug("This is test message number " + i);
101 }
102
103 }
102104 }
+0
-111
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderRestartTest.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.logging.log4j.core.appender.rolling;
17
18 import static org.apache.logging.log4j.hamcrest.Descriptors.that;
19 import static org.apache.logging.log4j.hamcrest.FileMatchers.hasName;
20 import static org.hamcrest.Matchers.endsWith;
21 import static org.hamcrest.Matchers.hasItemInArray;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24 import static org.junit.jupiter.api.Assertions.fail;
25
26 import java.io.File;
27 import java.io.IOException;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.nio.file.StandardOpenOption;
32 import java.nio.file.attribute.BasicFileAttributeView;
33 import java.nio.file.attribute.FileTime;
34 import java.time.Instant;
35 import java.time.temporal.ChronoUnit;
36 import java.util.Arrays;
37 import java.util.concurrent.TimeUnit;
38
39 import org.apache.commons.io.file.PathUtils;
40 import org.apache.logging.log4j.Logger;
41 import org.apache.logging.log4j.core.appender.RollingFileAppender;
42 import org.apache.logging.log4j.junit.LoggerContextRule;
43 import org.hamcrest.Matcher;
44 import org.junit.AfterClass;
45 import org.junit.BeforeClass;
46 import org.junit.Rule;
47 import org.junit.Test;
48 import org.junit.rules.RuleChain;
49
50 public class RollingAppenderRestartTest {
51
52 private static final String CONFIG = "log4j-rolling-restart.xml";
53
54 // Note that both paths are hardcoded in the configuration!
55 private static final Path DIR = Paths.get("target/rolling-restart");
56 private static final Path FILE = DIR.resolve("test.log");
57
58 private final LoggerContextRule loggerContextRule =
59 LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
60
61 @Rule
62 public RuleChain chain =
63 loggerContextRule.withCleanFoldersRule(
64 false, true, 5, DIR.toAbsolutePath().toString());
65
66 @BeforeClass
67 public static void setup() throws Exception {
68 tearDown();
69 Files.createDirectories(DIR);
70 Files.write(FILE, "Hello, world".getBytes(), StandardOpenOption.CREATE);
71 FileTime newTime = FileTime.from(Instant.now().minus(2, ChronoUnit.DAYS));
72 Files
73 .getFileAttributeView(FILE, BasicFileAttributeView.class)
74 .setTimes(newTime, newTime, newTime);
75 }
76
77 @AfterClass
78 public static void tearDown() throws IOException {
79 if (Files.exists(DIR)) {
80 PathUtils.deleteDirectory(DIR);
81 }
82 }
83
84 @Test
85 public void testAppender() throws Exception {
86 final Logger logger = loggerContextRule.getLogger();
87 logger.info("This is test message number 1");
88 // The GZ compression takes place asynchronously.
89 // Make sure it's done before validating.
90 Thread.yield();
91 final String name = "RollingFile";
92 RollingFileAppender appender = loggerContextRule.getAppender(name);
93 assertNotNull(appender, name);
94 if (appender.getManager().getSemaphore().tryAcquire(5, TimeUnit.SECONDS)) {
95 // If we are in here, either the rollover is done or has not taken place yet.
96 validate();
97 } else {
98 fail("Rolling over is taking too long.");
99 }
100 }
101
102 private void validate() {
103 final Matcher<File[]> hasGzippedFile = hasItemInArray(that(hasName(that(endsWith(".gz")))));
104 final File[] files = DIR.toFile().listFiles();
105 Arrays.sort(files);
106 assertTrue(hasGzippedFile.matches(files),
107 () -> "was expecting files with '.gz' suffix, found: " + Arrays.toString(files));
108 }
109
110 }
8989 assertEquals("r--r--r--",
9090 PosixFilePermissions.toString(Files.getPosixFilePermissions(file.toPath())));
9191 }
92 } else if (file.getName().startsWith("test1")) {
93 assertEquals("rw-------",
94 PosixFilePermissions.toString(Files.getPosixFilePermissions(file.toPath())));
9592 } else {
96 assertEquals("rwx------",
97 PosixFilePermissions.toString(Files.getPosixFilePermissions(file.toPath())));
93 if (file.getName().startsWith("test1")) {
94 assertEquals("rw-------",
95 PosixFilePermissions.toString(Files.getPosixFilePermissions(file.toPath())));
96 } else {
97 assertEquals("rwx------",
98 PosixFilePermissions.toString(Files.getPosixFilePermissions(file.toPath())));
99 }
98100 }
99101 }
100102 assertTrue("Files not rolled : " + files.length, files.length > 2);
7474 // @formatter:off
7575 {"log4j-rolling-gz-lazy.xml", ".gz", true},
7676 {"log4j-rolling-gz.xml", ".gz", false},
77 {"log4j-rolling-numbered-gz.xml", ".gz", false},
7877 {"log4j-rolling-zip-lazy.xml", ".zip", true},
7978 {"log4j-rolling-zip.xml", ".zip", false},
8079 // Apache Commons Compress
150149 in = new CompressorStreamFactory().createCompressorInputStream(ext.name().toLowerCase(), fis);
151150 } catch (final CompressorException ce) {
152151 ce.printStackTrace();
153 fail("Error creating input stream from " + file.toString() + ": " + ce.getMessage());
152 fail("Error creating intput stream from " + file.toString() + ": " + ce.getMessage());
154153 }
155154 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
156155 assertNotNull("No input stream for " + file.getName(), in);
+0
-87
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingDirectSizeTimeNewDirectoryTest.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.logging.log4j.core.appender.rolling;
17
18 import java.io.File;
19 import java.util.Collections;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.concurrent.atomic.AtomicInteger;
24
25 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.appender.RollingFileAppender;
27 import org.apache.logging.log4j.junit.LoggerContextRule;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.rules.RuleChain;
31
32 import static org.junit.Assert.assertTrue;
33
34 /**
35 * This test attempts to validate that logging rolls when the file size exceeds 5KB or every second.
36 * When the file rolls by time it should create a new directory. When rolling by size it should
37 * create multiple files per directory.
38 */
39 public class RollingDirectSizeTimeNewDirectoryTest implements RolloverListener {
40
41 private static final String CONFIG = "log4j-rolling-size-time-new-directory.xml";
42
43 // Note that the path is hardcoded in the configuration!
44 private static final String DIR = "target/rolling-size-time-new-directory";
45
46 public static LoggerContextRule loggerContextRule =
47 LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
48
49 @Rule
50 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
51
52 private Map<String, AtomicInteger> rolloverFiles = new HashMap<>();
53
54 @Test
55 public void streamClosedError() throws Exception {
56 ((RollingFileAppender) loggerContextRule.getAppender("RollingFile")).getManager()
57 .addRolloverListener(this);
58 final Logger logger = loggerContextRule.getLogger(RollingDirectSizeTimeNewDirectoryTest.class);
59
60 for (int i = 0; i < 1000; i++) {
61 logger.info("nHq6p9kgfvWfjzDRYbZp");
62 }
63 Thread.sleep(1500);
64 for (int i = 0; i < 1000; i++) {
65 logger.info("nHq6p9kgfvWfjzDRYbZp");
66 }
67
68 assertTrue("A time based rollover did not occur", rolloverFiles.size() > 1);
69 int maxFiles = Collections.max(rolloverFiles.values(), Comparator.comparing(AtomicInteger::get)).get();
70 assertTrue("No size based rollovers occurred", maxFiles > 1);
71 }
72
73 @Override
74 public void rolloverTriggered(String fileName) {
75
76 }
77
78 @Override
79 public void rolloverComplete(String fileName) {
80 File file = new File(fileName);
81 String logDir = file.getParentFile().getName();
82 AtomicInteger fileCount = rolloverFiles.computeIfAbsent(logDir, k -> new AtomicInteger(0));
83 fileCount.incrementAndGet();
84 }
85 }
86
+0
-108
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingDirectTimeNewDirectoryTest.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.logging.log4j.core.appender.rolling;
17
18 import org.apache.commons.io.FileUtils;
19 import org.apache.commons.io.filefilter.TrueFileFilter;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.junit.Rule;
23 import org.junit.Test;
24 import org.junit.rules.RuleChain;
25
26 import java.io.File;
27 import java.util.Arrays;
28 import java.util.Iterator;
29
30 import static org.junit.Assert.assertNotNull;
31 import static org.junit.Assert.assertTrue;
32
33 public class RollingDirectTimeNewDirectoryTest {
34
35 private static final String CONFIG = "log4j-rolling-folder-direct.xml";
36
37 // Note that the path is hardcoded in the configuration!
38 private static final String DIR = "target/rolling-folder-direct";
39
40 public static LoggerContextRule loggerContextRule =
41 LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
42
43 @Rule
44 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
45
46 /**
47 * This test logs directly to the target file. Rollover is set to happen once per second. We pause once
48 * to ensure a rollover takes place. However, it is possible that 3 or 4 rollovers could occur, depending
49 * on when the test starts and what else is going on on the machine running the test.
50 * @throws Exception
51 */
52 @Test
53 public void streamClosedError() throws Exception {
54
55 final Logger logger =
56 loggerContextRule.getLogger(
57 RollingDirectTimeNewDirectoryTest.class.getName());
58
59 for (int i = 0; i < 1000; i++) {
60 logger.info("nHq6p9kgfvWfjzDRYbZp");
61 }
62 Thread.sleep(1500);
63 for (int i = 0; i < 1000; i++) {
64 logger.info("nHq6p9kgfvWfjzDRYbZp");
65 }
66
67 File logDir = new File(DIR);
68 File[] logFolders = logDir.listFiles();
69 assertNotNull(logFolders);
70 Arrays.sort(logFolders);
71 int totalFiles = 0;
72 try {
73
74 final int minExpectedLogFolderCount = 2;
75 assertTrue(
76 "was expecting at least " + minExpectedLogFolderCount + " folders, " +
77 "found " + logFolders.length,
78 logFolders.length >= minExpectedLogFolderCount);
79
80 for (File logFolder : logFolders) {
81 File[] logFiles = logFolder.listFiles();
82 if (logFiles != null) {
83 assertTrue("Only 1 file per folder expected: got " + logFiles.length,
84 logFiles.length <= 1);
85 totalFiles += logFiles.length;
86 }
87 }
88 assertTrue("Expected at least 2 files", totalFiles >= 2);
89
90 } catch (AssertionError error) {
91 System.out.format("log directory (%s) contents:%n", DIR);
92 final Iterator<File> fileIterator =
93 FileUtils.iterateFilesAndDirs(
94 logDir, TrueFileFilter.TRUE, TrueFileFilter.TRUE);
95 int totalFileCount = 0;
96 while (fileIterator.hasNext()) {
97 totalFileCount++;
98 final File file = fileIterator.next();
99 System.out.format("-> %s (%d)%n", file, file.length());
100 }
101 System.out.format("total file count: %d%n", totalFileCount);
102 throw new AssertionError("check failure", error);
103 }
104
105 }
106
107 }
+0
-94
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileAppenderInterruptedThreadTest.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.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.appender.ConsoleAppender;
22 import org.apache.logging.log4j.core.appender.RollingFileAppender;
23 import org.apache.logging.log4j.core.config.Configurator;
24 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
25 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
26 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
27 import org.apache.logging.log4j.junit.CleanFolders;
28 import org.junit.After;
29 import org.junit.Assert;
30 import org.junit.Before;
31 import org.junit.Rule;
32 import org.junit.Test;
33
34 import java.io.File;
35
36 import static org.hamcrest.Matchers.hasItem;
37 import static org.hamcrest.Matchers.instanceOf;
38
39 /**
40 * Tests https://issues.apache.org/jira/browse/LOG4J2-1798
41 */
42 public class RollingFileAppenderInterruptedThreadTest {
43
44 private static final String ROLLING_APPENDER_FILES_DIR =
45 "target/" + RollingFileAppenderInterruptedThreadTest.class.getSimpleName();
46
47 @Rule
48 public CleanFolders cleanFolders = new CleanFolders(true, false, 3, ROLLING_APPENDER_FILES_DIR);
49
50 LoggerContext loggerContext;
51
52 @Before
53 public void setUp() {
54 ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
55 builder.setConfigurationName("LOG4J2-1798 test");
56
57 builder.add(builder.newAppender("consoleLog", "Console")
58 .addAttribute("target", ConsoleAppender.Target.SYSTEM_ERR));
59
60 builder.add(builder.newAppender("fileAppender", "RollingFile")
61 .addAttribute("filePattern", ROLLING_APPENDER_FILES_DIR + "/file-%i.log")
62 .add(builder.newLayout("PatternLayout").addAttribute("pattern", "%msg%n"))
63 .addComponent(builder.newComponent("SizeBasedTriggeringPolicy")
64 .addAttribute("size", "20B"))); // relatively small amount to trigger rotation quickly
65
66 builder.add(builder.newRootLogger(Level.INFO)
67 .add(builder.newAppenderRef("consoleLog"))
68 .add(builder.newAppenderRef("fileAppender")));
69
70 loggerContext = Configurator.initialize(builder.build());
71 }
72
73 @After
74 public void tearDown() {
75 Configurator.shutdown(loggerContext);
76 loggerContext = null;
77 }
78
79 @Test
80 public void testRolloverInInterruptedThread() {
81 Logger logger = loggerContext.getLogger(getClass().getName());
82
83 Assert.assertThat(logger.getAppenders().values(), hasItem(instanceOf(RollingFileAppender.class)));
84
85 logger.info("Sending logging event 1"); // send first event to initialize rollover system
86
87 Thread.currentThread().interrupt(); // mark thread as interrupted
88 logger.info("Sending logging event 2"); // send second event to trigger rotation, expecting 2 files in result
89
90 Assert.assertTrue(new File(ROLLING_APPENDER_FILES_DIR, "file-1.log").exists());
91 Assert.assertTrue(new File(ROLLING_APPENDER_FILES_DIR, "file-2.log").exists());
92 }
93 }
2727 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
2828 import org.junit.After;
2929 import org.junit.Assert;
30 import org.junit.BeforeClass;
31 import org.junit.Ignore;
3032 import org.junit.Test;
3133
3234 /**
+0
-87
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManagerTest.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.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.core.appender.RollingFileAppender;
20 import org.apache.logging.log4j.core.config.Configuration;
21 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
22 import org.apache.logging.log4j.core.util.IOUtils;
23 import org.junit.Assert;
24 import org.junit.Test;
25
26 import java.io.*;
27 import java.nio.charset.StandardCharsets;
28
29 public class RollingFileManagerTest {
30
31 /**
32 * Test the RollingFileManager with a custom DirectFileRolloverStrategy
33 *
34 * @throws IOException
35 */
36 @Test
37 public void testCustomDirectFileRolloverStrategy() throws IOException {
38 class CustomDirectFileRolloverStrategy extends AbstractRolloverStrategy implements DirectFileRolloverStrategy {
39 final File file;
40
41 CustomDirectFileRolloverStrategy(File file, StrSubstitutor strSubstitutor) {
42 super(strSubstitutor);
43 this.file = file;
44 }
45
46 @Override
47 public String getCurrentFileName(RollingFileManager manager) {
48 return file.getAbsolutePath();
49 }
50
51 @Override
52 public void clearCurrentFileName() {
53 // do nothing
54 }
55
56 @Override
57 public RolloverDescription rollover(RollingFileManager manager) throws SecurityException {
58 return null; // do nothing
59 }
60 }
61
62 try (final LoggerContext ctx = LoggerContext.getContext(false)) {
63 final Configuration config = ctx.getConfiguration();
64 final File file = File.createTempFile("RollingFileAppenderAccessTest", ".tmp");
65 file.deleteOnExit();
66
67 final RollingFileAppender appender = RollingFileAppender.newBuilder()
68 .withFilePattern("FilePattern")
69 .setName("RollingFileAppender")
70 .setConfiguration(config)
71 .withStrategy(new CustomDirectFileRolloverStrategy(file, config.getConfigurationStrSubstitutor()))
72 .withPolicy(new SizeBasedTriggeringPolicy(100))
73 .build();
74
75 Assert.assertNotNull(appender);
76 final String testContent = "Test";
77 try(final RollingFileManager manager = appender.getManager()) {
78 Assert.assertEquals(file.getAbsolutePath(), manager.getFileName());
79 manager.writeToDestination(testContent.getBytes(StandardCharsets.US_ASCII), 0, testContent.length());
80 }
81 try (final Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.US_ASCII)) {
82 Assert.assertEquals(testContent, IOUtils.toString(reader));
83 }
84 }
85 }
86 }
+0
-62
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingNewDirectoryTest.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.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.junit.Before;
21 import org.junit.Rule;
22 import org.junit.Test;
23 import org.junit.rules.RuleChain;
24
25 import java.io.File;
26
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertTrue;
29
30 /**
31 * Tests
32 */
33 public class RollingNewDirectoryTest {
34 private static final String CONFIG = "log4j-rolling-new-directory.xml";
35
36 private static final String DIR = "target/rolling-new-directory";
37
38 public static LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
39
40 @Rule
41 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
42
43 private Logger logger;
44
45 @Before
46 public void setUp() throws Exception {
47 this.logger = loggerContextRule.getLogger(RollingNewDirectoryTest.class.getName());
48 }
49
50
51 @Test
52 public void streamClosedError() throws Exception {
53 for (int i = 0; i < 10; ++i) {
54 logger.info("AAA");
55 Thread.sleep(300);
56 }
57 final File dir = new File(DIR);
58 assertNotNull("No directory created", dir);
59 assertTrue("Child irectories not created", dir.exists() && dir.listFiles().length > 2);
60 }
61 }
1616
1717 package org.apache.logging.log4j.core.appender.rolling;
1818
19 import org.apache.logging.log4j.core.config.DefaultConfiguration;
20 import org.apache.logging.log4j.core.util.Closer;
21 import org.apache.logging.log4j.core.util.FileUtils;
22 import org.apache.logging.log4j.core.util.NullOutputStream;
23 import org.apache.logging.log4j.util.Strings;
24 import org.junit.Test;
25
26 import java.io.File;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.io.RandomAccessFile;
31 import java.nio.file.Files;
32 import java.nio.file.Paths;
33 import java.nio.file.attribute.PosixFileAttributeView;
34 import java.nio.file.attribute.PosixFilePermission;
35 import java.nio.file.attribute.PosixFilePermissions;
36 import java.util.Set;
37 import java.util.concurrent.locks.LockSupport;
38
3919 import static org.apache.logging.log4j.hamcrest.FileMatchers.beforeNow;
4020 import static org.apache.logging.log4j.hamcrest.FileMatchers.hasLength;
4121 import static org.apache.logging.log4j.hamcrest.FileMatchers.isEmpty;
4424 import static org.hamcrest.Matchers.lessThanOrEqualTo;
4525 import static org.junit.Assert.assertEquals;
4626 import static org.junit.Assert.assertNotEquals;
47 import static org.junit.Assert.assertNotNull;
4827 import static org.junit.Assert.assertThat;
4928 import static org.junit.Assert.assertTrue;
29
30 import java.io.File;
31 import java.io.FileOutputStream;
32 import java.io.IOException;
33 import java.io.OutputStream;
34 import java.io.RandomAccessFile;
35 import java.util.concurrent.locks.LockSupport;
36
37 import org.apache.logging.log4j.core.util.Closer;
38 import org.apache.logging.log4j.core.util.NullOutputStream;
39 import org.apache.logging.log4j.util.Strings;
40 import org.junit.Test;
5041
5142 /**
5243 * Tests the RollingRandomAccessFileManager class.
206197 assertThat(file, lastModified(equalTo(manager.getFileTime())));
207198 }
208199
209 @Test
210 public void testRolloverRetainsFileAttributes() throws Exception {
211
212 // Short-circuit if host doesn't support file attributes.
213 if (!FileUtils.isFilePosixAttributeViewSupported()) {
214 return;
215 }
216
217 // Create the initial file.
218 final File file = File.createTempFile("log4j2", "test");
219 LockSupport.parkNanos(1000000); // 1 millisec
220
221 // Set the initial file attributes.
222 final String filePermissionsString = "rwxrwxrwx";
223 final Set<PosixFilePermission> filePermissions =
224 PosixFilePermissions.fromString(filePermissionsString);
225 FileUtils.defineFilePosixAttributeView(file.toPath(), filePermissions, null, null);
226
227 // Create the manager.
228 final RolloverStrategy rolloverStrategy = DefaultRolloverStrategy
229 .newBuilder()
230 .withMax("7")
231 .withMin("1")
232 .withFileIndex("max")
233 .withStopCustomActionsOnError(false)
234 .withConfig(new DefaultConfiguration())
235 .build();
236 final RollingRandomAccessFileManager manager =
237 RollingRandomAccessFileManager.getRollingRandomAccessFileManager(
238 file.getAbsolutePath(),
239 Strings.EMPTY,
240 true,
241 true,
242 RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE,
243 new SizeBasedTriggeringPolicy(Long.MAX_VALUE),
244 rolloverStrategy,
245 null,
246 null,
247 filePermissionsString,
248 null,
249 null,
250 null);
251 assertNotNull(manager);
252 manager.initialize();
253
254 // Trigger a rollover.
255 manager.rollover();
256
257 // Verify the rolled over file attributes.
258 final Set<PosixFilePermission> actualFilePermissions = Files
259 .getFileAttributeView(
260 Paths.get(manager.getFileName()),
261 PosixFileAttributeView.class)
262 .readAttributes()
263 .permissions();
264 assertEquals(filePermissions, actualFilePermissions);
265
266 }
267
268200 }
1616 package org.apache.logging.log4j.core.appender.rolling.action;
1717
1818 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.junit.StatusLoggerLevel;
19 import org.apache.logging.log4j.junit.StatusLoggerRule;
2020 import org.apache.logging.log4j.status.StatusData;
2121 import org.apache.logging.log4j.status.StatusLogger;
22 import org.junit.jupiter.api.Test;
22 import org.junit.Rule;
23 import org.junit.Test;
2324
2425 import java.io.IOException;
2526 import java.util.List;
2627
27 import static org.hamcrest.MatcherAssert.assertThat;
28 import static org.hamcrest.Matchers.containsString;
29 import static org.hamcrest.Matchers.hasSize;
30 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertTrue;
3130
32 @StatusLoggerLevel("WARN")
3331 public class AbstractActionTest {
32
33 @Rule
34 public StatusLoggerRule statusLogger = new StatusLoggerRule(Level.WARN);
3435
3536 // Test for LOG4J2-2658
3637 @Test
3940 statusLogger.clear();
4041 new TestAction().run();
4142 List<StatusData> statusDataList = statusLogger.getStatusData();
42 assertThat(statusDataList, hasSize(1));
43 assertEquals(1, statusDataList.size());
4344 StatusData statusData = statusDataList.get(0);
4445 assertEquals(Level.WARN, statusData.getLevel());
4546 String formattedMessage = statusData.getFormattedStatus();
46 assertThat(formattedMessage, containsString("Exception reported by action 'class org.apache."
47 + "logging.log4j.core.appender.rolling.action.AbstractActionTest$TestAction' java.io.IOException: "
48 + "failed" + System.lineSeparator()
49 + "\tat org.apache.logging.log4j.core.appender.rolling.action.AbstractActionTest"
50 + "$TestAction.execute(AbstractActionTest.java:"));
47 assertTrue(formattedMessage.contains("Exception reported by action 'class org.apache." +
48 "logging.log4j.core.appender.rolling.action.AbstractActionTest$TestAction' java.io.IOException: " +
49 "failed\n\tat org.apache.logging.log4j.core.appender.rolling.action.AbstractActionTest" +
50 "$TestAction.execute(AbstractActionTest.java:"));
5151 }
5252
5353 @Test
6161 }
6262 }.run();
6363 List<StatusData> statusDataList = statusLogger.getStatusData();
64 assertThat(statusDataList, hasSize(1));
64 assertEquals(1, statusDataList.size());
6565 StatusData statusData = statusDataList.get(0);
6666 assertEquals(Level.WARN, statusData.getLevel());
6767 String formattedMessage = statusData.getFormattedStatus();
68 assertThat(formattedMessage, containsString("Exception reported by action"));
68 assertTrue(formattedMessage.contains("Exception reported by action"));
6969 }
7070
7171 @Test
7979 }
8080 }.run();
8181 List<StatusData> statusDataList = statusLogger.getStatusData();
82 assertThat(statusDataList, hasSize(1));
82 assertEquals(1, statusDataList.size());
8383 StatusData statusData = statusDataList.get(0);
8484 assertEquals(Level.WARN, statusData.getLevel());
8585 String formattedMessage = statusData.getFormattedStatus();
86 assertThat(formattedMessage, containsString("Exception reported by action"));
86 assertTrue(formattedMessage.contains("Exception reported by action"));
8787 }
8888
8989 private static final class TestAction extends AbstractAction {
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.io.TempDir;
22
2319 import java.io.ByteArrayInputStream;
2420 import java.io.File;
2521 import java.io.FileInputStream;
2622 import java.io.FileWriter;
2723 import java.io.IOException;
2824
29 import static org.junit.jupiter.api.Assertions.*;
25 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
26 import org.junit.Test;
27
28 import static org.junit.Assert.*;
3029
3130 /**
3231 * Tests Bzip2CompressAction.
3332 */
3433 public class Bzip2CompressActionTest {
3534
36 @Test
35 @Test(expected = NullPointerException.class)
3736 public void testConstructorDisallowsNullSource() {
38 assertThrows(NullPointerException.class,
39 () -> new CommonsCompressAction("bzip2", null, new File("any"), true));
37 new CommonsCompressAction("bzip2", null, new File("any"), true);
4038 }
4139
42 @Test
40 @Test(expected = NullPointerException.class)
4341 public void testConstructorDisallowsNullDestination() {
44 assertThrows(NullPointerException.class,
45 () -> new CommonsCompressAction("bzip2", new File("any"), null, true));
42 new CommonsCompressAction("bzip2", new File("any"), null, true);
4643 }
4744
4845 @Test
5249 source = new File(source.getName() + Math.random());
5350 }
5451 final boolean actual = CommonsCompressAction.execute("bzip2", source, new File("any2"), true);
55 assertFalse(actual, "Cannot compress non-existing file");
52 assertEquals("Cannot compress non-existing file", false, actual);
5653 }
5754
5855 @Test
59 public void testExecuteCompressesSourceFileToDestinationFile(@TempDir final File tempDir) throws IOException {
56 public void testExecuteCompressesSourceFileToDestinationFile() throws IOException {
6057 final String LINE1 = "Here is line 1. Random text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
6158 final String LINE2 = "Here is line 2. Random text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
6259 final String LINE3 = "Here is line 3. Random text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
63 final File source = new File(tempDir, "compressme");
60 final File source = new File("target/compressme");
6461 try (FileWriter fw = new FileWriter(source, false)) {
6562 fw.write(LINE1);
6663 fw.write(LINE2);
6764 fw.write(LINE3);
6865 fw.flush();
6966 }
70 final File destination = new File(tempDir, "compressme.bz2");
71 assertFalse(destination.exists(), "Destination should not exist yet");
67 final File destination = new File("target/compressme.bz2");
68 destination.delete(); // just in case
69 assertFalse("Destination should not exist yet", destination.exists());
7270
7371 final boolean actual = CommonsCompressAction.execute("bzip2", source, destination, true);
74 assertTrue(actual, "Bzip2CompressAction should have succeeded");
75 assertTrue(destination.exists(), "Destination should exist after Bzip2CompressAction");
76 assertFalse(source.exists(), "Source should have been deleted");
72 assertEquals("Bzip2CompressAction should have succeeded", true, actual);
73 assertTrue("Destination should exist after Bzip2CompressAction", destination.exists());
74 assertFalse("Source should have been deleted", source.exists());
7775
7876 final byte[] bz2 = new byte[] { (byte) 0x42, (byte) 0x5A, (byte) 0x68, (byte) 0x39, (byte) 0x31, (byte) 0x41,
7977 (byte) 0x59, (byte) 0x26, (byte) 0x53, (byte) 0x59, (byte) 0x9C, (byte) 0xE1, (byte) 0xE8, (byte) 0x2D,
103101 n = fis.read(actualBz2, offset, actualBz2.length - offset);
104102 offset += n;
105103 } while (offset < actualBz2.length);
106 assertArrayEquals(bz2, actualBz2, "Compressed data corrupt");
104 assertArrayEquals("Compressed data corrupt", bz2, actualBz2);
107105 }
106 destination.delete();
108107
109108 // uncompress
110109 try (BZip2CompressorInputStream bzin = new BZip2CompressorInputStream(new ByteArrayInputStream(bz2))) {
1818
1919 import java.nio.file.Path;
2020 import java.nio.file.attribute.BasicFileAttributes;
21
22 import org.apache.logging.log4j.core.appender.rolling.action.PathCondition;
2123
2224 /**
2325 * Test helper class.
2525 import java.util.EnumSet;
2626
2727 import org.apache.logging.log4j.core.BasicConfigurationFactory;
28 import org.apache.logging.log4j.core.appender.rolling.action.DeleteAction;
29 import org.apache.logging.log4j.core.appender.rolling.action.DeletingVisitor;
30 import org.apache.logging.log4j.core.appender.rolling.action.PathCondition;
2831 import org.apache.logging.log4j.core.config.Configuration;
29 import org.junit.jupiter.api.Test;
32 import org.junit.Test;
3033
31 import static org.hamcrest.MatcherAssert.assertThat;
32 import static org.hamcrest.Matchers.instanceOf;
33 import static org.junit.jupiter.api.Assertions.*;
34 import static org.junit.Assert.*;
3435
3536 /**
3637 * Tests the {@code DeleteAction} class.
9697 public void testCreateFileVisitorReturnsDeletingVisitor() {
9798 final DeleteAction delete = createAnyFilter("any", true, 0, false);
9899 final FileVisitor<Path> visitor = delete.createFileVisitor(delete.getBasePath(), delete.getPathConditions());
99 assertThat(visitor, instanceOf(DeletingVisitor.class));
100 assertTrue(visitor instanceof DeletingVisitor);
100101 }
101102
102103 @Test
104105 final DeleteAction delete = createAnyFilter("any", true, 0, false);
105106 assertFalse(delete.isTestMode());
106107 final FileVisitor<Path> visitor = delete.createFileVisitor(delete.getBasePath(), delete.getPathConditions());
107 assertThat(visitor, instanceOf(DeletingVisitor.class));
108 assertTrue(visitor instanceof DeletingVisitor);
108109 assertFalse(((DeletingVisitor) visitor).isTestMode());
109110
110111 final DeleteAction deleteTestMode = createAnyFilter("any", true, 0, true);
111112 assertTrue(deleteTestMode.isTestMode());
112113 final FileVisitor<Path> testVisitor = deleteTestMode.createFileVisitor(delete.getBasePath(),
113114 delete.getPathConditions());
114 assertThat(testVisitor, instanceOf(DeletingVisitor.class));
115 assertTrue(testVisitor instanceof DeletingVisitor);
115116 assertTrue(((DeletingVisitor) testVisitor).isTestMode());
116117 }
117118 }
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
1919 import java.io.IOException;
20 import java.nio.file.FileVisitResult;
21 import java.nio.file.NoSuchFileException;
2220 import java.nio.file.Path;
2321 import java.nio.file.Paths;
2422 import java.nio.file.attribute.BasicFileAttributes;
2523 import java.util.ArrayList;
2624 import java.util.Arrays;
27 import java.util.Collections;
2825 import java.util.List;
2926
30 import org.junit.jupiter.api.Test;
27 import org.junit.Test;
3128
32 import static org.junit.jupiter.api.Assertions.*;
29 import static org.junit.Assert.*;
3330
3431 /**
3532 * Tests the {@code DeletingVisitor} class.
5754 public void testAcceptedFilesAreDeleted() throws IOException {
5855 final Path base = Paths.get("/a/b/c");
5956 final FixedCondition ACCEPT_ALL = new FixedCondition(true);
60 final DeletingVisitorHelper visitor = new DeletingVisitorHelper(base, Collections.singletonList(ACCEPT_ALL), false);
57 final DeletingVisitorHelper visitor = new DeletingVisitorHelper(base, Arrays.asList(ACCEPT_ALL), false);
6158
6259 final Path any = Paths.get("/a/b/c/any");
6360 visitor.visitFile(any, null);
6865 public void testRejectedFilesAreNotDeleted() throws IOException {
6966 final Path base = Paths.get("/a/b/c");
7067 final FixedCondition REJECT_ALL = new FixedCondition(false);
71 final DeletingVisitorHelper visitor = new DeletingVisitorHelper(base, Collections.singletonList(REJECT_ALL), false);
68 final DeletingVisitorHelper visitor = new DeletingVisitorHelper(base, Arrays.asList(REJECT_ALL), false);
7269
7370 final Path any = Paths.get("/a/b/c/any");
7471 visitor.visitFile(any, null);
129126 }
130127 };
131128 final Path base = Paths.get("/a/b/c");
132 final DeletingVisitorHelper visitor = new DeletingVisitorHelper(base, Collections.singletonList(filter), false);
129 final DeletingVisitorHelper visitor = new DeletingVisitorHelper(base, Arrays.asList(filter), false);
133130
134131 final Path child = Paths.get("/a/b/c/relative");
135132 visitor.visitFile(child, null);
136133 }
137
138 @Test
139 public void testNoSuchFileFailure() throws IOException {
140 final DeletingVisitorHelper visitor =
141 new DeletingVisitorHelper(Paths.get("/a/b/c"), Collections.emptyList(), true);
142 assertEquals(
143 FileVisitResult.CONTINUE,
144 visitor.visitFileFailed(Paths.get("doesNotExist"), new NoSuchFileException("doesNotExist")));
145 }
146
147 @Test
148 public void testIOException() {
149 final DeletingVisitorHelper visitor =
150 new DeletingVisitorHelper(Paths.get("/a/b/c"), Collections.emptyList(), true);
151 IOException exception = new IOException();
152 try {
153 visitor.visitFileFailed(Paths.get("doesNotExist"), exception);
154 fail();
155 } catch (IOException e) {
156 assertSame(exception, e);
157 }
158 }
159134 }
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.junit.jupiter.api.Test;
19 import org.apache.logging.log4j.core.appender.rolling.action.Duration;
20 import org.junit.Test;
2021
21 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2223
2324 /**
2425 * Tests the Duration class.
2526 */
2627 public class DurationTest {
2728
28 @Test
29 @Test(expected = NullPointerException.class)
2930 public void testParseFailsIfNullText() {
30 assertThrows(NullPointerException.class, () -> Duration.parse(null));
31 Duration.parse(null);
3132 }
3233
33 @Test
34 @Test(expected = IllegalArgumentException.class)
3435 public void testParseFailsIfInvalidPattern() {
35 assertThrows(IllegalArgumentException.class, () -> Duration.parse("abc"));
36 Duration.parse("abc");
3637 }
3738
38 @Test
39 @Test(expected = IllegalArgumentException.class)
3940 public void testParseFailsIfSectionsOutOfOrder() {
40 assertThrows(IllegalArgumentException.class, () -> Duration.parse("P4DT2M1S3H"));
41 Duration.parse("P4DT2M1S3H");
4142 }
4243
43 @Test
44 @Test(expected = IllegalArgumentException.class)
4445 public void testParseFailsIfTButMissingTime() {
45 assertThrows(IllegalArgumentException.class, () -> Duration.parse("P1dT"));
46 Duration.parse("P1dT");
4647 }
4748
4849 @Test
1515 */
1616 package org.apache.logging.log4j.core.appender.rolling.action;
1717
18 import org.junit.jupiter.api.AfterEach;
19 import org.junit.jupiter.api.Test;
20
2118 import java.io.File;
2219 import java.io.PrintStream;
2320
24 import static org.junit.jupiter.api.Assertions.assertFalse;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
21 import org.junit.After;
22 import org.junit.AfterClass;
23 import org.junit.BeforeClass;
24 import org.junit.Test;
2625
26 import static org.junit.Assert.*;
27
28 /**
29 *
30 */
2731 public class FileRenameActionTest {
2832
29 static File tempDir = new File("./target");
33 private static final String DIR = "target/fileRename";
3034
31 @AfterEach
32 public void cleanup() {
33 File file = new File(tempDir, "newFile.log");
34 file.delete();
35 @BeforeClass
36 public static void beforeClass() throws Exception {
37 final File file = new File(DIR);
38 file.mkdirs();
39 }
40
41 @AfterClass
42 public static void afterClass() {
43 deleteDir();
44 }
45
46 @After
47 public void after() {
48 deleteFiles();
3549 }
3650
3751 @Test
3852 public void testRename1() throws Exception {
39 final File file = new File(tempDir, "fileRename.log");
53 final File file = new File("target/fileRename/fileRename.log");
4054 try (final PrintStream pos = new PrintStream(file)) {
4155 for (int i = 0; i < 100; ++i) {
4256 pos.println("This is line " + i);
4357 }
4458 }
4559
46 final File dest = new File(tempDir, "newFile.log");
60 final File dest = new File("target/fileRename/newFile.log");
4761 final FileRenameAction action = new FileRenameAction(file, dest, false);
4862 action.execute();
49 assertTrue(dest.exists(), "Renamed file does not exist");
50 assertFalse(file.exists(), "Old file exists");
63 assertTrue("Renamed file does not exist", dest.exists());
64 assertTrue("Old file exists", !file.exists());
5165 }
5266
5367 @Test
5468 public void testEmpty() throws Exception {
55 final File file = new File(tempDir, "fileRename.log");
69 final File file = new File("target/fileRename/fileRename.log");
5670 try (final PrintStream pos = new PrintStream(file)) {
5771 // do nothing
5872 }
59 assertTrue(file.exists(), "File to rename does not exist");
60 final File dest = new File(tempDir, "newFile.log");
73
74 final File dest = new File("target/fileRename/newFile.log");
6175 final FileRenameAction action = new FileRenameAction(file, dest, false);
6276 action.execute();
63 assertFalse(dest.exists(), "Renamed file should not exist");
64 assertFalse(file.exists(), "Old file still exists");
65 }
66
67 @Test
68 public void testRenameEmpty() throws Exception {
69 final File file = new File(tempDir, "fileRename.log");
70 try (final PrintStream pos = new PrintStream(file)) {
71 // do nothing
72 }
73 assertTrue(file.exists(), "File to rename does not exist");
74 final File dest = new File(tempDir, "newFile.log");
75 final FileRenameAction action = new FileRenameAction(file, dest, true);
76 action.execute();
77 assertTrue(dest.exists(), "Renamed file should exist");
78 assertFalse(file.exists(), "Old file still exists");
77 assertTrue("Renamed file does not exist", !dest.exists());
78 assertTrue("Old file does not exist", !file.exists());
7979 }
8080
8181
8888 }
8989 }
9090
91 final File dest = new File(tempDir, "newFile.log");
92 final FileRenameAction action = new FileRenameAction(file, dest, false);
93 action.execute();
94 assertTrue(dest.exists(), "Renamed file does not exist");
95 assertFalse(file.exists(), "Old file exists");
91 final File dest = new File("newFile.log");
92 try {
93 final FileRenameAction action = new FileRenameAction(file, dest, false);
94 action.execute();
95 assertTrue("Renamed file does not exist", dest.exists());
96 assertTrue("Old file exists", !file.exists());
97 } finally {
98 try {
99 dest.delete();
100 file.delete();
101 } catch (final Exception ex) {
102 System.out.println("Unable to cleanup files written to main directory");
103 }
104 }
96105 }
97106
107
108 private static void deleteDir() {
109 final File dir = new File(DIR);
110 if (dir.exists()) {
111 final File[] files = dir.listFiles();
112 for (final File file : files) {
113 file.delete();
114 }
115 dir.delete();
116 }
117 }
118
119 private static void deleteFiles() {
120 final File dir = new File(DIR);
121 if (dir.exists()) {
122 final File[] files = dir.listFiles();
123 for (final File file : files) {
124 file.delete();
125 }
126 }
127 }
98128 }
+0
-47
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/FileSizeTest.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.logging.log4j.core.appender.rolling.action;
17
18 import org.apache.logging.log4j.core.appender.rolling.FileSize;
19 import org.junit.jupiter.api.Test;
20 import org.junit.jupiter.api.parallel.ResourceLock;
21 import org.junit.jupiter.api.parallel.Resources;
22
23 import java.util.Locale;
24
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26
27 public class FileSizeTest {
28
29 @Test
30 public void testParse() {
31 assertEquals(5 * 1024, FileSize.parse("5k", 0));
32 }
33
34 @Test
35 @ResourceLock(Resources.LOCALE)
36 public void testParseInEurope() {
37 // Caveat: Breaks the ability for this test to run in parallel with other tests :(
38 Locale previousDefault = Locale.getDefault();
39 try {
40 Locale.setDefault(new Locale("de", "DE"));
41 assertEquals(1000, FileSize.parse("1,000", 0));
42 } finally {
43 Locale.setDefault(previousDefault);
44 }
45 }
46 }
1919 import java.nio.file.Path;
2020 import java.nio.file.attribute.BasicFileAttributes;
2121
22 import org.apache.logging.log4j.core.appender.rolling.action.PathCondition;
23
2224 /**
2325 * Test helper class.
2426 */
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * Tests the IfAccumulatedFileCount class.
5353
5454 for (int i = 1; i < 10; i++) {
5555 if (i <= 3) {
56 assertFalse(condition.accept(null, null, null), "i=" + i);
56 assertFalse("i=" + i, condition.accept(null, null, null));
5757 assertEquals(0, counter.getAcceptCount());
5858 } else {
5959 assertTrue(condition.accept(null, null, null));
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * Tests the IfAccumulatedFileSize class.
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.junit.jupiter.api.Test;
19 import org.apache.logging.log4j.core.appender.rolling.action.IfAll;
20 import org.apache.logging.log4j.core.appender.rolling.action.PathCondition;
21 import org.junit.Test;
2022
21 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2224
2325 /**
2426 * Tests the And composite condition.
3436 assertFalse(IfAll.createAndCondition(TRUE, FALSE).accept(null, null, null));
3537 assertFalse(IfAll.createAndCondition(FALSE, FALSE).accept(null, null, null));
3638 }
37
39
3840 @Test
3941 public void testEmptyIsFalse() {
4042 assertFalse(IfAll.createAndCondition().accept(null, null, null));
4143 }
42
44
4345 @Test
4446 public void testBeforeTreeWalk() {
4547 final CountingCondition counter = new CountingCondition(true);
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * Tests the Or composite condition.
3434 assertTrue(IfAny.createOrCondition(TRUE, FALSE).accept(null, null, null));
3535 assertFalse(IfAny.createOrCondition(FALSE, FALSE).accept(null, null, null));
3636 }
37
37
3838 @Test
3939 public void testEmptyIsFalse() {
4040 assertFalse(IfAny.createOrCondition().accept(null, null, null));
4141 }
42
42
4343 @Test
4444 public void testBeforeTreeWalk() {
4545 final CountingCondition counter = new CountingCondition(true);
1919 import java.nio.file.Path;
2020 import java.nio.file.Paths;
2121
22 import org.junit.jupiter.api.Test;
22 import org.junit.Test;
2323
24 import static org.junit.jupiter.api.Assertions.*;
24 import static org.junit.Assert.*;
2525
2626 public class IfFileNameTest {
2727
28 @Test
28 @Test(expected = IllegalArgumentException.class)
2929 public void testCreateNameConditionFailsIfBothRegexAndPathAreNull() {
30 assertThrows(IllegalArgumentException.class, () -> IfFileName.createNameCondition(null, null));
30 IfFileName.createNameCondition(null, null);
3131 }
3232
33 @Test
33 @Test()
3434 public void testCreateNameConditionAcceptsIfEitherRegexOrPathOrBothAreNonNull() {
3535 IfFileName.createNameCondition("bar", null);
3636 IfFileName.createNameCondition(null, "foo");
5050 final IfFileName filter = IfFileName.createNameCondition("path", "regex");
5151 final Path relativePath = Paths.get("path");
5252 assertTrue(filter.accept(null, relativePath, null));
53
53
5454 final Path pathMatchingRegex = Paths.get("regex");
5555 assertFalse(filter.accept(null, pathMatchingRegex, null));
5656 }
6060 final IfFileName regexFilter = IfFileName.createNameCondition(null, "regex");
6161 final Path pathMatchingRegex = Paths.get("regex");
6262 assertTrue(regexFilter.accept(null, pathMatchingRegex, null));
63
63
6464 final Path noMatch = Paths.get("nomatch");
6565 assertFalse(regexFilter.accept(null, noMatch, null));
6666 }
7070 final IfFileName pathFilter = IfFileName.createNameCondition("path", null);
7171 final Path relativePath = Paths.get("path");
7272 assertTrue(pathFilter.accept(null, relativePath, null));
73
73
7474 final IfFileName regexFilter = IfFileName.createNameCondition(null, "regex");
7575 final Path pathMatchingRegex = Paths.get("regex");
7676 assertTrue(regexFilter.accept(null, pathMatchingRegex, null));
8181 final CountingCondition counter = new CountingCondition(true);
8282 final IfFileName regexFilter = IfFileName.createNameCondition(null, "regex", counter);
8383 final Path pathMatchingRegex = Paths.get("regex");
84
84
8585 assertTrue(regexFilter.accept(null, pathMatchingRegex, null));
8686 assertEquals(1, counter.getAcceptCount());
8787 assertTrue(regexFilter.accept(null, pathMatchingRegex, null));
8888 assertEquals(2, counter.getAcceptCount());
8989 assertTrue(regexFilter.accept(null, pathMatchingRegex, null));
9090 assertEquals(3, counter.getAcceptCount());
91
91
9292 final Path noMatch = Paths.get("nomatch");
9393 assertFalse(regexFilter.accept(null, noMatch, null));
9494 assertEquals(3, counter.getAcceptCount()); // no increase
103103 final CountingCondition counter = new CountingCondition(true);
104104 final IfFileName globFilter = IfFileName.createNameCondition("glob", null, counter);
105105 final Path pathMatchingGlob = Paths.get("glob");
106
106
107107 assertTrue(globFilter.accept(null, pathMatchingGlob, null));
108108 assertEquals(1, counter.getAcceptCount());
109109 assertTrue(globFilter.accept(null, pathMatchingGlob, null));
1818
1919 import java.nio.file.attribute.FileTime;
2020
21 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2222
23 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2424
2525 /**
2626 * Tests the FileAgeFilter class.
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.junit.jupiter.api.Test;
19 import org.apache.logging.log4j.core.appender.rolling.action.IfNot;
20 import org.junit.Test;
2021
21 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2223
2324 /**
2425 * Tests the Not composite condition.
3435 assertTrue(IfNot.createNotCondition(new FixedCondition(false)).accept(null, null, null));
3536 }
3637
37 @Test
38 @Test(expected = NullPointerException.class)
3839 public void testEmptyIsFalse() {
39 assertThrows(NullPointerException.class,
40 () -> IfNot.createNotCondition(null).accept(null, null, null));
40 assertFalse(IfNot.createNotCondition(null).accept(null, null, null));
4141 }
4242
4343 @Test
+0
-43
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/PathConditionTest.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.logging.log4j.core.appender.rolling.action;
17
18 import static org.junit.Assert.assertArrayEquals;
19 import static org.junit.Assert.assertNotSame;
20 import static org.junit.Assert.assertSame;
21
22 import org.junit.jupiter.api.Test;
23
24 public class PathConditionTest {
25
26 private static final PathCondition[] EMPTY_FIXTURE = {};
27 private static final PathCondition[] NULL_FIXTURE = null;
28
29 @Test
30 public void testCopy() {
31 assertArrayEquals(EMPTY_FIXTURE, PathCondition.copy(NULL_FIXTURE));
32 assertArrayEquals(EMPTY_FIXTURE, PathCondition.copy(EMPTY_FIXTURE));
33 assertArrayEquals(EMPTY_FIXTURE, PathCondition.copy(PathCondition.EMPTY_ARRAY));
34 assertSame(PathCondition.EMPTY_ARRAY, PathCondition.copy(PathCondition.EMPTY_ARRAY));
35 assertSame(PathCondition.EMPTY_ARRAY, PathCondition.copy(NULL_FIXTURE));
36 assertSame(PathCondition.EMPTY_ARRAY, PathCondition.copy(EMPTY_FIXTURE));
37 //
38 CountingCondition cc = new CountingCondition(true);
39 assertNotSame(cc, PathCondition.copy(cc));
40 }
41
42 }
2020 import java.nio.file.Paths;
2121 import java.nio.file.attribute.FileTime;
2222
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
2727 /**
2828 * Tests the {@code PathSortByModificationTime} class.
4848 final DummyFileAttributes a2 = new DummyFileAttributes();
4949 a1.lastModified = FileTime.fromMillis(100);
5050 a2.lastModified = FileTime.fromMillis(222);
51
52 assertEquals(1, sorter.compare(path(p1, a1), path(p1, a2)), "same path, 2nd more recent");
53 assertEquals(1, sorter.compare(path(p1, a1), path(p2, a2)), "path ignored, 2nd more recent");
54 assertEquals(1, sorter.compare(path(p2, a1), path(p1, a2)), "path ignored, 2nd more recent");
55
56 assertEquals(-1, sorter.compare(path(p1, a2), path(p1, a1)), "same path, 1st more recent");
57 assertEquals(-1, sorter.compare(path(p1, a2), path(p2, a1)), "path ignored, 1st more recent");
58 assertEquals(-1, sorter.compare(path(p2, a2), path(p1, a1)), "path ignored, 1st more recent");
59
60 assertEquals(0, sorter.compare(path(p1, a1), path(p1, a1)), "same path, same time");
61 assertEquals(1, sorter.compare(path(p1, a1), path(p2, a1)), "p2 < p1, same time");
62 assertEquals(-1, sorter.compare(path(p2, a1), path(p1, a1)), "p2 < p1, same time");
51
52 assertEquals("same path, 2nd more recent", 1, sorter.compare(path(p1, a1), path(p1, a2)));
53 assertEquals("path ignored, 2nd more recent", 1, sorter.compare(path(p1, a1), path(p2, a2)));
54 assertEquals("path ignored, 2nd more recent", 1, sorter.compare(path(p2, a1), path(p1, a2)));
55
56 assertEquals("same path, 1st more recent", -1, sorter.compare(path(p1, a2), path(p1, a1)));
57 assertEquals("path ignored, 1st more recent", -1, sorter.compare(path(p1, a2), path(p2, a1)));
58 assertEquals("path ignored, 1st more recent", -1, sorter.compare(path(p2, a2), path(p1, a1)));
59
60 assertEquals("same path, same time", 0, sorter.compare(path(p1, a1), path(p1, a1)));
61 assertEquals("p2 < p1, same time", 1, sorter.compare(path(p1, a1), path(p2, a1)));
62 assertEquals("p2 < p1, same time", -1, sorter.compare(path(p2, a1), path(p1, a1)));
6363 }
6464
6565 @Test
7171 final DummyFileAttributes a2 = new DummyFileAttributes();
7272 a1.lastModified = FileTime.fromMillis(100);
7373 a2.lastModified = FileTime.fromMillis(222);
74
75 assertEquals(-1, sorter.compare(path(p1, a1), path(p1, a2)), "same path, 2nd more recent");
76 assertEquals(-1, sorter.compare(path(p1, a1), path(p2, a2)), "path ignored, 2nd more recent");
77 assertEquals(-1, sorter.compare(path(p2, a1), path(p1, a2)), "path ignored, 2nd more recent");
78
79 assertEquals(1, sorter.compare(path(p1, a2), path(p1, a1)), "same path, 1st more recent");
80 assertEquals(1, sorter.compare(path(p1, a2), path(p2, a1)), "path ignored, 1st more recent");
81 assertEquals(1, sorter.compare(path(p2, a2), path(p1, a1)), "path ignored, 1st more recent");
82
83 assertEquals(0, sorter.compare(path(p1, a1), path(p1, a1)), "same path, same time");
84 assertEquals(-1, sorter.compare(path(p1, a1), path(p2, a1)), "p1 < p2, same time");
85 assertEquals(1, sorter.compare(path(p2, a1), path(p1, a1)), "p1 < p2, same time");
74
75 assertEquals("same path, 2nd more recent", -1, sorter.compare(path(p1, a1), path(p1, a2)));
76 assertEquals("path ignored, 2nd more recent", -1, sorter.compare(path(p1, a1), path(p2, a2)));
77 assertEquals("path ignored, 2nd more recent", -1, sorter.compare(path(p2, a1), path(p1, a2)));
78
79 assertEquals("same path, 1st more recent", 1, sorter.compare(path(p1, a2), path(p1, a1)));
80 assertEquals("path ignored, 1st more recent", 1, sorter.compare(path(p1, a2), path(p2, a1)));
81 assertEquals("path ignored, 1st more recent", 1, sorter.compare(path(p2, a2), path(p1, a1)));
82
83 assertEquals("same path, same time", 0, sorter.compare(path(p1, a1), path(p1, a1)));
84 assertEquals("p1 < p2, same time", -1, sorter.compare(path(p1, a1), path(p2, a1)));
85 assertEquals("p1 < p2, same time", 1, sorter.compare(path(p2, a1), path(p1, a1)));
8686 }
8787
8888 private PathWithAttributes path(final Path path, final DummyFileAttributes attributes) {
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.apache.logging.log4j.core.config.Configuration;
20 import org.apache.logging.log4j.core.config.DefaultConfiguration;
21 import org.apache.logging.log4j.core.script.Script;
22 import org.junit.jupiter.api.Tag;
23 import org.junit.jupiter.api.Test;
24
2519 import java.nio.file.Path;
2620 import java.nio.file.Paths;
2721 import java.util.ArrayList;
2822 import java.util.List;
2923
30 import static org.junit.jupiter.api.Assertions.*;
24 import org.apache.logging.log4j.categories.Scripts;
25 import org.apache.logging.log4j.core.config.Configuration;
26 import org.apache.logging.log4j.core.config.DefaultConfiguration;
27 import org.apache.logging.log4j.core.script.Script;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30
31 import static org.junit.Assert.*;
3132
3233 /**
3334 * Tests the ScriptCondition class.
3435 */
3536 public class ScriptConditionTest {
3637
37 @Test
38 @Test(expected = NullPointerException.class)
3839 public void testConstructorDisallowsNullScript() {
39 assertThrows(NullPointerException.class, () -> new ScriptCondition(null, new DefaultConfiguration()));
40 new ScriptCondition(null, new DefaultConfiguration());
4041 }
4142
42 @Test
43 @Test(expected = NullPointerException.class)
4344 public void testConstructorDisallowsNullConfig() {
44 assertThrows(NullPointerException.class,
45 () -> new ScriptCondition(new Script("test", "js", "print('hi')"), null));
45 new ScriptCondition(new Script("test", "js", "print('hi')"), null);
4646 }
4747
4848 @Test
5050 assertNull(ScriptCondition.createCondition(null, new DefaultConfiguration()));
5151 }
5252
53 @Test
53 @Test(expected = NullPointerException.class)
5454 public void testCreateConditionDisallowsNullConfig() {
55 assertThrows(NullPointerException.class, () -> ScriptCondition.createCondition(
56 new Script("test", "js", "print('hi')"), null));
55 ScriptCondition.createCondition(new Script("test", "js", "print('hi')"), null);
5756 }
5857
5958 @Test
9291 }
9392
9493 @Test
95 @Tag("groovy")
94 @Category(Scripts.Groovy.class)
9695 public void testSelectFilesToDelete3() {
9796 final Configuration config = new DefaultConfiguration();
9897 config.initialize(); // creates the ScriptManager
1616
1717 package org.apache.logging.log4j.core.appender.rolling.action;
1818
19 import org.junit.jupiter.api.BeforeEach;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.api.io.TempDir;
22
23 import java.io.IOException;
2419 import java.nio.file.FileVisitOption;
25 import java.nio.file.FileVisitResult;
2620 import java.nio.file.Files;
27 import java.nio.file.NoSuchFileException;
2821 import java.nio.file.Path;
29 import java.nio.file.Paths;
22 import java.nio.file.attribute.FileAttribute;
3023 import java.nio.file.attribute.FileTime;
3124 import java.util.Collections;
3225 import java.util.List;
3326 import java.util.Set;
3427
35 import static org.junit.jupiter.api.Assertions.*;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31
32 import static org.junit.Assert.*;
3633
3734 /**
3835 * Tests the SortingVisitor class.
3936 */
4037 public class SortingVisitorTest {
4138
42 @TempDir
43 Path base;
39 private Path base;
4440 private Path aaa;
4541 private Path bbb;
4642 private Path ccc;
4743
48 @BeforeEach
44 @Before
4945 public void setUp() throws Exception {
50 aaa = Files.createFile(base.resolve("aaa"));
51 bbb = Files.createFile(base.resolve("bbb"));
52 ccc = Files.createFile(base.resolve("ccc"));
46 base = Files.createTempDirectory("tempDir", new FileAttribute<?>[0]);
47 aaa = Files.createTempFile(base, "aaa", null, new FileAttribute<?>[0]);
48 bbb = Files.createTempFile(base, "bbb", null, new FileAttribute<?>[0]);
49 ccc = Files.createTempFile(base, "ccc", null, new FileAttribute<?>[0]);
5350
5451 // lastModified granularity is 1 sec(!) on some file systems...
5552 final long now = System.currentTimeMillis();
5653 Files.setLastModifiedTime(aaa, FileTime.fromMillis(now));
5754 Files.setLastModifiedTime(bbb, FileTime.fromMillis(now + 1000));
5855 Files.setLastModifiedTime(ccc, FileTime.fromMillis(now + 2000));
56 }
57
58 @After
59 public void tearDown() throws Exception {
60 Files.deleteIfExists(ccc);
61 Files.deleteIfExists(bbb);
62 Files.deleteIfExists(aaa);
63 Files.deleteIfExists(base);
5964 }
6065
6166 @Test
6671
6772 final List<PathWithAttributes> found = visitor.getSortedPaths();
6873 assertNotNull(found);
69 assertEquals(3, found.size(), "file count");
70 assertEquals(ccc, found.get(0).getPath(), "1st: most recent; sorted=" + found);
71 assertEquals(bbb, found.get(1).getPath(), "2nd; sorted=" + found);
72 assertEquals(aaa, found.get(2).getPath(), "3rd: oldest; sorted=" + found);
74 assertEquals("file count", 3, found.size());
75 assertEquals("1st: most recent; sorted=" + found, ccc, found.get(0).getPath());
76 assertEquals("2nd; sorted=" + found, bbb, found.get(1).getPath());
77 assertEquals("3rd: oldest; sorted=" + found, aaa, found.get(2).getPath());
7378 }
7479
7580 @Test
8085
8186 final List<PathWithAttributes> found = visitor.getSortedPaths();
8287 assertNotNull(found);
83 assertEquals(3, found.size(), "file count");
84 assertEquals(aaa, found.get(0).getPath(), "1st: oldest first; sorted=" + found);
85 assertEquals(bbb, found.get(1).getPath(), "2nd; sorted=" + found);
86 assertEquals(ccc, found.get(2).getPath(), "3rd: most recent sorted; list=" + found);
87 }
88
89 @Test
90 public void testNoSuchFileFailure() throws IOException {
91 SortingVisitor visitor = new SortingVisitor(new PathSortByModificationTime(false));
92 assertSame(
93 FileVisitResult.CONTINUE,
94 visitor.visitFileFailed(Paths.get("doesNotExist"), new NoSuchFileException("doesNotExist")));
95 }
96
97 @Test
98 public void testIOException() {
99 SortingVisitor visitor = new SortingVisitor(new PathSortByModificationTime(false));
100 IOException exception = new IOException();
101 assertSame(exception,
102 assertThrows(IOException.class, () -> visitor.visitFileFailed(Paths.get("doesNotExist"), exception)));
88 assertEquals("file count", 3, found.size());
89 assertEquals("1st: oldest first; sorted=" + found, aaa, found.get(0).getPath());
90 assertEquals("2nd; sorted=" + found, bbb, found.get(1).getPath());
91 assertEquals("3rd: most recent sorted; list=" + found, ccc, found.get(2).getPath());
10392 }
10493 }
+0
-67
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender2767Test.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.logging.log4j.core.appender.routing;
17
18 import org.apache.logging.log4j.EventLogger;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.apache.logging.log4j.message.StructuredDataMessage;
21 import org.junit.After;
22 import org.junit.Before;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.rules.RuleChain;
26
27 import java.io.File;
28 import java.nio.file.Files;
29 import java.util.List;
30 import java.util.stream.Collectors;
31
32 import static org.junit.Assert.assertEquals;
33 import static org.junit.Assert.assertTrue;
34
35 /**
36 *
37 */
38 public class RoutingAppender2767Test {
39 private static final String CONFIG = "log4j-routing-2767.xml";
40 private static final String ACTIVITY_LOG_FILE = "target/routing1/routingtest-Service.log";
41
42 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
43
44 @Rule
45 public RuleChain rules = loggerContextRule.withCleanFilesRule(ACTIVITY_LOG_FILE);
46
47 @Before
48 public void setUp() throws Exception {
49 }
50
51 @After
52 public void tearDown() throws Exception {
53 this.loggerContextRule.getLoggerContext().stop();
54 }
55
56 @Test
57 public void routingTest() throws Exception {
58 StructuredDataMessage msg = new StructuredDataMessage("Test", "This is a test", "Service");
59 EventLogger.logEvent(msg);
60 File file = new File(ACTIVITY_LOG_FILE);
61 assertTrue("Activity file was not created", file.exists());
62 List<String> lines = Files.lines(file.toPath()).collect(Collectors.toList());
63 assertEquals("Incorrect number of lines", 1, lines.size());
64 assertTrue("Incorrect content", lines.get(0).contains("This is a test"));
65 }
66 }
2525 import org.junit.Test;
2626
2727 import static org.junit.Assert.assertEquals;
28 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.junit.Assert.assertTrue;
2929
3030 public class RoutingAppenderKeyLookupEvaluationTest {
3131 private static final String CONFIG = "log4j-routing-lookup.xml";
5858 }
5959
6060 @Before
61 public void before() throws NamingException {
61 public void before() {
6262 listAppender1 = RoutingAppenderWithJndiTest.loggerContextRule.getListAppender("List1");
6363 listAppender2 = RoutingAppenderWithJndiTest.loggerContextRule.getListAppender("List2");
6464 }
+0
-98
log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncAppenderExceptionHandlingTest.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.logging.log4j.core.async;
17
18 import org.apache.logging.log4j.core.Appender;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.appender.AsyncAppender;
23 import org.apache.logging.log4j.core.config.AppenderControl;
24 import org.apache.logging.log4j.core.config.Configuration;
25 import org.apache.logging.log4j.core.config.Configurator;
26 import org.apache.logging.log4j.message.Message;
27 import org.apache.logging.log4j.test.appender.FailOnceAppender;
28 import org.apache.logging.log4j.util.Strings;
29 import org.junit.jupiter.api.Assertions;
30 import org.junit.jupiter.params.ParameterizedTest;
31 import org.junit.jupiter.params.provider.ValueSource;
32
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.stream.Collectors;
36
37 /**
38 * Verifies {@link AsyncAppender} works after certain type of {@link Appender}
39 * failures.
40 * <p>
41 * {@code AsyncAppender} thread is known to get killed due to
42 * {@link AppenderControl} leaking exceptions in the past. This class is more
43 * of an end-to-end test to verify that {@code AsyncAppender} still works even
44 * if the background thread gets killed.
45 */
46 class AsyncAppenderExceptionHandlingTest {
47
48 @ParameterizedTest
49 @ValueSource(strings = {
50 FailOnceAppender.ThrowableClassName.RUNTIME_EXCEPTION,
51 FailOnceAppender.ThrowableClassName.LOGGING_EXCEPTION,
52 FailOnceAppender.ThrowableClassName.EXCEPTION,
53 FailOnceAppender.ThrowableClassName.ERROR,
54 FailOnceAppender.ThrowableClassName.THROWABLE,
55 FailOnceAppender.ThrowableClassName.THREAD_DEATH
56 })
57 void AsyncAppender_should_not_stop_on_appender_failures(String throwableClassName) {
58
59 // Create the logger.
60 final String throwableClassNamePropertyName = "throwableClassName";
61 System.setProperty(throwableClassNamePropertyName, throwableClassName);
62 try (final LoggerContext loggerContext =
63 Configurator.initialize("Test", "AsyncAppenderExceptionHandlingTest.xml")) {
64 final Logger logger = loggerContext.getRootLogger();
65
66 // Log the 1st message, which should fail due to the FailOnceAppender.
67 logger.info("message #1");
68
69 // Log the 2nd message, which should succeed.
70 final String lastLogMessage = "message #2";
71 logger.info(lastLogMessage);
72
73 // Stop the AsyncAppender to drain the queued events.
74 Configuration configuration = loggerContext.getConfiguration();
75 AsyncAppender asyncAppender = configuration.getAppender("Async");
76 Assertions.assertNotNull(asyncAppender, "couldn't obtain the FailOnceAppender");
77 asyncAppender.stop();
78
79 // Verify the logged message.
80 final FailOnceAppender failOnceAppender = configuration.getAppender("FailOnce");
81 Assertions.assertNotNull(failOnceAppender, "couldn't obtain the FailOnceAppender");
82 Assertions.assertTrue(failOnceAppender.isFailed(), "FailOnceAppender hasn't failed yet");
83 final List<String> accumulatedMessages = failOnceAppender
84 .drainEvents()
85 .stream()
86 .map(LogEvent::getMessage)
87 .map(Message::getFormattedMessage)
88 .collect(Collectors.toList());
89 Assertions.assertEquals(Collections.singletonList(lastLogMessage), accumulatedMessages);
90
91 } finally {
92 System.setProperty(throwableClassNamePropertyName, Strings.EMPTY);
93 }
94
95 }
96
97 }
7070 final LoggerConfig rootLoggerConfig =
7171 AsyncLoggerConfig.RootLogger.createLogger(
7272 null, "INFO", null, new AppenderRef[0], null, new DefaultConfiguration(), null);
73 assertFalse("Include location should default to false for async loggers",
73 assertFalse("Include location should default to false for async logggers",
7474 rootLoggerConfig.isIncludeLocation());
7575
7676 final LoggerConfig loggerConfig =
7777 AsyncLoggerConfig.createLogger(
7878 null, "INFO", "com.foo.Bar", null, new AppenderRef[0], null, new DefaultConfiguration(),
7979 null);
80 assertFalse("Include location should default to false for async loggers",
80 assertFalse("Include location should default to false for async logggers",
8181 loggerConfig.isIncludeLocation());
8282 }
8383 }
6464 assertEquals(expectedContextName, context.getName());
6565 }
6666
67 @Test
68 public void testDependentOnClassLoader() {
69 final AsyncLoggerContextSelector selector = new AsyncLoggerContextSelector();
70 assertTrue(selector.isClassLoaderDependent());
71 }
7267 }
105105 public void removeContext(final LoggerContext context) {
106106 // does not remove anything
107107 }
108
109 @Override
110 public boolean isClassLoaderDependent() {
111 return false;
112 }
113108 }
114109 }
+0
-148
log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerEventTranslationExceptionTest.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.logging.log4j.core.async;
17
18 import com.lmax.disruptor.ExceptionHandler;
19 import org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.categories.AsyncLoggers;
23 import org.apache.logging.log4j.core.CoreLoggerContexts;
24 import org.apache.logging.log4j.core.util.Constants;
25 import org.apache.logging.log4j.message.Message;
26 import org.apache.logging.log4j.message.ReusableSimpleMessage;
27 import org.apache.logging.log4j.spi.AbstractLogger;
28 import org.junit.experimental.categories.Category;
29 import org.junit.jupiter.api.AfterAll;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.Test;
32
33 import static org.junit.jupiter.api.Assertions.*;
34
35 /**
36 * Test an exception thrown in {@link RingBufferLogEventTranslator#translateTo(RingBufferLogEvent, long)}
37 * does not cause another exception to be thrown later in the background thread
38 * in {@link RingBufferLogEventHandler#onEvent(RingBufferLogEvent, long, boolean)}.
39 *
40 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-2816">LOG4J2-2816</a>
41 */
42 @Category(AsyncLoggers.class)
43 class AsyncLoggerEventTranslationExceptionTest {
44
45 @BeforeAll
46 public static void beforeAll() {
47 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, AsyncLoggerContextSelector.class.getName());
48 System.setProperty("AsyncLogger.ExceptionHandler", TestExceptionHandler.class.getName());
49 }
50
51 @AfterAll
52 public static void afterAll() {
53 System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
54 System.clearProperty("AsyncLogger.ExceptionHandler");
55 }
56
57 @Test
58 void testEventTranslationExceptionDoesNotCauseAsyncEventException() {
59
60 final Logger log = LogManager.getLogger("com.foo.Bar");
61
62 assertTrue(
63 TestExceptionHandler.INSTANTIATED,
64 "TestExceptionHandler was not configured properly");
65
66 final Message exceptionThrowingMessage = new ExceptionThrowingMessage();
67 assertThrows(
68 TestMessageException.class,
69 () -> ((AbstractLogger) log).logMessage(
70 "com.foo.Bar",
71 Level.INFO,
72 null,
73 exceptionThrowingMessage,
74 null));
75
76 CoreLoggerContexts.stopLoggerContext(); // stop async thread
77
78 assertFalse(
79 TestExceptionHandler.EVENT_EXCEPTION_ENCOUNTERED,
80 "ExceptionHandler encountered an event exception");
81
82 }
83
84 public static final class TestExceptionHandler implements ExceptionHandler<RingBufferLogEvent> {
85
86 private static boolean INSTANTIATED = false;
87
88 private static boolean EVENT_EXCEPTION_ENCOUNTERED = false;
89
90 public TestExceptionHandler() {
91 INSTANTIATED = true;
92 }
93
94 @Override
95 public void handleEventException(final Throwable error, final long sequence, final RingBufferLogEvent event) {
96 EVENT_EXCEPTION_ENCOUNTERED = true;
97 }
98
99 @Override
100 public void handleOnStartException(final Throwable error) {
101 fail("Unexpected start exception: " + error.getMessage());
102 }
103
104 @Override
105 public void handleOnShutdownException(final Throwable error) {
106 fail("Unexpected shutdown exception: " + error.getMessage());
107 }
108
109 }
110
111 private static class TestMessageException extends RuntimeException {}
112
113 private static final class ExceptionThrowingMessage extends ReusableSimpleMessage {
114
115 @Override
116 public String getFormattedMessage() {
117 throw new TestMessageException();
118 }
119
120 @Override
121 public String getFormat() {
122 throw new TestMessageException();
123 }
124
125 @Override
126 public Object[] getParameters() {
127 throw new TestMessageException();
128 }
129
130 @Override
131 public void formatTo(final StringBuilder buffer) {
132 throw new TestMessageException();
133 }
134
135 @Override
136 public Object[] swapParameters(final Object[] emptyReplacement) {
137 throw new TestMessageException();
138 }
139
140 @Override
141 public short getParameterCount() {
142 throw new TestMessageException();
143 }
144
145 }
146
147 }
7171
7272 final String location = "testAsyncLogWritesToLog";
7373 assertTrue("no location", !line1.contains(location));
74
75 assertTrue(LogManager.getFactory().isClassLoaderDependent());
7674 }
7775
7876 // NOTE: only define one @Test method per test class with Async Loggers to prevent spurious failures
+0
-109
log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTestArgumentFreedOnError.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.logging.log4j.core.async;
17
18 import static org.junit.Assert.assertTrue;
19
20 import java.util.concurrent.CountDownLatch;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.categories.AsyncLoggers;
25 import org.apache.logging.log4j.core.GarbageCollectionHelper;
26 import org.apache.logging.log4j.core.util.Constants;
27 import org.apache.logging.log4j.message.Message;
28 import org.apache.logging.log4j.util.StringBuilderFormattable;
29 import org.apache.logging.log4j.util.Strings;
30 import org.junit.AfterClass;
31 import org.junit.BeforeClass;
32 import org.junit.Test;
33 import org.junit.experimental.categories.Category;
34
35 @Category(AsyncLoggers.class)
36 public class AsyncLoggerTestArgumentFreedOnError {
37
38 @BeforeClass
39 public static void beforeClass() {
40 System.setProperty("log4j2.enable.threadlocals", "true");
41 System.setProperty("log4j2.enable.direct.encoders", "true");
42 System.setProperty("log4j2.is.webapp", "false");
43 System.setProperty("log4j.format.msg.async", "true");
44 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
45 AsyncLoggerContextSelector.class.getName());
46 }
47
48 @AfterClass
49 public static void afterClass() {
50 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, Strings.EMPTY);
51 }
52
53 // LOG4J2-2725: events are cleared even after failure
54 @Test
55 public void testMessageIsGarbageCollected() throws Exception {
56 final AsyncLogger log = (AsyncLogger) LogManager.getLogger("com.foo.Bar");
57 CountDownLatch garbageCollectionLatch = new CountDownLatch(1);
58 log.fatal(new ThrowingMessage(garbageCollectionLatch));
59 GarbageCollectionHelper gcHelper = new GarbageCollectionHelper();
60 gcHelper.run();
61 try {
62 assertTrue("Parameter should have been garbage collected",
63 garbageCollectionLatch.await(30, TimeUnit.SECONDS));
64 } finally {
65 gcHelper.close();
66 }
67 }
68
69 private static class ThrowingMessage implements Message, StringBuilderFormattable {
70
71 private final CountDownLatch latch;
72
73 ThrowingMessage(CountDownLatch latch) {
74 this.latch = latch;
75 }
76
77 @Override
78 protected void finalize() throws Throwable {
79 latch.countDown();
80 super.finalize();
81 }
82
83 @Override
84 public String getFormattedMessage() {
85 throw new Error("Expected");
86 }
87
88 @Override
89 public String getFormat() {
90 return Strings.EMPTY;
91 }
92
93 @Override
94 public Object[] getParameters() {
95 return org.apache.logging.log4j.util.Constants.EMPTY_OBJECT_ARRAY;
96 }
97
98 @Override
99 public Throwable getThrowable() {
100 return null;
101 }
102
103 @Override
104 public void formatTo(StringBuilder buffer) {
105 throw new Error("Expected");
106 }
107 }
108 }
2525
2626 @Category(AsyncLoggers.class)
2727 public class AsyncLoggerThreadNameStrategyTest {
28 static final String DEFAULT_STRATEGY = System.getProperty("java.version").compareTo("1.8.0_102") < 0
29 ? "CACHED" // LOG4J2-2052 JDK 8u102 removed the String allocation in Thread.getName()
30 : "UNCACHED";
31
2832 @After
2933 public void after() {
3034 System.clearProperty("AsyncLogger.ThreadNameStrategy");
3640 }
3741
3842 @Test
39 public void testDefaultIfNotConfigured() throws Exception {
43 public void testDefaultThreadNameIsCached() throws Exception {
4044 final ThreadNameCachingStrategy tns = ThreadNameCachingStrategy.create();
41 assertSame(ThreadNameCachingStrategy.DEFAULT_STRATEGY, tns);
45 assertSame(ThreadNameCachingStrategy.valueOf(DEFAULT_STRATEGY), tns);
4246 }
4347
4448 @Test
45 public void testDefaultIfInvalidConfig() throws Exception {
49 public void testUseCachedThreadNameIfInvalidConfig() throws Exception {
4650 System.setProperty("AsyncLogger.ThreadNameStrategy", "\\%%InValid ");
4751 final ThreadNameCachingStrategy tns = ThreadNameCachingStrategy.create();
48 assertSame(ThreadNameCachingStrategy.DEFAULT_STRATEGY, tns);
52 assertSame(ThreadNameCachingStrategy.valueOf(DEFAULT_STRATEGY), tns);
4953 }
5054
5155 @Test
5050 final File configFile = FileUtils.fileFromUri(url.toURI());
5151
5252 final Logger logger = LogManager.getLogger(AsyncRootReloadTest.class);
53 logger.info("Log4j configured, will be reconfigured in approx. 5 sec");
53 logger.info("Log4j configured, will be reconfigured in aprox. 5 sec");
5454
5555 configFile.setLastModified(System.currentTimeMillis());
5656
+0
-107
log4j-core/src/test/java/org/apache/logging/log4j/core/async/BasicAsyncLoggerContextSelectorTest.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.logging.log4j.core.async;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.categories.AsyncLoggers;
20 import org.apache.logging.log4j.core.LifeCycle;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.util.Constants;
23 import org.junit.AfterClass;
24 import org.junit.BeforeClass;
25 import org.junit.Test;
26 import org.junit.experimental.categories.Category;
27
28 import java.util.List;
29
30 import static org.junit.Assert.assertEquals;
31 import static org.junit.Assert.assertFalse;
32 import static org.junit.Assert.assertTrue;
33
34 @Category(AsyncLoggers.class)
35 public class BasicAsyncLoggerContextSelectorTest {
36
37 private static final String FQCN = BasicAsyncLoggerContextSelectorTest.class.getName();
38
39 @BeforeClass
40 public static void beforeClass() {
41 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
42 BasicAsyncLoggerContextSelector.class.getName());
43 }
44
45 @AfterClass
46 public static void afterClass() {
47 System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
48 }
49
50 @Test
51 public void testContextReturnsAsyncLoggerContext() {
52 final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
53 final LoggerContext context = selector.getContext(FQCN, null, false);
54
55 assertTrue(context instanceof AsyncLoggerContext);
56 }
57
58 @Test
59 public void testContext2ReturnsAsyncLoggerContext() {
60 final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
61 final LoggerContext context = selector.getContext(FQCN, null, false, null);
62
63 assertTrue(context instanceof AsyncLoggerContext);
64 }
65
66 @Test
67 public void testLoggerContextsReturnsAsyncLoggerContext() {
68 final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
69
70 List<LoggerContext> list = selector.getLoggerContexts();
71 assertEquals(1, list.size());
72 assertTrue(list.get(0) instanceof AsyncLoggerContext);
73
74 selector.getContext(FQCN, null, false);
75
76 list = selector.getLoggerContexts();
77 assertEquals(1, list.size());
78 assertTrue(list.get(0) instanceof AsyncLoggerContext);
79 }
80
81 @Test
82 public void testContextNameIsAsyncDefault() {
83 final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
84 final LoggerContext context = selector.getContext(FQCN, null, false);
85 assertEquals("AsyncDefault" , context.getName());
86 }
87
88 @Test
89 public void testDependentOnClassLoader() {
90 final BasicAsyncLoggerContextSelector selector = new BasicAsyncLoggerContextSelector();
91 assertFalse(selector.isClassLoaderDependent());
92 }
93
94 @Test
95 public void testFactoryIsNotDependentOnClassLoader() {
96 assertFalse(LogManager.getFactory().isClassLoaderDependent());
97 }
98
99 @Test
100 public void testLogManagerShutdown() {
101 LoggerContext context = (LoggerContext) LogManager.getContext();
102 assertEquals(LifeCycle.State.STARTED, context.getState());
103 LogManager.shutdown();
104 assertEquals(LifeCycle.State.STOPPED, context.getState());
105 }
106 }
4141 @Plugin(name = "Blocking", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
4242 public class BlockingAppender extends AbstractAppender {
4343 private static final long serialVersionUID = 1L;
44 // logEvents may be nulled to disable event tracking, this is useful in scenarios testing garbage collection.
4544 public List<LogEvent> logEvents = new CopyOnWriteArrayList<>();
4645 public CountDownLatch countDownLatch = null;
4746
5655 event.getMessage().getFormattedMessage();
5756
5857 // may be a reusable event, make a copy, don't keep a reference to the original event
59 List<LogEvent> events = logEvents;
60 if (events != null) {
61 events.add(Log4jLogEvent.createMemento(event));
62 }
58 logEvents.add(Log4jLogEvent.createMemento(event));
6359
6460 if (countDownLatch == null) {
6561 return;
8383 }
8484 }
8585
86 static Stack<String> transform(final List<LogEvent> logEvents) {
86 static Stack transform(final List<LogEvent> logEvents) {
8787 final List<String> filtered = new ArrayList<>(logEvents.size());
8888 for (final LogEvent event : logEvents) {
8989 filtered.add(event.getMessage().getFormattedMessage());
+0
-131
log4j-core/src/test/java/org/apache/logging/log4j/core/async/QueueFullAsyncLoggerTest3.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.logging.log4j.core.async;
17
18 import static org.junit.Assert.assertTrue;
19
20 import java.util.concurrent.CountDownLatch;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.categories.AsyncLoggers;
26 import org.apache.logging.log4j.core.GarbageCollectionHelper;
27 import org.apache.logging.log4j.core.config.ConfigurationFactory;
28 import org.apache.logging.log4j.core.util.Constants;
29 import org.apache.logging.log4j.junit.LoggerContextRule;
30 import org.apache.logging.log4j.message.Message;
31 import org.apache.logging.log4j.util.Strings;
32 import org.junit.AfterClass;
33 import org.junit.Before;
34 import org.junit.BeforeClass;
35 import org.junit.Rule;
36 import org.junit.Test;
37 import org.junit.experimental.categories.Category;
38 import org.junit.runner.RunWith;
39 import org.junit.runners.BlockJUnit4ClassRunner;
40
41 /**
42 * Tests queue full scenarios with pure AsyncLoggers (all loggers async).
43 */
44 @RunWith(BlockJUnit4ClassRunner.class)
45 @Category(AsyncLoggers.class)
46 public class QueueFullAsyncLoggerTest3 extends QueueFullAbstractTest {
47
48 @BeforeClass
49 public static void beforeClass() {
50 //FORMAT_MESSAGES_IN_BACKGROUND
51 System.setProperty("log4j.format.msg.async", "true");
52 System.setProperty("log4j2.asyncQueueFullPolicy", "discard");
53
54 System.setProperty("AsyncLogger.RingBufferSize", "128"); // minimum ringbuffer size
55 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
56 "log4j2-queueFull.xml");
57 }
58
59 @AfterClass
60 public static void afterClass() {
61 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, Strings.EMPTY);
62 }
63
64 @Rule
65 public LoggerContextRule context = new LoggerContextRule(
66 "log4j2-queueFull.xml", AsyncLoggerContextSelector.class);
67
68 @Before
69 public void before() throws Exception {
70 blockingAppender = context.getRequiredAppender("Blocking", BlockingAppender.class);
71 }
72
73
74 @Test(timeout = 15000)
75 public void discardedMessagesShouldBeGarbageCollected() throws InterruptedException {
76 final Logger logger = LogManager.getLogger(this.getClass());
77
78 blockingAppender.logEvents = null;
79 blockingAppender.countDownLatch = new CountDownLatch(1);
80 int count = 200;
81 CountDownLatch garbageCollectionLatch = new CountDownLatch(count);
82 for (int i = 0; i < count; i++) {
83 logger.info(new CountdownOnGarbageCollectMessage(garbageCollectionLatch));
84 }
85 blockingAppender.countDownLatch.countDown();
86
87 final GarbageCollectionHelper gcHelper = new GarbageCollectionHelper();
88 gcHelper.run();
89 try {
90 assertTrue("Parameter should have been garbage collected", garbageCollectionLatch.await(30, TimeUnit.SECONDS));
91 } finally {
92 gcHelper.close();
93 }
94 }
95
96 private static final class CountdownOnGarbageCollectMessage implements Message {
97
98 private final CountDownLatch latch;
99
100 CountdownOnGarbageCollectMessage(CountDownLatch latch) {
101 this.latch = latch;
102 }
103
104 @Override
105 public String getFormattedMessage() {
106 return "formatted";
107 }
108
109 @Override
110 public String getFormat() {
111 return null;
112 }
113
114 @Override
115 public Object[] getParameters() {
116 return org.apache.logging.log4j.util.Constants.EMPTY_OBJECT_ARRAY;
117 }
118
119 @Override
120 public Throwable getThrowable() {
121 return null;
122 }
123
124 @Override
125 protected void finalize() throws Throwable {
126 latch.countDown();
127 super.finalize();
128 }
129 }
130 }
3131 import org.apache.logging.log4j.core.LogEvent;
3232 import org.apache.logging.log4j.core.util.DummyNanoClock;
3333 import org.apache.logging.log4j.core.time.internal.FixedPreciseClock;
34 import org.apache.logging.log4j.message.ParameterConsumer;
3435 import org.apache.logging.log4j.message.ReusableMessageFactory;
3536 import org.apache.logging.log4j.util.FilteredObjectInputStream;
3637 import org.apache.logging.log4j.util.StringMap;
5556 public void testToImmutable() {
5657 final LogEvent logEvent = new RingBufferLogEvent();
5758 Assert.assertNotSame(logEvent, logEvent.toImmutable());
58 }
59
60 /**
61 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-2816">LOG4J2-2816</a>
62 */
63 @Test
64 public void testIsPopulated() {
65 final RingBufferLogEvent evt = new RingBufferLogEvent();
66
67 assertFalse(evt.isPopulated());
68
69 final String loggerName = null;
70 final Marker marker = null;
71 final String fqcn = null;
72 final Level level = null;
73 final Message data = null;
74 final Throwable t = null;
75 final ContextStack contextStack = null;
76 final String threadName = null;
77 final StackTraceElement location = null;
78 evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(),
79 contextStack, -1, threadName, -1, location, new FixedPreciseClock(), new DummyNanoClock(1));
80
81 assertTrue(evt.isPopulated());
82
83 evt.clear();
84
85 assertFalse(evt.isPopulated());
8659 }
8760
8861 @Test
279252 @Test
280253 public void testForEachParameterNothingSet() {
281254 final RingBufferLogEvent evt = new RingBufferLogEvent();
282 evt.forEachParameter((parameter, parameterIndex, state) -> fail("Should not have been called"), null);
255 evt.forEachParameter(new ParameterConsumer<Void>() {
256 @Override
257 public void accept(final Object parameter, final int parameterIndex, final Void state) {
258 fail("Should not have been called");
259 }
260 }, null);
283261 }
284262 }
3030 private final Thread backGroundThread;
3131
3232 AbstractRunQueue() {
33 backGroundThread = new Thread(() -> {
34 for (; ; ) {
35 try {
36 if (Objects.equals(queue.take(), STOP)) {
33 backGroundThread = new Thread(new Runnable() {
34 @Override
35 public void run() {
36 for (; ; ) {
37 try {
38 if (Objects.equals(queue.take(), STOP)) {
39 break;
40 }
41 } catch (final InterruptedException e) {
42 e.printStackTrace();
3743 break;
3844 }
39 } catch (final InterruptedException e) {
40 e.printStackTrace();
41 break;
4245 }
4346 }
4447 });
212212 maxValue = 0L;
213213 minValue = Long.MAX_VALUE;
214214
215 Arrays.fill(counts, 0L);
215 for (int i = 0, size = counts.length; i < size; i++)
216 {
217 counts[i] = 0L;
218 }
216219 }
217220
218221 /**
3636 // warmup at least 2 rounds and at most 1 minute
3737 final Histogram warmupHist = PerfTest.createHistogram();
3838 final long stop = System.nanoTime() + TimeUnit.MINUTES.toNanos(1);
39 final Runnable run1 = () -> {
40 for (int i = 0; i < 10; i++) {
41 final int LINES = PerfTest.throughput ? 50000 : 200000;
42 runTest(runner, LINES, null, warmupHist, 2);
43 if (i > 0 && System.nanoTime() - stop >= 0) {
44 return;
39 final Runnable run1 = new Runnable() {
40 @Override
41 public void run() {
42 for (int i = 0; i < 10; i++) {
43 final int LINES = PerfTest.throughput ? 50000 : 200000;
44 runTest(runner, LINES, null, warmupHist, 2);
45 if (i > 0 && System.nanoTime() - stop >= 0) {
46 return;
47 }
4548 }
4649 }
4750 };
138138 // use reflection so we can use the same test with older versions of log4j2
139139 try {
140140 final Method setUseThreadLocals =
141 AsyncLoggerContext.class.getDeclaredMethod("setUseThreadLocals", boolean.class);
141 AsyncLoggerContext.class.getDeclaredMethod("setUseThreadLocals", new Class[]{boolean.class});
142142 final LoggerContext context = LogManager.getContext(false);
143 setUseThreadLocals.invoke(context, Boolean.TRUE);
143 setUseThreadLocals.invoke(context, new Object[] {Boolean.TRUE});
144144 } catch (final Throwable ignored) {
145145 }
146146 }
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
17 package org.apache.logging.log4j.core.config;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.fail;
22
23 import org.apache.logging.log4j.core.appender.RollingFileAppender;
24 import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
25 import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
26 import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
27 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
28 import org.apache.logging.log4j.junit.LoggerContextRule;
29 import org.junit.Rule;
30 import org.junit.Test;
31
32 public abstract class AbstractLog4j2_1100Test {
33
34 @Rule
35 public LoggerContextRule context = new LoggerContextRule(getConfigurationResource());
36
37 protected abstract String getConfigurationResource();
38
39 @Test
40 public void test() {
41 final Configuration configuration = context.getConfiguration();
42 assertNotNull(configuration);
43 final RollingFileAppender appender = configuration.getAppender("File");
44 assertNotNull(appender);
45 final CompositeTriggeringPolicy compositeTriggeringPolicy = appender.getTriggeringPolicy();
46 assertNotNull(compositeTriggeringPolicy);
47 final TriggeringPolicy[] triggeringPolicies = compositeTriggeringPolicy.getTriggeringPolicies();
48 SizeBasedTriggeringPolicy sizeBasedTriggeringPolicy = null;
49 TimeBasedTriggeringPolicy timeBasedTriggeringPolicy = null;
50 for (final TriggeringPolicy triggeringPolicy : triggeringPolicies) {
51 if (triggeringPolicy instanceof TimeBasedTriggeringPolicy) {
52 timeBasedTriggeringPolicy = (TimeBasedTriggeringPolicy) triggeringPolicy;
53 assertEquals(7, timeBasedTriggeringPolicy.getInterval());
54 }
55 if (triggeringPolicy instanceof SizeBasedTriggeringPolicy) {
56 sizeBasedTriggeringPolicy = (SizeBasedTriggeringPolicy) triggeringPolicy;
57 assertEquals(100 * 1024 * 1024, sizeBasedTriggeringPolicy.getMaxFileSize());
58 }
59 }
60 if (timeBasedTriggeringPolicy == null) {
61 fail("Missing TimeBasedTriggeringPolicy");
62 }
63 if (sizeBasedTriggeringPolicy == null) {
64 fail("Missing SizeBasedTriggeringPolicy");
65 }
66 }
67 }
2121 import org.apache.logging.log4j.core.LoggerContext;
2222 import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
2323 import org.apache.logging.log4j.status.StatusLogger;
24 import org.junit.jupiter.api.AfterAll;
25 import org.junit.jupiter.api.BeforeAll;
26 import org.junit.jupiter.api.Tag;
27 import org.junit.jupiter.api.Test;
24 import org.junit.AfterClass;
25 import org.junit.BeforeClass;
26 import org.junit.Test;
2827
29 import static org.junit.jupiter.api.Assertions.*;
28 import static org.junit.Assert.*;
3029
31 @Tag("functional")
30 /**
31 *
32 */
3233 public class AdvertiserTest {
3334
3435 private static final String CONFIG = "log4j-advertiser.xml";
3536 private static final String STATUS_LOG = "target/status.log";
3637
37 @BeforeAll
38 @BeforeClass
3839 public static void setupClass() {
3940 final File file = new File(STATUS_LOG);
4041 file.delete();
5152 }
5253 }
5354
54 @AfterAll
55 @AfterClass
5556 public static void cleanupClass() {
5657 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
5758 final LoggerContext ctx = LoggerContext.getContext();
8384 foundSocket2 = true;
8485 }
8586 }
86 assertTrue(foundFile1, "Entries for File1 appender do not exist");
87 assertFalse(foundFile2, "Entries for File2 appender exist");
88 assertTrue(foundSocket1, "Entries for Socket1 appender do not exist");
89 assertFalse(foundSocket2, "Entries for Socket2 appender exist");
87 assertTrue("Entries for File1 appender do not exist", foundFile1);
88 assertTrue("Entries for File2 appender exist", !foundFile2);
89 assertTrue("Entries for Socket1 appender do not exist", foundSocket1);
90 assertTrue("Entries for Socket2 appender exist", !foundSocket2);
9091 }
9192
9293 @Test
102103 ctx.stop();
103104
104105 final Map<Object, Map<String, String>> entries = InMemoryAdvertiser.getAdvertisedEntries();
105 assertTrue(entries.isEmpty(), "Entries found: " + entries);
106 assertTrue("Entries found: " + entries, entries.isEmpty());
106107
107108 //reconfigure for subsequent testing
108109 ctx.start();
116117 ctx.stop();
117118
118119 final Map<Object, Map<String, String>> entries = InMemoryAdvertiser.getAdvertisedEntries();
119 assertTrue(entries.isEmpty(), "Entries found: " + entries);
120 assertTrue("Entries found: " + entries, entries.isEmpty());
120121
121122 ctx.start();
122123
1818 import org.apache.logging.log4j.Level;
1919 import org.apache.logging.log4j.core.Appender;
2020 import org.apache.logging.log4j.test.appender.FailOnceAppender;
21 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2222
2323 import java.util.HashMap;
2424 import java.util.Map;
2525
26 import static org.junit.jupiter.api.Assertions.*;
26 import static org.junit.Assert.*;
2727
2828 /**
2929 * Tests the AppenderControlArraySet class..
3333 @Test
3434 public void testInitiallyEmpty() throws Exception {
3535 assertTrue(new AppenderControlArraySet().isEmpty());
36 assertEquals(0, new AppenderControlArraySet().get().length);
36 assertTrue(new AppenderControlArraySet().get().length == 0);
3737 }
3838
3939 private AppenderControl createControl(final String name) {
40 final Appender appender = FailOnceAppender.createAppender(name, null);
40 final Appender appender = FailOnceAppender.createAppender(name);
4141 return new AppenderControl(appender, Level.INFO, null);
4242 }
4343
173173 public void testIsEmptyMeansZeroLengthArray() throws Exception {
174174 final AppenderControlArraySet set = new AppenderControlArraySet();
175175 assertTrue(set.isEmpty());
176 assertEquals(0, set.get().length);
176 assertTrue(set.get().length == 0);
177177 }
178178
179179 @Test
+0
-48
log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationMissingTest.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.logging.log4j.core.config;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.junit.jupiter.api.BeforeAll;
22 import org.junit.jupiter.api.Test;
23
24 import static org.junit.jupiter.api.Assertions.*;
25
26 public class CompositeConfigurationMissingTest {
27
28 @BeforeAll
29 public static void beforeClass() {
30 System.setProperty("log4j2.configurationFile", "classpath:log4j-comp-logger-root.xml,log4j-does-not-exist.json");
31 }
32
33 @Test
34 public void testMissingConfig() {
35 LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
36
37 final AbstractConfiguration config = (AbstractConfiguration) ctx.getConfiguration();
38 assertNotNull(config, "No configuration returned");
39 //Test for Root log level override
40 assertEquals(Level.ERROR, config.getRootLogger().getLevel(), "Expected Root logger log level to be ERROR");
41
42 //Test for no cat2 level override
43 final LoggerConfig cat2 = config.getLogger("cat2");
44 assertNotNull(cat2, "cat2");
45 assertEquals(Level.DEBUG, cat2.getLevel(), "Expected cat2 log level to be INFO");
46 }
47 }
114114 appendersMap.size());
115115 assertTrue(appendersMap.get("File") instanceof FileAppender);
116116 assertTrue(appendersMap.get("STDOUT") instanceof ConsoleAppender);
117
118 assertEquals("Expected COMPOSITE_SOURCE for composite configuration but got " + config.getConfigurationSource(),
119 config.getConfigurationSource(), ConfigurationSource.COMPOSITE_SOURCE);
120117 }
121118 };
122119 runTest(lcr, test);
159156 //Regression
160157 //Check level on cat3 (not present in root config)
161158 assertEquals("Expected cat3 log level to be ERROR", Level.ERROR, config.getLogger("cat3").getLevel());
162 //Check level on cat1 (not present in overridden config)
159 //Check level on cat1 (not present in overriden config)
163160 assertEquals("Expected cat1 log level to be DEBUG", Level.DEBUG, config.getLogger("cat1").getLevel());
164 }
165 };
166 runTest(lcr, test);
167 }
168
169 @Test
170 public void testMissingConfig() {
171 final LoggerContextRule lcr = new LoggerContextRule("classpath:log4j-comp-logger-root.xml,log4j-does-not-exist.json");
172 final Statement test = new Statement() {
173 @Override
174 public void evaluate() throws Throwable {
175 final AbstractConfiguration config = (AbstractConfiguration) lcr.getConfiguration();
176 assertNotNull("No configuration returned", config);
177 //Test for Root log level override
178 assertEquals("Expected Root logger log level to be ERROR", Level.ERROR, config.getRootLogger().getLevel());
179
180 //Test for no cat2 level override
181 final LoggerConfig cat2 = config.getLogger("cat2");
182 assertEquals("Expected cat2 log level to be INFO", Level.DEBUG, cat2.getLevel());
183161 }
184162 };
185163 runTest(lcr, test);
+0
-134
log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfigurationFactoryTest.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
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.core.Appender;
21 import org.apache.logging.log4j.core.Filter;
22 import org.apache.logging.log4j.core.Logger;
23 import org.apache.logging.log4j.core.LoggerContext;
24 import org.apache.logging.log4j.core.appender.ConsoleAppender;
25 import org.apache.logging.log4j.core.filter.ThreadContextMapFilter;
26 import org.apache.logging.log4j.junit.CleanUpFiles;
27 import org.apache.logging.log4j.junit.LoggerContextSource;
28 import org.apache.logging.log4j.util.Strings;
29 import org.junit.jupiter.api.Tag;
30 import org.junit.jupiter.api.Test;
31
32 import java.io.IOException;
33 import java.nio.file.Files;
34 import java.nio.file.Path;
35 import java.nio.file.Paths;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39
40 import static org.apache.logging.log4j.util.Unbox.box;
41 import static org.junit.jupiter.api.Assertions.*;
42
43 @CleanUpFiles({
44 "target/test-xml.log",
45 "target/test-xinclude.log",
46 "target/test-json.log",
47 "target/test-yaml.log",
48 "target/test-properties.log"
49 })
50 class ConfigurationFactoryTest {
51
52 static final String LOGGER_NAME = "org.apache.logging.log4j.test1.Test";
53 static final String FILE_LOGGER_NAME = "org.apache.logging.log4j.test2.Test";
54 static final String APPENDER_NAME = "STDOUT";
55
56 /**
57 * Runs various configuration checks on a configured LoggerContext that should match the equivalent configuration in
58 * {@code log4j-test1.xml}.
59 */
60 static void checkConfiguration(final LoggerContext context) {
61 final Configuration configuration = context.getConfiguration();
62 final Map<String, Appender> appenders = configuration.getAppenders();
63 // these used to be separate tests
64 assertAll(() -> assertNotNull(appenders),
65 () -> assertEquals(3, appenders.size()),
66 () -> assertNotNull(configuration.getLoggerContext()),
67 () -> assertEquals(configuration.getRootLogger(), configuration.getLoggerConfig(Strings.EMPTY)),
68 () -> assertThrows(NullPointerException.class, () -> configuration.getLoggerConfig(null)));
69
70 final Logger logger = context.getLogger(LOGGER_NAME);
71 assertEquals(Level.DEBUG, logger.getLevel());
72
73 assertEquals(1, logger.filterCount());
74 final Iterator<Filter> filterIterator = logger.getFilters();
75 assertTrue(filterIterator.hasNext());
76 assertTrue(filterIterator.next() instanceof ThreadContextMapFilter);
77
78 final Appender appender = appenders.get(APPENDER_NAME);
79 assertTrue(appender instanceof ConsoleAppender);
80 assertEquals(APPENDER_NAME, appender.getName());
81 }
82
83 static void checkFileLogger(final LoggerContext context, final Path logFile) throws IOException {
84 final long currentThreadId = Thread.currentThread().getId();
85 final Logger logger = context.getLogger(FILE_LOGGER_NAME);
86 logger.debug("Greetings from ConfigurationFactoryTest in thread#{}", box(currentThreadId));
87 final List<String> lines = Files.readAllLines(logFile);
88 assertEquals(1, lines.size());
89 assertTrue(lines.get(0).endsWith(Long.toString(currentThreadId)));
90 }
91
92 @Test
93 @LoggerContextSource("log4j-test1.xml")
94 void xml(final LoggerContext context) throws IOException {
95 checkConfiguration(context);
96 final Path logFile = Paths.get("target", "test-xml.log");
97 checkFileLogger(context, logFile);
98 }
99
100 @Test
101 @LoggerContextSource("log4j-xinclude.xml")
102 void xinclude(final LoggerContext context) throws IOException {
103 checkConfiguration(context);
104 final Path logFile = Paths.get("target", "test-xinclude.log");
105 checkFileLogger(context, logFile);
106 }
107
108 @Test
109 @Tag("json")
110 @LoggerContextSource("log4j-test1.json")
111 void json(final LoggerContext context) throws IOException {
112 checkConfiguration(context);
113 final Path logFile = Paths.get("target", "test-json.log");
114 checkFileLogger(context, logFile);
115 }
116
117 @Test
118 @Tag("yaml")
119 @LoggerContextSource("log4j-test1.yaml")
120 void yaml(final LoggerContext context) throws IOException {
121 checkConfiguration(context);
122 final Path logFile = Paths.get("target", "test-yaml.log");
123 checkFileLogger(context, logFile);
124 }
125
126 @Test
127 @LoggerContextSource("log4j-test1.properties")
128 void properties(final LoggerContext context) throws IOException {
129 checkConfiguration(context);
130 final Path logFile = Paths.get("target", "test-properties.log");
131 checkFileLogger(context, logFile);
132 }
133 }
+0
-33
log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfigurationSourceTest.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
17 package org.apache.logging.log4j.core.config;
18
19 import org.junit.jupiter.api.Test;
20
21 import java.io.ByteArrayInputStream;
22
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24
25 public class ConfigurationSourceTest {
26
27 @Test
28 public void testJira_LOG4J2_2770_byteArray() throws Exception {
29 ConfigurationSource configurationSource = new ConfigurationSource(new ByteArrayInputStream(new byte[] { 'a', 'b' }));
30 assertNotNull(configurationSource.resetInputStream());
31 }
32 }
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
17 package org.apache.logging.log4j.core.config;
18
19 import java.io.BufferedReader;
20 import java.io.FileReader;
21 import java.security.SecureRandom;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.Map;
26
27 import org.apache.logging.log4j.Level;
28 import org.apache.logging.log4j.Logger;
29 import org.apache.logging.log4j.core.Appender;
30 import org.apache.logging.log4j.core.Filter;
31 import org.apache.logging.log4j.core.LoggerContext;
32 import org.apache.logging.log4j.core.filter.ThreadContextMapFilter;
33 import org.apache.logging.log4j.junit.CleanFiles;
34 import org.apache.logging.log4j.junit.LoggerContextRule;
35 import org.apache.logging.log4j.util.Strings;
36 import org.junit.Before;
37 import org.junit.Rule;
38 import org.junit.Test;
39 import org.junit.rules.RuleChain;
40 import org.junit.rules.TestRule;
41 import org.junit.runner.RunWith;
42 import org.junit.runners.Parameterized;
43 import org.junit.runners.Parameterized.Parameters;
44
45 import static org.hamcrest.CoreMatchers.*;
46
47 import static org.junit.Assert.*;
48
49 /**
50 * Unit tests for testing various supported configuration file formats. Each configuration file format should provide a
51 * compatible configuration to get some sweet, sweet tests.
52 */
53 @RunWith(Parameterized.class)
54 public class ConfigurationTest {
55
56 private static final String LOGGER_NAME = "org.apache.logging.log4j.test1.Test";
57 private static final String FILE_LOGGER_NAME = "org.apache.logging.log4j.test2.Test";
58 private static final String APPENDER_NAME = "STDOUT";
59
60 private final String logFileName;
61
62 @Rule
63 public TestRule rules;
64
65 private final LoggerContextRule init;
66
67 private LoggerContext ctx;
68
69 private final SecureRandom random = new SecureRandom();
70
71 public ConfigurationTest(final String configFileName, final String logFileName) {
72 this.logFileName = logFileName;
73 this.init = new LoggerContextRule(configFileName);
74 rules = RuleChain.outerRule(new CleanFiles(logFileName)).around(this.init);
75 }
76
77 @Parameters(name = "config={0}, log={1}")
78 public static Collection<Object[]> data() {
79 return Arrays.asList(
80 new Object[][]{
81 {"classpath:log4j-test1.xml", "target/test-xml.log"},
82 {"classpath:log4j-test1.json", "target/test-json.log"},
83 {"classpath:log4j-test1.yaml", "target/test-yaml.log"},
84 {"classpath:log4j-test1.properties", "target/test-properties.log"}
85 }
86 );
87 }
88
89 @Before
90 public void setUp() throws Exception {
91 this.ctx = this.init.getLoggerContext();
92 }
93
94 @Test
95 public void testConfiguredAppenders() throws Exception {
96 final Configuration configuration = this.ctx.getConfiguration();
97 final Map<String, Appender> appenders = configuration.getAppenders();
98 assertThat(appenders, is(notNullValue()));
99 assertThat(appenders.size(), is(equalTo(3)));
100 }
101
102 @Test
103 public void testConfigurationLoggerContext() throws Exception {
104 final Configuration configuration = this.ctx.getConfiguration();
105 assertThat(configuration.getLoggerContext(), is(notNullValue()));
106 }
107
108 @Test
109 public void testGetLoggerConfigEmpty() throws Exception {
110 final Configuration config = this.ctx.getConfiguration();
111 assertEquals(config.getRootLogger(), config.getLoggerConfig(Strings.EMPTY));
112 }
113
114 @Test(expected = NullPointerException.class)
115 public void testGetLoggerConfigNull() throws Exception {
116 final Configuration config = this.ctx.getConfiguration();
117 assertEquals(config.getRootLogger(), config.getLoggerConfig(null));
118 }
119
120 @Test
121 public void testLogger() throws Exception {
122 final Logger logger = this.ctx.getLogger(LOGGER_NAME);
123 assertThat(logger, is(instanceOf(org.apache.logging.log4j.core.Logger.class)));
124 final org.apache.logging.log4j.core.Logger l = (org.apache.logging.log4j.core.Logger) logger;
125 assertThat(l.getLevel(), is(equalTo(Level.DEBUG)));
126 assertThat(l.filterCount(), is(equalTo(1)));
127 final Iterator<Filter> iterator = l.getFilters();
128 assertThat(iterator.hasNext(), is(true));
129 final Filter filter = iterator.next();
130 assertThat(filter, is(instanceOf(ThreadContextMapFilter.class)));
131 final Map<String, Appender> appenders = l.getAppenders();
132 assertThat(appenders, is(notNullValue()));
133 assertThat(appenders.size(), is(equalTo(1)));
134 final Appender appender = appenders.get(APPENDER_NAME);
135 assertThat(appender, is(notNullValue()));
136 assertThat(appender.getName(), is(equalTo("STDOUT")));
137 }
138
139 @Test
140 public void testLogToFile() throws Exception {
141 final Logger logger = this.ctx.getLogger(FILE_LOGGER_NAME);
142 final long random = this.random.nextLong();
143 logger.debug("This is test message number {}", random);
144 int count = 0;
145 String line = Strings.EMPTY;
146 try (final BufferedReader in = new BufferedReader(new FileReader(this.logFileName))) {
147 while (in.ready()) {
148 ++count;
149 line = in.readLine();
150 }
151 }
152 assertThat(count, is(equalTo(1)));
153 assertThat(line, endsWith(Long.toString(random)));
154 }
155
156 }
1919 import java.net.URI;
2020
2121 import org.apache.logging.log4j.core.LoggerContext;
22 import org.junit.jupiter.api.Tag;
23 import org.junit.jupiter.api.Test;
22 import org.junit.Test;
2423
25 import static org.junit.jupiter.api.Assertions.*;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertEquals;
2626
27 @Tag("functional")
2827 public class ConfiguratorTest {
2928
3029 @Test
4544 try (final LoggerContext loggerContext = Configurator.initialize(getClass().getName(), null, path)) {
4645 assertNotNull(loggerContext.getConfiguration().getAppender("List"));
4746 URI uri = loggerContext.getConfigLocation();
48 assertNotNull(uri, "No configuration location returned");
47 assertNotNull("No configuration location returned", uri);
4948 Configurator.reconfigure();
50 assertEquals(uri, loggerContext.getConfigLocation(), "Unexpected configuration location returned");
49 assertEquals("Unexpected configuration location returned", uri, loggerContext.getConfigLocation());
5150 }
5251 }
5352
5756 try (final LoggerContext loggerContext = Configurator.initialize(getClass().getName(), null, path)) {
5857 assertNotNull(loggerContext.getConfiguration().getAppender("List"));
5958 URI uri = loggerContext.getConfigLocation();
60 assertNotNull(uri, "No configuration location returned");
59 assertNotNull("No configuration location returned", uri);
6160 final URI location = new File("src/test/resources/log4j2-config.xml").toURI();
6261 Configurator.reconfigure(location);
63 assertEquals(location, loggerContext.getConfigLocation(), "Unexpected configuration location returned");
62 assertEquals("Unexpected configuration location returned", location, loggerContext.getConfigLocation());
6463 }
6564 }
6665
1515 */
1616 package org.apache.logging.log4j.core.config;
1717
18 import java.io.File;
19 import java.io.Serializable;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.Logger;
2023 import org.apache.logging.log4j.core.Layout;
2225 import org.apache.logging.log4j.core.appender.FileAppender;
2326 import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
2427 import org.apache.logging.log4j.core.layout.PatternLayout;
25 import org.apache.logging.log4j.junit.CleanUpFiles;
26 import org.apache.logging.log4j.junit.LoggerContextSource;
28 import org.apache.logging.log4j.junit.LoggerContextRule;
2729 import org.apache.logging.log4j.status.StatusConsoleListener;
2830 import org.apache.logging.log4j.status.StatusListener;
2931 import org.apache.logging.log4j.status.StatusLogger;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.Test;
32 import org.junit.Before;
33 import org.junit.BeforeClass;
34 import org.junit.Rule;
35 import org.junit.Test;
3236
33 import java.io.IOException;
34 import java.io.Serializable;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38
39 import static org.hamcrest.MatcherAssert.assertThat;
37 import static org.apache.logging.log4j.hamcrest.FileMatchers.exists;
38 import static org.apache.logging.log4j.hamcrest.FileMatchers.hasLength;
4039 import static org.hamcrest.Matchers.greaterThan;
4140 import static org.hamcrest.Matchers.instanceOf;
42 import static org.junit.jupiter.api.Assertions.assertSame;
43 import static org.junit.jupiter.api.Assertions.assertTrue;
41 import static org.junit.Assert.*;
4442
45 @CleanUpFiles("target/test.log")
43 /**
44 *
45 */
4646 public class CustomConfigurationTest {
4747
48 public static final Path LOG_FILE = Paths.get("target", "test.log");
48 public static final String LOG_FILE = "target/test.log";
4949
50 @BeforeAll
50 @BeforeClass
5151 public static void before() {
5252 System.setProperty("log4j.level", "info");
5353 System.setProperty("log.level", "info");
5454 }
5555
56 @Rule
57 public LoggerContextRule init = new LoggerContextRule("log4j-props.xml");
58
59 @Before
60 public void setUp() throws Exception {
61 new File(LOG_FILE).delete();
62 }
63
5664 @Test
57 @LoggerContextSource("log4j-props.xml")
58 public void testConfig(final LoggerContext ctx) throws IOException {
65 public void testConfig() {
5966 // don't bother using "error" since that's the default; try another level
67 final LoggerContext ctx = this.init.getLoggerContext();
68 ctx.reconfigure();
6069 final Configuration config = ctx.getConfiguration();
6170 assertThat(config, instanceOf(XmlConfiguration.class));
6271 for (final StatusListener listener : StatusLogger.getLogger().getListeners()) {
7180 .build();
7281 // @formatter:off
7382 final FileAppender appender = FileAppender.newBuilder()
74 .withFileName(LOG_FILE.toString())
83 .withFileName(LOG_FILE)
7584 .withAppend(false).setName("File").setIgnoreExceptions(false)
7685 .withBufferSize(4000)
7786 .withBufferedIo(false).setLayout(layout)
8796 loggerConfig.addAppender(appender, null, null);
8897 config.addLogger("org.apache.logging.log4j", loggerConfig);
8998 ctx.updateLoggers();
90 final Logger logger = ctx.getLogger(CustomConfigurationTest.class);
99 final Logger logger = ctx.getLogger(CustomConfigurationTest.class.getName());
91100 logger.info("This is a test");
92 assertTrue(Files.exists(LOG_FILE));
93 assertThat(Files.size(LOG_FILE), greaterThan(0L));
101 final File file = new File(LOG_FILE);
102 assertThat(file, exists());
103 assertThat(file, hasLength(greaterThan(0L)));
94104 }
95105 }
1515 */
1616 package org.apache.logging.log4j.core.config;
1717
18 import static org.junit.jupiter.api.Assertions.assertTrue;
18 import java.io.File;
1919
20 import java.io.IOException;
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
20 import org.apache.logging.log4j.junit.CleanFiles;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.junit.Rule;
23 import org.junit.Test;
24 import org.junit.rules.RuleChain;
2425
25 import org.apache.logging.log4j.junit.CleanUpFiles;
26 import org.apache.logging.log4j.junit.LoggerContextSource;
27 import org.junit.jupiter.api.Test;
26 import static org.apache.logging.log4j.hamcrest.FileMatchers.exists;
27 import static org.apache.logging.log4j.hamcrest.FileMatchers.hasLength;
28 import static org.hamcrest.Matchers.greaterThan;
29 import static org.junit.Assert.*;
2830
29 @CleanUpFiles("target/test.log") // File name MUST match the one in log4j-filetest.xml.
31 /**
32 *
33 */
3034 public class FileOutputTest {
3135
36 private static final String CONFIG = "classpath:log4j-filetest.xml";
37 private static final String STATUS_LOG = "target/status.log";
38
39 @Rule
40 public RuleChain rules = RuleChain.outerRule(new CleanFiles(STATUS_LOG)).around(new LoggerContextRule(CONFIG));
41
3242 @Test
33 @LoggerContextSource(value="classpath:log4j-filetest.xml")
34 public void testConfig() throws IOException {
35 final Path logFile = Paths.get("target", "status.log");
36 assertTrue(Files.exists(logFile), "Status output file does not exist");
37 assertTrue(Files.size(logFile) > 0, "File is empty");
43 public void testConfig() {
44 final File file = new File(STATUS_LOG);
45 assertThat("Status output file does not exist", file, exists());
46 assertThat("File is empty", file, hasLength(greaterThan(0L)));
3847 }
3948
4049 }
2626 public class InMemoryAdvertiser implements Advertiser {
2727 private static Map<Object, Map<String, String>> properties = new HashMap<>();
2828
29 public static Map<Object, Map<String, String>> getAdvertisedEntries() {
30 return new HashMap<>(properties);
29 public static Map<Object, Map<String, String>> getAdvertisedEntries()
30 {
31 final Map<Object, Map<String, String>> result = new HashMap<>();
32 result.putAll(properties);
33 return result;
3134 }
3235
3336 @Override
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
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.categories.Configurations;
20 import org.junit.experimental.categories.Category;
21
22 @Category(Configurations.Json.class)
23 public class JiraLog4j2_1100JsonTest extends AbstractLog4j2_1100Test {
24
25 @Override
26 protected String getConfigurationResource() {
27 return "LOG4J2-1100/log4j2.json";
28 }
29
30 }
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
17 package org.apache.logging.log4j.core.config;
18
19 public class JiraLog4j2_1100XmlTest extends AbstractLog4j2_1100Test {
20
21 @Override
22 protected String getConfigurationResource() {
23 return "LOG4J2-1100/log4j2.xml";
24 }
25
26 }
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
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.categories.Configurations;
20 import org.junit.Ignore;
21 import org.junit.experimental.categories.Category;
22
23 @Ignore
24 @Category(Configurations.Yaml.class)
25 public class JiraLog4j2_1100YamlBadTest extends AbstractLog4j2_1100Test {
26
27 @Override
28 protected String getConfigurationResource() {
29 return "LOG4J2-1100/log4j2-good.yaml";
30 }
31
32 }
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
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.categories.Configurations;
20 import org.junit.experimental.categories.Category;
21
22 @Category(Configurations.Yaml.class)
23 public class JiraLog4j2_1100YamlGoodTest extends AbstractLog4j2_1100Test {
24
25 @Override
26 protected String getConfigurationResource() {
27 return "LOG4J2-1100/log4j2-good.yaml";
28 }
29
30 }
2626 import org.apache.logging.log4j.core.LoggerContext;
2727 import org.apache.logging.log4j.core.appender.FileAppender;
2828 import org.apache.logging.log4j.core.layout.PatternLayout;
29 import org.apache.logging.log4j.junit.LoggerContextSource;
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.api.Tag;
29 import org.apache.logging.log4j.junit.LoggerContextRule;
30 import org.junit.Rule;
31 import org.junit.Test;
3232
33 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
33 public class JiraLog4j2_2134Test {
3434
35 @Tag("yaml")
36 @LoggerContextSource("log4j2-2134.yml")
37 public class JiraLog4j2_2134Test {
35 @Rule
36 public final LoggerContextRule loggerContextRule = new LoggerContextRule("src/test/resources/log4j2-2134.yml");
3837
3938 @Test
4039 public void testRefresh() {
6160 ctx.stop();
6261 ctx.start(config);
6362
64 assertDoesNotThrow(() -> log.error("Info message"));
63 log.error("Info message");
6564 }
6665
6766 @Test
7170 final Configuration config = ctx.getConfiguration();
7271 ctx.start(config);
7372
74 assertDoesNotThrow(() -> log.error("Info message"));
73 log.error("Info message");
7574 }
7675
7776 @Test
8180 ctx.stop();
8281 ctx.start();
8382
84 assertDoesNotThrow(() -> log.error("Info message"));
83 log.error("Info message");
8584 }
8685
8786 @Test
9291 ctx.stop();
9392 ctx.start(config);
9493
95 assertDoesNotThrow(() -> log.error("Info message"));
94 log.error("Info message");
9695 }
9796
9897 @SuppressWarnings("deprecation")
116115 ctx.stop();
117116 ctx.start(config);
118117
119 assertDoesNotThrow(() -> log.error("Info message"));
118 log.error("Info message");
120119 }
121120 }
1414 * limitations under the license.
1515 */
1616
17 import org.apache.logging.log4j.Level;
18 import org.apache.logging.log4j.core.impl.Log4jLogEvent.Builder;
19 import org.apache.logging.log4j.message.SimpleMessage;
20 import org.junit.jupiter.api.Test;
17 import static org.junit.Assert.assertEquals;
18 import static org.junit.Assert.assertNotSame;
19 import static org.junit.Assert.assertNull;
20 import static org.junit.Assert.assertSame;
2121
2222 import java.util.HashSet;
2323 import java.util.List;
24 import java.util.concurrent.atomic.AtomicReference;
2524
26 import static org.junit.jupiter.api.Assertions.*;
25 import org.apache.logging.log4j.Level;
26 import org.apache.logging.log4j.Marker;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.impl.Log4jLogEvent.Builder;
29 import org.apache.logging.log4j.core.impl.LogEventFactory;
30 import org.apache.logging.log4j.message.Message;
31 import org.apache.logging.log4j.message.SimpleMessage;
32 import org.junit.Test;
2733
2834 /**
2935 * Tests for LoggerConfig.
3844 @SuppressWarnings({"deprecation"})
3945 @Test
4046 public void testPropertiesWithoutSubstitution() {
41 assertNull(createForProperties(null).getPropertyList(), "null propertiesList");
47 assertNull("null propertiesList", createForProperties(null).getPropertyList());
48 assertNull("null property Map", createForProperties(null).getProperties());
4249
4350 final Property[] all = new Property[] {
4451 Property.createProperty("key1", "value1"),
4653 };
4754 final LoggerConfig loggerConfig = createForProperties(all);
4855 final List<Property> list = loggerConfig.getPropertyList();
49 assertEquals(new HashSet<>(list),
50 new HashSet<>(loggerConfig.getPropertyList()), "map and list contents equal");
56 assertEquals("map and list contents equal", new HashSet<>(list),
57 new HashSet<>(loggerConfig.getPropertyList()));
5158
52 final AtomicReference<Object> actualList = new AtomicReference<>();
53 loggerConfig.setLogEventFactory((loggerName, marker, fqcn, level, data, properties, t) -> {
54 actualList.set(properties);
55 return new Builder().setTimeMillis(System.currentTimeMillis()).build();
59 final Object[] actualList = new Object[1];
60 loggerConfig.setLogEventFactory(new LogEventFactory() {
61 @Override
62 public LogEvent createEvent(final String loggerName, final Marker marker, final String fqcn,
63 final Level level, final Message data,
64 final List<Property> properties, final Throwable t) {
65 actualList[0] = properties;
66 return new Builder().setTimeMillis(System.currentTimeMillis()).build();
67 }
5668 });
5769 loggerConfig.log("name", "fqcn", null, Level.INFO, new SimpleMessage("msg"), null);
58 assertSame(list, actualList.get(), "propertiesList passed in as is if no substitutions required");
70 assertSame("propertiesList passed in as is if no substitutions required", list, actualList[0]);
5971 }
6072
6173 @Test
6678 };
6779 final LoggerConfig loggerConfig = createForProperties(all);
6880 final List<Property> list = loggerConfig.getPropertyList();
69 assertEquals(new HashSet<>(list),
70 new HashSet<>(loggerConfig.getPropertyList()), "map and list contents equal");
81 assertEquals("map and list contents equal", new HashSet<>(list),
82 new HashSet<>(loggerConfig.getPropertyList()));
7183
72 final AtomicReference<Object> actualListHolder = new AtomicReference<>();
73 loggerConfig.setLogEventFactory((loggerName, marker, fqcn, level, data, properties, t) -> {
74 actualListHolder.set(properties);
75 return new Builder().setTimeMillis(System.currentTimeMillis()).build();
84 final Object[] actualListHolder = new Object[1];
85 loggerConfig.setLogEventFactory(new LogEventFactory() {
86 @Override
87 public LogEvent createEvent(final String loggerName, final Marker marker, final String fqcn,
88 final Level level, final Message data,
89 final List<Property> properties, final Throwable t) {
90 actualListHolder[0] = properties;
91 return new Builder().setTimeMillis(System.currentTimeMillis()).build();
92 }
7693 });
7794 loggerConfig.log("name", "fqcn", null, Level.INFO, new SimpleMessage("msg"), null);
78 assertNotSame(list, actualListHolder.get(), "propertiesList with substitutions");
95 assertNotSame("propertiesList with substitutions", list, actualListHolder[0]);
7996
8097 @SuppressWarnings("unchecked")
81 final List<Property> actualList = (List<Property>) actualListHolder.get();
98 final List<Property> actualList = (List<Property>) actualListHolder[0];
8299
83100 for (int i = 0; i < list.size(); i++) {
84 assertEquals(list.get(i).getName(), actualList.get(i).getName(), "name[" + i + "]");
101 assertEquals("name[" + i + "]", list.get(i).getName(), actualList.get(i).getName());
85102 final String value = list.get(i).getValue().replace("${sys:user.name}", System.getProperty("user.name"));
86 assertEquals(value, actualList.get(i).getValue(), "value[" + i + "]");
103 assertEquals("value[" + i + "]", value, actualList.get(i).getValue());
87104 }
88105 }
89106 }
1919 import org.apache.logging.log4j.Level;
2020 import org.apache.logging.log4j.LogManager;
2121 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2323 import org.apache.logging.log4j.status.StatusData;
2424 import org.apache.logging.log4j.status.StatusLogger;
25 import org.junit.jupiter.api.Test;
25 import org.junit.ClassRule;
26 import org.junit.Test;
2627
27 import static org.junit.jupiter.api.Assertions.*;
28 import static org.junit.Assert.*;
2829
2930 /**
3031 * Tests LoggersPlugin.
3132 */
32 @LoggerContextSource("multipleRootLoggersTest.xml")
3333 public class LoggersPluginTest {
34 private static final String CONFIG = "multipleRootLoggersTest.xml";
35
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
3438
3539 @Test
3640 public void testEmptyAttribute() throws Exception {
2121 import org.apache.logging.log4j.Logger;
2222 import org.apache.logging.log4j.core.Appender;
2323 import org.apache.logging.log4j.core.LoggerContext;
24 import org.apache.logging.log4j.junit.LoggerContextSource;
25 import org.junit.jupiter.api.Test;
24 import org.apache.logging.log4j.junit.LoggerContextRule;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 import org.junit.runners.JUnit4;
2629
2730 import static org.apache.logging.log4j.hamcrest.MapMatchers.hasSize;
28 import static org.hamcrest.MatcherAssert.*;
2931 import static org.hamcrest.Matchers.hasKey;
3032 import static org.hamcrest.Matchers.instanceOf;
3133 import static org.hamcrest.Matchers.is;
32 import static org.junit.jupiter.api.Assertions.*;
34 import static org.junit.Assert.*;
3335
34 @LoggerContextSource("missingRootLogger.xml")
36 @RunWith(JUnit4.class)
3537 public class MissingRootLoggerTest {
3638
39 @Rule
40 public LoggerContextRule context = new LoggerContextRule("missingRootLogger.xml");
41
3742 @Test
38 public void testMissingRootLogger(final LoggerContext ctx) throws Exception {
43 public void testMissingRootLogger() throws Exception {
44 final LoggerContext ctx = context.getLoggerContext();
3945 final Logger logger = ctx.getLogger("sample.Logger1");
40 assertTrue(logger.isInfoEnabled(), "Logger should have the INFO level enabled");
41 assertFalse(logger.isDebugEnabled(), "Logger should have the DEBUG level disabled");
46 assertTrue("Logger should have the INFO level enabled", logger.isInfoEnabled());
47 assertFalse("Logger should have the DEBUG level disabled", logger.isDebugEnabled());
4248 final Configuration config = ctx.getConfiguration();
43 assertNotNull(config, "Config not null");
49 assertNotNull("Config not null", config);
4450 // final String MISSINGROOT = "MissingRootTest";
4551 // assertTrue("Incorrect Configuration. Expected " + MISSINGROOT + " but found " + config.getName(),
4652 // MISSINGROOT.equals(config.getName()));
4753 final Map<String, Appender> map = config.getAppenders();
48 assertNotNull(map, "Appenders not null");
54 assertNotNull("Appenders not null", map);
4955 assertThat("There should only be two appenders", map, hasSize(2));
5056 assertThat(map, hasKey("List"));
5157 assertThat(map, hasKey("DefaultConsole-2"));
5258
5359 final Map<String, LoggerConfig> loggerMap = config.getLoggers();
54 assertNotNull(loggerMap, "loggerMap not null");
60 assertNotNull("loggerMap not null", loggerMap);
5561 assertThat("There should only be one configured logger", loggerMap, hasSize(1));
5662 // only the sample logger, no root logger in loggerMap!
5763 assertThat("contains key=sample", loggerMap, hasKey("sample"));
+0
-98
log4j-core/src/test/java/org/apache/logging/log4j/core/config/MockReliabilityStrategy.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
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.Marker;
21 import org.apache.logging.log4j.core.Appender;
22 import org.apache.logging.log4j.core.LifeCycle;
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.message.Message;
25 import org.apache.logging.log4j.util.Supplier;
26 import org.opentest4j.MultipleFailuresError;
27
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
31
32 import static org.junit.jupiter.api.Assertions.assertSame;
33
34 /**
35 * Mock object for validating the behavior of a configuration interacting with ReliabilityStrategy.
36 */
37 public class MockReliabilityStrategy implements ReliabilityStrategy {
38
39 private final LoggerConfig config;
40 private final List<AssertionError> errors = Collections.synchronizedList(new ArrayList<>());
41
42 public MockReliabilityStrategy(final LoggerConfig config) {
43 this.config = config;
44 }
45
46 @Override
47 public void log(
48 final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn, final Marker marker,
49 final Level level, final Message data, final Throwable t) {
50 config.log(loggerName, fqcn, marker, level, data, t);
51 }
52
53 @Override
54 public void log(final Supplier<LoggerConfig> reconfigured, final LogEvent event) {
55 config.log(event);
56 }
57
58 @Override
59 public LoggerConfig getActiveLoggerConfig(final Supplier<LoggerConfig> next) {
60 return config;
61 }
62
63 @Override
64 public void afterLogEvent() {
65 // no-op
66 }
67
68 @Override
69 public void beforeStopAppenders() {
70 checkState(LifeCycle.State.STOPPED, config);
71 for (final Appender appender : config.getAppenders().values()) {
72 checkState(LifeCycle.State.STARTED, appender);
73 }
74 }
75
76 @Override
77 public void beforeStopConfiguration(final Configuration configuration) {
78 checkState(LifeCycle.State.STOPPING, configuration);
79 checkState(LifeCycle.State.STARTED, config);
80 }
81
82 void rethrowAssertionErrors() {
83 synchronized (errors) {
84 if (!errors.isEmpty()) {
85 throw new MultipleFailuresError(null, errors);
86 }
87 }
88 }
89
90 private void checkState(final LifeCycle.State expected, final LifeCycle object) {
91 try {
92 assertSame(expected, object.getState(), () -> "Expected state " + expected + " for LifeCycle object " + object);
93 } catch (final AssertionError e) {
94 errors.add(e);
95 }
96 }
97 }
+0
-84
log4j-core/src/test/java/org/apache/logging/log4j/core/config/MultipleTriggeringPolicyTest.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
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.core.appender.RollingFileAppender;
20 import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
21 import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
22 import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
23 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
24 import org.apache.logging.log4j.junit.LoggerContextSource;
25 import org.junit.jupiter.api.Disabled;
26 import org.junit.jupiter.api.Tag;
27 import org.junit.jupiter.api.Test;
28
29 import static org.junit.jupiter.api.Assertions.assertEquals;
30 import static org.junit.jupiter.api.Assertions.assertNotNull;
31
32 /**
33 * Tests related to <a href="https://issues.apache.org/jira/browse/LOG4J2-1100">LOG4J2-1100</a>.
34 */
35 class MultipleTriggeringPolicyTest {
36 @Test
37 @LoggerContextSource("LOG4J2-1100/log4j2.xml")
38 void xml(final Configuration configuration) {
39 assertBothTriggeringPoliciesConfigured(configuration);
40 }
41
42 @Test
43 @Tag("json")
44 @LoggerContextSource("LOG4J2-1100/log4j2.json")
45 void json(final Configuration configuration) {
46 assertBothTriggeringPoliciesConfigured(configuration);
47 }
48
49 @Test
50 @Tag("yaml")
51 @LoggerContextSource("LOG4J2-1100/log4j2-good.yaml")
52 void yaml(final Configuration configuration) {
53 assertBothTriggeringPoliciesConfigured(configuration);
54 }
55
56 @Test
57 @Tag("yaml")
58 @Disabled("LOG4J2-1100 demonstration")
59 @LoggerContextSource("LOG4J2-1100/log4j2-good.yaml")
60 void unsupportedYamlSyntax(final Configuration configuration) {
61 assertBothTriggeringPoliciesConfigured(configuration);
62 }
63
64 void assertBothTriggeringPoliciesConfigured(final Configuration configuration) {
65 final RollingFileAppender appender = configuration.getAppender("File");
66 assertNotNull(appender);
67 final CompositeTriggeringPolicy compositeTriggeringPolicy = appender.getTriggeringPolicy();
68 assertNotNull(compositeTriggeringPolicy);
69 final TriggeringPolicy[] triggeringPolicies = compositeTriggeringPolicy.getTriggeringPolicies();
70 assertEquals(2, triggeringPolicies.length);
71 final SizeBasedTriggeringPolicy sizeBasedTriggeringPolicy;
72 final TimeBasedTriggeringPolicy timeBasedTriggeringPolicy;
73 if (triggeringPolicies[0] instanceof SizeBasedTriggeringPolicy) {
74 sizeBasedTriggeringPolicy = (SizeBasedTriggeringPolicy) triggeringPolicies[0];
75 timeBasedTriggeringPolicy = (TimeBasedTriggeringPolicy) triggeringPolicies[1];
76 } else {
77 sizeBasedTriggeringPolicy = (SizeBasedTriggeringPolicy) triggeringPolicies[1];
78 timeBasedTriggeringPolicy = (TimeBasedTriggeringPolicy) triggeringPolicies[0];
79 }
80 assertEquals(7, timeBasedTriggeringPolicy.getInterval());
81 assertEquals(100 * 1024 * 1024, sizeBasedTriggeringPolicy.getMaxFileSize());
82 }
83 }
6767 }
6868
6969 private Configuration loadConfiguration(final String resourcePath) throws IOException {
70 try (InputStream in = getClass().getClassLoader().getResourceAsStream(resourcePath)) {
70 final InputStream in = getClass().getClassLoader().getResourceAsStream(resourcePath);
71 try {
7172 final Configuration configuration = new XmlConfiguration(new LoggerContext("test"), new ConfigurationSource(in));
7273 configuration.initialize();
7374 configuration.start();
7475 return configuration;
76 } finally {
77 in.close();
7578 }
7679 }
7780 }
1414 * limitations under the license.
1515 */
1616
17 import static org.junit.Assert.assertEquals;
18 import static org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
1722 import java.util.List;
1823
1924 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
2226 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Test;
24
25 import static org.junit.jupiter.api.Assertions.*;
27 import org.junit.ClassRule;
28 import org.junit.Test;
2629
2730 /**
2831 * Test for LOG4J2-1313
2932 * <Property name="" value="" /> not working
3033 */
31 @LoggerContextSource("configPropertyTest.xml")
3234 public class PropertyTest {
35 private static final String CONFIG = "configPropertyTest.xml";
36
37 @ClassRule
38 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
3339
3440 @Test
35 public void testEmptyAttribute(@Named("List") final ListAppender app) throws Exception {
41 public void testEmptyAttribute() throws Exception {
3642 final org.apache.logging.log4j.Logger logger = LogManager.getLogger();
3743 logger.info("msg");
3844
45 final ListAppender app = (ListAppender) context.getRequiredAppender("List");
46 assertNotNull("No ListAppender", app);
47
3948 final List<String> messages = app.getMessages();
40 assertNotNull(messages, "No Messages");
41 assertEquals(1, messages.size(), "message count" + messages);
49 assertNotNull("No Messages", messages);
50 assertEquals("message count" + messages, 1, messages.size());
4251
4352 //<Property name="emptyElementKey" />
4453 //<Property name="emptyAttributeKey" value="" />
6574
6675 @Test
6776 public void testIsValueNeedsLookup() {
68 assertTrue(Property.createProperty("", "${").isValueNeedsLookup(), "with ${ as value");
69 assertTrue(Property.createProperty("", "blah${blah").isValueNeedsLookup(), "with ${ in value");
70 assertFalse(Property.createProperty("", "").isValueNeedsLookup(), "empty value");
71 assertFalse(Property.createProperty("", "blahblah").isValueNeedsLookup(), "without ${ in value");
72 assertFalse(Property.createProperty("", "blahb{sys:lah").isValueNeedsLookup(), "without $ in value");
73 assertFalse(Property.createProperty("", "blahb$sys:lah").isValueNeedsLookup(), "without { in value");
77 assertTrue("with ${ as value", Property.createProperty("", "${").isValueNeedsLookup());
78 assertTrue("with ${ in value", Property.createProperty("", "blah${blah").isValueNeedsLookup());
79 assertFalse("empty value", Property.createProperty("", "").isValueNeedsLookup());
80 assertFalse("without ${ in value", Property.createProperty("", "blahblah").isValueNeedsLookup());
81 assertFalse("without $ in value", Property.createProperty("", "blahb{sys:lah").isValueNeedsLookup());
82 assertFalse("without { in value", Property.createProperty("", "blahb$sys:lah").isValueNeedsLookup());
7483 }
7584 }
1515 */
1616 package org.apache.logging.log4j.core.config;
1717
18 import java.io.File;
19
1820 import org.apache.logging.log4j.LogManager;
1921 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.Appender;
21 import org.apache.logging.log4j.core.Core;
22 import org.apache.logging.log4j.core.Filter;
23 import org.apache.logging.log4j.core.Layout;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.appender.AbstractAppender;
26 import org.apache.logging.log4j.core.config.plugins.Plugin;
27 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
28 import org.apache.logging.log4j.core.config.plugins.PluginElement;
29 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
31 import org.apache.logging.log4j.junit.LoggerContextSource;
32 import org.junit.jupiter.api.AfterEach;
33 import org.junit.jupiter.api.Assertions;
34 import org.junit.jupiter.api.BeforeEach;
35 import org.junit.jupiter.api.RepeatedTest;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.message.ThreadDumpMessage;
24 import org.junit.Rule;
25 import org.junit.Test;
3626
37 import java.io.File;
38 import java.util.List;
39 import java.util.concurrent.CountDownLatch;
40 import java.util.concurrent.ExecutorService;
41 import java.util.concurrent.Executors;
42 import java.util.concurrent.Future;
43 import java.util.concurrent.TimeUnit;
44 import java.util.stream.Collectors;
45 import java.util.stream.IntStream;
27 import static org.junit.Assert.*;
4628
4729 /**
48 * Performs reconfiguration whilst logging.
4930 *
50 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-620">LOG4J2-620</a>
51 * @see TestAppender
5231 */
53 @LoggerContextSource("reconfiguration-deadlock.xml")
5432 public class ReconfigurationDeadlockTest {
5533
56 private static final int WORKER_COUNT = 100;
34 @Rule
35 public LoggerContextRule init = new LoggerContextRule("reconfiguration-deadlock.xml");
36 private static final int THREAD_COUNT = 5;
37 private static final boolean[] finished = new boolean[THREAD_COUNT];
38 private static LoggerThread[] threads = new LoggerThread[THREAD_COUNT];
5739
58 private ExecutorService executor;
40 @Test
41 public void testReconfig() throws InterruptedException {
5942
60 @BeforeEach
61 public void startExecutor() {
62 executor = Executors.newFixedThreadPool(WORKER_COUNT);
63 }
43 final Updater updater = new Updater();
44 for (int i = 0; i < THREAD_COUNT; ++i) {
45 threads[i] = new LoggerThread(i);
46 threads[i].setDaemon(true);
47 }
48 for (int i = 0; i < THREAD_COUNT; ++i) {
6449
65 @AfterEach
66 public void stopExecutor() throws InterruptedException {
67 executor.shutdownNow();
68 final boolean terminated = executor.awaitTermination(30, TimeUnit.SECONDS);
69 Assertions.assertTrue(terminated, "couldn't terminate the executor");
70 }
71
72 @RepeatedTest(100)
73 public void reconfiguration_should_not_cause_deadlock_for_ongoing_logging() throws Exception {
74
75 // Try to update the config file to ensure that we can indeed update it.
76 updateConfigFileModTime();
77
78 // Start the workers.
79 final CountDownLatch workerStartLatch = new CountDownLatch(WORKER_COUNT);
80 List<Future<?>> workerFutures = initiateWorkers(workerStartLatch, executor);
81
82 // Await workers to start and update the config file.
83 workerStartLatch.await(10, TimeUnit.SECONDS);
84 updateConfigFileModTime();
85
86 // Verify that all workers have finished okay.
87 for (int workerIndex = 0; workerIndex < WORKER_COUNT; workerIndex++) {
88 final Future<?> workerFuture = workerFutures.get(workerIndex);
89 try {
90 Object workerResult = workerFuture.get(30, TimeUnit.SECONDS);
91 Assertions.assertNull(workerResult);
92 } catch (final Throwable failure) {
93 final String message = String.format(
94 "check for worker %02d/%02d has failed",
95 (workerIndex + 1), WORKER_COUNT);
96 throw new AssertionError(message, failure);
50 threads[i].start();
51 }
52 updater.setDaemon(true);
53 updater.start();
54 Thread.sleep(100);
55 boolean stillWaiting = true;
56 for (int i = 0; i < 200; ++i) {
57 int index = 0;
58 for (; index < THREAD_COUNT; ++index) {
59 if (!finished[index]) {
60 break;
61 }
62 }
63 if (index == THREAD_COUNT) {
64 stillWaiting = false;
65 break;
66 }
67 Thread.sleep(100);
68 }
69 updater.shutdown = true;
70 if (stillWaiting) {
71 final ThreadDumpMessage message = new ThreadDumpMessage("Waiting");
72 System.err.print(message.getFormattedMessage());
73 }
74 for (int i = 0; i < THREAD_COUNT; ++i) {
75 if (threads[i].isAlive()) {
76 threads[i].interrupt();
9777 }
9878 }
79 assertFalse("loggerThread didn't finish", stillWaiting);
9980
10081 }
10182
102 private static void updateConfigFileModTime() {
103 final File file = new File("target/test-classes/reconfiguration-deadlock.xml");
104 final boolean fileModified = file.setLastModified(System.currentTimeMillis());
105 Assertions.assertTrue(fileModified, "couldn't update file modification time");
83 private class LoggerThread extends Thread {
84
85 private final Logger logger = LogManager.getRootLogger();
86 private final int index;
87
88 public LoggerThread(final int i) {
89 index = i;
90 }
91 @Override
92 public void run() {
93 int i = 0;
94 try {
95 for (i=0; i < 30; ++i) {
96 logger.error("Thread: " + index + ", Test: " + i++);
97 }
98 } catch (final Exception ie) {
99 return;
100 }
101 finished[index] = true;
102 }
106103 }
107104
108 @SuppressWarnings("SameParameterValue")
109 private static List<Future<?>> initiateWorkers(
110 final CountDownLatch workerStartLatch,
111 final ExecutorService executor) {
112 final Logger logger = LogManager.getRootLogger();
113 return IntStream
114 .range(0, WORKER_COUNT)
115 .mapToObj((final int workerIndex) -> executor.submit(() -> {
116 int i = 0;
117 for (; i < 1_000; i++) {
118 logger.error("worker={}, iteration={}", workerIndex, i);
119 }
120 workerStartLatch.countDown();
121 for (; i < 5_000; i++) {
122 logger.error("worker={}, iteration={}", workerIndex, i);
123 }
124 }))
125 .collect(Collectors.toList());
126 }
105 private class Updater extends Thread {
127106
128 /**
129 * A dummy appender doing nothing but burning CPU cycles whilst randomly accessing the logger.
130 */
131 @Plugin(name = "ReconfigurationDeadlockTestAppender",
132 category = Core.CATEGORY_NAME,
133 elementType = Appender.ELEMENT_TYPE,
134 printObject = true)
135 public static final class TestAppender extends AbstractAppender {
107 public volatile boolean shutdown = false;
136108
137 private final Logger logger;
138
139 private TestAppender(
140 final String name,
141 final Filter filter,
142 final Layout<?> layout,
143 final boolean ignoreExceptions) {
144 super(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY);
145 this.logger = LogManager.getRootLogger();
109 @Override
110 public void run() {
111 while (!shutdown) {
112 try {
113 Thread.sleep(1000);
114 } catch (final InterruptedException e) {
115 e.printStackTrace();
116 }
117 // for running from IDE
118 final File file = new File("target/test-classes/reconfiguration-deadlock.xml");
119 if (file.exists()) {
120 file.setLastModified(System.currentTimeMillis());
121 }
122 }
146123 }
147
148 @PluginFactory
149 public static TestAppender createAppender(
150 @PluginAttribute("name") @Required(message = "A name for the Appender must be specified") final String name,
151 @PluginAttribute("ignoreExceptions") final boolean ignore,
152 @PluginElement("Layout") final Layout<?> layout,
153 @PluginElement("Filter") final Filter filter) {
154 return new TestAppender(name, filter, layout, ignore);
155 }
156
157 /**
158 * Does nothing but burning CPU cycles and accessing to the logger.
159 */
160 @Override
161 public void append(final LogEvent event) {
162 boolean endOfBatch;
163 final int eventHashCode = event.hashCode();
164 switch (Math.abs(eventHashCode % 4)) {
165 case 0: endOfBatch = logger.isTraceEnabled(); break;
166 case 1: endOfBatch = logger.isDebugEnabled(); break;
167 case 2: endOfBatch = logger.isInfoEnabled(); break;
168 case 3: endOfBatch = logger.isWarnEnabled(); break;
169 default: throw new IllegalStateException();
170 }
171 event.setEndOfBatch(endOfBatch);
172 }
173
174124 }
175125
176126 }
+0
-51
log4j-core/src/test/java/org/apache/logging/log4j/core/config/ReliabilityStrategyTest.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
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.core.appender.AsyncAppender;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
22 import org.junit.jupiter.api.AfterAll;
23 import org.junit.jupiter.api.BeforeAll;
24 import org.junit.jupiter.api.Test;
25
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27
28 class ReliabilityStrategyTest {
29
30 @BeforeAll
31 static void setUp() {
32 System.setProperty("log4j2.reliabilityStrategy", MockReliabilityStrategy.class.getName());
33 }
34
35 @AfterAll
36 static void tearDown() {
37 System.clearProperty("log4j2.reliabilityStrategy");
38 }
39
40 @Test
41 @LoggerContextSource("ReliabilityStrategyTest.xml")
42 void beforeStopAppendersCalledBeforeAsyncAppendersStopped(@Named final AsyncAppender async, final Configuration config) {
43 assertTrue(async.isStarted());
44 final MockReliabilityStrategy reliabilityStrategy =
45 (MockReliabilityStrategy) config.getRootLogger().getReliabilityStrategy();
46 config.stop();
47 assertTrue(async.isStopped());
48 reliabilityStrategy.rethrowAssertionErrors();
49 }
50 }
3838 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
3939 import org.apache.logging.log4j.core.filter.CompositeFilter;
4040 import org.apache.logging.log4j.core.layout.PatternLayout;
41 import org.junit.jupiter.api.AfterEach;
42 import org.junit.jupiter.api.Tag;
43 import org.junit.jupiter.api.Test;
41 import org.junit.After;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.junit.runners.JUnit4;
4445
4546 import static org.apache.logging.log4j.hamcrest.MapMatchers.hasSize;
46 import static org.hamcrest.MatcherAssert.*;
4747 import static org.hamcrest.Matchers.equalTo;
4848 import static org.hamcrest.Matchers.greaterThan;
4949 import static org.hamcrest.Matchers.hasKey;
5151 import static org.hamcrest.Matchers.is;
5252 import static org.hamcrest.Matchers.not;
5353 import static org.hamcrest.Matchers.theInstance;
54 import static org.junit.jupiter.api.Assertions.*;
55
56 @Tag("functional")
54 import static org.junit.Assert.*;
55
56 /**
57 *
58 */
59 @RunWith(JUnit4.class)
5760 public class TestConfigurator {
5861
5962 private static final String CONFIG_NAME = "ConfigTest";
7982 "mmmmmmmmmm",
8083 };
8184
82 @AfterEach
85 @After
8386 public void cleanup() {
8487 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
8588 if (ctx != null) {
9396 ctx = Configurator.initialize("Test1", "target/test-classes/log4j2-config.xml");
9497 LogManager.getLogger("org.apache.test.TestConfigurator");
9598 Configuration config = ctx.getConfiguration();
96 assertNotNull(config, "No configuration");
97 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
98 final Map<String, Appender> map = config.getAppenders();
99 assertNotNull(map, "Appenders map should not be null.");
100 assertThat(map, hasSize(greaterThan(0)));
101 assertThat("Wrong configuration", map, hasKey("List"));
102 Configurator.shutdown(ctx);
103 config = ctx.getConfiguration();
104 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
99 assertNotNull("No configuration", config);
100 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
101 final Map<String, Appender> map = config.getAppenders();
102 assertNotNull("Appenders map should not be null.", map);
103 assertThat(map, hasSize(greaterThan(0)));
104 assertThat("Wrong configuration", map, hasKey("List"));
105 Configurator.shutdown(ctx);
106 config = ctx.getConfiguration();
107 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
105108 }
106109
107110 @Test
109112 ctx = Configurator.initialize("Test1", null, new File("target/test-classes/log4j2-config.xml").toURI());
110113 LogManager.getLogger("org.apache.test.TestConfigurator");
111114 Configuration config = ctx.getConfiguration();
112 assertNotNull(config, "No configuration");
113 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
114 final Map<String, Appender> map = config.getAppenders();
115 assertNotNull(map, "Appenders map should not be null.");
116 assertThat(map, hasSize(greaterThan(0)));
117 assertThat("Wrong configuration", map, hasKey("List"));
118 Configurator.shutdown(ctx);
119 config = ctx.getConfiguration();
120 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
115 assertNotNull("No configuration", config);
116 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
117 final Map<String, Appender> map = config.getAppenders();
118 assertNotNull("Appenders map should not be null.", map);
119 assertThat(map, hasSize(greaterThan(0)));
120 assertThat("Wrong configuration", map, hasKey("List"));
121 Configurator.shutdown(ctx);
122 config = ctx.getConfiguration();
123 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
121124 }
122125
123126 @Test
128131 ctx = Configurator.initialize(null, source);
129132 LogManager.getLogger("org.apache.test.TestConfigurator");
130133 Configuration config = ctx.getConfiguration();
131 assertNotNull(config, "No configuration");
132 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
133 final Map<String, Appender> map = config.getAppenders();
134 assertNotNull(map, "Appenders map should not be null.");
135 assertThat(map, hasSize(greaterThan(0)));
136 assertThat("Wrong configuration", map, hasKey("List"));
137 Configurator.shutdown(ctx);
138 config = ctx.getConfiguration();
139 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
134 assertNotNull("No configuration", config);
135 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
136 final Map<String, Appender> map = config.getAppenders();
137 assertNotNull("Appenders map should not be null.", map);
138 assertThat(map, hasSize(greaterThan(0)));
139 assertThat("Wrong configuration", map, hasKey("List"));
140 Configurator.shutdown(ctx);
141 config = ctx.getConfiguration();
142 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
140143 }
141144
142145 @Test
147150 ctx = Configurator.initialize(null, source);
148151 LogManager.getLogger("org.apache.test.TestConfigurator");
149152 Configuration config = ctx.getConfiguration();
150 assertNotNull(config, "No configuration");
151 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
152 final Map<String, Appender> map = config.getAppenders();
153 assertNotNull(map, "Appenders map should not be null.");
154 assertThat(map, hasSize(greaterThan(0)));
155 assertThat("Wrong configuration", map, hasKey("List"));
156 Configurator.shutdown(ctx);
157 config = ctx.getConfiguration();
158 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
153 assertNotNull("No configuration", config);
154 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
155 final Map<String, Appender> map = config.getAppenders();
156 assertNotNull("Appenders map should not be null.", map);
157 assertThat(map, hasSize(greaterThan(0)));
158 assertThat("Wrong configuration", map, hasKey("List"));
159 Configurator.shutdown(ctx);
160 config = ctx.getConfiguration();
161 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
159162 }
160163
161164 @Test
163166 ctx = Configurator.initialize("Test1", "log4j2-config.xml");
164167 LogManager.getLogger("org.apache.test.TestConfigurator");
165168 Configuration config = ctx.getConfiguration();
166 assertNotNull(config, "No configuration");
167 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
168 final Map<String, Appender> map = config.getAppenders();
169 assertNotNull(map, "Appenders map should not be null.");
170 assertThat(map, hasSize(greaterThan(0)));
171 assertThat("Wrong configuration", map, hasKey("List"));
172 Configurator.shutdown(ctx);
173 config = ctx.getConfiguration();
174 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
169 assertNotNull("No configuration", config);
170 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
171 final Map<String, Appender> map = config.getAppenders();
172 assertNotNull("Appenders map should not be null.", map);
173 assertThat(map, hasSize(greaterThan(0)));
174 assertThat("Wrong configuration", map, hasKey("List"));
175 Configurator.shutdown(ctx);
176 config = ctx.getConfiguration();
177 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
175178 }
176179
177180 @Test
180183 ctx = Configurator.initialize("Test1", null);
181184 LogManager.getLogger("org.apache.test.TestConfigurator");
182185 Configuration config = ctx.getConfiguration();
183 assertNotNull(config, "No configuration");
184 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
185 final Map<String, Appender> map = config.getAppenders();
186 assertNotNull(map, "Appenders map should not be null.");
187 assertThat(map, hasSize(greaterThan(0)));
188 assertThat("Wrong configuration", map, hasKey("List"));
189 Configurator.shutdown(ctx);
190 config = ctx.getConfiguration();
191 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
186 assertNotNull("No configuration", config);
187 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
188 final Map<String, Appender> map = config.getAppenders();
189 assertNotNull("Appenders map should not be null.", map);
190 assertThat(map, hasSize(greaterThan(0)));
191 assertThat("Wrong configuration", map, hasKey("List"));
192 Configurator.shutdown(ctx);
193 config = ctx.getConfiguration();
194 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
192195 }
193196
194197 @Test
196199 ctx = Configurator.initialize("Test1", "classpath:log4j2-config.xml");
197200 LogManager.getLogger("org.apache.test.TestConfigurator");
198201 Configuration config = ctx.getConfiguration();
199 assertNotNull(config, "No configuration");
200 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
201 final Map<String, Appender> map = config.getAppenders();
202 assertNotNull(map, "Appenders map should not be null.");
203 assertThat(map, hasSize(greaterThan(0)));
204 assertThat("Wrong configuration", map, hasKey("List"));
205 Configurator.shutdown(ctx);
206 config = ctx.getConfiguration();
207 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Incorrect Configuration.");
202 assertNotNull("No configuration", config);
203 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
204 final Map<String, Appender> map = config.getAppenders();
205 assertNotNull("Appenders map should not be null.", map);
206 assertThat(map, hasSize(greaterThan(0)));
207 assertThat("Wrong configuration", map, hasKey("List"));
208 Configurator.shutdown(ctx);
209 config = ctx.getConfiguration();
210 assertEquals("Incorrect Configuration.", NullConfiguration.NULL_NAME, config.getName());
208211 }
209212
210213 @Test
212215 ctx = Configurator.initialize("Test1", "classloader:log4j2-config.xml");
213216 LogManager.getLogger("org.apache.test.TestConfigurator");
214217 Configuration config = ctx.getConfiguration();
215 assertNotNull(config, "No configuration");
216 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
217 final Map<String, Appender> map = config.getAppenders();
218 assertNotNull(map, "Appenders map should not be null.");
219 assertThat(map, hasSize(greaterThan(0)));
220 assertThat("Wrong configuration", map, hasKey("List"));
221 Configurator.shutdown(ctx);
222 config = ctx.getConfiguration();
223 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Incorrect Configuration.");
218 assertNotNull("No configuration", config);
219 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
220 final Map<String, Appender> map = config.getAppenders();
221 assertNotNull("Appenders map should not be null.", map);
222 assertThat(map, hasSize(greaterThan(0)));
223 assertThat("Wrong configuration", map, hasKey("List"));
224 Configurator.shutdown(ctx);
225 config = ctx.getConfiguration();
226 assertEquals("Incorrect Configuration.", NullConfiguration.NULL_NAME, config.getName());
224227 }
225228
226229 @Test
228231 ctx = Configurator.initialize("-config", null);
229232 LogManager.getLogger("org.apache.test.TestConfigurator");
230233 Configuration config = ctx.getConfiguration();
231 assertNotNull(config, "No configuration");
232 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
233 final Map<String, Appender> map = config.getAppenders();
234 assertNotNull(map, "Appenders map should not be null.");
235 assertThat(map, hasSize(greaterThan(0)));
236 assertThat("Wrong configuration", map, hasKey("List"));
237 Configurator.shutdown(ctx);
238 config = ctx.getConfiguration();
239 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
234 assertNotNull("No configuration", config);
235 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
236 final Map<String, Appender> map = config.getAppenders();
237 assertNotNull("Appenders map should not be null.", map);
238 assertThat(map, hasSize(greaterThan(0)));
239 assertThat("Wrong configuration", map, hasKey("List"));
240 Configurator.shutdown(ctx);
241 config = ctx.getConfiguration();
242 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
240243 }
241244
242245 @Test
243246 public void testReconfiguration() throws Exception {
244247 final File file = new File("target/test-classes/log4j2-config.xml");
245 assertTrue(file.setLastModified(System.currentTimeMillis() - 120000), "setLastModified should have succeeded.");
248 assertTrue("setLastModified should have succeeded.", file.setLastModified(System.currentTimeMillis() - 120000));
246249 ctx = Configurator.initialize("Test1", "target/test-classes/log4j2-config.xml");
247250 final Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
248251 Configuration config = ctx.getConfiguration();
249 assertNotNull(config, "No configuration");
250 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
251 final Map<String, Appender> map = config.getAppenders();
252 assertNotNull(map, "Appenders map should not be null.");
252 assertNotNull("No configuration", config);
253 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
254 final Map<String, Appender> map = config.getAppenders();
255 assertNotNull("Appenders map should not be null.", map);
253256 assertThat(map, hasSize(greaterThan(0)));
254257 assertThat("Wrong configuration", map, hasKey("List"));
255258
258261 if (!file.setLastModified(System.currentTimeMillis())) {
259262 Thread.sleep(500);
260263 }
261 assertTrue(file.setLastModified(System.currentTimeMillis()), "setLastModified should have succeeded.");
264 assertTrue("setLastModified should have succeeded.", file.setLastModified(System.currentTimeMillis()));
262265 TimeUnit.SECONDS.sleep(config.getWatchManager().getIntervalSeconds()+1);
263 for (int i = 0; i < 100; ++i) {
266 for (int i = 0; i < 17; ++i) {
264267 logger.debug("Test message " + i);
265268 }
266269
267270 // Sleep and check
268 Thread.sleep(100);
271 Thread.sleep(50);
269272 if (is(theInstance(config)).matches(ctx.getConfiguration())) {
270 Thread.sleep(2000);
273 Thread.sleep(500);
271274 }
272275 final Configuration newConfig = ctx.getConfiguration();
273276 assertThat("Configuration not reset", newConfig, is(not(theInstance(config))));
274277 Configurator.shutdown(ctx);
275278 config = ctx.getConfiguration();
276 assertEquals(NullConfiguration.NULL_NAME, config.getName(), "Unexpected Configuration.");
279 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
277280 }
278281
279282
282285 ctx = Configurator.initialize("-config", null);
283286 LogManager.getLogger("org.apache.test.TestConfigurator");
284287 final Configuration config = ctx.getConfiguration();
285 assertNotNull(config, "No configuration");
286 assertEquals(CONFIG_NAME, config.getName(), "Incorrect Configuration.");
287 final Map<String, Appender> map = config.getAppenders();
288 assertNotNull(map, "Appenders map should not be null.");
288 assertNotNull("No configuration", config);
289 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
290 final Map<String, Appender> map = config.getAppenders();
291 assertNotNull("Appenders map should not be null.", map);
289292 assertThat(map, hasSize(greaterThan(0)));
290293 assertThat("No ListAppender named List2", map, hasKey("List2"));
291294 final Appender app = map.get("List2");
292295 final Layout<? extends Serializable> layout = app.getLayout();
293 assertNotNull(layout, "Appender List2 does not have a Layout");
296 assertNotNull("Appender List2 does not have a Layout", layout);
294297 assertThat("Appender List2 is not configured with a PatternLayout", layout, instanceOf(PatternLayout.class));
295298 final String pattern = ((PatternLayout) layout).getConversionPattern();
296 assertNotNull(pattern, "No conversion pattern for List2 PatternLayout");
297 assertFalse(pattern.startsWith("${env:PATH}"), "Environment variable was not substituted");
299 assertNotNull("No conversion pattern for List2 PatternLayout", pattern);
300 assertFalse("Environment variable was not substituted", pattern.startsWith("${env:PATH}"));
298301 }
299302
300303 @Test
302305 ctx = Configurator.initialize("Test1", "bad/log4j-loggers.xml");
303306 LogManager.getLogger("org.apache.test.TestConfigurator");
304307 final Configuration config = ctx.getConfiguration();
305 assertNotNull(config, "No configuration");
308 assertNotNull("No configuration", config);
306309 final String name = DefaultConfiguration.DEFAULT_NAME + "@" + Integer.toHexString(config.hashCode());
307 assertEquals(name, config.getName(), "Unexpected Configuration.");
310 assertEquals("Unexpected Configuration.", name, config.getName());
308311 }
309312
310313 @Test
312315 ctx = Configurator.initialize("Test1", "bad/log4j-status.xml");
313316 LogManager.getLogger("org.apache.test.TestConfigurator");
314317 final Configuration config = ctx.getConfiguration();
315 assertNotNull(config, "No configuration");
316 assertEquals("XMLConfigTest", config.getName(), "Unexpected Configuration");
318 assertNotNull("No configuration", config);
319 assertEquals("Unexpected Configuration", "XMLConfigTest", config.getName());
317320 final LoggerConfig root = config.getLoggerConfig("");
318 assertNotNull(root, "No Root Logger");
319 assertSame(Level.ERROR, root.getLevel(), "Expected error level, was " + root.getLevel());
321 assertNotNull("No Root Logger", root);
322 assertTrue("Expected error level, was " + root.getLevel(), Level.ERROR == root.getLevel());
320323 }
321324
322325 @Test
324327 ctx = Configurator.initialize("Test1", "bad/log4j-badfilterparam.xml");
325328 LogManager.getLogger("org.apache.test.TestConfigurator");
326329 final Configuration config = ctx.getConfiguration();
327 assertNotNull(config, "No configuration");
328 assertEquals("XMLConfigTest", config.getName(), "Unexpected Configuration");
330 assertNotNull("No configuration", config);
331 assertEquals("Unexpected Configuration", "XMLConfigTest", config.getName());
329332 final LoggerConfig lcfg = config.getLoggerConfig("org.apache.logging.log4j.test1");
330 assertNotNull(lcfg, "No Logger");
333 assertNotNull("No Logger", lcfg);
331334 final Filter filter = lcfg.getFilter();
332 assertNull(filter, "Unexpected Filter");
335 assertNull("Unexpected Filter", filter);
333336 }
334337
335338 @Test
337340 ctx = Configurator.initialize("Test1", "bad/log4j-nofilter.xml");
338341 LogManager.getLogger("org.apache.test.TestConfigurator");
339342 final Configuration config = ctx.getConfiguration();
340 assertNotNull(config, "No configuration");
341 assertEquals("XMLConfigTest", config.getName(), "Unexpected Configuration");
343 assertNotNull("No configuration", config);
344 assertEquals("Unexpected Configuration", "XMLConfigTest", config.getName());
342345 final LoggerConfig lcfg = config.getLoggerConfig("org.apache.logging.log4j.test1");
343 assertNotNull(lcfg, "No Logger");
346 assertNotNull("No Logger", lcfg);
344347 final Filter filter = lcfg.getFilter();
345 assertNotNull(filter, "No Filter");
348 assertNotNull("No Filter", filter);
346349 assertThat(filter, instanceOf(CompositeFilter.class));
347 assertTrue(((CompositeFilter) filter).isEmpty(), "Unexpected filters");
350 assertTrue("Unexpected filters", ((CompositeFilter) filter).isEmpty());
348351 }
349352
350353 @Test
352355 ctx = Configurator.initialize("Test1", "bad/log4j-badlayout.xml");
353356 LogManager.getLogger("org.apache.test.TestConfigurator");
354357 final Configuration config = ctx.getConfiguration();
355 assertNotNull(config, "No configuration");
356 assertEquals("XMLConfigTest", config.getName(), "Unexpected Configuration");
358 assertNotNull("No configuration", config);
359 assertEquals("Unexpected Configuration", "XMLConfigTest", config.getName());
357360 }
358361
359362 @Test
369372 ctx = Configurator.initialize("Test1", "bad/log4j-badfilename.xml");
370373 LogManager.getLogger("org.apache.test.TestConfigurator");
371374 final Configuration config = ctx.getConfiguration();
372 assertNotNull(config, "No configuration");
373 assertEquals("XMLConfigTest", config.getName(), "Unexpected Configuration");
375 assertNotNull("No configuration", config);
376 assertEquals("Unexpected Configuration", "XMLConfigTest", config.getName());
374377 assertThat(config.getAppenders(), hasSize(equalTo(2)));
375378 }
376379
394397 builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
395398 ctx = Configurator.initialize(builder.build());
396399 final Configuration config = ctx.getConfiguration();
397 assertNotNull(config, "No configuration");
398 assertEquals("BuilderTest", config.getName(), "Unexpected Configuration");
400 assertNotNull("No configuration", config);
401 assertEquals("Unexpected Configuration", "BuilderTest", config.getName());
399402 assertThat(config.getAppenders(), hasSize(equalTo(1)));
400403 }
401404
434437 .add( builder.newAppenderRef( "rolling" ) ) );
435438 final Configuration config = builder.build();
436439 config.initialize();
437 assertNotNull(config.getAppender("rolling"), "No rolling file appender");
438 assertEquals("RollingBuilder", config.getName(), "Unexpected Configuration");
440 assertNotNull("No rolling file appender", config.getAppender("rolling"));
441 assertEquals("Unexpected Configuration", "RollingBuilder", config.getName());
439442 // Initialize the new configuration
440443 final LoggerContext ctx = Configurator.initialize( config );
441444 Configurator.shutdown(ctx);
474477 builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
475478 ctx = Configurator.initialize(builder.build());
476479 final Configuration config = ctx.getConfiguration();
477 assertNotNull(config, "No configuration");
478 assertEquals("BuilderTest", config.getName(), "Unexpected Configuration");
480 assertNotNull("No configuration", config);
481 assertEquals("Unexpected Configuration", "BuilderTest", config.getName());
479482 assertThat(config.getAppenders(), hasSize(equalTo(1)));
480 assertNotNull(config.getScriptManager().getScript("filter.groovy"), "Filter script not found");
481 assertNotNull(config.getScriptManager().getScript("selectorScript"), "pattern selector script not found");
483 assertNotNull("Filter script not found", config.getScriptManager().getScript("filter.groovy"));
484 assertNotNull("pattern selector script not found", config.getScriptManager().getScript("selectorScript"));
482485 }
483486
484487 }
1616 package org.apache.logging.log4j.core.config;
1717
1818 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.junit.LoggerContextFactoryExtension;
2019 import org.apache.logging.log4j.simple.SimpleLoggerContextFactory;
21 import org.junit.jupiter.api.Test;
22 import org.junit.jupiter.api.extension.RegisterExtension;
23 import org.junit.jupiter.api.parallel.ResourceLock;
20 import org.junit.BeforeClass;
21 import org.junit.Test;
2422
25 import static org.junit.jupiter.api.Assertions.assertNull;
23 import static org.junit.Assert.*;
2624
27 @ResourceLock("log4j2.LoggerContextFactory")
25 /**
26 *
27 */
2828 public class TestConfiguratorError {
2929
30 @RegisterExtension
31 static final LoggerContextFactoryExtension extension = new LoggerContextFactoryExtension(new SimpleLoggerContextFactory());
30 private static final String FACTORY_PROPERTY_NAME = "log4j2.loggerContextFactory";
31
32 @BeforeClass
33 public static void beforeClass() {
34 System.setProperty(FACTORY_PROPERTY_NAME, SimpleLoggerContextFactory.class.getName());
35 }
3236
3337 @Test
3438 public void testErrorNoClassLoader() throws Exception {
3539 try (final LoggerContext ctx = Configurator.initialize("Test1", "target/test-classes/log4j2-config.xml")) {
36 assertNull(ctx, "No LoggerContext should have been returned");
40 assertNull("No LoggerContext should have been returned", ctx);
3741 }
3842 }
3943
4145 public void testErrorNullClassLoader() throws Exception {
4246 try (final LoggerContext ctx = Configurator.initialize("Test1", null,
4347 "target/test-classes/log4j2-config.xml")) {
44 assertNull(ctx, "No LoggerContext should have been returned");
48 assertNull("No LoggerContext should have been returned", ctx);
4549 }
4650 }
4751 }
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
17 package org.apache.logging.log4j.core.config;
18
19 import java.io.BufferedReader;
20 import java.io.FileReader;
21 import java.security.SecureRandom;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.Map;
26
27 import org.apache.logging.log4j.Level;
28 import org.apache.logging.log4j.Logger;
29 import org.apache.logging.log4j.core.Appender;
30 import org.apache.logging.log4j.core.Filter;
31 import org.apache.logging.log4j.core.LoggerContext;
32 import org.apache.logging.log4j.core.filter.ThreadContextMapFilter;
33 import org.apache.logging.log4j.junit.CleanFiles;
34 import org.apache.logging.log4j.junit.LoggerContextRule;
35 import org.apache.logging.log4j.util.Strings;
36 import org.junit.Before;
37 import org.junit.Rule;
38 import org.junit.Test;
39 import org.junit.rules.RuleChain;
40 import org.junit.rules.TestRule;
41 import org.junit.runner.RunWith;
42 import org.junit.runners.Parameterized;
43 import org.junit.runners.Parameterized.Parameters;
44
45 import static org.apache.logging.log4j.hamcrest.MapMatchers.hasSize;
46 import static org.hamcrest.Matchers.endsWith;
47 import static org.hamcrest.Matchers.equalTo;
48 import static org.hamcrest.Matchers.instanceOf;
49 import static org.hamcrest.Matchers.is;
50 import static org.hamcrest.Matchers.notNullValue;
51 import static org.junit.Assert.*;
52
53 /**
54 * Tests XInclude.
55 */
56 @RunWith(Parameterized.class)
57 public class XIncludeTest {
58
59 private static final String LOGGER_NAME = "org.apache.logging.log4j.test1.Test";
60 private static final String FILE_LOGGER_NAME = "org.apache.logging.log4j.test2.Test";
61 private static final String APPENDER_NAME = "STDOUT";
62
63 private final String logFileName;
64
65 @Rule
66 public TestRule rules;
67
68 private final LoggerContextRule init;
69
70 private LoggerContext ctx;
71
72 private final SecureRandom random = new SecureRandom();
73
74 public XIncludeTest(final String configFileName, final String logFileName) {
75 this.logFileName = logFileName;
76 this.init = new LoggerContextRule(configFileName);
77 this.rules = RuleChain.outerRule(new CleanFiles(logFileName)).around(this.init);
78 }
79
80 @Parameters(name = "config={0}, log={1}")
81 public static Collection<Object[]> data() {
82 return Arrays.asList(
83 new Object[][]{
84 {"classpath:log4j-xinclude.xml", "target/test-xinclude.log"},
85 }
86 );
87 }
88
89 @Before
90 public void setUp() throws Exception {
91 this.ctx = this.init.getLoggerContext();
92 }
93
94 @Test
95 public void testConfiguredAppenders() throws Exception {
96 final Configuration configuration = this.ctx.getConfiguration();
97 final Map<String, Appender> appenders = configuration.getAppenders();
98 assertThat(appenders, is(notNullValue()));
99 assertThat(appenders.size(), is(equalTo(3)));
100 }
101
102 @Test
103 public void testLogger() throws Exception {
104 final Logger logger = this.ctx.getLogger(LOGGER_NAME);
105 assertThat(logger, is(instanceOf(org.apache.logging.log4j.core.Logger.class)));
106 final org.apache.logging.log4j.core.Logger l = (org.apache.logging.log4j.core.Logger) logger;
107 assertThat(l.getLevel(), is(equalTo(Level.DEBUG)));
108 assertThat(l.filterCount(), is(equalTo(1)));
109 final Iterator<Filter> iterator = l.getFilters();
110 assertThat(iterator.hasNext(), is(true));
111 final Filter filter = iterator.next();
112 assertThat(filter, is(instanceOf(ThreadContextMapFilter.class)));
113 final Map<String, Appender> appenders = l.getAppenders();
114 assertThat(appenders, is(notNullValue()));
115 assertThat(appenders, hasSize(1));
116 final Appender appender = appenders.get(APPENDER_NAME);
117 assertThat(appender, is(notNullValue()));
118 assertThat(appender.getName(), is(equalTo("STDOUT")));
119 }
120
121 @Test
122 public void testLogToFile() throws Exception {
123 final Logger logger = this.ctx.getLogger(FILE_LOGGER_NAME);
124 final long random = this.random.nextLong();
125 logger.debug("This is test message number {}", random);
126 int count = 0;
127 String line = Strings.EMPTY;
128 try (BufferedReader in = new BufferedReader(new FileReader(this.logFileName))) {
129 while (in.ready()) {
130 ++count;
131 line = in.readLine();
132 }
133 }
134 assertThat(count, is(equalTo(1)));
135 assertThat(line, endsWith(Long.toString(random)));
136 }
137
138 }
+0
-62
log4j-core/src/test/java/org/apache/logging/log4j/core/config/arbiters/BasicArbiterTest.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.logging.log4j.core.config.arbiters;
17
18 import org.apache.logging.log4j.core.Appender;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.appender.ConsoleAppender;
21 import org.apache.logging.log4j.core.config.Configurator;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.AfterEach;
24 import org.junit.jupiter.api.Test;
25
26 import static org.junit.jupiter.api.Assertions.*;
27
28 /**
29 * Tests basic condition processing.
30 */
31 public class BasicArbiterTest {
32
33 static final String CONFIG = "log4j2-arbiters.xml";
34 static LoggerContext loggerContext = null;
35
36 @AfterEach
37 public void after() {
38 loggerContext.stop();
39 loggerContext = null;
40 }
41
42 @Test
43 public void prodTest() {
44 System.setProperty("env", "prod");
45 loggerContext = Configurator.initialize(null, CONFIG);
46 assertNotNull(loggerContext);
47 Appender app = loggerContext.getConfiguration().getAppender("Out");
48 assertNotNull(app);
49 assertTrue(app instanceof ListAppender);
50 }
51
52 @Test
53 public void devTest() {
54 System.setProperty("env", "dev");
55 loggerContext = Configurator.initialize(null, CONFIG);
56 assertNotNull(loggerContext);
57 Appender app = loggerContext.getConfiguration().getAppender("Out");
58 assertNotNull(app);
59 assertTrue(app instanceof ConsoleAppender);
60 }
61 }
+0
-63
log4j-core/src/test/java/org/apache/logging/log4j/core/config/arbiters/ScriptArbiterTest.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.logging.log4j.core.config.arbiters;
17
18 import org.apache.logging.log4j.core.Appender;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.appender.ConsoleAppender;
21 import org.apache.logging.log4j.core.config.Configurator;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.AfterEach;
24 import org.junit.jupiter.api.Test;
25
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28
29 /**
30 * Tests basic condition processing.
31 */
32 public class ScriptArbiterTest {
33
34 static final String CONFIG = "log4j2-scriptArbiters.xml";
35 static LoggerContext loggerContext = null;
36
37 @AfterEach
38 public void after() {
39 loggerContext.stop();
40 loggerContext = null;
41 }
42
43 @Test
44 public void prodTest() {
45 System.setProperty("env", "prod");
46 loggerContext = Configurator.initialize(null, CONFIG);
47 assertNotNull(loggerContext);
48 Appender app = loggerContext.getConfiguration().getAppender("Out");
49 assertNotNull(app);
50 assertTrue(app instanceof ListAppender);
51 }
52
53 @Test
54 public void devTest() {
55 System.setProperty("env", "dev");
56 loggerContext = Configurator.initialize(null, CONFIG);
57 assertNotNull(loggerContext);
58 Appender app = loggerContext.getConfiguration().getAppender("Out");
59 assertNotNull(app);
60 assertTrue(app instanceof ConsoleAppender);
61 }
62 }
+0
-63
log4j-core/src/test/java/org/apache/logging/log4j/core/config/arbiters/SelectArbiterTest.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.logging.log4j.core.config.arbiters;
17
18 import org.apache.logging.log4j.core.Appender;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.appender.ConsoleAppender;
21 import org.apache.logging.log4j.core.config.Configurator;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.AfterEach;
24 import org.junit.jupiter.api.Test;
25
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28
29 /**
30 * Tests basic condition processing.
31 */
32 public class SelectArbiterTest {
33
34 static final String CONFIG = "log4j2-selectArbiters.xml";
35 static LoggerContext loggerContext = null;
36
37 @AfterEach
38 public void after() {
39 loggerContext.stop();
40 loggerContext = null;
41 }
42
43 @Test
44 public void prodTest() {
45 System.setProperty("env", "prod");
46 loggerContext = Configurator.initialize(null, CONFIG);
47 assertNotNull(loggerContext);
48 Appender app = loggerContext.getConfiguration().getAppender("Out");
49 assertNotNull(app);
50 assertTrue(app instanceof ListAppender);
51 }
52
53 @Test
54 public void devTest() {
55 System.setProperty("env", "dev");
56 loggerContext = Configurator.initialize(null, CONFIG);
57 assertNotNull(loggerContext);
58 Appender app = loggerContext.getConfiguration().getAppender("Out");
59 assertNotNull(app);
60 assertTrue(app instanceof ConsoleAppender);
61 }
62 }
1515 */
1616 package org.apache.logging.log4j.core.config.builder;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22
1823 import java.util.List;
1924 import java.util.Map;
2025
2530 import org.apache.logging.log4j.core.Filter;
2631 import org.apache.logging.log4j.core.LifeCycle;
2732 import org.apache.logging.log4j.core.LoggerContext;
28 import org.apache.logging.log4j.core.appender.ConsoleAppender;
2933 import org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender;
3034 import org.apache.logging.log4j.core.config.Configuration;
3135 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3741 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
3842 import org.apache.logging.log4j.core.filter.ThresholdFilter;
3943 import org.apache.logging.log4j.core.layout.GelfLayout;
40 import org.apache.logging.log4j.core.layout.PatternLayout;
4144 import org.apache.logging.log4j.core.util.Constants;
42 import org.junit.jupiter.api.Test;
45 import org.junit.Test;
4346
44 import static org.hamcrest.MatcherAssert.assertThat;
45 import static org.hamcrest.Matchers.instanceOf;
46 import static org.junit.jupiter.api.Assertions.*;
47
47 /**
48 *
49 */
4850 public class ConfigurationAssemblerTest {
4951
5052 @Test
8284 assertNotNull(config);
8385 assertNotNull(config.getName());
8486 assertFalse(config.getName().isEmpty());
85 assertNotNull(config, "No configuration created");
86 assertEquals(config.getState(), LifeCycle.State.STARTED, "Incorrect State: " + config.getState());
87 assertNotNull("No configuration created", config);
88 assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
8789 final Map<String, Appender> appenders = config.getAppenders();
8890 assertNotNull(appenders);
89 assertEquals(appenders.size(), 2, "Incorrect number of Appenders: " + appenders.size());
91 assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 2);
9092 final KafkaAppender kafkaAppender = (KafkaAppender)appenders.get("Kafka");
9193 final GelfLayout gelfLayout = (GelfLayout)kafkaAppender.getLayout();
92 final ConsoleAppender consoleAppender = (ConsoleAppender)appenders.get("Stdout");
93 final PatternLayout patternLayout = (PatternLayout)consoleAppender.getLayout();
9494 final Map<String, LoggerConfig> loggers = config.getLoggers();
9595 assertNotNull(loggers);
96 assertEquals(loggers.size(), 2, "Incorrect number of LoggerConfigs: " + loggers.size());
96 assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
9797 final LoggerConfig rootLoggerConfig = loggers.get("");
9898 assertEquals(Level.ERROR, rootLoggerConfig.getLevel());
9999 assertFalse(rootLoggerConfig.isIncludeLocation());
101101 assertEquals(Level.DEBUG, loggerConfig.getLevel());
102102 assertTrue(loggerConfig.isIncludeLocation());
103103 final Filter filter = config.getFilter();
104 assertNotNull(filter, "No Filter");
105 assertThat(filter, instanceOf(ThresholdFilter.class));
104 assertNotNull("No Filter", filter);
105 assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
106106 final List<CustomLevelConfig> customLevels = config.getCustomLevels();
107 assertNotNull(filter, "No CustomLevels");
107 assertNotNull("No CustomLevels", filter);
108108 assertEquals(1, customLevels.size());
109109 final CustomLevelConfig customLevel = customLevels.get(0);
110110 assertEquals("Panic", customLevel.getLevelName());
1515 */
1616 package org.apache.logging.log4j.core.config.builder;
1717
18 import java.util.concurrent.TimeUnit;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.core.Filter;
2022 import org.apache.logging.log4j.core.appender.ConsoleAppender;
2224 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
2325 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
2426 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
25 import org.junit.jupiter.api.Test;
26 import java.util.concurrent.TimeUnit;
27 import org.junit.Test;
2728
28 import static org.junit.jupiter.api.Assertions.assertEquals;
29 import static org.junit.Assert.*;
30 import static org.junit.Assume.assumeTrue;
2931
3032 public class ConfigurationBuilderTest {
3133
6769 }
6870
6971 private final static String expectedXml =
70 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" /*+ EOL*/ +
72 "<?xml version='1.0' encoding='UTF-8'?>" + EOL +
7173 "<Configuration name=\"config name\" status=\"ERROR\" packages=\"foo,bar\" shutdownTimeout=\"5000\">" + EOL +
7274 INDENT + "<Properties>" + EOL +
7375 INDENT + INDENT + "<Property name=\"MyKey\">MyValue</Property>" + EOL +
104106 INDENT + "</Loggers>" + EOL +
105107 "</Configuration>" + EOL;
106108
109 // TODO make test run properly on Windows
107110 @Test
108111 public void testXmlConstructing() throws Exception {
112 assumeTrue(System.lineSeparator().length() == 1); // Only run test on platforms with single character line endings (such as Linux), not on Windows
109113 final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
110114 addTestFixtures("config name", builder);
111115 final String xmlConfiguration = builder.toXmlConfiguration();
2323 public class TypeConverterRegistryTest {
2424
2525 @Test(expected = NullPointerException.class)
26 public void testFindNullConverter() {
26 public void testFindNullConverter() throws Exception {
2727 TypeConverterRegistry.getInstance().findCompatibleConverter(null);
2828 }
2929
6262 // TODO: is there a specific converter this should return?
6363 }
6464
65 public enum Foo {
65 public static enum Foo {
6666 I, PITY, THE
6767 }
6868
7676 assertEquals(Foo.PITY, fooTypeConverter.convert("pity"));
7777 assertEquals(Foo.THE, fooTypeConverter.convert("THE"));
7878 }
79
8079 }
216216 public void testConvert() throws Exception {
217217 final Object actual = TypeConverters.convert(value, clazz, defaultValue);
218218 final String assertionMessage = "\nGiven: " + value + "\nDefault: " + defaultValue;
219 if (expected instanceof char[]) {
219 if (expected != null && expected instanceof char[]) {
220220 assertArrayEquals(assertionMessage, (char[]) expected, (char[]) actual);
221 } else if (expected instanceof byte[]) {
221 } else if (expected != null && expected instanceof byte[]) {
222222 assertArrayEquals(assertionMessage, (byte[]) expected, (byte[]) actual);
223223 } else {
224224 assertEquals(assertionMessage, expected, actual);
+0
-71
log4j-core/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/PluginCacheTest.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
17 package org.apache.logging.log4j.core.config.plugins.processor;
18
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.junit.runners.JUnit4;
31
32 @RunWith(JUnit4.class)
33 public class PluginCacheTest {
34
35 @Test
36 public void testOutputIsReproducibleWhenInputOrderingChanges() throws IOException {
37 PluginCache cacheA = new PluginCache();
38 createCategory(cacheA, "one", Arrays.asList("bravo", "alpha", "charlie"));
39 createCategory(cacheA, "two", Arrays.asList("alpha", "charlie", "bravo"));
40 assertEquals(cacheA.getAllCategories().size(), 2);
41 assertEquals(cacheA.getAllCategories().get("one").size(), 3);
42 assertEquals(cacheA.getAllCategories().get("two").size(), 3);
43 PluginCache cacheB = new PluginCache();
44 createCategory(cacheB, "two", Arrays.asList("bravo", "alpha", "charlie"));
45 createCategory(cacheB, "one", Arrays.asList("alpha", "charlie", "bravo"));
46 assertEquals(cacheB.getAllCategories().size(), 2);
47 assertEquals(cacheB.getAllCategories().get("one").size(), 3);
48 assertEquals(cacheB.getAllCategories().get("two").size(), 3);
49 assertArrayEquals(cacheData(cacheA), cacheData(cacheB));
50 }
51
52 private void createCategory(PluginCache cache, String categoryName, List<String> entryNames) {
53 Map<String, PluginEntry> category = cache.getCategory(categoryName);
54 for (String entryName: entryNames) {
55 PluginEntry entry = new PluginEntry();
56 entry.setKey(entryName);
57 entry.setClassName("com.example.Plugin");
58 entry.setName("name");
59 entry.setCategory(categoryName);
60 category.put(entryName, entry);
61 }
62 }
63
64 private byte[] cacheData(PluginCache cache) throws IOException {
65 ByteArrayOutputStream outputB = new ByteArrayOutputStream();
66 cache.writeCache(outputB);
67 return outputB.toByteArray();
68 }
69
70 }
1515 */
1616 package org.apache.logging.log4j.core.config.plugins.util;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertTrue;
20
1821 import java.io.File;
1922 import java.io.IOException;
2023 import java.util.ArrayList;
21 import java.util.Collections;
24 import java.util.Arrays;
2225 import java.util.List;
2326 import java.util.Locale;
2427
3740 import org.apache.logging.log4j.core.config.Configurator;
3841 import org.apache.logging.log4j.status.StatusLogger;
3942 import org.apache.logging.log4j.test.appender.ListAppender;
40 import org.junit.jupiter.api.AfterAll;
41 import org.junit.jupiter.api.Test;
42
43 import static org.junit.jupiter.api.Assertions.*;
43 import org.junit.AfterClass;
44 import org.junit.Test;
4445
4546 public class PluginManagerPackagesTest {
4647 private static Configuration config;
4748 private static ListAppender listAppender;
4849 private static LoggerContext ctx;
4950
50 @AfterAll
51 @AfterClass
5152 public static void cleanupClass() {
5253 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
5354 ctx.reconfigure();
6263 // So we don't create the custom plugin class until this test is run.
6364 final File orig = new File("target/test-classes/customplugin/FixedStringLayout.java.source");
6465 final File f = new File(orig.getParentFile(), "FixedStringLayout.java");
65 assertTrue(orig.renameTo(f), "renamed source file failed");
66 assertTrue("renamed source file OK", orig.renameTo(f));
6667 compile(f);
67 assertTrue(f.renameTo(orig), "reverted source file failed");
68 assertTrue("reverted source file OK", f.renameTo(orig));
6869
6970 // load the compiled class
7071 Class.forName("customplugin.FixedStringLayout");
7980 logger.info("this message is ignored");
8081
8182 final List<String> messages = listAppender.getMessages();
82 assertEquals(1, messages.size(), messages.toString());
83 assertEquals(messages.toString(), 1, messages.size());
8384 assertEquals("abc123XYZ", messages.get(0));
8485 }
8586
8990 final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
9091 final List<String> errors = new ArrayList<>();
9192 try (final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null)) {
92 final Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(
93 Collections.singletonList(f));
93 final Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays
94 .asList(f));
9495
9596 // compile generated source
9697 // (switch off annotation processing: no need to create Log4j2Plugins.dat)
97 final List<String> options = Collections.singletonList("-proc:none");
98 final List<String> options = Arrays.asList("-proc:none");
9899 compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits).call();
99100
100101 // check we don't have any compilation errors
104105 }
105106 }
106107 }
107 assertTrue(errors.isEmpty(), errors.toString());
108 assertTrue(errors.toString(), errors.isEmpty());
108109 }
109110 }
4848 private final String thing;
4949
5050 public AbstractPluginWithGenericBuilder(final String thing) {
51 super();
5152 this.thing = thing;
5253 }
5354
2121 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
2222 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
2323 import org.apache.logging.log4j.core.config.plugins.validation.ValidatingPlugin;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.Test;
2626
27 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.*;
2828
2929 public class RequiredValidatorTest {
3030
3232 private Node node;
3333
3434 @SuppressWarnings("unchecked")
35 @BeforeEach
35 @Before
3636 public void setUp() throws Exception {
3737 final PluginManager manager = new PluginManager("Test");
3838 manager.collectPlugins();
3939 plugin = (PluginType<ValidatingPlugin>) manager.getPluginType("Validator");
40 assertNotNull(plugin, "Rebuild this module to make sure annotation processing kicks in.");
40 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
4141 node = new Node(null, "Validator", plugin);
4242 }
4343
1515 */
1616 package org.apache.logging.log4j.core.config.plugins.validation.validators;
1717
18 import org.apache.logging.log4j.Level;
1819 import org.apache.logging.log4j.core.config.Node;
1920 import org.apache.logging.log4j.core.config.NullConfiguration;
2021 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
2122 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
2223 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
2324 import org.apache.logging.log4j.core.config.plugins.validation.HostAndPort;
24 import org.apache.logging.log4j.junit.StatusLoggerLevel;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
25 import org.apache.logging.log4j.junit.StatusLoggerRule;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
2729
28 import static org.junit.jupiter.api.Assertions.*;
30 import static org.junit.Assert.*;
2931
30 @StatusLoggerLevel("FATAL")
3132 public class ValidHostValidatorTest {
33
34 @Rule
35 public StatusLoggerRule rule = new StatusLoggerRule(Level.FATAL);
3236
3337 private PluginType<HostAndPort> plugin;
3438 private Node node;
3539
3640 @SuppressWarnings("unchecked")
37 @BeforeEach
41 @Before
3842 public void setUp() throws Exception {
3943 final PluginManager manager = new PluginManager("Test");
4044 manager.collectPlugins();
4145 plugin = (PluginType<HostAndPort>) manager.getPluginType("HostAndPort");
42 assertNotNull(plugin, "Rebuild this module to ensure annotation processing has been done.");
46 assertNotNull("Rebuild this module to ensure annotation processing has been done.", plugin);
4347 node = new Node(null, "HostAndPort", plugin);
4448 }
4549
5357 node.getAttributes().put("host", "256.256.256.256");
5458 node.getAttributes().put("port", "1");
5559 final HostAndPort plugin = buildPlugin();
56 assertNull(plugin, "Expected null, but got: " + plugin);
60 assertNull("Expected null, but got: " + plugin, plugin);
5761 }
5862
5963 @Test
7175 .withConfigurationNode(node)
7276 .build();
7377 }
74 }
78 }
2121 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
2222 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
2323 import org.apache.logging.log4j.core.config.plugins.validation.HostAndPort;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.Test;
2626
27 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.*;
2828
2929 public class ValidPortValidatorTest {
3030 private PluginType<HostAndPort> plugin;
3131 private Node node;
3232
3333 @SuppressWarnings("unchecked")
34 @BeforeEach
34 @Before
3535 public void setUp() throws Exception {
3636 final PluginManager manager = new PluginManager("Test");
3737 manager.collectPlugins();
3838 plugin = (PluginType<HostAndPort>) manager.getPluginType("HostAndPort");
39 assertNotNull(plugin, "Rebuild this module to ensure annotation processing has been done.");
39 assertNotNull("Rebuild this module to ensure annotation processing has been done.", plugin);
4040 node = new Node(null, "HostAndPort", plugin);
4141 node.getAttributes().put("host", "localhost");
4242 }
6666 .build();
6767 }
6868
69 }
69 }
2828 import org.apache.logging.log4j.status.StatusData;
2929 import org.apache.logging.log4j.status.StatusListener;
3030 import org.apache.logging.log4j.status.StatusLogger;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
31 import org.junit.Before;
32 import org.junit.Test;
3333
3434 import java.util.ArrayList;
3535 import java.util.List;
3636
37 import static org.hamcrest.MatcherAssert.assertThat;
3837 import static org.hamcrest.Matchers.emptyCollectionOf;
39 import static org.junit.jupiter.api.Assertions.assertEquals;
40 import static org.junit.jupiter.api.Assertions.assertNotNull;
38 import static org.junit.Assert.*;
4139
4240 public class ValidatingPluginWithFailoverTest {
4341
4543 private Node node;
4644
4745 @SuppressWarnings("unchecked")
48 @BeforeEach
46 @Before
4947 public void setUp() throws Exception {
5048 final PluginManager manager = new PluginManager(Core.CATEGORY_NAME);
5149 manager.collectPlugins();
5250 plugin = (PluginType<FailoverAppender>) manager.getPluginType("failover");
53 assertNotNull(plugin, "Rebuild this module to make sure annotation processing kicks in.");
51 assertNotNull("Rebuild this module to make sure annotation processing kicks in.", plugin);
5452
5553 AppenderRef appenderRef = AppenderRef.createAppenderRef("List", Level.ALL, null);
5654 node = new Node(null, "failover", plugin);
1515 */
1616 package org.apache.logging.log4j.core.config.plugins.validation.validators;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertNull;
21
1822 import org.apache.logging.log4j.core.config.Node;
1923 import org.apache.logging.log4j.core.config.NullConfiguration;
2024 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
2125 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
2226 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
2327 import org.apache.logging.log4j.core.config.plugins.validation.ValidatingPluginWithGenericBuilder;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
28 import org.junit.Before;
29 import org.junit.Test;
2830
2931 public class ValidatingPluginWithGenericBuilderTest {
3032
3234 private Node node;
3335
3436 @SuppressWarnings("unchecked")
35 @BeforeEach
37 @Before
3638 public void setUp() throws Exception {
3739 final PluginManager manager = new PluginManager("Test");
3840 manager.collectPlugins();
3941 plugin = (PluginType<ValidatingPluginWithGenericBuilder>) manager.getPluginType("ValidatingPluginWithGenericBuilder");
40 assertNotNull(plugin, "Rebuild this module to make sure annotation processing kicks in.");
42 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
4143 node = new Node(null, "Validator", plugin);
4244 }
4345
1515 */
1616 package org.apache.logging.log4j.core.config.plugins.validation.validators;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertNull;
21
1822 import org.apache.logging.log4j.core.config.Node;
1923 import org.apache.logging.log4j.core.config.NullConfiguration;
2024 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
2125 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
2226 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
2327 import org.apache.logging.log4j.core.config.plugins.validation.PluginWithGenericSubclassFoo1Builder;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
28 import org.junit.Before;
29 import org.junit.Test;
2830
2931 public class ValidatingPluginWithGenericSubclassFoo1BuilderTest {
3032
3234 private Node node;
3335
3436 @SuppressWarnings("unchecked")
35 @BeforeEach
37 @Before
3638 public void setUp() throws Exception {
3739 final PluginManager manager = new PluginManager("Test");
3840 manager.collectPlugins();
3941 plugin = (PluginType<PluginWithGenericSubclassFoo1Builder>) manager.getPluginType("PluginWithGenericSubclassFoo1Builder");
40 assertNotNull(plugin, "Rebuild this module to make sure annotation processing kicks in.");
42 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
4143 node = new Node(null, "Validator", plugin);
4244 }
4345
1515 */
1616 package org.apache.logging.log4j.core.config.plugins.validation.validators;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertNull;
21
1822 import org.apache.logging.log4j.core.config.Node;
1923 import org.apache.logging.log4j.core.config.NullConfiguration;
2024 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
2125 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
2226 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
2327 import org.apache.logging.log4j.core.config.plugins.validation.ValidatingPluginWithTypedBuilder;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
28 import org.junit.Before;
29 import org.junit.Test;
2830
2931 public class ValidatingPluginWithTypedBuilderTest {
3032
3234 private Node node;
3335
3436 @SuppressWarnings("unchecked")
35 @BeforeEach
37 @Before
3638 public void setUp() throws Exception {
3739 final PluginManager manager = new PluginManager("Test");
3840 manager.collectPlugins();
3941 plugin = (PluginType<ValidatingPluginWithTypedBuilder>) manager
4042 .getPluginType("ValidatingPluginWithTypedBuilder");
41 assertNotNull(plugin, "Rebuild this module to make sure annotation processing kicks in.");
43 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
4244 node = new Node(null, "Validator", plugin);
4345 }
4446
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.config.properties;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.Appender;
21 import org.apache.logging.log4j.core.Filter;
22 import org.apache.logging.log4j.core.LifeCycle;
23 import org.apache.logging.log4j.core.config.Configuration;
24 import org.apache.logging.log4j.core.config.LoggerConfig;
25 import org.apache.logging.log4j.core.filter.ThresholdFilter;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29
30 import java.util.Map;
31
32 import static org.junit.Assert.*;
33
34 /**
35 *
36 */
37 public class PropertiesConfigurationRootLoggerOnlyTest {
38
39 @ClassRule
40 public static LoggerContextRule context = new LoggerContextRule("log4j2-properties-root-only.properties");
41
42 @Test
43 public void testPropertiesConfiguration() {
44 final Configuration config = context.getConfiguration();
45 assertNotNull("No configuration created", config);
46 assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
47 final Map<String, Appender> appenders = config.getAppenders();
48 assertNotNull(appenders);
49 assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 1);
50 final Map<String, LoggerConfig> loggers = config.getLoggers();
51 assertNotNull(loggers);
52 assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 1);
53 final Filter filter = config.getFilter();
54 assertNotNull("No Filter", filter);
55 assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
56 final Logger logger = LogManager.getLogger(getClass());
57 logger.info("Welcome to Log4j!");
58 }
59 }
1515 */
1616 package org.apache.logging.log4j.core.config.properties;
1717
18 import org.apache.logging.log4j.Level;
1918 import org.apache.logging.log4j.LogManager;
2019 import org.apache.logging.log4j.Logger;
2120 import org.apache.logging.log4j.core.Appender;
2423 import org.apache.logging.log4j.core.config.Configuration;
2524 import org.apache.logging.log4j.core.config.LoggerConfig;
2625 import org.apache.logging.log4j.core.filter.ThresholdFilter;
27 import org.apache.logging.log4j.junit.LoggerContextSource;
28 import org.junit.jupiter.api.Test;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.ClassRule;
28 import org.junit.Test;
2929
3030 import java.util.Map;
3131
32 import static org.hamcrest.MatcherAssert.assertThat;
33 import static org.hamcrest.Matchers.instanceOf;
34 import static org.junit.jupiter.api.Assertions.*;
32 import static org.junit.Assert.*;
3533
36 class PropertiesConfigurationTest {
34 /**
35 *
36 */
37 public class PropertiesConfigurationTest {
38
39 @ClassRule
40 public static LoggerContextRule context = new LoggerContextRule("log4j2-properties.properties");
3741
3842 @Test
39 @LoggerContextSource("log4j2-properties.properties")
40 void testPropertiesConfiguration(final Configuration config) {
41 assertEquals(config.getState(), LifeCycle.State.STARTED, "Incorrect State: " + config.getState());
43 public void testPropertiesConfiguration() {
44 final Configuration config = context.getConfiguration();
45 assertNotNull("No configuration created", config);
46 assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
4247 final Map<String, Appender> appenders = config.getAppenders();
4348 assertNotNull(appenders);
44 assertEquals(1, appenders.size(), "Incorrect number of Appenders: " + appenders.size());
49 assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 1);
4550 final Map<String, LoggerConfig> loggers = config.getLoggers();
4651 assertNotNull(loggers);
47 assertEquals(2, loggers.size(), "Incorrect number of LoggerConfigs: " + loggers.size());
52 assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
4853 final Filter filter = config.getFilter();
49 assertNotNull(filter, "No Filter");
50 assertTrue(filter instanceof ThresholdFilter, "Not a Threshold Filter");
54 assertNotNull("No Filter", filter);
55 assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
5156 final Logger logger = LogManager.getLogger(getClass());
5257 logger.info("Welcome to Log4j!");
5358 }
54
55 @Test
56 @LoggerContextSource("log4j2-properties-root-only.properties")
57 void testRootLoggerOnly(final Configuration config) {
58 assertEquals(config.getState(), LifeCycle.State.STARTED, "Incorrect State: " + config.getState());
59 final Map<String, Appender> appenders = config.getAppenders();
60 assertNotNull(appenders);
61 assertEquals(appenders.size(), 1, "Incorrect number of Appenders: " + appenders.size());
62 final Map<String, LoggerConfig> loggers = config.getLoggers();
63 assertNotNull(loggers);
64 assertEquals(loggers.size(), 1, "Incorrect number of LoggerConfigs: " + loggers.size());
65 final Filter filter = config.getFilter();
66 assertNotNull(filter, "No Filter");
67 assertThat(filter, instanceOf(ThresholdFilter.class));
68 final Logger logger = LogManager.getLogger(getClass());
69 logger.info("Welcome to Log4j!");
70 }
71
72 @Test
73 @LoggerContextSource("log4j-rolling.properties")
74 void testRollingFile(final Configuration config) {
75 assertEquals(config.getState(), LifeCycle.State.STARTED, "Incorrect State: " + config.getState());
76 final Map<String, Appender> appenders = config.getAppenders();
77 assertNotNull(appenders);
78 assertEquals(appenders.size(), 3, "Incorrect number of Appenders: " + appenders.size());
79 final Map<String, LoggerConfig> loggers = config.getLoggers();
80 assertNotNull(loggers);
81 assertEquals(loggers.size(), 2, "Incorrect number of LoggerConfigs: " + loggers.size());
82 final Filter filter = config.getFilter();
83 assertNotNull(filter, "No Filter");
84 assertThat(filter, instanceOf(ThresholdFilter.class));
85 final Logger logger = LogManager.getLogger(getClass());
86 logger.info("Welcome to Log4j!");
87 }
88
89 @Test
90 @LoggerContextSource("log4j2-properties-trailing-space-on-level.properties")
91 void testTrailingSpaceOnLevel(final Configuration config) {
92 assertEquals(config.getState(), LifeCycle.State.STARTED, "Incorrect State: " + config.getState());
93 final Map<String, Appender> appenders = config.getAppenders();
94 assertNotNull(appenders);
95 assertEquals(appenders.size(), 1, "Incorrect number of Appenders: " + appenders.size());
96 final Map<String, LoggerConfig> loggers = config.getLoggers();
97 assertNotNull(loggers);
98 assertEquals(loggers.size(), 2, "Incorrect number of LoggerConfigs: " + loggers.size());
99 final Filter filter = config.getFilter();
100 assertNotNull(filter, "No Filter");
101 assertThat(filter, instanceOf(ThresholdFilter.class));
102 final Logger logger = LogManager.getLogger(getClass());
103
104 assertEquals(Level.DEBUG, logger.getLevel(), "Incorrect level " + logger.getLevel());
105
106 logger.debug("Welcome to Log4j!");
107 }
10859 }
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.config.properties;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
22 import java.util.Map;
23
24 import org.apache.logging.log4j.Level;
25 import org.apache.logging.log4j.LogManager;
26 import org.apache.logging.log4j.Logger;
27 import org.apache.logging.log4j.core.Appender;
28 import org.apache.logging.log4j.core.Filter;
29 import org.apache.logging.log4j.core.LifeCycle;
30 import org.apache.logging.log4j.core.config.Configuration;
31 import org.apache.logging.log4j.core.config.LoggerConfig;
32 import org.apache.logging.log4j.core.filter.ThresholdFilter;
33 import org.apache.logging.log4j.junit.LoggerContextRule;
34 import org.junit.ClassRule;
35 import org.junit.Test;
36
37 /**
38 *
39 */
40 public class PropertiesConfigurationTrailingSpaceOnLevelTest {
41
42 @ClassRule
43 public static LoggerContextRule context = new LoggerContextRule(
44 "log4j2-properties-trailing-space-on-level.properties");
45
46 @Test
47 public void testPropertiesConfiguration() {
48 final Configuration config = context.getConfiguration();
49 assertNotNull("No configuration created", config);
50 assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
51 final Map<String, Appender> appenders = config.getAppenders();
52 assertNotNull(appenders);
53 assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 1);
54 final Map<String, LoggerConfig> loggers = config.getLoggers();
55 assertNotNull(loggers);
56 assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
57 final Filter filter = config.getFilter();
58 assertNotNull("No Filter", filter);
59 assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
60 final Logger logger = LogManager.getLogger(getClass());
61
62 assertEquals("Incorrect level " + logger.getLevel(), Level.DEBUG, logger.getLevel());
63
64 logger.debug("Welcome to Log4j!");
65 }
66 }
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.config.properties;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.Appender;
21 import org.apache.logging.log4j.core.Filter;
22 import org.apache.logging.log4j.core.LifeCycle;
23 import org.apache.logging.log4j.core.config.Configuration;
24 import org.apache.logging.log4j.core.config.LoggerConfig;
25 import org.apache.logging.log4j.core.filter.ThresholdFilter;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29
30 import java.util.Map;
31
32 import static org.junit.Assert.*;
33
34 /**
35 *
36 */
37 public class RollingFilePropertiesTest {
38
39 @ClassRule
40 public static LoggerContextRule context = new LoggerContextRule("log4j-rolling.properties");
41
42 @Test
43 public void testPropertiesConfiguration() {
44 final Configuration config = context.getConfiguration();
45 assertNotNull("No configuration created", config);
46 assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
47 final Map<String, Appender> appenders = config.getAppenders();
48 assertNotNull(appenders);
49 assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 3);
50 final Map<String, LoggerConfig> loggers = config.getLoggers();
51 assertNotNull(loggers);
52 assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
53 final Filter filter = config.getFilter();
54 assertNotNull("No Filter", filter);
55 assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
56 final Logger logger = LogManager.getLogger(getClass());
57 logger.info("Welcome to Log4j!");
58 }
59 }
2020 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2121 import org.apache.logging.log4j.core.util.Constants;
2222 import org.apache.logging.log4j.status.StatusLogger;
23 import org.junit.jupiter.api.AfterAll;
24 import org.junit.jupiter.api.Test;
23 import org.junit.AfterClass;
24 import org.junit.Test;
2525
26 import static org.hamcrest.MatcherAssert.assertThat;
27 import static org.hamcrest.Matchers.instanceOf;
26 import static org.junit.Assert.*;
2827
28 /**
29 *
30 */
2931 public class XmlConfigurationPropsTest {
3032
3133 private static final String CONFIG = "log4j-props.xml";
3234 private static final String CONFIG1 = "log4j-props1.xml";
3335
34 @AfterAll
36 @AfterClass
3537 public static void cleanupClass() {
3638 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
3739 final LoggerContext ctx = LoggerContext.getContext();
4547 final LoggerContext ctx = LoggerContext.getContext();
4648 ctx.reconfigure();
4749 final Configuration config = ctx.getConfiguration();
48 assertThat(config, instanceOf(XmlConfiguration.class));
50 assertTrue("Configuration is not an XmlConfiguration", config instanceof XmlConfiguration);
4951 }
52
5053
5154 @Test
5255 public void testDefaultStatus() {
5659 final LoggerContext ctx = LoggerContext.getContext();
5760 ctx.reconfigure();
5861 final Configuration config = ctx.getConfiguration();
59 assertThat(config, instanceOf(XmlConfiguration.class));
62 assertTrue("Configuration is not an XmlConfiguration", config instanceof XmlConfiguration);
6063 } finally {
6164 System.clearProperty(Constants.LOG4J_DEFAULT_STATUS_LEVEL);
6265 }
7073 final LoggerContext ctx = LoggerContext.getContext();
7174 ctx.reconfigure();
7275 final Configuration config = ctx.getConfiguration();
73 assertThat(config, instanceOf(XmlConfiguration.class));
76 assertTrue("Configuration is not an XmlConfiguration", config instanceof XmlConfiguration);
7477 } finally {
7578 System.clearProperty("log4j.level");
79
7680 }
7781 }
7882
8589 final LoggerContext ctx = LoggerContext.getContext();
8690 ctx.reconfigure();
8791 final Configuration config = ctx.getConfiguration();
88 assertThat(config, instanceOf(XmlConfiguration.class));
92 assertTrue("Configuration is not an XmlConfiguration", config instanceof XmlConfiguration);
8993 } finally {
9094 System.clearProperty("log4j.level");
9195 System.clearProperty("log.level");
+0
-41
log4j-core/src/test/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationSecurity.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.logging.log4j.core.config.xml;
17
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.core.config.Configurator;
20 import org.junit.jupiter.api.Tag;
21 import org.junit.jupiter.api.Test;
22 import org.junit.jupiter.api.Timeout;
23
24 import java.io.IOException;
25
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27
28 @Tag("functional")
29 @Tag("security")
30 public class XmlConfigurationSecurity {
31
32 @Test
33 @Timeout(5)
34 public void xmlSecurity() throws IOException {
35 final LoggerContext context = Configurator.initialize("XmlConfigurationSecurity", "XmlConfigurationSecurity.xml");
36 assertNotNull(context.getConfiguration().getAppender("list"));
37 }
38
39 }
40
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.config.xml;
17
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.core.config.Configurator;
20 import org.junit.Test;
21
22 import java.io.IOException;
23
24 import static org.junit.Assert.assertNotNull;
25
26 public class XmlConigurationSecurity {
27
28 @Test(timeout = 5000L)
29 public void xmlSecurity() throws IOException {
30 final LoggerContext context = Configurator.initialize("XmlConfigurationSecurity", "XmlConfigurationSecurity.xml");
31 assertNotNull(context.getConfiguration().getAppender("list"));
32 }
33
34 }
35
1515 */
1616 package org.apache.logging.log4j.core.config.xml;
1717
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.junit.LoggerContextSource;
20 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.test.appender.ListAppender;
22 import org.junit.jupiter.api.AfterAll;
23 import org.junit.jupiter.api.BeforeAll;
24 import org.junit.jupiter.api.Test;
25
2618 import java.util.List;
2719
28 import static org.hamcrest.MatcherAssert.assertThat;
29 import static org.hamcrest.Matchers.*;
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.junit.BeforeClass;
25 import org.junit.Rule;
26 import org.junit.Test;
3027
28 import static org.hamcrest.Matchers.allOf;
29 import static org.hamcrest.Matchers.containsString;
30 import static org.hamcrest.Matchers.instanceOf;
31 import static org.hamcrest.Matchers.is;
32 import static org.junit.Assert.*;
33
34 /**
35 *
36 */
3137 public class XmlLoggerPropsTest {
3238
33 @BeforeAll
34 static void setupClass() {
39 private static final String CONFIG = "log4j-loggerprops.xml";
40
41 @Rule
42 public final LoggerContextRule context = new LoggerContextRule(CONFIG);
43
44 @BeforeClass
45 public static void setupClass() {
3546 System.setProperty("test", "test");
3647 }
3748
38 @AfterAll
39 static void tearDownClass() {
40 System.clearProperty("test");
41 }
49 @Test
50 public void testWithProps() {
51 final ListAppender listAppender = context.getListAppender("List");
52 assertNotNull("No List Appender", listAppender);
4253
43 @Test
44 @LoggerContextSource("log4j-loggerprops.xml")
45 public void testWithProps(final LoggerContext context, @Named("List") final ListAppender listAppender) {
46 assertThat(context.getConfiguration(), is(instanceOf(XmlConfiguration.class)));
47 context.getLogger(getClass()).debug("Test with props");
48 context.getLogger("tiny.bubbles").debug("Test on root");
49 final List<String> events = listAppender.getMessages();
50 listAppender.clear();
51 assertThat(events, hasSize(2));
52 assertThat(events.get(0), allOf(
54 try {
55 assertThat(context.getConfiguration(), is(instanceOf(XmlConfiguration.class)));
56 Logger logger = LogManager.getLogger(XmlLoggerPropsTest.class);
57 logger.debug("Test with props");
58 logger = LogManager.getLogger("tiny.bubbles");
59 logger.debug("Test on root");
60 final List<String> events = listAppender.getMessages();
61 assertTrue("No events", events.size() > 0);
62 assertTrue("Incorrect number of events", events.size() == 2);
63 assertThat(events.get(0), allOf(
5364 containsString("user="),
5465 containsString("phrasex=****"),
5566 containsString("test=test"),
5970 containsString("test5=test"),
6071 containsString("attribKey=attribValue"),
6172 containsString("duplicateKey=nodeValue")
62 ));
63 assertThat(events.get(1), allOf(
73 ));
74 assertThat(events.get(1), allOf(
6475 containsString("user="),
6576 containsString("phrasex=****"),
6677 containsString("test=test"),
7081 containsString("test5=test"),
7182 containsString("attribKey=attribValue"),
7283 containsString("duplicateKey=nodeValue")
73 ));
84 ));
85 } finally {
86 System.clearProperty("test");
87 }
7488 }
7589 }
2121 import org.apache.logging.log4j.core.LogEvent;
2222 import org.apache.logging.log4j.core.Logger;
2323 import org.apache.logging.log4j.message.Message;
24 import org.junit.jupiter.api.Test;
24 import org.junit.Test;
2525
26 import static org.junit.jupiter.api.Assertions.*;
26 import static org.junit.Assert.*;
2727
2828 /**
2929 * Tests the AbstractFilter test.
1616 */
1717 package org.apache.logging.log4j.core.filter;
1818
19 import static org.junit.Assert.*;
20
1921 import org.apache.logging.log4j.Level;
2022 import org.apache.logging.log4j.core.Filter;
21 import org.junit.jupiter.api.BeforeEach;
22 import org.junit.jupiter.api.Test;
23
24 import static org.junit.jupiter.api.Assertions.*;
23 import org.junit.Before;
24 import org.junit.Test;
2525
2626 public class AbstractFilterableTest {
2727
2828 MockedAbstractFilterable filterable;
2929
30 @BeforeEach
30 @Before
3131 public void setup() {
3232 filterable = new MockedAbstractFilterable();
3333 }
252252 assertSame(anotherFilter, filterable.getFilter());
253253 }
254254
255 private static class MockedAbstractFilterable extends AbstractFilterable {}
256
257 private static class EqualFilter extends AbstractFilter {
255 private class MockedAbstractFilterable extends AbstractFilterable {}
256
257 private class EqualFilter extends AbstractFilter {
258258 private final String key;
259259 public EqualFilter(final String key) {
260260 this.key = key;
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
1821 import java.util.List;
1922
23 import org.apache.logging.log4j.LogManager;
2024 import org.apache.logging.log4j.Logger;
2125 import org.apache.logging.log4j.ThreadContext;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.junit.Named;
24 import org.apache.logging.log4j.junit.UsingThreadContextMap;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
2527 import org.apache.logging.log4j.test.appender.ListAppender;
26 import org.junit.jupiter.api.Tag;
27 import org.junit.jupiter.api.Test;
28 import org.junit.Test;
2829
29 import static org.junit.jupiter.api.Assertions.*;
30
31 @UsingThreadContextMap
32 @Tag("groovy")
30 /**
31 *
32 */
3333 public abstract class AbstractScriptFilterTest {
3434
35 public abstract LoggerContextRule getContext();
36
3537 @Test
36 public void testGroovyFilter(final LoggerContext context, @Named("List") final ListAppender app) throws Exception {
37 final Logger logger = context.getLogger("TestGroovyFilter");
38 public void testGroovyFilter() throws Exception {
39 final Logger logger = LogManager.getLogger("TestGroovyFilter");
3840 logger.traceEntry();
3941 logger.info("This should not be logged");
4042 ThreadContext.put("UserId", "JohnDoe");
4143 logger.info("This should be logged");
4244 ThreadContext.clearMap();
45 final ListAppender app = getContext().getListAppender("List");
4346 try {
4447 final List<String> messages = app.getMessages();
45 assertNotNull(messages, "No Messages");
46 assertEquals(messages.size(), 2, "Incorrect number of messages. Expected 2, Actual " + messages.size());
48 assertNotNull("No Messages", messages);
49 assertTrue("Incorrect number of messages. Expected 2, Actual " + messages.size(), messages.size() == 2);
4750 } finally {
4851 app.clear();
4952 }
5053 }
5154
5255 @Test
53 public void testJavascriptFilter(final LoggerContext context, @Named("List") final ListAppender app) throws Exception {
54 final Logger logger = context.getLogger("TestJavaScriptFilter");
56 public void testJavascriptFilter() throws Exception {
57 final Logger logger = LogManager.getLogger("TestJavaScriptFilter");
5558 logger.traceEntry();
5659 logger.info("This should not be logged");
5760 ThreadContext.put("UserId", "JohnDoe");
5861 logger.info("This should be logged");
5962 ThreadContext.clearMap();
63 final ListAppender app = getContext().getListAppender("List");
6064 final List<String> messages = app.getMessages();
6165 try {
62 assertNotNull(messages, "No Messages");
63 assertEquals(messages.size(), 2, "Incorrect number of messages. Expected 2, Actual " + messages.size());
66 assertNotNull("No Messages", messages);
67 assertTrue("Incorrect number of messages. Expected 2, Actual " + messages.size(), messages.size() == 2);
6468 } finally {
6569 app.clear();
6670 }
1616 */
1717 package org.apache.logging.log4j.core.filter;
1818
19 import org.junit.jupiter.api.Test;
19 import static org.hamcrest.Matchers.greaterThan;
20 import static org.hamcrest.Matchers.is;
21 import static org.junit.Assert.assertThat;
2022
2123 import java.util.concurrent.Delayed;
2224 import java.util.concurrent.TimeUnit;
2325
24 import static org.hamcrest.MatcherAssert.assertThat;
25 import static org.hamcrest.Matchers.greaterThan;
26 import static org.hamcrest.Matchers.is;
26 import org.junit.Test;
2727
2828 /**
2929 * Unit test for <code>BurstFilter</code>.
1919 import java.util.List;
2020
2121 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2523 import org.apache.logging.log4j.test.appender.ListAppender;
26 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.ClassRule;
26 import org.junit.Test;
2727
28 import static org.junit.jupiter.api.Assertions.*;
29
28 import static org.junit.Assert.*;
3029 /**
3130 * Unit test for <code>BurstFilter</code>.
3231 */
33 @LoggerContextSource("log4j-burst.xml")
3432 public class BurstFilterTest {
3533
36 private final ListAppender app;
37 private final BurstFilter filter;
38 private final Logger logger;
34 private static final String CONFIG = "log4j-burst.xml";
3935
40 public BurstFilterTest(final LoggerContext context, @Named("ListAppender") final ListAppender app) {
41 this.app = app;
42 this.filter = (BurstFilter) app.getFilter();
43 assertNotNull(filter);
44 this.logger = context.getLogger(getClass());
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
38
39 @Before
40 public void setUp() throws Exception {
41 app = context.getListAppender("ListAppender");
42 filter = (BurstFilter) app.getFilter();
43 assertNotNull("No BurstFilter", filter);
4544 }
45
46 private ListAppender app;
47 private BurstFilter filter;
48
49 private final Logger logger = context.getLogger();
4650
4751 /**
4852 * Test BurstFilter by surpassing maximum number of log messages allowed by filter and
5761 Thread.sleep(200);
5862 }
5963 logger.info("Logging 110 messages, should only see 100 logs # " + (i + 1));
60 assertTrue(filter.getAvailable() < 100, "Incorrect number of available slots");
64 assertTrue("Incorrect number of available slots", filter.getAvailable() < 100);
6165 }
6266 List<String> msgs = app.getMessages();
63 assertEquals(100, msgs.size(), "Incorrect message count. Should be 100, actual " + msgs.size());
67 assertEquals("Incorrect message count. Should be 100, actual " + msgs.size(), 100, msgs.size());
6468 app.clear();
6569
66 assertTrue(filter.getAvailable() < 100, "Incorrect number of available slots");
70 assertTrue("Incorrect number of available slots", filter.getAvailable() < 100);
6771 // Allow some of the events to clear
6872 Thread.sleep(1500);
6973
7276 }
7377
7478 msgs = app.getMessages();
75 assertFalse(msgs.isEmpty(), "No messages were counted.");
76 assertTrue(msgs.size() < 100, "Incorrect message count. Should be > 0 and < 100, actual " + msgs.size());
79 assertFalse("No messages were counted.", msgs.isEmpty());
80 assertTrue("Incorrect message count. Should be > 0 and < 100, actual " + msgs.size(), msgs.size() < 100);
7781 app.clear();
7882
7983 filter.clear();
8185 for (int i = 0; i < 110; i++) {
8286 logger.info("Waited 1.5 seconds and trying to log again, should see more than 0 and less than 100" + (i + 1));
8387 }
84 assertEquals(0, filter.getAvailable(), "");
88 assertEquals("", 0, filter.getAvailable());
8589 app.clear();
8690
8791
9296 }
9397
9498 msgs = app.getMessages();
95 assertTrue(msgs.isEmpty(), "Incorrect message count. Should be 0, actual " + msgs.size());
99 assertTrue("Incorrect message count. Should be 0, actual " + msgs.size(), msgs.isEmpty());
96100 app.clear();
97101
98102 // now log 100 warns, they should all get through because the filter's level is set at info
101105 }
102106
103107 msgs = app.getMessages();
104 assertEquals(110, msgs.size(), "Incorrect message count. Should be 110, actual " + msgs.size());
108 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
105109 app.clear();
106110
107111 // now log 100 errors, they should all get through because the filter level is set at info
110114 }
111115
112116 msgs = app.getMessages();
113 assertEquals(110, msgs.size(), "Incorrect message count. Should be 110, actual " + msgs.size());
117 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
114118 app.clear();
115119
116120 // now log 100 fatals, they should all get through because the filter level is set at info
119123 }
120124
121125 msgs = app.getMessages();
122 assertEquals(110, msgs.size(), "Incorrect message count. Should be 110, actual " + msgs.size());
126 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
123127 app.clear();
124128
125129 // wait and make sure we can log messages again despite the fact we just logged a bunch of warns, errors, fatals
129133 logger.debug("Waited 3+ seconds, should see 100 logs #" + (i + 1));
130134 }
131135 msgs = app.getMessages();
132 assertEquals(100, msgs.size(), "Incorrect message count. Should be 100, actual " + msgs.size());
136 assertEquals("Incorrect message count. Should be 100, actual " + msgs.size(), 100, msgs.size());
133137 app.clear();
134138
135139 }
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertSame;
21 import static org.junit.Assert.assertTrue;
22
23 import java.util.Map;
24
1825 import org.apache.logging.log4j.Level;
1926 import org.apache.logging.log4j.ThreadContext;
2027 import org.apache.logging.log4j.core.Filter;
2128 import org.apache.logging.log4j.core.LogEvent;
29 import org.apache.logging.log4j.core.LoggerContext;
2230 import org.apache.logging.log4j.core.config.Configuration;
31 import org.apache.logging.log4j.core.config.Configurator;
2332 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2433 import org.apache.logging.log4j.core.util.KeyValuePair;
25 import org.apache.logging.log4j.junit.LoggerContextSource;
26 import org.apache.logging.log4j.junit.UsingThreadContextMap;
34 import org.apache.logging.log4j.junit.ThreadContextMapRule;
2735 import org.apache.logging.log4j.message.SimpleMessage;
28 import org.junit.jupiter.api.Test;
36 import org.apache.logging.log4j.status.StatusLogger;
37 import org.junit.After;
38 import org.junit.Rule;
39 import org.junit.Test;
2940
30 import java.util.Map;
41 /**
42 *
43 */
44 public class DynamicThresholdFilterTest {
3145
32 import static org.junit.jupiter.api.Assertions.*;
46 @Rule
47 public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
3348
34 @UsingThreadContextMap
35 public class DynamicThresholdFilterTest {
49 @After
50 public void cleanup() {
51 final LoggerContext ctx = LoggerContext.getContext(false);
52 ctx.reconfigure();
53 StatusLogger.getLogger().reset();
54 }
3655
3756 @Test
3857 public void testFilter() {
7291 assertSame(Filter.Result.ACCEPT, filter.filter(null, Level.DEBUG, null, "some test message", "one", "two", "three"));
7392 ThreadContext.clearMap();
7493 }
75
94
7695 @Test
77 @LoggerContextSource("log4j2-dynamicfilter.xml")
78 public void testConfig(final Configuration config) {
79 final Filter filter = config.getFilter();
80 assertNotNull(filter, "No DynamicThresholdFilter");
81 assertTrue(filter instanceof DynamicThresholdFilter, "Not a DynamicThresholdFilter");
82 final DynamicThresholdFilter dynamic = (DynamicThresholdFilter) filter;
83 final String key = dynamic.getKey();
84 assertNotNull(key, "Key is null");
85 assertEquals("loginId", key, "Incorrect key value");
86 final Map<String, Level> map = dynamic.getLevelMap();
87 assertNotNull(map, "Map is null");
88 assertEquals(1, map.size(), "Incorrect number of map elements");
96 public void testConfig() {
97 try (final LoggerContext ctx = Configurator.initialize("Test1",
98 "target/test-classes/log4j2-dynamicfilter.xml")) {
99 final Configuration config = ctx.getConfiguration();
100 final Filter filter = config.getFilter();
101 assertNotNull("No DynamicThresholdFilter", filter);
102 assertTrue("Not a DynamicThresholdFilter", filter instanceof DynamicThresholdFilter);
103 final DynamicThresholdFilter dynamic = (DynamicThresholdFilter) filter;
104 final String key = dynamic.getKey();
105 assertNotNull("Key is null", key);
106 assertEquals("Incorrect key value", "loginId", key);
107 final Map<String, Level> map = dynamic.getLevelMap();
108 assertNotNull("Map is null", map);
109 assertEquals("Incorrect number of map elements", 1, map.size());
110 }
89111 }
90112 }
2020 import org.apache.logging.log4j.core.LogEvent;
2121 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2222 import org.apache.logging.log4j.message.SimpleMessage;
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
27 /**
28 *
29 */
2730 public class LevelRangeFilterTest {
2831
2932 @Test
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import java.util.Collection;
1918 import java.util.HashMap;
2019 import java.util.List;
2120 import java.util.Map;
2625 import org.apache.logging.log4j.core.Filter;
2726 import org.apache.logging.log4j.core.config.Configuration;
2827 import org.apache.logging.log4j.core.util.KeyValuePair;
29 import org.apache.logging.log4j.junit.LoggerContextSource;
30 import org.apache.logging.log4j.junit.Named;
28 import org.apache.logging.log4j.junit.LoggerContextRule;
3129 import org.apache.logging.log4j.message.StringMapMessage;
3230 import org.apache.logging.log4j.test.appender.ListAppender;
33 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
34 import org.junit.jupiter.api.Test;
31 import org.junit.ClassRule;
32 import org.junit.Test;
3533
36 import static org.junit.jupiter.api.Assertions.*;
34 import static org.junit.Assert.*;
3735
36 /**
37 *
38 */
3839 public class MapFilterTest {
40
41 @ClassRule
42 public static LoggerContextRule context = new LoggerContextRule("log4j2-mapfilter.xml");
3943
4044 @Test
4145 public void testFilter() {
4246 final KeyValuePair[] pairs = new KeyValuePair[] { new KeyValuePair("FromAccount", "211000"),
4347 new KeyValuePair("ToAccount", "123456")};
4448 MapFilter filter = MapFilter.createFilter(pairs, "and", null, null);
45 assertNotNull(filter);
4649 filter.start();
4750 StringMapMessage msg = new StringMapMessage();
4851 msg.put("ToAccount", "123456");
5356 msg.put("ToAccount", "111111");
5457 assertSame(Filter.Result.DENY, filter.filter(null, Level.ERROR, null, msg, null));
5558 filter = MapFilter.createFilter(pairs, "or", null, null);
56 assertNotNull(filter);
5759 filter.start();
5860 msg = new StringMapMessage();
5961 msg.put("ToAccount", "123456");
6668 }
6769
6870 @Test
69 @LoggerContextSource("log4j2-mapfilter.xml")
70 public void testConfig(final Configuration config, @Named("LIST") final ListAppender app) {
71 public void testConfig() {
72 final Configuration config = context.getConfiguration();
7173 final Filter filter = config.getFilter();
72 assertNotNull(filter, "No MapFilter");
73 assertTrue(filter instanceof MapFilter, "Not a MapFilter");
74 assertNotNull("No MapFilter", filter);
75 assertTrue("Not a MapFilter", filter instanceof MapFilter);
7476 final MapFilter mapFilter = (MapFilter) filter;
75 assertFalse(mapFilter.isAnd(), "Should not be And filter");
76 final IndexedReadOnlyStringMap map = mapFilter.getStringMap();
77 assertNotNull(map, "No Map");
78 assertFalse(map.isEmpty(), "No elements in Map");
79 assertEquals(1, map.size(), "Incorrect number of elements in Map");
80 assertTrue(map.containsKey("eventId"), "Map does not contain key eventId");
81 assertEquals(2, map.<Collection<?>>getValue("eventId").size(), "List does not contain 2 elements");
77 assertFalse("Should not be And filter", mapFilter.isAnd());
78 final Map<String, List<String>> map = mapFilter.getMap();
79 assertNotNull("No Map", map);
80 assertFalse("No elements in Map", map.isEmpty());
81 assertEquals("Incorrect number of elements in Map", 1, map.size());
82 assertTrue("Map does not contain key eventId", map.containsKey("eventId"));
83 assertEquals("List does not contain 2 elements", 2, map.get("eventId").size());
8284 final Logger logger = LogManager.getLogger(MapFilterTest.class);
8385 final Map<String, String> eventMap = new HashMap<>();
8486 eventMap.put("eventId", "Login");
8587 logger.debug(new StringMapMessage(eventMap));
88 final ListAppender app = context.getListAppender("LIST");
8689 final List<String> msgs = app.getMessages();
87 assertNotNull(msgs, "No messages");
88 assertFalse(msgs.isEmpty(), "No messages");
90 assertNotNull("No messages", msgs);
91 assertFalse("No messages", msgs.isEmpty());
92
93
8994 }
9095 }
2222 import org.apache.logging.log4j.core.LogEvent;
2323 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2424 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.junit.jupiter.api.Test;
25 import org.junit.Test;
2626
27 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.*;
2828
29 /**
30 *
31 */
2932 public class MarkerFilterTest {
3033
3134 @Test
2222 import org.apache.logging.log4j.core.LogEvent;
2323 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2424 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.junit.jupiter.api.Test;
25 import org.junit.Test;
2626
27 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.assertSame;
28 import static org.junit.Assert.assertTrue;
2829
2930 public class NoMarkerFilterTest {
3031
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import static org.hamcrest.CoreMatchers.equalTo;
19 import static org.hamcrest.MatcherAssert.assertThat;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertSame;
22 import static org.junit.Assert.assertTrue;
23
1824 import org.apache.logging.log4j.Level;
1925 import org.apache.logging.log4j.core.Filter;
2026 import org.apache.logging.log4j.core.Filter.Result;
2329 import org.apache.logging.log4j.message.Message;
2430 import org.apache.logging.log4j.message.SimpleMessage;
2531 import org.apache.logging.log4j.status.StatusLogger;
26 import org.junit.jupiter.api.BeforeAll;
27 import org.junit.jupiter.api.Test;
32 import org.junit.BeforeClass;
33 import org.junit.Test;
2834
29 import static org.hamcrest.CoreMatchers.equalTo;
30 import static org.hamcrest.MatcherAssert.assertThat;
31 import static org.junit.jupiter.api.Assertions.*;
32
35 /**
36 *
37 */
3338 public class RegexFilterTest {
34 @BeforeAll
39 @BeforeClass
3540 public static void before() {
3641 StatusLogger.getLogger().setLevel(Level.OFF);
3742 }
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import org.apache.logging.log4j.junit.LoggerContextSource;
18 import org.apache.logging.log4j.categories.Scripts;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.junit.ClassRule;
21 import org.junit.experimental.categories.Category;
1922
20 @LoggerContextSource("log4j-scriptFile-filters.properties")
23 /**
24 *
25 */
26 @Category(Scripts.Groovy.class)
2127 public class ScriptFileFilterPropertiesTest extends AbstractScriptFilterTest {
28
29 private static final String CONFIG = "log4j-scriptFile-filters.properties";
30
31 @ClassRule
32 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
33
34 @Override
35 public LoggerContextRule getContext() {
36 return context;
37 }
38
2239 }
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import org.apache.logging.log4j.junit.LoggerContextSource;
18 import org.apache.logging.log4j.categories.Scripts;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.junit.ClassRule;
21 import org.junit.experimental.categories.Category;
1922
20 @LoggerContextSource("log4j-scriptFile-filters.xml")
23 /**
24 *
25 */
26 @Category(Scripts.Groovy.class)
2127 public class ScriptFileFilterTest extends AbstractScriptFilterTest {
28
29 private static final String CONFIG = "log4j-scriptFile-filters.xml";
30
31 @ClassRule
32 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
33
34 @Override
35 public LoggerContextRule getContext() {
36 return context;
37 }
38
2239 }
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import org.apache.logging.log4j.junit.LoggerContextSource;
18 import org.apache.logging.log4j.categories.Scripts;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.junit.ClassRule;
21 import org.junit.experimental.categories.Category;
1922
20 @LoggerContextSource("log4j-script-filters.xml")
23 /**
24 *
25 */
26 @Category(Scripts.Groovy.class)
2127 public class ScriptFilterTest extends AbstractScriptFilterTest {
28
29 private static final String CONFIG = "log4j-script-filters.xml";
30
31 @ClassRule
32 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
33
34 @Override
35 public LoggerContextRule getContext() {
36 return context;
37 }
38
2239 }
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import org.apache.logging.log4j.junit.LoggerContextSource;
18 import org.apache.logging.log4j.categories.Scripts;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
20 import org.junit.ClassRule;
21 import org.junit.experimental.categories.Category;
1922
20 @LoggerContextSource("log4j-scriptRef-filters.xml")
23 /**
24 *
25 */
26 @Category(Scripts.Groovy.class)
2127 public class ScriptRefFilterTest extends AbstractScriptFilterTest {
28
29 private static final String CONFIG = "log4j-scriptRef-filters.xml";
30
31 @ClassRule
32 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
33
34 @Override
35 public LoggerContextRule getContext() {
36 return context;
37 }
38
2239 }
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import java.util.Collection;
19
2018 import org.apache.logging.log4j.Level;
2119 import org.apache.logging.log4j.core.Filter;
2220 import org.apache.logging.log4j.core.config.Configuration;
2321 import org.apache.logging.log4j.core.util.KeyValuePair;
24 import org.apache.logging.log4j.junit.LoggerContextSource;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
2523 import org.apache.logging.log4j.message.StructuredDataMessage;
26 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
27 import org.junit.jupiter.api.Test;
24 import org.junit.ClassRule;
25 import org.junit.Test;
2826
29 import static org.junit.jupiter.api.Assertions.*;
27 import java.util.List;
28 import java.util.Map;
3029
30 import static org.junit.Assert.*;
31
32 /**
33 *
34 */
3135 public class StructuredDataFilterTest {
36
37 @ClassRule
38 public static LoggerContextRule context = new LoggerContextRule("log4j2-sdfilter.xml");
3239
3340 @Test
3441 public void testFilter() {
3542 final KeyValuePair[] pairs = new KeyValuePair[] { new KeyValuePair("id.name", "AccountTransfer"),
3643 new KeyValuePair("ToAccount", "123456")};
3744 StructuredDataFilter filter = StructuredDataFilter.createFilter(pairs, "and", null, null);
38 assertNotNull(filter);
3945 filter.start();
4046 StructuredDataMessage msg = new StructuredDataMessage("AccountTransfer@18060", "Transfer Successful", "Audit");
4147 msg.put("ToAccount", "123456");
4652 msg.put("ToAccount", "111111");
4753 assertSame(Filter.Result.DENY, filter.filter(null, Level.ERROR, null, msg, null));
4854 filter = StructuredDataFilter.createFilter(pairs, "or", null, null);
49 assertNotNull(filter);
5055 filter.start();
5156 msg = new StructuredDataMessage("AccountTransfer@18060", "Transfer Successful", "Audit");
5257 msg.put("ToAccount", "123456");
5964 }
6065
6166 @Test
62 @LoggerContextSource("log4j2-sdfilter.xml")
63 public void testConfig(final Configuration config) {
67 public void testConfig() {
68 final Configuration config = context.getConfiguration();
6469 final Filter filter = config.getFilter();
65 assertNotNull(filter, "No StructuredDataFilter");
66 assertTrue(filter instanceof StructuredDataFilter, "Not a StructuredDataFilter");
70 assertNotNull("No StructuredDataFilter", filter);
71 assertTrue("Not a StructuredDataFilter", filter instanceof StructuredDataFilter);
6772 final StructuredDataFilter sdFilter = (StructuredDataFilter) filter;
68 assertFalse(sdFilter.isAnd(), "Should not be And filter");
69 final IndexedReadOnlyStringMap map = sdFilter.getStringMap();
70 assertNotNull(map, "No Map");
71 assertFalse(map.isEmpty(), "No elements in Map");
72 assertEquals(1, map.size(), "Incorrect number of elements in Map");
73 assertTrue(map.containsKey("eventId"), "Map does not contain key eventId");
74 assertEquals(2, map.<Collection<?>>getValue("eventId").size(), "List does not contain 2 elements");
73 assertFalse("Should not be And filter", sdFilter.isAnd());
74 final Map<String, List<String>> map = sdFilter.getMap();
75 assertNotNull("No Map", map);
76 assertFalse("No elements in Map", map.isEmpty());
77 assertEquals("Incorrect number of elements in Map", 1, map.size());
78 assertTrue("Map does not contain key eventId", map.containsKey("eventId"));
79 assertEquals("List does not contain 2 elements", 2, map.get("eventId").size());
7580 }
7681 }
1919 import org.apache.logging.log4j.ThreadContext;
2020 import org.apache.logging.log4j.core.Filter;
2121 import org.apache.logging.log4j.core.util.KeyValuePair;
22 import org.junit.jupiter.api.Test;
22 import org.junit.Test;
2323
24 import static org.junit.jupiter.api.Assertions.*;
24 import static org.junit.Assert.*;
2525
26
27 /**
28 *
29 */
2630 public class ThreadContextMapFilterTest {
2731
2832 @Test
3236 final KeyValuePair[] pairs = new KeyValuePair[] { new KeyValuePair("userid", "JohnDoe"),
3337 new KeyValuePair("organization", "Apache")};
3438 ThreadContextMapFilter filter = ThreadContextMapFilter.createFilter(pairs, "and", null, null);
35 assertNotNull(filter);
3639 filter.start();
3740 assertTrue(filter.isStarted());
3841 assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
4447 assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
4548 ThreadContext.clearMap();
4649 filter = ThreadContextMapFilter.createFilter(pairs, "or", null, null);
47 assertNotNull(filter);
4850 filter.start();
4951 assertTrue(filter.isStarted());
5052 ThreadContext.put("userid", "testuser");
5658 assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
5759 final KeyValuePair[] single = new KeyValuePair[] {new KeyValuePair("userid", "testuser")};
5860 filter = ThreadContextMapFilter.createFilter(single, null, null, null);
59 assertNotNull(filter);
6061 filter.start();
6162 assertTrue(filter.isStarted());
6263 assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
2020 import org.apache.logging.log4j.core.LogEvent;
2121 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2222 import org.apache.logging.log4j.message.SimpleMessage;
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
27 /**
28 *
29 */
2730 public class ThresholdFilterTest {
2831
2932 @Test
1515 */
1616 package org.apache.logging.log4j.core.filter;
1717
18 import java.time.LocalDate;
19 import java.time.LocalTime;
20 import java.time.ZoneId;
21 import java.time.ZonedDateTime;
2218 import java.util.Calendar;
2319 import java.util.TimeZone;
2420
21 import org.apache.logging.log4j.Level;
2522 import org.apache.logging.log4j.core.Filter;
2623 import org.apache.logging.log4j.core.LogEvent;
2724 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
28
2925 import org.apache.logging.log4j.core.util.Clock;
3026 import org.apache.logging.log4j.core.util.ClockFactory;
3127 import org.apache.logging.log4j.core.util.ClockFactoryTest;
32 import org.junit.jupiter.api.AfterAll;
33 import org.junit.jupiter.api.BeforeAll;
34 import org.junit.jupiter.api.Test;
28 import org.junit.AfterClass;
29 import org.junit.BeforeClass;
30 import org.junit.Test;
3531
36 import static org.junit.jupiter.api.Assertions.*;
32 import static org.junit.Assert.*;
3733
34 /**
35 *
36 */
3837 public class TimeFilterTest {
3938 private static long CLOCKTIME = System.currentTimeMillis();
4039
4645 }
4746 }
4847
49 @BeforeAll
48 @BeforeClass
5049 public static void beforeClass() {
5150 System.setProperty(ClockFactory.PROPERTY_NAME, FixedTimeClock.class.getName());
5251 }
5352
54 @AfterAll
53 @AfterClass
5554 public static void afterClass() throws IllegalAccessException {
5655 ClockFactoryTest.resetClocks();
5756 }
5857
5958 @Test
60 public void springForward() {
61 final TimeFilter filter = new TimeFilter(LocalTime.of(2,0), LocalTime.of(3,0),
62 ZoneId.of("America/Los_Angeles"), null, null, LocalDate.of(2020, 3, 8));
59 public void testTime() {
60 final TimeFilter filter = TimeFilter.createFilter("02:00:00", "03:00:00", "America/LosAngeles", null, null);
6361 filter.start();
6462 assertTrue(filter.isStarted());
65 ZonedDateTime date = ZonedDateTime.of(2020, 3, 8, 2, 6, 30, 0, ZoneId.of("America/Los_Angeles"));
66 CLOCKTIME = date.toInstant().toEpochMilli();
67 LogEvent event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
68 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
69 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
70 date = date.plusDays(1).withHour(2);
71 CLOCKTIME = date.toInstant().toEpochMilli();
72 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
73 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
74 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
75 date = date.withHour(4);
76 CLOCKTIME = date.toInstant().toEpochMilli();
77 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
78 assertSame(Filter.Result.DENY, filter.filter(event),
79 "Time " + CLOCKTIME + " is within range: " + filter.toString());
80 }
81
82
83 @Test
84 public void fallBack() {
85 final TimeFilter filter = new TimeFilter(LocalTime.of(1,0), LocalTime.of(2,0),
86 ZoneId.of("America/Los_Angeles"), null, null, LocalDate.of(2020, 11, 1));
87 filter.start();
88 assertTrue(filter.isStarted());
89 ZonedDateTime date = ZonedDateTime.of(2020, 11, 1, 1, 6, 30, 0, ZoneId.of("America/Los_Angeles")).withEarlierOffsetAtOverlap();
90 CLOCKTIME = date.toInstant().toEpochMilli();
91 LogEvent event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
92 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
93 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
94 date = ZonedDateTime.of(2020, 11, 1, 1, 6, 30, 0, ZoneId.of("America/Los_Angeles")).withLaterOffsetAtOverlap();
95 CLOCKTIME = date.toInstant().toEpochMilli();
96 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
97 assertSame(Filter.Result.DENY, filter.filter(event),
98 "Time " + CLOCKTIME + " is within range: " + filter.toString());
99 date = date.plusDays(1).withHour(1).withMinute(30);
100 CLOCKTIME = date.toInstant().toEpochMilli();
101 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
102 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
103 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
104 date = date.withHour(4);
105 CLOCKTIME = date.toInstant().toEpochMilli();
106 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
107 assertSame(Filter.Result.DENY, filter.filter(event),
108 "Time " + CLOCKTIME + " is within range: " + filter.toString());
109 }
110
111
112 @Test
113 public void overnight() {
114 final TimeFilter filter = new TimeFilter(LocalTime.of(23,0), LocalTime.of(1,0),
115 ZoneId.of("America/Los_Angeles"), null, null, LocalDate.of(2020, 3, 10));
116 filter.start();
117 assertTrue(filter.isStarted());
118 ZonedDateTime date = ZonedDateTime.of(2020, 3, 10, 23, 30, 30, 0, ZoneId.of("America/Los_Angeles")).withEarlierOffsetAtOverlap();
119 CLOCKTIME = date.toInstant().toEpochMilli();
120 LogEvent event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
121 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
122 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
123 date = date.plusHours(1);
124 CLOCKTIME = date.toInstant().toEpochMilli();
125 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
126 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
127 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
128 date = date.plusHours(1);
129 CLOCKTIME = date.toInstant().toEpochMilli();
130 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
131 assertSame(Filter.Result.DENY, filter.filter(event),
132 "Time " + CLOCKTIME + " is within range: " + filter.toString());
133 date = date.plusDays(1).withHour(0);
134 CLOCKTIME = date.toInstant().toEpochMilli();
135 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
136 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
137 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
138 }
139
140 @Test
141 public void overnightForward() {
142 final TimeFilter filter = new TimeFilter(LocalTime.of(23,0), LocalTime.of(2,0),
143 ZoneId.of("America/Los_Angeles"), null, null, LocalDate.of(2020, 3, 7));
144 filter.start();
145 assertTrue(filter.isStarted());
146 ZonedDateTime date = ZonedDateTime.of(2020, 3, 7, 23, 30, 30, 0, ZoneId.of("America/Los_Angeles")).withEarlierOffsetAtOverlap();
147 CLOCKTIME = date.toInstant().toEpochMilli();
148 LogEvent event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
149 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
150 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
151 date = date.plusHours(1);
152 CLOCKTIME = date.toInstant().toEpochMilli();
153 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
154 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
155 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
156 date = date.plusHours(2);
157 CLOCKTIME = date.toInstant().toEpochMilli();
158 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
159 assertSame(Filter.Result.DENY, filter.filter(event),
160 "Time " + CLOCKTIME + " is within range: " + filter.toString());
161 date = date.plusDays(1).withHour(0);
162 CLOCKTIME = date.toInstant().toEpochMilli();
163 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
164 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
165 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
166 }
167
168
169 @Test
170 public void overnightFallback() {
171 final TimeFilter filter = new TimeFilter(LocalTime.of(23,0), LocalTime.of(2,0),
172 ZoneId.of("America/Los_Angeles"), null, null, LocalDate.of(2020, 10, 31));
173 filter.start();
174 assertTrue(filter.isStarted());
175 ZonedDateTime date = ZonedDateTime.of(2020, 10, 31, 23, 30, 30, 0, ZoneId.of("America/Los_Angeles")).withEarlierOffsetAtOverlap();
176 CLOCKTIME = date.toInstant().toEpochMilli();
177 LogEvent event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
178 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
179 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
180 date = date.plusHours(1);
181 CLOCKTIME = date.toInstant().toEpochMilli();
182 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
183 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
184 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
185 date = date.plusHours(2);
186 CLOCKTIME = date.toInstant().toEpochMilli();
187 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
188 assertSame(Filter.Result.DENY, filter.filter(event),
189 "Time " + CLOCKTIME + " is within range: " + filter.toString());
190 date = date.plusDays(1).withHour(0);
191 CLOCKTIME = date.toInstant().toEpochMilli();
192 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
193 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
194 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
195 }
196
197 @Test
198 public void testTime() {
199 // https://garygregory.wordpress.com/2013/06/18/what-are-the-java-timezone-ids/
200 final TimeFilter filter = TimeFilter.createFilter("02:00:00", "03:00:00", "America/Los_Angeles", null, null);
201 filter.start();
202 assertTrue(filter.isStarted());
203 final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
63 final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/LosAngeles"));
20464 cal.set(Calendar.HOUR_OF_DAY, 2);
20565 CLOCKTIME = cal.getTimeInMillis();
20666 LogEvent event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
207 //assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
208 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
209 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
67 assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
68 assertSame(Filter.Result.NEUTRAL, filter.filter(event));
21069
211 cal.add(Calendar.DATE, 1);
212 cal.set(Calendar.HOUR_OF_DAY, 2);
70 cal.roll(Calendar.DAY_OF_MONTH, true);
21371 CLOCKTIME = cal.getTimeInMillis();
21472 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
215 assertSame(Filter.Result.NEUTRAL, filter.filter(event),
216 "Time " + CLOCKTIME + " is not within range: " + filter.toString());
217 //assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
73 assertSame(Filter.Result.NEUTRAL, filter.filter(event));
74 assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
21875
21976 cal.set(Calendar.HOUR_OF_DAY, 4);
22077 CLOCKTIME = cal.getTimeInMillis();
22178 event = Log4jLogEvent.newBuilder().setTimeMillis(CLOCKTIME).build();
222 //assertSame(Filter.Result.DENY, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
223 assertSame(Filter.Result.DENY, filter.filter(event),
224 "Time " + CLOCKTIME + " is within range: " + filter.toString());
79 assertSame(Filter.Result.DENY, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
80 assertSame(Filter.Result.DENY, filter.filter(event));
22581 }
22682 }
1818 import java.lang.reflect.Field;
1919
2020 import org.apache.logging.log4j.util.SortedArrayStringMap;
21 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2222
23 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2424
2525 /**
2626 * Tests the ContextDataFactory class.
1515 */
1616 package org.apache.logging.log4j.core.impl;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 /**
2323 * Tests the ContextDataFactory class.
1818 import java.lang.reflect.Field;
1919
2020 import org.apache.logging.log4j.util.SortedArrayStringMap;
21 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2222
23 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2424
2525 /**
2626 * Tests the ContextDataFactory class.
2525
2626 import org.apache.logging.log4j.util.BiConsumer;
2727 import org.apache.logging.log4j.util.TriConsumer;
28 import org.junit.jupiter.api.Test;
29
30 import static org.junit.jupiter.api.Assertions.*;
28 import org.junit.Test;
29
30 import static org.junit.Assert.*;
3131
3232 /**
3333 * Tests the JdkMapAdapterStringMap class.
3434 */
3535 public class JdkMapAdapterStringMapTest {
3636
37 @Test
38 public void testConstructorDisallowsNull() {
39 assertThrows(NullPointerException.class, () -> new JdkMapAdapterStringMap(null));
37 @Test(expected = NullPointerException.class)
38 public void testConstructorDisallowsNull() throws Exception {
39 new JdkMapAdapterStringMap(null);
4040 }
4141
4242 @Test
113113 other.putValue("c", "cc");
114114 original.putAll(other);
115115
116 assertEquals(7, original.size(), "size after put other");
116 assertEquals("size after put other", 7, original.size());
117117 assertEquals("aa", original.getValue("a"));
118118 assertEquals("bORIG", original.getValue("b"));
119119 assertEquals("cc", original.getValue("c"));
138138 other.putValue("a", "aa");
139139 original.putAll(other);
140140
141 assertEquals(7, original.size(), "size after put other");
141 assertEquals("size after put other", 7, original.size());
142142 assertEquals("aa", original.getValue("a"));
143143 assertEquals("bORIG", original.getValue("b"));
144144 assertEquals("cORIG", original.getValue("c"));
162162 other.putValue("a", "aa");
163163 original.putAll(other);
164164
165 assertEquals(6, original.size(), "size after put other");
165 assertEquals("size after put other", 6, original.size());
166166 assertEquals("aa", original.getValue("a"));
167167 assertEquals("bORIG", original.getValue("b"));
168168 assertEquals("11", original.getValue("1"));
186186 other.putValue("a", "aa");
187187 original.putAll(other);
188188
189 assertEquals(7, original.size(), "size after put other");
189 assertEquals("size after put other", 7, original.size());
190190 assertEquals("aa", original.getValue("a"));
191191 assertEquals("bORIG", original.getValue("b"));
192192 assertEquals("cORIG", original.getValue("c"));
210210 other.putValue("a", "aa");
211211 original.putAll(other);
212212
213 assertEquals(6, original.size(), "size after put other");
213 assertEquals("size after put other", 6, original.size());
214214 assertEquals("aa", original.getValue("a"));
215215 assertEquals("bORIG", original.getValue("b"));
216216 assertEquals("11", original.getValue("1"));
235235 other.putValue("a", "aa");
236236 original.putAll(other);
237237
238 assertEquals(7, original.size(), "size after put other");
238 assertEquals("size after put other", 7, original.size());
239239 assertEquals("aa", original.getValue("a"));
240240 assertEquals("bORIG", original.getValue("b"));
241241 assertEquals("cORIG", original.getValue("c"));
260260 other.putValue("a", "aa");
261261 original.putAll(other);
262262
263 assertEquals(6, original.size(), "size after put other");
263 assertEquals("size after put other", 6, original.size());
264264 assertEquals("aa", original.getValue("a"));
265265 assertEquals("bORIG", original.getValue("b"));
266266 assertEquals("11", original.getValue("1"));
283283 other.putValue("c", "cc");
284284 original.putAll(other);
285285
286 assertEquals(5, original.size(), "size after put other");
286 assertEquals("size after put other", 5, original.size());
287287 assertEquals("aa", original.getValue("a"));
288288 assertEquals("bORIG", original.getValue("b"));
289289 assertEquals("cc", original.getValue("c"));
346346 original.putValue("a", "aaa");
347347 original.putValue("b", "bbb");
348348 original.putValue("c", "ccc");
349 assertEquals(3, original.size(), "size");
349 assertEquals("size", 3, original.size());
350350
351351 // add empty context data
352352 original.putAll(new JdkMapAdapterStringMap());
353 assertEquals(3, original.size(), "size after put empty");
353 assertEquals("size after put empty", 3, original.size());
354354 assertEquals("aaa", original.getValue("a"));
355355 assertEquals("bbb", original.getValue("b"));
356356 assertEquals("ccc", original.getValue("c"));
361361 other.putValue("3", "333");
362362 original.putAll(other);
363363
364 assertEquals(6, original.size(), "size after put other");
364 assertEquals("size after put other", 6, original.size());
365365 assertEquals("aaa", original.getValue("a"));
366366 assertEquals("bbb", original.getValue("b"));
367367 assertEquals("ccc", original.getValue("c"));
377377 original.putValue("b", "bbb");
378378 original.putValue("c", "ccc");
379379 original.putValue("d", "ddd");
380 assertEquals(4, original.size(), "size");
380 assertEquals("size", 4, original.size());
381381
382382 // add empty context data
383383 original.putAll(new JdkMapAdapterStringMap());
384 assertEquals(4, original.size(), "size after put empty");
384 assertEquals("size after put empty", 4, original.size());
385385 assertEquals("aaa", original.getValue("a"));
386386 assertEquals("bbb", original.getValue("b"));
387387 assertEquals("ccc", original.getValue("c"));
394394 other.putValue("4", "444");
395395 original.putAll(other);
396396
397 assertEquals(8, original.size(), "size after put other");
397 assertEquals("size after put other", 8, original.size());
398398 assertEquals("aaa", original.getValue("a"));
399399 assertEquals("bbb", original.getValue("b"));
400400 assertEquals("ccc", original.getValue("c"));
413413 original.putValue("b", "bbb");
414414 original.putValue("c", "ccc");
415415 original.putValue("d", "ddd");
416 assertEquals(5, original.size(), "size");
416 assertEquals("size", 5, original.size());
417417
418418 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
419419 for (int i = 0 ; i < 500; i++) {
422422 other.putValue(null, "otherVal");
423423 original.putAll(other);
424424
425 assertEquals(505, original.size(), "size after put other");
425 assertEquals("size after put other", 505, original.size());
426426 assertEquals("otherVal", original.getValue(null));
427427 assertEquals("aaa", original.getValue("a"));
428428 assertEquals("bbb", original.getValue("b"));
439439 original.putValue("a", "aaa");
440440 original.putValue("b", "bbb");
441441 original.putValue("c", "ccc");
442 assertEquals(3, original.size(), "size");
442 assertEquals("size", 3, original.size());
443443
444444 // putAll with self
445445 original.putAll(original);
446 assertEquals(3, original.size(), "size after put empty");
446 assertEquals("size after put empty", 3, original.size());
447447 assertEquals("aaa", original.getValue("a"));
448448 assertEquals("bbb", original.getValue("b"));
449449 assertEquals("ccc", original.getValue("c"));
457457 original.putValue("c", "aaa");
458458 original.putValue("d", "aaa");
459459 original.putValue("e", "aaa");
460 original.forEach((s, o) -> original.putValue("c" + s, "other"));
460 original.forEach(new BiConsumer<String, Object>() {
461 @Override
462 public void accept(final String s, final Object o) {
463 original.putValue("c" + s, "other");
464 }
465 });
461466 }
462467
463468 @Test
468473 original.putValue("c", "aaa");
469474 original.putValue("d", "aaa");
470475 original.putValue("e", "aaa");
471 original.forEach((s, o) -> original.putValue("c" + s, "other"));
476 original.forEach(new BiConsumer<String, Object>() {
477 @Override
478 public void accept(final String s, final Object o) {
479 original.putValue("c" + s, "other");
480 }
481 });
472482 }
473483
474484 @Test
477487 original.putValue("a", "aaa");
478488 original.putValue("b", "aaa");
479489 original.putValue("c", "aaa");
480 original.forEach((s, o) -> original.remove("a"));
490 original.forEach(new BiConsumer<String, Object>() {
491 @Override
492 public void accept(final String s, final Object o) {
493 original.remove("a");
494 }
495 });
481496 }
482497
483498 @Test
488503 original.putValue("c", "aaa");
489504 original.putValue("d", "aaa");
490505 original.putValue("e", "aaa");
491 original.forEach((s, o) -> original.clear());
506 original.forEach(new BiConsumer<String, Object>() {
507 @Override
508 public void accept(final String s, final Object o) {
509 original.clear();
510 }
511 });
492512 }
493513
494514 @Test
498518 original.putValue("b", "aaa");
499519 original.putValue("d", "aaa");
500520 original.putValue("e", "aaa");
501 original.forEach((s, o, o2) -> original.putValue("c", "other"), null);
521 original.forEach(new TriConsumer<String, Object, Object>() {
522 @Override
523 public void accept(final String s, final Object o, final Object o2) {
524 original.putValue("c", "other");
525 }
526 }, null);
502527 }
503528
504529 @Test
509534 original.putValue("c", "aaa");
510535 original.putValue("d", "aaa");
511536 original.putValue("e", "aaa");
512 original.forEach((s, o, o2) -> original.putValue("c" + s, "other"), null);
537 original.forEach(new TriConsumer<String, Object, Object>() {
538 @Override
539 public void accept(final String s, final Object o, final Object o2) {
540 original.putValue("c" + s, "other");
541 }
542 }, null);
513543 }
514544
515545 @Test
518548 original.putValue("a", "aaa");
519549 original.putValue("b", "aaa");
520550 original.putValue("c", "aaa");
521 original.forEach((s, o, o2) -> original.remove("a"), null);
551 original.forEach(new TriConsumer<String, Object, Object>() {
552 @Override
553 public void accept(final String s, final Object o, final Object o2) {
554 original.remove("a");
555 }
556 }, null);
522557 }
523558
524559 @Test
528563 original.putValue("b", "aaa");
529564 original.putValue("c", "aaa");
530565 original.putValue("d", "aaa");
531 original.forEach((s, o, o2) -> original.clear(), null);
566 original.forEach(new TriConsumer<String, Object, Object>() {
567 @Override
568 public void accept(final String s, final Object o, final Object o2) {
569 original.clear();
570 }
571 }, null);
532572 }
533573
534574 @Test
539579 @Test
540580 public void testIsFrozenAfterCallingFreeze() {
541581 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
542 assertFalse(original.isFrozen(), "before freeze");
582 assertFalse("before freeze", original.isFrozen());
543583 original.freeze();
544 assertTrue(original.isFrozen(), "after freeze");
545 }
546
547 @Test
584 assertTrue("after freeze", original.isFrozen());
585 }
586
587 @Test(expected = UnsupportedOperationException.class)
548588 public void testFreezeProhibitsPutValue() {
549589 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
550590 original.freeze();
551 assertThrows(UnsupportedOperationException.class, () -> original.putValue("a", "aaa"));
552 }
553
554 @Test
591 original.putValue("a", "aaa");
592 }
593
594 @Test(expected = UnsupportedOperationException.class)
555595 public void testFreezeProhibitsRemove() {
556596 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
557597 original.putValue("b", "bbb");
558598 original.freeze();
559 assertThrows(UnsupportedOperationException.class, () -> original.remove("b")); // existing key: modifies the collection
599 original.remove("b"); // existing key: modifies the collection
560600 }
561601
562602 @Test
574614 original.remove("a"); // no exception
575615 }
576616
577 @Test
617 @Test(expected = UnsupportedOperationException.class)
578618 public void testFreezeProhibitsClear() {
579619 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
580620 original.putValue("a", "aaa");
581621 original.freeze();
582 assertThrows(UnsupportedOperationException.class, original::clear);
622 original.clear();
583623 }
584624
585625 @Test
633673 expected.put("3", "3value");
634674 expected.put("c", "cvalue");
635675 expected.put("d", "dvalue");
636 assertEquals(expected, original.toMap(), "initial");
676 assertEquals("initial", expected, original.toMap());
637677
638678 original.putValue(null, "nullvalue");
639679 expected.put(null, "nullvalue");
640680 assertEquals(6, original.size());
641 assertEquals(expected, original.toMap(), "with null key");
681 assertEquals("with null key", expected, original.toMap());
642682
643683 original.putValue(null, "otherNullvalue");
644684 expected.put(null, "otherNullvalue");
645685 assertEquals(6, original.size());
646 assertEquals(expected, original.toMap(), "with null key value2");
686 assertEquals("with null key value2", expected, original.toMap());
647687
648688 original.putValue(null, "nullvalue");
649689 expected.put(null, "nullvalue");
650690 assertEquals(6, original.size());
651 assertEquals(expected, original.toMap(), "with null key value1 again");
691 assertEquals("with null key value1 again", expected, original.toMap());
652692
653693 original.putValue(null, "abc");
654694 expected.put(null, "abc");
655695 assertEquals(6, original.size());
656 assertEquals(expected, original.toMap(), "with null key value3");
696 assertEquals("with null key value3", expected, original.toMap());
657697 }
658698
659699 @Test
665705
666706 original.remove("a");
667707 assertEquals(0, original.size());
668 assertNull(original.getValue("a"), "no a val");
708 assertNull("no a val", original.getValue("a"));
669709
670710 original.remove("B");
671711 assertEquals(0, original.size());
672 assertNull(original.getValue("B"), "no B val");
712 assertNull("no B val", original.getValue("B"));
673713 }
674714
675715 @Test
691731
692732 original.putValue("a", null);
693733 assertEquals(1, original.size());
694 assertNull(original.getValue("a"), "no a val");
734 assertNull("no a val", original.getValue("a"));
695735
696736 original.putValue("B", null);
697737 assertEquals(2, original.size());
698 assertNull(original.getValue("B"), "no B val");
738 assertNull("no B val", original.getValue("B"));
699739 }
700740
701741 @Test
731771 @Test
732772 public void testContainsKey() throws Exception {
733773 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
734 assertFalse(original.containsKey("a"), "a");
735 assertFalse(original.containsKey("B"), "B");
736 assertFalse(original.containsKey("3"), "3");
737 assertFalse(original.containsKey("A"), "A");
738
739 original.putValue("a", "avalue");
740 assertTrue(original.containsKey("a"), "a");
741 assertFalse(original.containsKey("B"), "B");
742 assertFalse(original.containsKey("3"), "3");
743 assertFalse(original.containsKey("A"), "A");
744
745 original.putValue("B", "Bvalue");
746 assertTrue(original.containsKey("a"), "a");
747 assertTrue(original.containsKey("B"), "B");
748 assertFalse(original.containsKey("3"), "3");
749 assertFalse(original.containsKey("A"), "A");
750
751 original.putValue("3", "3value");
752 assertTrue(original.containsKey("a"), "a");
753 assertTrue(original.containsKey("B"), "B");
754 assertTrue(original.containsKey("3"), "3");
755 assertFalse(original.containsKey("A"), "A");
774 assertFalse("a", original.containsKey("a"));
775 assertFalse("B", original.containsKey("B"));
776 assertFalse("3", original.containsKey("3"));
777 assertFalse("A", original.containsKey("A"));
778
779 original.putValue("a", "avalue");
780 assertTrue("a", original.containsKey("a"));
781 assertFalse("B", original.containsKey("B"));
782 assertFalse("3", original.containsKey("3"));
783 assertFalse("A", original.containsKey("A"));
784
785 original.putValue("B", "Bvalue");
786 assertTrue("a", original.containsKey("a"));
787 assertTrue("B", original.containsKey("B"));
788 assertFalse("3", original.containsKey("3"));
789 assertFalse("A", original.containsKey("A"));
790
791 original.putValue("3", "3value");
792 assertTrue("a", original.containsKey("a"));
793 assertTrue("B", original.containsKey("B"));
794 assertTrue("3", original.containsKey("3"));
795 assertFalse("A", original.containsKey("A"));
756796
757797 original.putValue("A", "AAA");
758 assertTrue(original.containsKey("a"), "a");
759 assertTrue(original.containsKey("B"), "B");
760 assertTrue(original.containsKey("3"), "3");
761 assertTrue(original.containsKey("A"), "A");
798 assertTrue("a", original.containsKey("a"));
799 assertTrue("B", original.containsKey("B"));
800 assertTrue("3", original.containsKey("3"));
801 assertTrue("A", original.containsKey("A"));
762802 }
763803
764804 @Test
765805 public void testSizeAndIsEmpty() throws Exception {
766806 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
767807 assertEquals(0, original.size());
768 assertTrue(original.isEmpty(), "initial");
808 assertTrue("initial", original.isEmpty());
769809
770810 original.putValue("a", "avalue");
771811 assertEquals(1, original.size());
772 assertFalse(original.isEmpty(), "size=" + original.size());
812 assertFalse("size=" + original.size(), original.isEmpty());
773813
774814 original.putValue("B", "Bvalue");
775815 assertEquals(2, original.size());
776 assertFalse(original.isEmpty(), "size=" + original.size());
816 assertFalse("size=" + original.size(), original.isEmpty());
777817
778818 original.putValue("3", "3value");
779819 assertEquals(3, original.size());
780 assertFalse(original.isEmpty(), "size=" + original.size());
820 assertFalse("size=" + original.size(), original.isEmpty());
781821
782822 original.remove("B");
783823 assertEquals(2, original.size());
784 assertFalse(original.isEmpty(), "size=" + original.size());
824 assertFalse("size=" + original.size(), original.isEmpty());
785825
786826 original.remove("3");
787827 assertEquals(1, original.size());
788 assertFalse(original.isEmpty(), "size=" + original.size());
828 assertFalse("size=" + original.size(), original.isEmpty());
789829
790830 original.remove("a");
791831 assertEquals(0, original.size());
792 assertTrue(original.isEmpty(), "size=" + original.size());
832 assertTrue("size=" + original.size(), original.isEmpty());
793833 }
794834
795835 @Test
806846 // assertEquals("key", key, original.getKeyAt(count));
807847 // assertEquals("val", value, original.getValueAt(count));
808848 count++;
809 assertTrue(count <= original.size(), "count should not exceed size but was " + count);
849 assertTrue("count should not exceed size but was " + count, count <= original.size());
810850 }
811851 });
812852 }
815855 JdkMapAdapterStringMap data;
816856 int count;
817857 }
818 static TriConsumer<String, String, JdkMapAdapterStringMapTest.State> COUNTER = (key, value, state) -> {
858 static TriConsumer<String, String, JdkMapAdapterStringMapTest.State> COUNTER = new TriConsumer<String, String, JdkMapAdapterStringMapTest.State>() {
859 @Override
860 public void accept(final String key, final String value, final JdkMapAdapterStringMapTest.State state) {
819861 // assertEquals("key", key, state.data.getKeyAt(state.count));
820862 // assertEquals("val", value, state.data.getValueAt(state.count));
821 state.count++;
822 assertTrue(
823 state.count <= state.data.size(), "count should not exceed size but was " + state.count);
863 state.count++;
864 assertTrue("count should not exceed size but was " + state.count,
865 state.count <= state.data.size());
866 }
824867 };
825868
826869 @Test
2828 import org.apache.logging.log4j.core.util.DummyNanoClock;
2929 import org.apache.logging.log4j.core.util.SystemNanoClock;
3030 import org.apache.logging.log4j.util.Strings;
31 import org.junit.jupiter.api.AfterAll;
32 import org.junit.jupiter.api.BeforeAll;
33 import org.junit.jupiter.api.Tag;
34 import org.junit.jupiter.api.Test;
31 import org.junit.AfterClass;
32 import org.junit.BeforeClass;
33 import org.junit.Test;
3534
36 import static org.junit.jupiter.api.Assertions.*;
35 import static org.junit.Assert.*;
3736
38 @Tag("functional")
3937 public class Log4jLogEventNanoTimeTest {
4038
41 @BeforeAll
39 @BeforeClass
4240 public static void beforeClass() {
4341 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
4442 "NanoTimeToFileTest.xml");
4543 }
4644
47 @AfterAll
45 @AfterClass
4846 public static void afterClass() {
4947 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, Strings.EMPTY);
5048 }
5755 final Logger log = LogManager.getLogger("com.foo.Bar");
5856 final long before = System.nanoTime();
5957 log.info("Use actual System.nanoTime()");
60 assertTrue(Log4jLogEvent.getNanoClock() instanceof SystemNanoClock, "using SystemNanoClock");
58 assertTrue("using SystemNanoClock", Log4jLogEvent.getNanoClock() instanceof SystemNanoClock);
6159
6260 final long DUMMYNANOTIME = 123;
6361 Log4jLogEvent.setNanoClock(new DummyNanoClock(DUMMYNANOTIME));
6462 log.info("Use dummy nano clock");
65 assertTrue(Log4jLogEvent.getNanoClock() instanceof DummyNanoClock, "using SystemNanoClock");
66
63 assertTrue("using SystemNanoClock", Log4jLogEvent.getNanoClock() instanceof DummyNanoClock);
64
6765 CoreLoggerContexts.stopLoggerContext(file); // stop async thread
6866
6967 String line1;
7674 }
7775 file.delete();
7876
79 assertNotNull(line1, "line1");
80 assertNotNull(line2, "line2");
77 assertNotNull("line1", line1);
78 assertNotNull("line2", line2);
8179 final String[] line1Parts = line1.split(" AND ");
8280 assertEquals("Use actual System.nanoTime()", line1Parts[2]);
8381 assertEquals(line1Parts[0], line1Parts[1]);
8482 final long loggedNanoTime = Long.parseLong(line1Parts[0]);
85 assertTrue(loggedNanoTime - before < TimeUnit.SECONDS.toNanos(1), "used system nano time");
86
83 assertTrue("used system nano time", loggedNanoTime - before < TimeUnit.SECONDS.toNanos(1));
84
8785 final String[] line2Parts = line2.split(" AND ");
8886 assertEquals("Use dummy nano clock", line2Parts[2]);
8987 assertEquals(String.valueOf(DUMMYNANOTIME), line2Parts[0]);
1414 * limitations under the license.
1515 */
1616 package org.apache.logging.log4j.core.impl;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertNull;
22 import static org.junit.Assert.assertSame;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25
26 import java.io.ByteArrayInputStream;
27 import java.io.ByteArrayOutputStream;
28 import java.io.IOException;
29 import java.io.ObjectInputStream;
30 import java.io.ObjectOutputStream;
31 import java.lang.reflect.Field;
1732
1833 import org.apache.logging.log4j.Level;
1934 import org.apache.logging.log4j.Marker;
3550 import org.apache.logging.log4j.util.SortedArrayStringMap;
3651 import org.apache.logging.log4j.util.StringMap;
3752 import org.apache.logging.log4j.util.Strings;
38 import org.junit.jupiter.api.AfterAll;
39 import org.junit.jupiter.api.BeforeAll;
40 import org.junit.jupiter.api.Test;
41
42 import java.io.ByteArrayInputStream;
43 import java.io.ByteArrayOutputStream;
44 import java.io.IOException;
45 import java.io.ObjectInputStream;
46 import java.io.ObjectOutputStream;
47 import java.lang.reflect.Field;
48
49 import static org.junit.jupiter.api.Assertions.*;
53 import org.junit.AfterClass;
54 import org.junit.Assert;
55 import org.junit.BeforeClass;
56 import org.junit.Test;
5057
5158 public class Log4jLogEventTest {
5259
6572 }
6673 }
6774
68 @BeforeAll
75 @BeforeClass
6976 public static void beforeClass() {
7077 System.setProperty(ClockFactory.PROPERTY_NAME, FixedTimeClock.class.getName());
7178 }
7279
73 @AfterAll
80 @AfterClass
7481 public static void afterClass() throws IllegalAccessException {
7582 ClockFactoryTest.resetClocks();
7683 }
7885 @Test
7986 public void testToImmutableSame() {
8087 final LogEvent logEvent = new Log4jLogEvent();
81 assertSame(logEvent, logEvent.toImmutable());
88 Assert.assertSame(logEvent, logEvent.toImmutable());
8289 }
8390
8491 @Test
8592 public void testToImmutableNotSame() {
8693 final LogEvent logEvent = new Log4jLogEvent.Builder().setMessage(new ReusableObjectMessage()).build();
8794 final LogEvent immutable = logEvent.toImmutable();
88 assertSame(logEvent, immutable);
89 assertFalse(immutable.getMessage() instanceof ReusableMessage);
95 Assert.assertSame(logEvent, immutable);
96 Assert.assertFalse(immutable.getMessage() instanceof ReusableMessage);
9097 }
9198
9299 @Test
202209 assertEquals(marker, evt2.getMarker());
203210 assertEquals(msg, evt2.getMessage());
204211 assertEquals(threadName, evt2.getThreadName());
205 assertNull(evt2.getThrown());
212 assertEquals(null, evt2.getThrown());
206213 assertEquals(this.getClass().getName() + "$DeletedException", evt2.getThrownProxy().getName());
207214 assertEquals(errorMessage, evt2.getThrownProxy().getMessage());
208215 }
223230 @Test
224231 public void testInitiallyDummyNanoClock() {
225232 assertTrue(Log4jLogEvent.getNanoClock() instanceof DummyNanoClock);
226 assertEquals(0, Log4jLogEvent.getNanoClock().nanoTime(), "initial dummy nanotime");
233 assertEquals("initial dummy nanotime", 0, Log4jLogEvent.getNanoClock().nanoTime());
227234 }
228235
229236 @Test
238245 private void verifyNanoTimeWithAllConstructors(final long expected) {
239246 assertEquals(expected, Log4jLogEvent.getNanoClock().nanoTime());
240247
241 assertEquals(expected, new Log4jLogEvent().getNanoTime(), "No-arg constructor");
242 assertEquals(expected, new Log4jLogEvent(98).getNanoTime(), "1-arg constructor");
243 assertEquals(expected, new Log4jLogEvent("l", null, "a", null, null, null).getNanoTime(), "6-arg constructor");
244 assertEquals(expected, new Log4jLogEvent("l", null, "a", null, null, null, null).getNanoTime(), "7-arg constructor");
245 assertEquals(expected, new Log4jLogEvent("l", null, "a", null, null, null, null, null, null, null, 0).getNanoTime(),
246 "11-arg constructor");
247 assertEquals(expected,
248 Log4jLogEvent.createEvent("l", null, "a", null, null, null, null, null, null, null, null, 0).getNanoTime(),
249 "12-arg factory method");
248 assertEquals("No-arg constructor", expected, new Log4jLogEvent().getNanoTime());
249 assertEquals("1-arg constructor", expected, new Log4jLogEvent(98).getNanoTime());
250 assertEquals("6-arg constructor", expected, new Log4jLogEvent("l", null, "a", null, null, null).getNanoTime());
251 assertEquals("7-arg constructor", expected, new Log4jLogEvent("l", null, "a", null, null, null, null)
252 .getNanoTime());
253 assertEquals("11-arg constructor", expected, new Log4jLogEvent("l", null, "a", null, null, null, null, null,
254 null, null, 0).getNanoTime());
255 assertEquals("12-arg factory method", expected, Log4jLogEvent.createEvent("l", null, "a", null, null, null,
256 null, null, null, null, null, 0).getNanoTime());
250257 }
251258
252259 @SuppressWarnings("deprecation")
281288
282289 assertEquals(contextData, event.getContextData());
283290 assertSame(contextStack, event.getContextStack());
284 assertTrue(event.isEndOfBatch());
285 assertTrue(event.isIncludeLocation());
291 assertEquals(true, event.isEndOfBatch());
292 assertEquals(true, event.isIncludeLocation());
286293 assertSame(Level.FATAL, event.getLevel());
287294 assertSame(fqcn, event.getLoggerFqcn());
288295 assertSame(name, event.getLoggerName());
295302 assertEquals(987654321L, event.getTimeMillis());
296303
297304 final LogEvent event2 = new Log4jLogEvent.Builder(event).build();
298 assertEquals(event2, event, "copy constructor builder");
299 assertEquals(event2.hashCode(), event.hashCode(), "same hashCode");
305 assertEquals("copy constructor builder", event2, event);
306 assertEquals("same hashCode", event2.hashCode(), event.hashCode());
300307 }
301308
302309 @Test
330337
331338 assertSame(contextData, event.getContextData());
332339 assertSame(contextStack, event.getContextStack());
333 assertTrue(event.isEndOfBatch());
334 assertTrue(event.isIncludeLocation());
340 assertEquals(true, event.isEndOfBatch());
341 assertEquals(true, event.isIncludeLocation());
335342 assertSame(Level.FATAL, event.getLevel());
336343 assertSame(fqcn, event.getLoggerFqcn());
337344 assertSame(name, event.getLoggerName());
344351 assertEquals(987654321L, event.getTimeMillis());
345352
346353 final LogEvent event2 = new Log4jLogEvent.Builder(event).build();
347 assertEquals(event2, event, "copy constructor builder");
348 assertEquals(event2.hashCode(), event.hashCode(), "same hashCode");
354 assertEquals("copy constructor builder", event2, event);
355 assertEquals("same hashCode", event2.hashCode(), event.hashCode());
349356 }
350357
351358 @Test
378385
379386 assertSame(contextData, event.getContextData());
380387 assertSame(contextStack, event.getContextStack());
381 assertTrue(event.isEndOfBatch());
382 assertTrue(event.isIncludeLocation());
388 assertEquals(true, event.isEndOfBatch());
389 assertEquals(true, event.isIncludeLocation());
383390 assertSame(Level.FATAL, event.getLevel());
384391 assertSame(fqcn, event.getLoggerFqcn());
385392 assertSame(name, event.getLoggerName());
394401 final LogEvent e2 = new Log4jLogEvent.Builder(event).build();
395402 assertEquals(contextData, e2.getContextData());
396403 assertSame(contextStack, e2.getContextStack());
397 assertTrue(e2.isEndOfBatch());
398 assertTrue(e2.isIncludeLocation());
404 assertEquals(true, e2.isEndOfBatch());
405 assertEquals(true, e2.isIncludeLocation());
399406 assertSame(Level.FATAL, e2.getLevel());
400407 assertSame(fqcn, e2.getLoggerFqcn());
401408 assertSame(name, e2.getLoggerName());
412419 final Field fieldSource = Log4jLogEvent.class.getDeclaredField("source");
413420 fieldSource.setAccessible(true);
414421 final Object value = fieldSource.get(e2);
415 assertNull(value, "source in copy");
422 assertNull("source in copy", value);
416423 }
417424
418425 @SuppressWarnings("deprecation")
448455
449456 assertEquals(contextData, event.getContextData());
450457 assertSame(contextStack, event.getContextStack());
451 assertTrue(event.isEndOfBatch());
452 assertTrue(event.isIncludeLocation());
458 assertEquals(true, event.isEndOfBatch());
459 assertEquals(true, event.isIncludeLocation());
453460 assertSame(Level.FATAL, event.getLevel());
454461 assertSame(fqcn, event.getLoggerFqcn());
455462 assertSame(name, event.getLoggerName());
462469 assertEquals(987654321L, event.getTimeMillis());
463470
464471 final LogEvent event2 = builder(event).build();
465 assertEquals(event2, event, "copy constructor builder");
466 assertEquals(event2.hashCode(), event.hashCode(), "same hashCode");
472 assertEquals("copy constructor builder", event2, event);
473 assertEquals("same hashCode", event2.hashCode(), event.hashCode());
467474
468475 assertEquals(contextData, event2.getContextData());
469476 assertSame(contextStack, event2.getContextStack());
470 assertTrue(event2.isEndOfBatch());
471 assertTrue(event2.isIncludeLocation());
477 assertEquals(true, event2.isEndOfBatch());
478 assertEquals(true, event2.isIncludeLocation());
472479 assertSame(Level.FATAL, event2.getLevel());
473480 assertSame(fqcn, event2.getLoggerFqcn());
474481 assertSame(name, event2.getLoggerName());
499506 different("null fqcn", builder(event).setLoggerFqcn(null), event);
500507
501508 different("different name", builder(event).setLoggerName("different"), event);
502 assertThrows(NullPointerException.class, () -> different("null name", builder(event).setLoggerName(null), event));
509 try { // TODO null logger name throws NPE in equals. Use Objects.requireNonNull in constructor?
510 different("null name", builder(event).setLoggerName(null), event);
511 fail("Expected NullPointerException");
512 } catch (final NullPointerException ok) {
513 }
503514
504515 different("different marker", builder(event).setMarker(MarkerManager.getMarker("different")), event);
505516 different("null marker", builder(event).setMarker(null), event);
506517
507518 different("different message", builder(event).setMessage(new ObjectMessage("different")), event);
508 assertThrows(NullPointerException.class, () -> different("null message", builder(event).setMessage(null), event));
519 try { // TODO null message throws NPE in equals(). Use Objects.requireNonNull in constructor?
520 different("null message", builder(event).setMessage(null), event);
521 fail("Expected NullPointerException");
522 } catch (final NullPointerException ok) {
523 }
509524
510525 different("different nanoTime", builder(event).setNanoTime(135), event);
511526 different("different milliTime", builder(event).setTimeMillis(137), event);
527542
528543 private void different(final String reason, final Log4jLogEvent.Builder builder, final LogEvent event) {
529544 final LogEvent other = builder.build();
530 assertNotEquals(other, event, reason);
531 assertNotEquals(other.hashCode(), event.hashCode(), reason + " hashCode");
545 assertNotEquals(reason, other, event);
546 assertNotEquals(reason + " hashCode", other.hashCode(), event.hashCode());
532547 }
533548
534549 @Test
3030 import org.apache.logging.log4j.message.Message;
3131 import org.apache.logging.log4j.message.ParameterizedMessage;
3232 import org.apache.logging.log4j.message.ReusableMessageFactory;
33 import org.apache.logging.log4j.message.ReusableSimpleMessage;
3433 import org.apache.logging.log4j.message.SimpleMessage;
3534 import org.apache.logging.log4j.util.FilteredObjectInputStream;
3635 import org.apache.logging.log4j.util.SortedArrayStringMap;
3736 import org.apache.logging.log4j.util.StringMap;
3837 import org.apache.logging.log4j.spi.MutableThreadContextStack;
39 import org.junit.jupiter.api.BeforeAll;
40 import org.junit.jupiter.api.Test;
41
42 import static org.junit.jupiter.api.Assertions.*;
38 import org.junit.Assert;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41
42 import static org.junit.Assert.*;
4343
4444 /**
4545 * Tests the MutableLogEvent class.
5757 return result;
5858 }
5959
60 @BeforeAll
60 @BeforeClass
6161 public static void setupClass() {
6262 try {
6363 Class.forName("java.io.ObjectInputFilter");
7070 @Test
7171 public void testToImmutable() {
7272 final LogEvent logEvent = new MutableLogEvent();
73 assertNotSame(logEvent, logEvent.toImmutable());
73 Assert.assertNotSame(logEvent, logEvent.toImmutable());
7474 }
7575
7676 @Test
9494 .build();
9595 final MutableLogEvent mutable = new MutableLogEvent();
9696 mutable.initFrom(source);
97 assertEquals(CONTEXT_DATA, mutable.getContextData(), "contextMap");
98 assertEquals(STACK, mutable.getContextStack(), "stack");
99 assertTrue(mutable.isEndOfBatch(), "endOfBatch");
100 assertTrue(mutable.isIncludeLocation(), "IncludeLocation()");
101 assertEquals(Level.FATAL, mutable.getLevel(), "level");
102 assertEquals(source.getLoggerFqcn(), mutable.getLoggerFqcn(), "LoggerFqcn()");
103 assertEquals(source.getLoggerName(), mutable.getLoggerName(), "LoggerName");
104 assertEquals(source.getMarker(), mutable.getMarker(), "marker");
105 assertEquals(source.getMessage(), mutable.getMessage(), "msg");
106 assertEquals(source.getNanoTime(), mutable.getNanoTime(), "nano");
107 assertEquals(source.getSource(), mutable.getSource(), "src");
108 assertEquals(source.getThreadId(), mutable.getThreadId(), "tid");
109 assertEquals(source.getThreadName(), mutable.getThreadName(), "tname");
110 assertEquals(source.getThreadPriority(), mutable.getThreadPriority(), "tpriority");
111 assertEquals(source.getThrown(), mutable.getThrown(), "throwns");
112 assertEquals(source.getThrownProxy(), mutable.getThrownProxy(), "proxy");
113 assertEquals(source.getTimeMillis(), mutable.getTimeMillis(), "millis");
97 assertEquals("contextMap", CONTEXT_DATA, mutable.getContextData());
98 assertEquals("stack", STACK, mutable.getContextStack());
99 assertEquals("endOfBatch", true, mutable.isEndOfBatch());
100 assertEquals("IncludeLocation()", true, mutable.isIncludeLocation());
101 assertEquals("level", Level.FATAL, mutable.getLevel());
102 assertEquals("LoggerFqcn()", source.getLoggerFqcn(), mutable.getLoggerFqcn());
103 assertEquals("LoggerName", source.getLoggerName(), mutable.getLoggerName());
104 assertEquals("marker", source.getMarker(), mutable.getMarker());
105 assertEquals("msg", source.getMessage(), mutable.getMessage());
106 assertEquals("nano", source.getNanoTime(), mutable.getNanoTime());
107 assertEquals("src", source.getSource(), mutable.getSource());
108 assertEquals("tid", source.getThreadId(), mutable.getThreadId());
109 assertEquals("tname", source.getThreadName(), mutable.getThreadName());
110 assertEquals("tpriority", source.getThreadPriority(), mutable.getThreadPriority());
111 assertEquals("throwns", source.getThrown(), mutable.getThrown());
112 assertEquals("proxy", source.getThrownProxy(), mutable.getThrownProxy());
113 assertEquals("millis", source.getTimeMillis(), mutable.getTimeMillis());
114114 }
115115
116116 @Test
134134 .build();
135135 final MutableLogEvent mutable = new MutableLogEvent();
136136 mutable.initFrom(source);
137 assertEquals("msg in a {}", mutable.getFormat(), "format");
138 assertEquals("msg in a bottle", mutable.getFormattedMessage(), "formatted");
139 assertArrayEquals(new String[] {"bottle"}, mutable.getParameters(), "parameters");
140 Message memento = mutable.memento();
141 assertEquals("msg in a {}", memento.getFormat(), "format");
142 assertEquals("msg in a bottle", memento.getFormattedMessage(), "formatted");
143 assertArrayEquals(new String[] {"bottle"}, memento.getParameters(), "parameters");
144
145 Message eventMementoMessage = mutable.createMemento().getMessage();
146 assertEquals("msg in a {}", eventMementoMessage.getFormat(), "format");
147 assertEquals("msg in a bottle", eventMementoMessage.getFormattedMessage(), "formatted");
148 assertArrayEquals(new String[] {"bottle"}, eventMementoMessage.getParameters(), "parameters");
149
150 Message log4JLogEventMessage = new Log4jLogEvent.Builder(mutable).build().getMessage();
151 assertEquals("msg in a {}", log4JLogEventMessage.getFormat(), "format");
152 assertEquals("msg in a bottle", log4JLogEventMessage.getFormattedMessage(), "formatted");
153 assertArrayEquals(new String[] {"bottle"}, log4JLogEventMessage.getParameters(), "parameters");
137 assertEquals("format", "msg in a {}", mutable.getFormat());
138 assertEquals("formatted", "msg in a bottle", mutable.getFormattedMessage());
139 assertEquals("parameters", new String[] {"bottle"}, mutable.getParameters());
140 final Message memento = mutable.memento();
141 assertEquals("format", "msg in a {}", memento.getFormat());
142 assertEquals("formatted", "msg in a bottle", memento.getFormattedMessage());
143 assertEquals("parameters", new String[] {"bottle"}, memento.getParameters());
144
145 final Message eventMementoMessage = mutable.createMemento().getMessage();
146 assertEquals("format", "msg in a {}", eventMementoMessage.getFormat());
147 assertEquals("formatted", "msg in a bottle", eventMementoMessage.getFormattedMessage());
148 assertEquals("parameters", new String[] {"bottle"}, eventMementoMessage.getParameters());
149
150 final Message log4JLogEventMessage = new Log4jLogEvent.Builder(mutable).build().getMessage();
151 assertEquals("format", "msg in a {}", log4JLogEventMessage.getFormat());
152 assertEquals("formatted", "msg in a bottle", log4JLogEventMessage.getFormattedMessage());
153 assertEquals("parameters", new String[] {"bottle"}, log4JLogEventMessage.getParameters());
154154 }
155155
156156 @Test
176176 .build();
177177 final MutableLogEvent mutable = new MutableLogEvent();
178178 mutable.initFrom(source);
179 assertNull(mutable.getFormat(), "format");
180 assertEquals(param.toString(), mutable.getFormattedMessage(), "formatted");
181 assertArrayEquals(new Object[] {param}, mutable.getParameters(), "parameters");
182 Message memento = mutable.memento();
183 assertNull(memento.getFormat(), "format");
184 assertEquals(param.toString(), memento.getFormattedMessage(), "formatted");
185 assertArrayEquals(new Object[] {param}, memento.getParameters(), "parameters");
179 assertNull("format", mutable.getFormat());
180 assertEquals("formatted", param.toString(), mutable.getFormattedMessage());
181 assertEquals("parameters", new Object[] {param}, mutable.getParameters());
182 final Message memento = mutable.memento();
183 assertNull("format", memento.getFormat());
184 assertEquals("formatted", param.toString(), memento.getFormattedMessage());
185 assertEquals("parameters", new Object[] {param}, memento.getParameters());
186186 }
187187
188188 @Test
189189 public void testClear() {
190190 final MutableLogEvent mutable = new MutableLogEvent();
191 // initialize the event with an empty message
192 ReusableSimpleMessage simpleMessage = new ReusableSimpleMessage();
193 simpleMessage.set("");
194 mutable.setMessage(simpleMessage);
195 assertEquals(0, mutable.getContextData().size(), "context data");
196 assertNull(mutable.getContextStack(), "context stack");
197 assertFalse(mutable.isEndOfBatch(), "end of batch");
198 assertFalse(mutable.isIncludeLocation(), "incl loc");
199 assertSame(Level.OFF, mutable.getLevel(), "level");
200 assertNull(mutable.getLoggerFqcn(), "fqcn");
201 assertNull(mutable.getLoggerName(), "logger");
202 assertNull(mutable.getMarker(), "marker");
203 assertEquals(mutable, mutable.getMessage(), "msg");
204 assertEquals(0, mutable.getNanoTime(), "nanoTm");
205 assertEquals(0, mutable.getThreadId(), "tid");
206 assertNull(mutable.getThreadName(), "tname");
207 assertEquals(0, mutable.getThreadPriority(), "tpriority");
208 assertNull(mutable.getThrown(), "thrwn");
209 assertEquals(0, mutable.getTimeMillis(), "timeMs");
210
211 assertNull(mutable.getSource(), "source");
212 assertNull(mutable.getThrownProxy(), "thrownProxy");
191 assertEquals("context data", 0, mutable.getContextData().size());
192 assertNull("context stack", mutable.getContextStack());
193 assertFalse("end of batch", mutable.isEndOfBatch());
194 assertFalse("incl loc", mutable.isIncludeLocation());
195 assertSame("level", Level.OFF, mutable.getLevel());
196 assertNull("fqcn", mutable.getLoggerFqcn());
197 assertNull("logger", mutable.getLoggerName());
198 assertNull("marker", mutable.getMarker());
199 assertEquals("msg", mutable, mutable.getMessage());
200 assertEquals("nanoTm", 0, mutable.getNanoTime());
201 assertEquals("tid", 0, mutable.getThreadId());
202 assertNull("tname", mutable.getThreadName());
203 assertEquals("tpriority", 0, mutable.getThreadPriority());
204 assertNull("thrwn", mutable.getThrown());
205 assertEquals("timeMs", 0, mutable.getTimeMillis());
206
207 assertNull("source", mutable.getSource());
208 assertNull("thrownProxy", mutable.getThrownProxy());
213209
214210 mutable.setContextData(CONTEXT_DATA);
215211 mutable.setContextStack(STACK);
227223 mutable.setThrown(new Exception());
228224 mutable.setTimeMillis(56789);
229225
230 assertNotNull(mutable.getContextStack(), "context stack");
231 assertTrue(mutable.isEndOfBatch(), "end of batch");
232 assertTrue(mutable.isIncludeLocation(), "incl loc");
233 assertNotNull(mutable.getLevel(), "level");
234 assertNotNull(mutable.getLoggerFqcn(), "fqcn");
235 assertNotNull(mutable.getLoggerName(), "logger");
236 assertNotNull(mutable.getMarker(), "marker");
237 assertEquals(new ParameterizedMessage("message in a {}", "bottle"), mutable.getMessage(), "msg");
238 assertNotEquals(0, mutable.getNanoTime(), "nanoTm");
239 assertNotEquals(0, mutable.getThreadId(), "tid");
240 assertNotNull(mutable.getThreadName(), "tname");
241 assertNotEquals(0, mutable.getThreadPriority(), "tpriority");
242 assertNotNull(mutable.getThrown(), "thrwn");
243 assertNotEquals(0, mutable.getTimeMillis(), "timeMs");
244
245 assertNotNull(mutable.getSource(), "source");
246 assertNotNull(mutable.getThrownProxy(), "thrownProxy");
226 assertNotNull("context map", mutable.getContextMap());
227 assertNotNull("context stack", mutable.getContextStack());
228 assertTrue("end of batch", mutable.isEndOfBatch());
229 assertTrue("incl loc", mutable.isIncludeLocation());
230 assertNotNull("level", mutable.getLevel());
231 assertNotNull("fqcn", mutable.getLoggerFqcn());
232 assertNotNull("logger", mutable.getLoggerName());
233 assertNotNull("marker", mutable.getMarker());
234 assertEquals("msg", new ParameterizedMessage("message in a {}", "bottle"), mutable.getMessage());
235 assertNotEquals("nanoTm", 0, mutable.getNanoTime());
236 assertNotEquals("tid", 0, mutable.getThreadId());
237 assertNotNull("tname", mutable.getThreadName());
238 assertNotEquals("tpriority", 0, mutable.getThreadPriority());
239 assertNotNull("thrwn", mutable.getThrown());
240 assertNotEquals("timeMs", 0, mutable.getTimeMillis());
241
242 assertNotNull("source", mutable.getSource());
243 assertNotNull("thrownProxy", mutable.getThrownProxy());
247244
248245 mutable.clear();
249 assertEquals(0, mutable.getContextData().size(), "context map");
250 assertNull(mutable.getContextStack(), "context stack");
251 assertSame(Level.OFF, mutable.getLevel(), "level");
252 assertNull(mutable.getLoggerFqcn(), "fqcn");
253 assertNull(mutable.getLoggerName(), "logger");
254 assertNull(mutable.getMarker(), "marker");
255 assertEquals(mutable, mutable.getMessage(), "msg");
256 assertNull(mutable.getThrown(), "thrwn");
257
258 assertNull(mutable.getSource(), "source");
259 assertNull(mutable.getThrownProxy(), "thrownProxy");
246 assertEquals("context map", 0, mutable.getContextData().size());
247 assertNull("context stack", mutable.getContextStack());
248 assertSame("level", Level.OFF, mutable.getLevel());
249 assertNull("fqcn", mutable.getLoggerFqcn());
250 assertNull("logger", mutable.getLoggerName());
251 assertNull("marker", mutable.getMarker());
252 assertEquals("msg", mutable, mutable.getMessage());
253 assertNull("thrwn", mutable.getThrown());
254
255 assertNull("source", mutable.getSource());
256 assertNull("thrownProxy", mutable.getThrownProxy());
260257
261258 // primitive fields are NOT reset:
262 assertTrue(mutable.isEndOfBatch(), "end of batch");
263 assertTrue(mutable.isIncludeLocation(), "incl loc");
264 assertNotEquals(0, mutable.getNanoTime(), "nanoTm");
265 assertNotEquals(0, mutable.getTimeMillis(), "timeMs");
259 assertTrue("end of batch", mutable.isEndOfBatch());
260 assertTrue("incl loc", mutable.isIncludeLocation());
261 assertNotEquals("nanoTm", 0, mutable.getNanoTime());
262 assertNotEquals("timeMs", 0, mutable.getTimeMillis());
266263
267264 // thread-local fields are NOT reset:
268 assertNotEquals(0, mutable.getThreadId(), "tid");
269 assertNotNull(mutable.getThreadName(), "tname");
270 assertNotEquals(0, mutable.getThreadPriority(), "tpriority");
265 assertNotEquals("tid", 0, mutable.getThreadId());
266 assertNotNull("tname", mutable.getThreadName());
267 assertNotEquals("tpriority", 0, mutable.getThreadPriority());
271268 }
272269
273270 @Test
315312
316313 @Test
317314 public void testJavaIoSerializableWithThrown() throws Exception {
315 new InternalError("test error");
318316 final MutableLogEvent evt = new MutableLogEvent();
319317 evt.setContextData(CONTEXT_DATA);
320318 evt.setContextStack(STACK);
374372 }
375373
376374
377 }
375 }
8686
8787 private static Set<String> readUniqueLines(final File input) throws IOException {
8888 final Set<String> lines = new HashSet<>();
89 try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(input)))) {
89 final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(input)));
90 try {
9091 String line;
9192 while ((line = reader.readLine()) != null) {
9293 assertTrue("Read duplicate line: " + line, lines.add(line));
9394 }
95 } finally {
96 reader.close();
9497 }
9598 return lines;
9699 }
1919 import org.apache.logging.log4j.core.LogEvent;
2020 import org.apache.logging.log4j.message.Message;
2121 import org.apache.logging.log4j.message.SimpleMessage;
22 import org.junit.jupiter.api.Test;
22 import org.junit.Test;
2323
24 import static org.junit.jupiter.api.Assertions.*;
25
26 import java.util.concurrent.atomic.AtomicReference;
24 import static org.junit.Assert.*;
2725
2826 /**
2927 * Tests the ReusableLogEventFactory class.
5856 public void testCreateEventOverwritesFields() throws Exception {
5957 final ReusableLogEventFactory factory = new ReusableLogEventFactory();
6058 final LogEvent event1 = callCreateEvent(factory, "a", Level.DEBUG, new SimpleMessage("abc"), null);
61 assertEquals("a", event1.getLoggerName(), "logger");
62 assertEquals(Level.DEBUG, event1.getLevel(), "level");
63 assertEquals(new SimpleMessage("abc"), event1.getMessage(), "msg");
59 assertEquals("logger", "a", event1.getLoggerName());
60 assertEquals("level", Level.DEBUG, event1.getLevel());
61 assertEquals("msg", new SimpleMessage("abc"), event1.getMessage());
6462
6563 ReusableLogEventFactory.release(event1);
6664 final LogEvent event2 = callCreateEvent(factory, "b", Level.INFO, new SimpleMessage("xyz"), null);
6765 assertSame(event1, event2);
6866
69 assertEquals("b", event1.getLoggerName(), "logger");
70 assertEquals(Level.INFO, event1.getLevel(), "level");
71 assertEquals(new SimpleMessage("xyz"), event1.getMessage(), "msg");
72 assertEquals("b", event2.getLoggerName(), "logger");
73 assertEquals(Level.INFO, event2.getLevel(), "level");
74 assertEquals(new SimpleMessage("xyz"), event2.getMessage(), "msg");
67 assertEquals("logger", "b", event1.getLoggerName());
68 assertEquals("level", Level.INFO, event1.getLevel());
69 assertEquals("msg", new SimpleMessage("xyz"), event1.getMessage());
70 assertEquals("logger", "b", event2.getLoggerName());
71 assertEquals("level", Level.INFO, event2.getLevel());
72 assertEquals("msg", new SimpleMessage("xyz"), event2.getMessage());
7573 }
7674
7775 private LogEvent callCreateEvent(final ReusableLogEventFactory factory, final String logger, final Level level,
8280 @Test
8381 public void testCreateEventReturnsThreadLocalInstance() throws Exception {
8482 final ReusableLogEventFactory factory = new ReusableLogEventFactory();
85 final AtomicReference<LogEvent> event1 = new AtomicReference<>();
86 final AtomicReference<LogEvent> event2 = new AtomicReference<>();
83 final LogEvent[] event1 = new LogEvent[1];
84 final LogEvent[] event2 = new LogEvent[1];
8785 final Thread t1 = new Thread("THREAD 1") {
8886 @Override
8987 public void run() {
90 event1.set(callCreateEvent(factory, "a", Level.DEBUG, new SimpleMessage("abc"), null));
88 event1[0] = callCreateEvent(factory, "a", Level.DEBUG, new SimpleMessage("abc"), null);
9189 }
9290 };
9391 final Thread t2 = new Thread("Thread 2") {
9492 @Override
9593 public void run() {
96 event2.set(callCreateEvent(factory, "b", Level.INFO, new SimpleMessage("xyz"), null));
94 event2[0] = callCreateEvent(factory, "b", Level.INFO, new SimpleMessage("xyz"), null);
9795 }
9896 };
9997 t1.start();
10098 t2.start();
10199 t1.join();
102100 t2.join();
103 assertNotNull(event1.get());
104 assertNotNull(event2.get());
105 assertNotSame(event1.get(), event2.get());
106 assertEquals("a", event1.get().getLoggerName(), "logger");
107 assertEquals(Level.DEBUG, event1.get().getLevel(), "level");
108 assertEquals(new SimpleMessage("abc"), event1.get().getMessage(), "msg");
109 assertEquals("THREAD 1", event1.get().getThreadName(), "thread name");
110 assertEquals(t1.getId(), event1.get().getThreadId(), "tid");
101 assertNotNull(event1[0]);
102 assertNotNull(event2[0]);
103 assertNotSame(event1[0], event2[0]);
104 assertEquals("logger", "a", event1[0].getLoggerName());
105 assertEquals("level", Level.DEBUG, event1[0].getLevel());
106 assertEquals("msg", new SimpleMessage("abc"), event1[0].getMessage());
107 assertEquals("thread name", "THREAD 1", event1[0].getThreadName());
108 assertEquals("tid", t1.getId(), event1[0].getThreadId());
111109
112 assertEquals("b", event2.get().getLoggerName(), "logger");
113 assertEquals(Level.INFO, event2.get().getLevel(), "level");
114 assertEquals(new SimpleMessage("xyz"), event2.get().getMessage(), "msg");
115 assertEquals("Thread 2", event2.get().getThreadName(), "thread name");
116 assertEquals(t2.getId(), event2.get().getThreadId(), "tid");
117 ReusableLogEventFactory.release(event1.get());
118 ReusableLogEventFactory.release(event2.get());
110 assertEquals("logger", "b", event2[0].getLoggerName());
111 assertEquals("level", Level.INFO, event2[0].getLevel());
112 assertEquals("msg", new SimpleMessage("xyz"), event2[0].getMessage());
113 assertEquals("thread name", "Thread 2", event2[0].getThreadName());
114 assertEquals("tid", t2.getId(), event2[0].getThreadId());
115 ReusableLogEventFactory.release(event1[0]);
116 ReusableLogEventFactory.release(event2[0]);
119117 }
120118
121119 @SuppressWarnings("deprecation")
123123 public void testInheritableThreadContextImmutability() throws Throwable {
124124 prepareThreadContext(true);
125125 try {
126 newSingleThreadExecutor().submit(this::testContextDataInjector).get();
126 newSingleThreadExecutor().submit(new Runnable() {
127 @Override
128 public void run() {
129 testContextDataInjector();
130 }
131 }).get();
127132 } catch (final ExecutionException ee) {
128133 throw ee.getCause();
129134 }
1515 */
1616 package org.apache.logging.log4j.core.impl;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20
1821 import java.util.Arrays;
19 import java.util.Collections;
2022 import java.util.List;
2123 import java.util.Map;
2224
2426 import org.apache.logging.log4j.core.pattern.TextRenderer;
2527 import org.apache.logging.log4j.util.Strings;
2628 import org.fusesource.jansi.AnsiRenderer.Code;
27 import org.junit.jupiter.api.Test;
28
29 import static org.junit.jupiter.api.Assertions.*;
29 import org.junit.Assert;
30 import org.junit.Test;
3031
3132 /**
3233 * Unit tests for {@code ThrowableFormatOptions}.
4849 private static ThrowableFormatOptions test(final String[] options, final int expectedLines,
4950 final String expectedSeparator, final List<String> expectedPackages) {
5051 final ThrowableFormatOptions tfo = ThrowableFormatOptions.newInstance(options);
51 assertEquals(expectedLines, tfo.getLines(), "getLines");
52 assertEquals(expectedSeparator, tfo.getSeparator(), "getSeparator");
53 assertEquals(expectedPackages, tfo.getIgnorePackages(), "getPackages");
54 assertEquals(expectedLines == Integer.MAX_VALUE, tfo.allLines(), "allLines");
55 assertEquals(expectedLines != 0, tfo.anyLines(), "anyLines");
56 assertEquals(0, tfo.minLines(0), "minLines");
57 assertEquals(expectedLines, tfo.minLines(Integer.MAX_VALUE), "minLines");
58 assertEquals(expectedPackages != null && !expectedPackages.isEmpty(), tfo.hasPackages(), "hasPackages");
59 assertNotNull(tfo.toString(), "toString");
52 assertEquals("getLines", expectedLines, tfo.getLines());
53 assertEquals("getSeparator", expectedSeparator, tfo.getSeparator());
54 assertEquals("getPackages", expectedPackages, tfo.getIgnorePackages());
55 assertEquals("allLines", expectedLines == Integer.MAX_VALUE, tfo.allLines());
56 assertEquals("anyLines", expectedLines != 0, tfo.anyLines());
57 assertEquals("minLines", 0, tfo.minLines(0));
58 assertEquals("minLines", expectedLines, tfo.minLines(Integer.MAX_VALUE));
59 assertEquals("hasPackages", expectedPackages != null && !expectedPackages.isEmpty(), tfo.hasPackages());
60 assertNotNull("toString", tfo.toString());
6061 return tfo;
6162 }
6263
122123
123124 private void testFullAnsiEmptyConfig(final ThrowableFormatOptions tfo) {
124125 final TextRenderer textRenderer = tfo.getTextRenderer();
125 assertNotNull(textRenderer);
126 assertTrue(textRenderer instanceof JAnsiTextRenderer);
126 Assert.assertNotNull(textRenderer);
127 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
127128 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
128129 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
129130 // We have defaults
130 assertFalse(styleMap.isEmpty());
131 assertNotNull(styleMap.get("Name"));
131 Assert.assertFalse(styleMap.isEmpty());
132 Assert.assertNotNull(styleMap.get("Name"));
132133 }
133134
134135 /**
139140 final ThrowableFormatOptions tfo = test(new String[] { "full", "ansi(Warning=red)" },
140141 Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
141142 final TextRenderer textRenderer = tfo.getTextRenderer();
142 assertNotNull(textRenderer);
143 assertTrue(textRenderer instanceof JAnsiTextRenderer);
143 Assert.assertNotNull(textRenderer);
144 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
144145 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
145146 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
146 assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
147 Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
147148 }
148149
149150 /**
154155 final ThrowableFormatOptions tfo = test(new String[] { "full", "ansi(Warning=red Key=blue Value=cyan)" },
155156 Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
156157 final TextRenderer textRenderer = tfo.getTextRenderer();
157 assertNotNull(textRenderer);
158 assertTrue(textRenderer instanceof JAnsiTextRenderer);
158 Assert.assertNotNull(textRenderer);
159 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
159160 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
160161 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
161 assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
162 assertArrayEquals(new Code[] { Code.BLUE }, styleMap.get("Key"));
163 assertArrayEquals(new Code[] { Code.CYAN }, styleMap.get("Value"));
162 Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
163 Assert.assertArrayEquals(new Code[] { Code.BLUE }, styleMap.get("Key"));
164 Assert.assertArrayEquals(new Code[] { Code.CYAN }, styleMap.get("Value"));
164165 }
165166
166167 /**
172173 new String[] { "full", "ansi(Warning=red Key=blue,bg_red Value=cyan,bg_black,underline)" }, Integer.MAX_VALUE,
173174 Strings.LINE_SEPARATOR, null);
174175 final TextRenderer textRenderer = tfo.getTextRenderer();
175 assertNotNull(textRenderer);
176 assertTrue(textRenderer instanceof JAnsiTextRenderer);
176 Assert.assertNotNull(textRenderer);
177 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
177178 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
178179 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
179 assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
180 assertArrayEquals(new Code[] { Code.BLUE, Code.BG_RED }, styleMap.get("Key"));
181 assertArrayEquals(new Code[] { Code.CYAN, Code.BG_BLACK, Code.UNDERLINE }, styleMap.get("Value"));
180 Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
181 Assert.assertArrayEquals(new Code[] { Code.BLUE, Code.BG_RED }, styleMap.get("Key"));
182 Assert.assertArrayEquals(new Code[] { Code.CYAN, Code.BG_BLACK, Code.UNDERLINE }, styleMap.get("Value"));
182183 }
183184
184185 /**
251252 */
252253 @Test
253254 public void testFullAndFiltersAndSeparator() {
254 test(new String[] { "full", "filters(org.junit)", "separator(|)" }, Integer.MAX_VALUE, "|",
255 Collections.singletonList("org.junit"));
255 test(new String[] { "full", "filters(org.junit)", "separator(|)" }, Integer.MAX_VALUE, "|", Arrays.asList("org.junit"));
256256 }
257257
258258 /**
285285 @Test
286286 public void testFilters() {
287287 test(new String[] { "filters(packages)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
288 Collections.singletonList("packages"));
288 Arrays.asList("packages"));
289289 }
290290
291291 /**
311311 @Test
312312 public void testFullAndFilters() {
313313 test(new String[] { "full", "filters(packages)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
314 Collections.singletonList("packages"));
314 Arrays.asList("packages"));
315315 }
316316
317317 /**
319319 */
320320 @Test
321321 public void testNoneAndFilters() {
322 test(new String[] { "none", "filters(packages)" }, 0, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
322 test(new String[] { "none", "filters(packages)" }, 0, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
323323 }
324324
325325 /**
327327 */
328328 @Test
329329 public void testShortAndFilters() {
330 test(new String[] { "short", "filters(packages)" }, 2, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
330 test(new String[] { "short", "filters(packages)" }, 2, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
331331 }
332332
333333 /**
335335 */
336336 @Test
337337 public void testDepthAndFilters() {
338 test(new String[] { "10", "filters(packages)" }, 10, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
338 test(new String[] { "10", "filters(packages)" }, 10, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
339339 }
340340
341341 /**
344344 @Test
345345 public void testFullAndSeparatorAndFilter() {
346346 test(new String[] { "full", "separator(|)", "filters(packages)" }, Integer.MAX_VALUE, "|",
347 Collections.singletonList("packages"));
347 Arrays.asList("packages"));
348348 }
349349
350350 /**
361361 */
362362 @Test
363363 public void testNoneAndSeparatorAndFilters() {
364 test(new String[] { "none", "separator(|)", "filters(packages)" }, 0, "|", Collections.singletonList("packages"));
364 test(new String[] { "none", "separator(|)", "filters(packages)" }, 0, "|", Arrays.asList("packages"));
365365 }
366366
367367 /**
369369 */
370370 @Test
371371 public void testShortAndSeparatorAndFilters() {
372 test(new String[] { "short", "separator(|)", "filters(packages)" }, 2, "|", Collections.singletonList("packages"));
372 test(new String[] { "short", "separator(|)", "filters(packages)" }, 2, "|", Arrays.asList("packages"));
373373 }
374374
375375 /**
377377 */
378378 @Test
379379 public void testDepthAndSeparatorAndFilters() {
380 test(new String[] { "10", "separator(|)", "filters(packages)" }, 10, "|", Collections.singletonList("packages"));
380 test(new String[] { "10", "separator(|)", "filters(packages)" }, 10, "|", Arrays.asList("packages"));
381381 }
382382
383383 /**
386386 @Test
387387 public void testSingleOptionFullAndFilters() {
388388 test(new String[] { "full,filters(packages)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
389 Collections.singletonList("packages"));
389 Arrays.asList("packages"));
390390 }
391391
392392 /**
394394 */
395395 @Test
396396 public void testSingleOptionNoneAndFilters() {
397 test(new String[] { "none,filters(packages)" }, 0, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
397 test(new String[] { "none,filters(packages)" }, 0, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
398398 }
399399
400400 /**
402402 */
403403 @Test
404404 public void testSingleOptionShortAndFilters() {
405 test(new String[] { "short,filters(packages)" }, 2, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
405 test(new String[] { "short,filters(packages)" }, 2, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
406406 }
407407
408408 /**
410410 */
411411 @Test
412412 public void testSingleOptionDepthAndFilters() {
413 test(new String[] { "10,filters(packages)" }, 10, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
413 test(new String[] { "10,filters(packages)" }, 10, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
414414 }
415415
416416 /**
+0
-34
log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyRendererTest.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.logging.log4j.core.impl;
17
18 import java.util.ArrayList;
19
20 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
21 import org.junit.jupiter.api.Test;
22
23 /**
24 * Tests ThrowableProxyRenderer.
25 */
26 public class ThrowableProxyRendererTest {
27
28 @Test
29 public void test_formatExtendedStackTraceTo() {
30 ThrowableProxyRenderer.formatExtendedStackTraceTo(new ThrowableProxy(), new StringBuilder(), new ArrayList<>(),
31 new PlainTextRenderer(), "", System.lineSeparator());
32 }
33 }
1515 */
1616 package org.apache.logging.log4j.core.impl;
1717
18 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
19 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
18 import static org.junit.Assert.assertArrayEquals;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
2423
2524 import java.io.ByteArrayInputStream;
2625 import java.io.ByteArrayOutputStream;
3534 import java.util.HashMap;
3635 import java.util.Map;
3736 import java.util.Stack;
38
3937 import javax.crypto.BadPaddingException;
4038 import javax.crypto.Cipher;
4139 import javax.crypto.KeyGenerator;
4240 import javax.crypto.spec.IvParameterSpec;
4341
42 import com.fasterxml.jackson.annotation.JsonProperty;
43 import com.fasterxml.jackson.databind.ObjectMapper;
4444 import org.apache.logging.log4j.LogManager;
4545 import org.apache.logging.log4j.Logger;
4646 import org.apache.logging.log4j.core.config.plugins.convert.Base64Converter;
4747 import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
4848 import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
4949 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
50 import org.apache.logging.log4j.util.Constants;
5150 import org.apache.logging.log4j.util.Strings;
52 import org.junit.jupiter.api.Test;
53
54 import com.fasterxml.jackson.annotation.JsonProperty;
55 import com.fasterxml.jackson.databind.ObjectMapper;
51 import org.junit.Test;
5652
5753 /**
5854 *
132128 */
133129 @Test
134130 public void testLogStackTraceWithClassThatCannotInitialize() {
135 final Error e = assertThrows(Error.class, AlwaysThrowsError::new);
136 // Print the stack trace to System.out for informational purposes
137 // System.err.println("### Here's the stack trace that we'll log with log4j ###");
138 // e.printStackTrace();
139 // System.err.println("### End stack trace ###");
140
141 final Logger logger = LogManager.getLogger(getClass());
142
143 assertDoesNotThrow(() -> {
131 try {
132 // Try to create the object, which will always fail during class initialization
133 final AlwaysThrowsError error = new AlwaysThrowsError();
134
135 // If the error was not triggered then fail
136 fail("Test did not throw expected error: " + error);
137 } catch (final Throwable e) {
138 // Print the stack trace to System.out for informational purposes
139 // System.err.println("### Here's the stack trace that we'll log with log4j ###");
140 // e.printStackTrace();
141 // System.err.println("### End stack trace ###");
142
143 final Logger logger = LogManager.getLogger(getClass());
144
144145 // This is the critical portion of the test. The log message must be printed without
145146 // throwing a java.lang.Error when introspecting the AlwaysThrowError class in the
146147 // stack trace.
147148 logger.error(e.getMessage(), e);
148149 logger.error(e);
149 });
150 }
150151 }
151152
152153 @Test
165166 }
166167 }
167168 });
168 final BindException e = assertThrows(BindException.class, () -> {
169 ServerSocketChannel.open().socket().bind(new InetSocketAddress("localhost", 9300));
170 ServerSocketChannel.open().socket().bind(new InetSocketAddress("localhost", 9300));
171 });
172 assertDoesNotThrow(() -> new ThrowableProxy(e));
169 ServerSocketChannel.open().socket().bind(new InetSocketAddress("localhost", 9300));
170 ServerSocketChannel.open().socket().bind(new InetSocketAddress("localhost", 9300));
171 fail("expected a java.net.BindException");
172 } catch (final BindException e) {
173 new ThrowableProxy(e);
173174 } finally {
174175 // restore the security manager
175176 System.setSecurityManager(sm);
201202 generator.init(128);
202203 final IvParameterSpec algorithmParameterSpec = new IvParameterSpec(bytes);
203204 ec.init(Cipher.ENCRYPT_MODE, generator.generateKey(), algorithmParameterSpec, secureRandom);
204 final byte[] raw = Constants.EMPTY_BYTE_ARRAY;
205 final byte[] raw = new byte[0];
205206 final byte[] encrypted = ec.doFinal(raw);
206207 final Cipher dc = Cipher.getInstance(algorithm);
207208 dc.init(Cipher.DECRYPT_MODE, generator.generateKey(), algorithmParameterSpec, secureRandom);
208 final BadPaddingException e = assertThrows(BadPaddingException.class, () -> dc.doFinal(encrypted));
209 assertDoesNotThrow(() -> new ThrowableProxy(e));
209 dc.doFinal(encrypted);
210 fail("expected a javax.crypto.BadPaddingException");
211 } catch (final BadPaddingException e) {
212 new ThrowableProxy(e);
210213 } finally {
211214 // restore the existing security manager
212215 System.setSecurityManager(sm);
304307 final String separator = " | ";
305308 final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString(null,
306309 PlainTextRenderer.getInstance(), " | ", Strings.EMPTY);
307 assertTrue(allLinesContain(extendedStackTraceAsString, separator), extendedStackTraceAsString);
310 assertTrue(extendedStackTraceAsString, allLinesContain(extendedStackTraceAsString, separator));
308311 }
309312
310313 @Test
314317
315318 final String suffix = "some suffix";
316319 final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString(suffix);
317 assertTrue(lastLineContains(extendedStackTraceAsString, suffix), extendedStackTraceAsString);
320 assertTrue(extendedStackTraceAsString, lastLineContains(extendedStackTraceAsString, suffix));
318321 }
319322
320323 @Test
374377 final ThrowableProxy proxy = new ThrowableProxy(throwable);
375378 final ExtendedStackTraceElement[] callerPackageData = ThrowableProxyHelper.toExtendedStackTrace(proxy, stack, map, null,
376379 throwable.getStackTrace());
377 assertNotNull(callerPackageData, "No package data returned");
380 assertNotNull("No package data returned", callerPackageData);
378381 }
379382
380383 /**
1616 package org.apache.logging.log4j.core.jackson;
1717
1818 import java.io.IOException;
19 import java.util.Objects;
2019
2120 import org.apache.logging.log4j.Level;
2221 import org.apache.logging.log4j.categories.Layouts;
5251 return false;
5352 }
5453 final Fixture other = (Fixture) obj;
55 if (!Objects.equals(this.level, other.level)) {
54 if (this.level == null) {
55 if (other.level != null) {
56 return false;
57 }
58 } else if (!this.level.equals(other.level)) {
5659 return false;
5760 }
5861 return true;
6063
6164 @Override
6265 public int hashCode() {
63 return 31 + Objects.hashCode(level);
66 final int prime = 31;
67 int result = 1;
68 result = prime * result + ((this.level == null) ? 0 : this.level.hashCode());
69 return result;
6470 }
6571 }
6672 private ObjectMapper log4jObjectMapper;
1818
1919 import javax.management.ObjectName;
2020
21 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2222
23 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2424
2525 /**
2626 * Unit tests for the Server class.
1717 import java.nio.charset.Charset;
1818
1919 import org.apache.logging.log4j.core.LogEvent;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2323
2424 /**
2525 * Tests AbstractStringLayout.
4747 public void testGetStringBuilderCapacityRestrictedToMax() throws Exception {
4848 final StringBuilder sb = ConcreteStringLayout.getStringBuilder();
4949 final int initialCapacity = sb.capacity();
50 assertEquals(ConcreteStringLayout.DEFAULT_STRING_BUILDER_SIZE, sb.capacity(), "initial capacity");
50 assertEquals("initial capacity", ConcreteStringLayout.DEFAULT_STRING_BUILDER_SIZE, sb.capacity());
5151
5252 final int SMALL = 100;
5353 final String smallMessage = new String(new char[SMALL]);
5454 sb.append(smallMessage);
55 assertEquals(initialCapacity, sb.capacity(), "capacity not grown");
56 assertEquals(SMALL, sb.length(), "length=msg length");
55 assertTrue("capacity not grown", sb.capacity() == initialCapacity);
56 assertEquals("length=msg length", SMALL, sb.length());
5757
5858 final StringBuilder sb2 = ConcreteStringLayout.getStringBuilder();
59 assertEquals(sb2.capacity(), initialCapacity, "capacity unchanged");
60 assertEquals(0, sb2.length(), "empty, ready for use");
59 assertEquals("capacity unchanged", sb2.capacity(), initialCapacity);
60 assertEquals("empty, ready for use", 0, sb2.length());
6161
6262 final int LARGE = ConcreteStringLayout.MAX_STRING_BUILDER_SIZE * 2;
6363 final String largeMessage = new String(new char[LARGE]);
6464 sb2.append(largeMessage);
65 assertTrue(sb2.capacity() >= LARGE, "capacity grown to fit msg length");
66 assertTrue(sb2.capacity() >= ConcreteStringLayout.MAX_STRING_BUILDER_SIZE,
67 "capacity is now greater than max length");
68 assertEquals(LARGE, sb2.length(), "length=msg length");
65 assertTrue("capacity grown to fit msg length", sb2.capacity() >= LARGE);
66 assertTrue("capacity is now greater than max length", sb2.capacity() >= ConcreteStringLayout.MAX_STRING_BUILDER_SIZE);
67 assertEquals("length=msg length", LARGE, sb2.length());
6968 sb2.setLength(0); // set 0 before next getStringBuilder() call
70 assertEquals(0, sb2.length(), "empty, cleared");
71 assertTrue(sb2.capacity() >= ConcreteStringLayout.MAX_STRING_BUILDER_SIZE, "capacity remains very large");
69 assertEquals("empty, cleared", 0, sb2.length());
70 assertTrue("capacity remains very large", sb2.capacity() >= ConcreteStringLayout.MAX_STRING_BUILDER_SIZE);
7271
7372 final StringBuilder sb3 = ConcreteStringLayout.getStringBuilder();
74 assertEquals(ConcreteStringLayout.MAX_STRING_BUILDER_SIZE, sb3.capacity(),
75 "capacity, trimmed to MAX_STRING_BUILDER_SIZE");
76 assertEquals(0, sb3.length(), "empty, ready for use");
73 assertEquals("capacity, trimmed to MAX_STRING_BUILDER_SIZE", ConcreteStringLayout.MAX_STRING_BUILDER_SIZE, sb3.capacity());
74 assertEquals("empty, ready for use", 0, sb3.length());
7775 }
7876 }
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.junit.jupiter.api.AfterAll;
22 import org.junit.jupiter.api.Tag;
23 import org.junit.jupiter.api.Test;
24
25 import java.io.IOException;
18 import java.io.File;
2619 import java.nio.charset.Charset;
2720 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
3021 import java.util.ArrayList;
3122 import java.util.Collections;
23 import java.util.HashSet;
3224 import java.util.List;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.stream.Stream;
25 import java.util.Set;
3526
36 import static org.hamcrest.CoreMatchers.*;
37 import static org.hamcrest.MatcherAssert.assertThat;
27 import org.apache.logging.log4j.Logger;
28 import org.apache.logging.log4j.junit.LoggerContextRule;
29 import org.junit.AfterClass;
30 import org.junit.ClassRule;
31 import org.junit.Test;
32
33 import static org.hamcrest.CoreMatchers.endsWith;
34 import static org.hamcrest.CoreMatchers.startsWith;
35 import static org.junit.Assert.*;
3836
3937 /**
4038 * Test for LOG4J2-1769, kind of.
4139 *
4240 * @since 2.8
4341 */
44 @Tag("concurrency")
4542 public class ConcurrentLoggingWithGelfLayoutTest {
46 private static final Path PATH = Paths.get("target", "test-gelf-layout.log");
43 @ClassRule
44 public static LoggerContextRule context = new LoggerContextRule("log4j2-gelf-layout.xml");
45 private static final String PATH = "target/test-gelf-layout.log";
4746
48 @AfterAll
49 static void after() throws IOException {
50 // on Windows, this will need to happen after the LoggerContext is stopped
51 Files.deleteIfExists(PATH);
47 @AfterClass
48 public static void after() {
49 new File(PATH).delete();
5250 }
5351
5452 @Test
55 @LoggerContextSource("log4j2-gelf-layout.xml")
56 public void testConcurrentLogging(final LoggerContext context) throws Throwable {
53 public void testConcurrentLogging() throws Throwable {
5754 final Logger log = context.getLogger(ConcurrentLoggingWithGelfLayoutTest.class);
58 final int threadCount = Runtime.getRuntime().availableProcessors() * 2;
59 final CountDownLatch latch = new CountDownLatch(threadCount);
60 final List<Throwable> thrown = Collections.synchronizedList(new ArrayList<>());
55 final Set<Thread> threads = Collections.synchronizedSet(new HashSet<Thread>());
56 final List<Throwable> thrown = Collections.synchronizedList(new ArrayList<Throwable>());
6157
62 for (int x = 0; x < threadCount; x++) {
63 final Thread t = new Thread(() -> {
64 log.info(latch.getCount());
65 try {
66 for (int i = 0; i < 64; i++) {
67 log.info("First message.");
68 log.info("Second message.");
69 }
70 } finally {
71 latch.countDown();
72 }
73 });
58 for (int x = 0; x < Runtime.getRuntime().availableProcessors() * 2; x++) {
59 final Thread t = new LoggingThread(threads, log);
60 threads.add(t);
7461
7562 // Appender is configured with ignoreExceptions="false";
7663 // any exceptions are propagated to the caller, so we can catch them here.
77 t.setUncaughtExceptionHandler((t1, e) -> thrown.add(e));
64 t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
65 @Override
66 public void uncaughtException(final Thread t, final Throwable e) {
67 thrown.add(e);
68 }
69 });
7870 t.start();
7971 }
8072
81 latch.await();
73 while (!threads.isEmpty()) {
74 log.info("not done going to sleep...");
75 Thread.sleep(10);
76 }
8277
8378 // if any error occurred, fail this test
8479 if (!thrown.isEmpty()) {
8681 }
8782
8883 // simple test to ensure content is not corrupted
89 if (Files.exists(PATH)) {
90 try (Stream<String> lines = Files.lines(PATH, Charset.defaultCharset())) {
91 lines.forEach(line -> assertThat(line,
92 both(startsWith("{\"version\":\"1.1\",\"host\":\"myself\",\"timestamp\":")).and(endsWith("\"}"))));
84 if (new File(PATH).exists()) {
85 final List<String> lines = Files.readAllLines(new File(PATH).toPath(), Charset.defaultCharset());
86 for (final String line : lines) {
87 assertThat(line, startsWith("{\"version\":\"1.1\",\"host\":\"myself\",\"timestamp\":"));
88 assertThat(line, endsWith("\"}"));
9389 }
9490 }
9591 }
9692
93 private class LoggingThread extends Thread {
94 private final Set<Thread> threads;
95 private final Logger log;
96
97 LoggingThread(final Set<Thread> threads, final Logger log) {
98 this.threads = threads;
99 this.log = log;
100 }
101
102 @Override
103 public void run() {
104 log.info(threads.size());
105 try {
106 for (int i = 0; i < 64; i++) {
107 log.info("First message.");
108 log.info("Second message.");
109 }
110 } finally {
111 threads.remove(this);
112 }
113 }
114 }
97115 }
6161
6262 // Appender is configured with ignoreExceptions="false";
6363 // any exceptions are propagated to the caller, so we can catch them here.
64 t.setUncaughtExceptionHandler((t1, e) -> thrown.add(e));
64 t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
65 @Override
66 public void uncaughtException(final Thread t, final Throwable e) {
67 thrown.add(e);
68 }
69 });
6570 t.start();
6671 }
6772
7984 if (new File(PATH).exists()) {
8085 final List<String> lines = Files.readAllLines(new File(PATH).toPath(), Charset.defaultCharset());
8186 for (final String line : lines) {
82 assertThat(line, containsString("\"thread\":"));
87 assertThat(line, startsWith("{\"thread\":"));
8388 assertThat(line, endsWith("\"threadPriority\":5}"));
8489 }
8590 }
+0
-51
log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout2Test.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.logging.log4j.core.layout;
17
18 import java.io.IOException;
19
20 import com.fasterxml.jackson.databind.JsonNode;
21 import com.fasterxml.jackson.databind.ObjectMapper;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.core.LoggerContext;
24 import org.apache.logging.log4j.core.lookup.JavaLookup;
25 import org.apache.logging.log4j.junit.LoggerContextSource;
26 import org.apache.logging.log4j.junit.Named;
27 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.jupiter.api.Test;
29
30 import static org.junit.jupiter.api.Assertions.*;
31
32 @LoggerContextSource("GelfLayout2Test.xml")
33 public class GelfLayout2Test {
34
35 @Test
36 public void gelfLayout(final LoggerContext context, @Named final ListAppender list) throws IOException {
37 list.clear();
38 final Logger logger = context.getLogger(getClass());
39 logger.info("Message");
40 final String gelf = list.getMessages().get(0);
41 final ObjectMapper mapper = new ObjectMapper();
42 final JsonNode json = mapper.readTree(gelf);
43 assertEquals("Message", json.get("short_message").asText());
44 assertEquals("myhost", json.get("host").asText());
45 assertEquals("FOO", json.get("_foo").asText());
46 assertEquals(new JavaLookup().getRuntime(), json.get("_runtime").asText());
47 }
48
49 }
50
+0
-100
log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayout3Test.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.logging.log4j.core.layout;
17
18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.ThreadContext;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.Named;
25 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
26 import org.apache.logging.log4j.message.StringMapMessage;
27 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.jupiter.api.Tag;
29 import org.junit.jupiter.api.Test;
30
31 import java.io.IOException;
32
33 import static org.junit.jupiter.api.Assertions.*;
34
35 @LoggerContextSource("GelfLayout3Test.xml")
36 @UsingAnyThreadContext
37 @Tag("json")
38 public class GelfLayout3Test {
39
40 @Test
41 public void gelfLayout(final LoggerContext context, @Named final ListAppender list) throws IOException {
42 list.clear();
43 final Logger logger = context.getLogger(getClass());
44 ThreadContext.put("loginId", "rgoers");
45 ThreadContext.put("internalId", "12345");
46 logger.info("My Test Message");
47 final String gelf = list.getMessages().get(0);
48 final ObjectMapper mapper = new ObjectMapper();
49 final JsonNode json = mapper.readTree(gelf);
50 assertEquals("My Test Message", json.get("short_message").asText());
51 assertEquals("myhost", json.get("host").asText());
52 assertNotNull(json.get("_mdc.loginId"));
53 assertEquals("rgoers", json.get("_mdc.loginId").asText());
54 assertNull(json.get("_mdc.internalId"));
55 assertNull(json.get("_mdc.requestId"));
56 String message = json.get("full_message").asText();
57 assertTrue(message.contains("loginId=rgoers"));
58 assertTrue(message.contains("GelfLayout3Test"));
59 assertNull(json.get("_map.arg1"));
60 assertNull(json.get("_map.arg2"));
61 assertNull(json.get("_empty"));
62 assertEquals("FOO", json.get("_foo").asText());
63 }
64
65 @Test
66 public void mapMessage(final LoggerContext context, @Named final ListAppender list) throws IOException {
67 list.clear();
68 final Logger logger = context.getLogger(getClass());
69 ThreadContext.put("loginId", "rgoers");
70 ThreadContext.put("internalId", "12345");
71 StringMapMessage message = new StringMapMessage();
72 message.put("arg1", "test1");
73 message.put("arg2", "");
74 message.put("arg3", "test3");
75 message.put("message", "My Test Message");
76 logger.info(message);
77 final String gelf = list.getMessages().get(0);
78 final ObjectMapper mapper = new ObjectMapper();
79 final JsonNode json = mapper.readTree(gelf);
80 assertEquals("arg1=\"test1\" arg2=\"\" arg3=\"test3\" message=\"My Test Message\"",
81 json.get("short_message").asText());
82 assertEquals("myhost", json.get("host").asText());
83 assertNotNull(json.get("_mdc.loginId"));
84 assertEquals("rgoers", json.get("_mdc.loginId").asText());
85 assertNull(json.get("_mdc.internalId"));
86 assertNull(json.get("_mdc.requestId"));
87 String msg = json.get("full_message").asText();
88 assertTrue(msg.contains("loginId=rgoers"));
89 assertTrue(msg.contains("GelfLayout3Test"));
90 assertTrue(msg.contains("arg1=\"test1\""));
91 assertNull(json.get("_map.arg2"));
92 assertEquals("test1", json.get("_map.arg1").asText());
93 assertEquals("test3", json.get("_map.arg3").asText());
94 assertNull(json.get("_empty"));
95 assertEquals("FOO", json.get("_foo").asText());
96 }
97
98 }
99
+0
-82
log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutPatternSelectorTest.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.logging.log4j.core.layout;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.ThreadContext;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.Named;
25 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
26 import org.apache.logging.log4j.spi.AbstractLogger;
27 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.jupiter.api.Tag;
29 import org.junit.jupiter.api.Test;
30
31 import com.fasterxml.jackson.databind.JsonNode;
32 import com.fasterxml.jackson.databind.ObjectMapper;
33
34 import static org.junit.jupiter.api.Assertions.assertEquals;
35 import static org.junit.jupiter.api.Assertions.assertFalse;
36 import static org.junit.jupiter.api.Assertions.assertNotNull;
37 import static org.junit.jupiter.api.Assertions.assertNull;
38 import static org.junit.jupiter.api.Assertions.assertTrue;
39
40 @LoggerContextSource("GelfLayoutPatternSelectorTest.xml")
41 @UsingAnyThreadContext
42 @Tag("json")
43 public class GelfLayoutPatternSelectorTest {
44
45 @Test
46 public void gelfLayout(final LoggerContext context, @Named final ListAppender list) throws IOException {
47 list.clear();
48 final Logger logger = context.getLogger(getClass());
49 ThreadContext.put("loginId", "rgoers");
50 ThreadContext.put("internalId", "12345");
51 logger.info("My Test Message");
52 logger.info(AbstractLogger.FLOW_MARKER, "My Test Message");
53 String gelf = list.getMessages().get(0);
54 final ObjectMapper mapper = new ObjectMapper();
55 JsonNode json = mapper.readTree(gelf);
56 assertEquals("My Test Message", json.get("short_message").asText());
57 assertEquals("myhost", json.get("host").asText());
58 assertNotNull(json.get("_loginId"));
59 assertEquals("rgoers", json.get("_loginId").asText());
60 assertNull(json.get("_internalId"));
61 assertNull(json.get("_requestId"));
62 String message = json.get("full_message").asText();
63 assertFalse(message.contains("====="));
64 assertTrue(message.contains("loginId=rgoers"));
65 assertTrue(message.contains("GelfLayoutPatternSelectorTest"));
66 gelf = list.getMessages().get(1);
67 json = mapper.readTree(gelf);
68 assertEquals("My Test Message", json.get("short_message").asText());
69 assertEquals("myhost", json.get("host").asText());
70 assertNotNull(json.get("_loginId"));
71 assertEquals("rgoers", json.get("_loginId").asText());
72 assertNull(json.get("_internalId"));
73 assertNull(json.get("_requestId"));
74 message = json.get("full_message").asText();
75 assertTrue(message.contains("====="));
76 assertTrue(message.contains("loginId=rgoers"));
77 assertTrue(message.contains("GelfLayoutPatternSelectorTest"));
78 }
79
80 }
81
1919 import org.apache.commons.io.IOUtils;
2020 import org.apache.logging.log4j.Level;
2121 import org.apache.logging.log4j.ThreadContext;
22 import org.apache.logging.log4j.core.Appender;
23 import org.apache.logging.log4j.core.BasicConfigurationFactory;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.Logger;
26 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.*;
2723 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2824 import org.apache.logging.log4j.core.layout.GelfLayout.CompressionType;
2925 import org.apache.logging.log4j.core.lookup.JavaLookup;
3026 import org.apache.logging.log4j.core.util.KeyValuePair;
3127 import org.apache.logging.log4j.core.util.NetUtils;
32 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
28 import org.apache.logging.log4j.junit.ThreadContextRule;
3329 import org.apache.logging.log4j.test.appender.EncodingListAppender;
3430 import org.apache.logging.log4j.test.appender.ListAppender;
35 import org.junit.jupiter.api.AfterAll;
36 import org.junit.jupiter.api.BeforeAll;
37 import org.junit.jupiter.api.Test;
31 import org.junit.AfterClass;
32 import org.junit.BeforeClass;
33 import org.junit.Rule;
34 import org.junit.Test;
3835
3936 import java.io.ByteArrayInputStream;
4037 import java.io.IOException;
4441 import java.util.zip.InflaterInputStream;
4542
4643 import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
47 import static org.junit.jupiter.api.Assertions.*;
48
49 @UsingAnyThreadContext
44 import static org.junit.Assert.assertEquals;
45
5046 public class GelfLayoutTest {
5147
5248 static ConfigurationFactory configFactory = new BasicConfigurationFactory();
6359 private static final String MDCVALUE2 = "MdcValue2";
6460 private static final String VALUE1 = "Value1";
6561
66 @AfterAll
62 @Rule
63 public final ThreadContextRule threadContextRule = new ThreadContextRule();
64
65 @AfterClass
6766 public static void cleanupClass() {
6867 ConfigurationFactory.removeConfigurationFactory(configFactory);
6968 }
7069
71 @BeforeAll
70 @BeforeClass
7271 public static void setupClass() {
7372 ConfigurationFactory.setConfigurationFactory(configFactory);
7473 final LoggerContext ctx = LoggerContext.getContext();
8079 Logger root = ctx.getRootLogger();
8180
8281 private void testCompressedLayout(final CompressionType compressionType, final boolean includeStacktrace,
83 final boolean includeThreadContext, String host, final boolean includeNullDelimiter,
84 final boolean includeNewLineDelimiter) throws IOException {
82 final boolean includeThreadContext, String host, final boolean includeNullDelimiter) throws IOException {
8583 for (final Appender appender : root.getAppenders().values()) {
8684 root.removeAppender(appender);
8785 }
8886 // set up appenders
8987 final GelfLayout layout = GelfLayout.newBuilder()
90 .setConfiguration(ctx.getConfiguration())
91 .setHost(host)
92 .setAdditionalFields(new KeyValuePair[]{
93 new KeyValuePair(KEY1, VALUE1),
94 new KeyValuePair(KEY2, "${java:runtime}"),})
95 .setCompressionType(compressionType)
96 .setCompressionThreshold(1024)
97 .setIncludeStacktrace(includeStacktrace)
98 .setIncludeThreadContext(includeThreadContext)
99 .setIncludeNullDelimiter(includeNullDelimiter)
100 .setIncludeNewLineDelimiter(includeNewLineDelimiter)
101 .build();
88 .setConfiguration(ctx.getConfiguration())
89 .setHost(host)
90 .setAdditionalFields(new KeyValuePair[] {
91 new KeyValuePair(KEY1, VALUE1),
92 new KeyValuePair(KEY2, "${java:runtime}"), })
93 .setCompressionType(compressionType)
94 .setCompressionThreshold(1024)
95 .setIncludeStacktrace(includeStacktrace)
96 .setIncludeThreadContext(includeThreadContext)
97 .setIncludeNullDelimiter(includeNullDelimiter)
98 .build();
10299 final ListAppender eventAppender = new ListAppender("Events", null, null, true, false);
103100 final ListAppender rawAppender = new ListAppender("Raw", null, layout, true, true);
104101 final ListAppender formattedAppender = new ListAppender("Formatted", null, layout, true, false);
161158 "\"_thread\": \"" + threadName + "\"," +
162159 "\"_logger\": \"\"," +
163160 "\"short_message\": \"" + LINE2 + "\"," +
164 (includeThreadContext ?
165 "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
166 "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\","
167 :
168 "") +
161 (includeThreadContext ?
162 "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
163 "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\","
164 :
165 "") +
169166 "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
170167 "\"_" + KEY2 + "\": \"" + javaLookup.getRuntime() + "\"" +
171168 "}",
178175 InputStream inflaterStream;
179176 InputStream inflaterStream2;
180177 switch (compressionType) {
181 case GZIP:
182 inflaterStream = new GZIPInputStream(bais);
183 inflaterStream2 = new GZIPInputStream(bais2);
184 break;
185 case ZLIB:
186 inflaterStream = new InflaterInputStream(bais);
187 inflaterStream2 = new InflaterInputStream(bais2);
188 break;
189 case OFF:
190 inflaterStream = bais;
191 inflaterStream2 = bais2;
192 break;
193 default:
194 throw new IllegalStateException("Missing test case clause");
178 case GZIP:
179 inflaterStream = new GZIPInputStream(bais);
180 inflaterStream2 = new GZIPInputStream(bais2);
181 break;
182 case ZLIB:
183 inflaterStream = new InflaterInputStream(bais);
184 inflaterStream2 = new InflaterInputStream(bais2);
185 break;
186 case OFF:
187 inflaterStream = bais;
188 inflaterStream2 = bais2;
189 break;
190 default:
191 throw new IllegalStateException("Missing test case clause");
195192 }
196193 final byte[] uncompressed = IOUtils.toByteArray(inflaterStream);
197194 final byte[] uncompressed2 = IOUtils.toByteArray(inflaterStream2);
211208 "\"full_message\": \"" + String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
212209 includeStacktrace ? GelfLayout.formatThrowable(exception).toString() : exception.toString())) + "\"," +
213210 (includeThreadContext ?
214 "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
215 "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\","
216 : "") +
211 "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
212 "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\","
213 : "") +
217214 "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
218215 "\"_" + KEY2 + "\": \"" + javaLookup.getRuntime() + "\"" +
219216 "}";
220217 //@formatter:on
221218 assertJsonEquals(expected, uncompressedString);
222219 assertJsonEquals(expected, uncompressedString2);
223 if (includeNullDelimiter) {
224 assertEquals(uncompressedString.indexOf('\0'), uncompressedString.length() - 1);
225 assertEquals(uncompressedString2.indexOf('\0'), uncompressedString2.length() - 1);
226 }
227 if (includeNewLineDelimiter) {
228 assertEquals(uncompressedString.indexOf('\n'), uncompressedString.length() - 1);
229 assertEquals(uncompressedString2.indexOf('\n'), uncompressedString2.length() - 1);
230 }
231220 }
232221
233222 @Test
234223 public void testLayoutGzipCompression() throws Exception {
235 testCompressedLayout(CompressionType.GZIP, true, true, HOSTNAME, false, false);
224 testCompressedLayout(CompressionType.GZIP, true, true, HOSTNAME, false);
236225 }
237226
238227 @Test
239228 public void testLayoutNoCompression() throws Exception {
240 testCompressedLayout(CompressionType.OFF, true, true, HOSTNAME, false, false);
229 testCompressedLayout(CompressionType.OFF, true, true, HOSTNAME, false);
241230 }
242231
243232 @Test
244233 public void testLayoutZlibCompression() throws Exception {
245 testCompressedLayout(CompressionType.ZLIB, true, true, HOSTNAME, false, false);
234 testCompressedLayout(CompressionType.ZLIB, true, true, HOSTNAME, false);
246235 }
247236
248237 @Test
249238 public void testLayoutNoStacktrace() throws Exception {
250 testCompressedLayout(CompressionType.OFF, false, true, HOSTNAME, false, false);
239 testCompressedLayout(CompressionType.OFF, false, true, HOSTNAME, false);
251240 }
252241
253242 @Test
254243 public void testLayoutNoThreadContext() throws Exception {
255 testCompressedLayout(CompressionType.OFF, true, false, HOSTNAME, false, false);
244 testCompressedLayout(CompressionType.OFF, true, false, HOSTNAME, false);
256245 }
257246
258247 @Test
259248 public void testLayoutNoHost() throws Exception {
260 testCompressedLayout(CompressionType.OFF, true, true, null, false, false);
249 testCompressedLayout(CompressionType.OFF, true, true, null, false);
261250 }
262251
263252 @Test
264253 public void testLayoutNullDelimiter() throws Exception {
265 testCompressedLayout(CompressionType.OFF, false, true, HOSTNAME, true, false);
266 }
267
268 @Test
269 public void testLayoutNewLineDelimiter() throws Exception {
270 testCompressedLayout(CompressionType.OFF, true, true, HOSTNAME, false, true);
254 testCompressedLayout(CompressionType.OFF, false, true, HOSTNAME, true);
271255 }
272256
273257 @Test
280264 assertEquals("1458741206.653", GelfLayout.formatTimestamp(1458741206653L).toString());
281265 assertEquals("9223372036854775.807", GelfLayout.formatTimestamp(Long.MAX_VALUE).toString());
282266 }
283
284 private void testRequiresLocation(String messagePattern, Boolean requiresLocation) {
285
286 GelfLayout layout = GelfLayout.newBuilder()
287 .setMessagePattern(messagePattern)
288 .build();
289
290 assertEquals(layout.requiresLocation(), requiresLocation);
291 }
292
293 @Test
294 public void testRequiresLocationPatternNotSet() {
295 testRequiresLocation(null, false);
296 }
297
298 @Test
299 public void testRequiresLocationPatternNotContainsLocation() {
300 testRequiresLocation("%m %n", false);
301 }
302
303 @Test
304 public void testRequiresLocationPatternContainsLocation() {
305 testRequiresLocation("%C %m %t", true);
306 }
307267 }
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.layout;
17
18 import java.io.IOException;
19
20 import com.fasterxml.jackson.databind.JsonNode;
21 import com.fasterxml.jackson.databind.ObjectMapper;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.core.lookup.JavaLookup;
24 import org.apache.logging.log4j.junit.LoggerContextRule;
25 import org.junit.ClassRule;
26 import org.junit.Test;
27
28 import static org.junit.Assert.assertEquals;
29
30 public class GelfLayoutTest2 {
31
32 @ClassRule
33 public static LoggerContextRule context = new LoggerContextRule("GelfLayoutTest2.xml");
34
35 @Test
36 public void gelfLayout() throws IOException {
37 final Logger logger = context.getLogger();
38 logger.info("Message");
39 final String gelf = context.getListAppender("list").getMessages().get(0);
40 final ObjectMapper mapper = new ObjectMapper();
41 final JsonNode json = mapper.readTree(gelf);
42 assertEquals("Message", json.get("short_message").asText());
43 assertEquals("myhost", json.get("host").asText());
44 assertEquals("FOO", json.get("_foo").asText());
45 assertEquals(new JavaLookup().getRuntime(), json.get("_runtime").asText());
46 }
47
48 }
49
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import java.lang.management.ManagementFactory;
1918 import java.nio.charset.StandardCharsets;
20 import java.text.MessageFormat;
21 import java.time.ZoneId;
22 import java.time.ZonedDateTime;
23 import java.time.format.DateTimeFormatter;
24 import java.util.Calendar;
2519 import java.util.List;
2620 import java.util.Map;
2721
2822 import org.apache.logging.log4j.Level;
2923 import org.apache.logging.log4j.ThreadContext;
30 import org.apache.logging.log4j.core.AbstractLogEvent;
3124 import org.apache.logging.log4j.core.Appender;
3225 import org.apache.logging.log4j.core.BasicConfigurationFactory;
33 import org.apache.logging.log4j.core.LogEvent;
3426 import org.apache.logging.log4j.core.Logger;
3527 import org.apache.logging.log4j.core.LoggerContext;
3628 import org.apache.logging.log4j.core.config.ConfigurationFactory;
37 import org.apache.logging.log4j.core.time.Instant;
38 import org.apache.logging.log4j.core.time.MutableInstant;
39 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
40 import org.apache.logging.log4j.message.Message;
41 import org.apache.logging.log4j.message.SimpleMessage;
29 import org.apache.logging.log4j.junit.ThreadContextRule;
4230 import org.apache.logging.log4j.test.appender.ListAppender;
43 import org.junit.jupiter.api.AfterAll;
44 import org.junit.jupiter.api.BeforeAll;
45 import org.junit.jupiter.api.Test;
31 import org.junit.AfterClass;
32 import org.junit.BeforeClass;
33 import org.junit.Rule;
34 import org.junit.Test;
4635
47 import static org.junit.jupiter.api.Assertions.*;
48 import static org.apache.logging.log4j.core.util.datetime.FixedDateFormat.FixedFormat;
36 import static org.junit.Assert.*;
4937
50 @UsingAnyThreadContext
38 /**
39 *
40 */
5141 public class HtmlLayoutTest {
52 private static class MyLogEvent extends AbstractLogEvent {
53 private static final long serialVersionUID = 0;
54
55 @Override
56 public Instant getInstant() {
57 MutableInstant result = new MutableInstant();
58 result.initFromEpochMilli(getTimeMillis(), 456789);
59 return result;
60 }
61
62 @Override
63 public long getTimeMillis() {
64 final Calendar cal = Calendar.getInstance();
65 cal.set(2012, Calendar.NOVEMBER, 02, 14, 34, 02);
66 cal.set(Calendar.MILLISECOND, 123);
67 return cal.getTimeInMillis();
68 }
69
70 @Override
71 public Level getLevel() {
72 return Level.DEBUG;
73 }
74
75 @Override
76 public Message getMessage() {
77 return new SimpleMessage("msg");
78 }
79 }
80
81 private final LoggerContext ctx = LoggerContext.getContext();
82 private final Logger root = ctx.getRootLogger();
42 LoggerContext ctx = LoggerContext.getContext();
43 Logger root = ctx.getRootLogger();
8344
8445 static ConfigurationFactory cf = new BasicConfigurationFactory();
8546
86 @BeforeAll
47 @Rule
48 public final ThreadContextRule threadContextRule = new ThreadContextRule();
49
50 @BeforeClass
8751 public static void setupClass() {
8852 ConfigurationFactory.setConfigurationFactory(cf);
8953 final LoggerContext ctx = LoggerContext.getContext();
9054 ctx.reconfigure();
9155 }
9256
93 @AfterAll
57 @AfterClass
9458 public static void cleanupClass() {
9559 ConfigurationFactory.removeConfigurationFactory(cf);
9660 }
175139 sb.append(string);
176140 }
177141 final String html = sb.toString();
178 assertTrue(list.size() > 85, "Incorrect number of lines. Require at least 85 " + list.size());
142 assertTrue("Incorrect number of lines. Require at least 85 " + list.size(), list.size() > 85);
179143 final String string = list.get(3);
180 assertEquals("<meta charset=\"UTF-8\"/>", string, "Incorrect header: " + string);
181 assertEquals("<title>Log4j Log Messages</title>", list.get(4), "Incorrect title");
182 assertEquals("</body></html>", list.get(list.size() - 1), "Incorrect footer");
144 assertTrue("Incorrect header: " + string, string.equals("<meta charset=\"UTF-8\"/>"));
145 assertTrue("Incorrect title", list.get(4).equals("<title>Log4j Log Messages</title>"));
146 assertTrue("Incorrect footer", list.get(list.size() - 1).equals("</body></html>"));
183147 if (includeLocation) {
184 assertEquals(list.get(50), multiLine, "Incorrect multiline");
185 assertTrue(html.contains("HtmlLayoutTest.java:"), "Missing location");
186 assertEquals(list.get(71), body, "Incorrect body");
148 assertTrue("Incorrect multiline", list.get(50).equals(multiLine));
149 assertTrue("Missing location", html.contains("HtmlLayoutTest.java:"));
150 assertTrue("Incorrect body", list.get(71).equals(body));
187151 } else {
188 assertFalse(html.contains("<td>HtmlLayoutTest.java:"), "Location should not be in the output table");
152 assertFalse("Location should not be in the output table", html.contains("<td>HtmlLayoutTest.java:"));
189153 }
190154 for (final Appender app : appenders.values()) {
191155 root.addAppender(app);
192156 }
193157 }
194
195 @Test
196 public void testLayoutWithoutDataPattern() {
197 final HtmlLayout layout = HtmlLayout.newBuilder().build();
198
199 MyLogEvent event = new MyLogEvent();
200 String actual = getDateLine(layout.toSerializable(event));
201
202 long jvmStratTime = ManagementFactory.getRuntimeMXBean().getStartTime();
203 assertEquals("<td>" + (event.getTimeMillis() - jvmStratTime) + "</td>", actual, "Incorrect date:" + actual);
204 }
205
206 @Test
207 public void testLayoutWithDatePatternJvmElapseTime() {
208 final HtmlLayout layout = HtmlLayout.newBuilder().setDatePattern("JVM_ELAPSE_TIME").build();
209
210 MyLogEvent event = new MyLogEvent();
211 String actual = getDateLine(layout.toSerializable(event));
212
213 long jvmStratTime = ManagementFactory.getRuntimeMXBean().getStartTime();
214 assertEquals("<td>" + (event.getTimeMillis() - jvmStratTime) + "</td>", actual, "Incorrect date:" + actual);
215 }
216
217 @Test
218 public void testLayoutWithDatePatternUnix() {
219 final HtmlLayout layout = HtmlLayout.newBuilder().setDatePattern("UNIX").build();
220
221 MyLogEvent event = new MyLogEvent();
222 String actual = getDateLine(layout.toSerializable(event));
223
224 assertEquals("<td>" + event.getInstant().getEpochSecond() + "</td>", actual, "Incorrect date:" + actual);
225 }
226
227 @Test
228 public void testLayoutWithDatePatternUnixMillis() {
229 final HtmlLayout layout = HtmlLayout.newBuilder().setDatePattern("UNIX_MILLIS").build();
230
231 MyLogEvent event = new MyLogEvent();
232 String actual = getDateLine(layout.toSerializable(event));
233
234 assertEquals("<td>" + event.getTimeMillis() + "</td>", actual, "Incorrect date:" + actual);
235 }
236
237 @Test
238 public void testLayoutWithDatePatternFixedFormat() {
239 for (final String timeZone : new String[] {"GMT+8", "UTC", null}) {
240 for (final FixedFormat format : FixedFormat.values()) {
241 testLayoutWithDatePatternFixedFormat(format, timeZone);
242 }
243 }
244 }
245
246 private String getDateLine(String logEventString) {
247 return logEventString.split(System.lineSeparator())[2];
248 }
249
250 private void testLayoutWithDatePatternFixedFormat(FixedFormat format, String timezone) {
251 final HtmlLayout layout = HtmlLayout.newBuilder().setDatePattern(format.name()).setTimezone(timezone).build();
252
253 LogEvent event = new MyLogEvent();
254 String actual = getDateLine(layout.toSerializable(event));
255
256 // build expected date string
257 java.time.Instant instant =
258 java.time.Instant.ofEpochSecond(event.getInstant().getEpochSecond(), event.getInstant().getNanoOfSecond());
259 ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
260 if (timezone != null) {
261 zonedDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of(timezone));
262 }
263
264 // For DateTimeFormatter of jdk,
265 // Pattern letter 'S' means fraction-of-second, 'n' means nano-of-second. Log4j2 needs S.
266 // Pattern letter 'X' (upper case) will output 'Z' when the offset to be output would be zero,
267 // whereas pattern letter 'x' (lower case) will output '+00', '+0000', or '+00:00'. Log4j2 needs x.
268 DateTimeFormatter dateTimeFormatter =
269 DateTimeFormatter.ofPattern(format.getPattern().replace('n', 'S').replace('X', 'x'));
270 String expected = zonedDateTime.format(dateTimeFormatter);
271
272 assertEquals("<td>" + expected + "</td>", actual,
273 MessageFormat.format("Incorrect date={0}, format={1}, timezone={2}", actual, format.name(), timezone));
274 }
275158 }
+0
-74
log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutMillisTest.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.logging.log4j.core.layout;
17
18 import org.apache.logging.log4j.categories.Layouts;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.Logger;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.Before;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.experimental.categories.Category;
27
28 import java.util.List;
29
30 import static org.junit.Assert.assertEquals;
31 import static org.junit.Assert.assertFalse;
32 import static org.junit.Assert.assertNotNull;
33 import static org.junit.Assert.assertTrue;
34
35 /**
36 * Tests the JsonLayout class with millis.
37 */
38 @Category(Layouts.Json.class)
39 public class JsonLayoutMillisTest {
40
41 private static final String CONFIG = "log4j2-json-layout-timestamp.xml";
42
43 private ListAppender app;
44
45 @Rule
46 public LoggerContextRule context = new LoggerContextRule(CONFIG);
47
48 private Logger logger;
49
50 private void assertEventCount(final List<LogEvent> events, final int expected) {
51 assertEquals("Incorrect number of events.", expected, events.size());
52 }
53
54 @Before
55 public void before() {
56 logger = context.getLogger("LayoutTest");
57 //
58 app = context.getListAppender("List").clear();
59 }
60
61 @Test
62 public void testTimestamp() {
63 logger.info("This is a test message");
64 List<String> message = app.getMessages();
65 assertTrue("No messages", message != null && message.size() > 0);
66 String json = message.get(0);
67 System.out.println(json);
68 assertNotNull("No JSON message", json);
69 assertTrue("No timestamp", json.contains("\"timeMillis\":"));
70 assertFalse("Instant is present", json.contains("instant:"));
71 }
72
73 }
545545 }
546546
547547 @Test
548 public void testInstantSortsBeforeMessage() {
549 final String str = prepareJSONForEventWithTimeAsInstant();
550 assertTrue(str, str.startsWith("{\"instant\":{\"epochSecond\":0,\"nanoOfSecond\":1000000},"));
551 assertTrue(str, str.contains("\"message\":\"message\""));
552 }
553
554 private String prepareJSONForEventWithTimeAsInstant() {
555 final TestClass testClass = new TestClass();
556 // @formatter:off
557 final Log4jLogEvent expected = Log4jLogEvent.newBuilder()
558 .setLoggerName("a.B")
559 .setLoggerFqcn("f.q.c.n")
560 .setLevel(Level.DEBUG)
561 .setMessage(new SimpleMessage("message"))
562 .setThreadName("threadName")
563 .setTimeMillis(1)
564 .build();
565 // @formatter:off
566 final AbstractJacksonLayout layout = JsonLayout.newBuilder()
567 .setCompact(true)
568 .build();
569 // @formatter:off
570 return layout.toSerializable(expected);
571 }
572
573 @Test
574548 public void testIncludeNullDelimiterTrue() throws Exception {
575549 final AbstractJacksonLayout layout = JsonLayout.newBuilder()
576550 .setCompact(true)
588562 .build();
589563 final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
590564 assertFalse(str.endsWith("\0"));
591 }
592
593 @Test // LOG4J2-2749
594 public void testEmptyValuesAreIgnored() {
595 final AbstractJacksonLayout layout = JsonLayout.newBuilder()
596 .setAdditionalFields(new KeyValuePair[] {
597 new KeyValuePair("empty", "${ctx:empty:-}")
598 })
599 .setConfiguration(ctx.getConfiguration())
600 .build();
601
602 final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
603 assertFalse(str, str.contains("\"empty\""));
604565 }
605566
606567 private String toPropertySeparator(final boolean compact) {
1919 import java.io.Serializable;
2020 import java.util.List;
2121
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
2224 import org.apache.logging.log4j.core.Layout;
23 import org.apache.logging.log4j.core.LoggerContext;
2425 import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
25 import org.apache.logging.log4j.junit.LoggerContextSource;
26 import org.apache.logging.log4j.junit.Named;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
2727 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.jupiter.api.Test;
28 import org.junit.Assert;
29 import org.junit.ClassRule;
30 import org.junit.Test;
2931
30 import static org.junit.jupiter.api.Assertions.*;
31
32 @LoggerContextSource("LOG4J-2195/log4j2.xml")
3332 public class Log4j2_2195_Test {
3433
34 @ClassRule
35 public static final LoggerContextRule loggerContextRule = new LoggerContextRule(
36 "src/test/resources/LOG4J-2195/log4j2.xml");
37
38 private static final Logger logger = LogManager.getLogger(Log4j2_2195_Test.class);
39
3540 @Test
36 public void test(final LoggerContext context, @Named("ListAppender") final ListAppender listAppender) {
37 listAppender.clear();
38 context.getLogger(getClass()).info("This is a test.", new Exception("Test exception!"));
39 assertNotNull(listAppender);
40 List<String> events = listAppender.getMessages();
41 assertNotNull(events);
42 assertEquals(1, events.size());
43 String logEvent = events.get(0);
44 assertNotNull(logEvent);
45 assertFalse(logEvent.contains("org.junit"), "\"org.junit\" should not be here");
46 assertFalse(logEvent.contains("org.eclipse"), "\"org.eclipse\" should not be here");
41 public void test() {
42 logger.info("This is a test.", new Exception("Test exception!"));
43 final ListAppender listAppender = loggerContextRule.getListAppender("ListAppender");
44 Assert.assertNotNull(listAppender);
45 final List<String> events = listAppender.getMessages();
46 Assert.assertNotNull(events);
47 Assert.assertEquals(1, events.size());
48 final String logEvent = events.get(0);
49 Assert.assertNotNull(logEvent);
50 Assert.assertFalse("\"org.junit\" should not be here", logEvent.contains("org.junit"));
51 Assert.assertFalse("\"org.eclipse\" should not be here", logEvent.contains("org.eclipse"));
4752 //
48 Layout<? extends Serializable> layout = listAppender.getLayout();
49 PatternLayout pLayout = (PatternLayout) layout;
50 assertNotNull(pLayout);
51 Serializer eventSerializer = pLayout.getEventSerializer();
52 assertNotNull(eventSerializer);
53 final Layout<? extends Serializable> layout = listAppender.getLayout();
54 final PatternLayout pLayout = (PatternLayout) layout;
55 Assert.assertNotNull(pLayout);
56 final Serializer eventSerializer = pLayout.getEventSerializer();
57 Assert.assertNotNull(eventSerializer);
5358 //
54 assertTrue(logEvent.contains("|"), "Missing \"|\"");
59 Assert.assertTrue("Missing \"|\"", logEvent.contains("|"));
5560 }
5661 }
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.junit.LoggerContextSource;
20 import org.apache.logging.log4j.junit.Named;
18 import org.apache.logging.log4j.junit.LoggerContextRule;
2119 import org.apache.logging.log4j.test.appender.ListAppender;
22 import org.junit.jupiter.api.Test;
23
24 import static org.junit.jupiter.api.Assertions.assertTrue;
20 import org.junit.Assert;
21 import org.junit.Rule;
22 import org.junit.Test;
2523
2624 /**
2725 * See (LOG4J2-905) Ability to disable (date) lookup completely, compatibility issues with other libraries like camel.
2826 *
2927 * This shows the behavior this user wants to disable.
3028 */
31 @LoggerContextSource("log4j-list-lookups.xml")
3229 public class PatternLayoutLookupDateTest {
3330
31 @Rule
32 public final LoggerContextRule context = new LoggerContextRule("log4j-list.xml");
33
3434 @Test
35 public void testDateLookupInMessage(final LoggerContext context, @Named("List") final ListAppender listAppender) {
36 listAppender.clear();
35 public void testDateLookupInMessage() {
3736 final String template = "${date:YYYY-MM-dd}";
3837 context.getLogger(PatternLayoutLookupDateTest.class.getName()).info(template);
38 final ListAppender listAppender = context.getListAppender("List");
3939 final String string = listAppender.getMessages().get(0);
40 assertTrue(string.contains(template), string);
40 Assert.assertTrue(string, string.contains(template));
4141 }
4242
4343 }
1616
1717 package org.apache.logging.log4j.core.layout;
1818
19 import java.util.List;
20
1921 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
2122 import org.apache.logging.log4j.core.appender.FileAppender;
2223 import org.apache.logging.log4j.core.lookup.MainMapLookup;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.apache.logging.log4j.junit.Named;
25 import org.apache.logging.log4j.junit.ReconfigurationPolicy;
24 import org.apache.logging.log4j.junit.LoggerContextRule;
2625 import org.apache.logging.log4j.test.appender.ListAppender;
27 import org.junit.jupiter.api.Test;
28
29 import java.util.List;
30
31 import static org.junit.jupiter.api.Assertions.assertEquals;
32 import static org.junit.jupiter.api.Assertions.assertFalse;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
3329
3430 /**
3531 * Tests LOG4j2-962.
3632 */
37 @LoggerContextSource(value = "log4j2-962.xml", reconfigure = ReconfigurationPolicy.BEFORE_EACH)
3833 public class PatternLayoutMainMapLookupTest {
3934
4035 static {
4237 MainMapLookup.setMainArguments("value0", "value1", "value2");
4338 }
4439
40 @ClassRule
41 public static LoggerContextRule context = new LoggerContextRule("log4j2-962.xml");
42
4543 @Test
46 public void testFileName(@Named("File") final FileAppender fileApp) {
44 public void testFileName() {
45 final FileAppender fileApp = (FileAppender) context.getRequiredAppender("File");
4746 final String name = fileApp.getFileName();
48 assertEquals("target/value0.log", name);
47 Assert.assertEquals("target/value0.log", name);
4948 }
5049
5150 @Test
52 public void testHeader(final LoggerContext context, @Named("List") final ListAppender listApp) {
53 final Logger logger = context.getLogger(getClass());
51 public void testHeader() {
52 final ListAppender listApp = context.getListAppender("List");
53 final Logger logger = context.getLogger(this.getClass().getName());
5454 logger.info("Hello World");
5555 final List<String> initialMessages = listApp.getMessages();
56 assertFalse(initialMessages.isEmpty());
56 Assert.assertFalse(initialMessages.isEmpty());
5757 final String messagesStr = initialMessages.toString();
58 assertEquals("Header: value0", initialMessages.get(0), messagesStr);
58 Assert.assertEquals(messagesStr, "Header: value0", initialMessages.get(0));
5959 listApp.stop();
6060 final List<String> finalMessages = listApp.getMessages();
61 assertEquals(3, finalMessages.size());
62 assertEquals("Footer: value1", finalMessages.get(2));
63 listApp.clear();
61 Assert.assertEquals(3, finalMessages.size());
62 Assert.assertEquals("Footer: value1", finalMessages.get(2));
6463 }
6564
6665 }
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.junit.LoggerContextSource;
20 import org.apache.logging.log4j.junit.Named;
18 import org.apache.logging.log4j.junit.LoggerContextRule;
2119 import org.apache.logging.log4j.test.appender.ListAppender;
22 import org.junit.jupiter.api.Assertions;
23 import org.junit.jupiter.api.Test;
20 import org.junit.Assert;
21 import org.junit.Rule;
22 import org.junit.Test;
2423
2524 /**
2625 * See (LOG4J2-905) Ability to disable (date) lookup completely, compatibility issues with other libraries like camel.
2726 */
28 @LoggerContextSource("log4j-list.xml")
2927 public class PatternLayoutNoLookupDateTest {
3028
29 @Rule
30 public final LoggerContextRule context = new LoggerContextRule("log4j-list-nolookups.xml");
31
3132 @Test
32 public void testDateLookupInMessage(final LoggerContext context, @Named("List") final ListAppender listAppender) {
33 listAppender.clear();
33 public void testDateLookupInMessage() {
3434 final String template = "${date:YYYY-MM-dd}";
35 context.getLogger(PatternLayoutNoLookupDateTest.class).info(template);
35 context.getLogger(PatternLayoutNoLookupDateTest.class.getName()).info(template);
36 final ListAppender listAppender = context.getListAppender("List");
3637 final String string = listAppender.getMessages().get(0);
37 Assertions.assertTrue(string.contains(template), string);
38 Assert.assertTrue(string, string.contains(template));
3839 }
3940
4041 }
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22
1823 import java.nio.ByteBuffer;
1924 import java.nio.charset.Charset;
2025 import java.nio.charset.StandardCharsets;
3035 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3136 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3237 import org.apache.logging.log4j.core.lookup.MainMapLookup;
33 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
38 import org.apache.logging.log4j.junit.ThreadContextRule;
3439 import org.apache.logging.log4j.message.SimpleMessage;
3540 import org.apache.logging.log4j.util.Strings;
36 import org.junit.jupiter.api.BeforeAll;
37 import org.junit.jupiter.api.Test;
38
39 import static org.junit.jupiter.api.Assertions.*;
40
41 @UsingAnyThreadContext
41 import org.junit.BeforeClass;
42 import org.junit.Rule;
43 import org.junit.Test;
44
45 /**
46 *
47 */
4248 public class PatternLayoutTest {
43 public static class FauxLogger {
49 public class FauxLogger {
4450 public String formatEvent(final LogEvent event, final Layout<?> layout) {
4551 return new String(layout.toByteArray(event));
4652 }
5662 ConfigurationFactory.removeConfigurationFactory(cf);
5763 }
5864
59 @BeforeAll
65 @BeforeClass
6066 public static void setupClass() {
6167 ConfigurationFactory.setConfigurationFactory(cf);
6268 final LoggerContext ctx = LoggerContext.getContext();
6672 LoggerContext ctx = LoggerContext.getContext();
6773
6874 Logger root = ctx.getRootLogger();
75
76 @Rule
77 public final ThreadContextRule threadContextRule = new ThreadContextRule();
6978
7079 private static class Destination implements ByteBufferDestination {
7180 ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[2048]);
135144 final PatternLayout layout = PatternLayout.newBuilder().withConfiguration(ctx.getConfiguration())
136145 .withHeader("Header: " + pattern).withFooter("Footer: " + pattern).build();
137146 final byte[] header = layout.getHeader();
138 assertNotNull(header, "No header");
147 assertNotNull("No header", header);
139148 final String headerStr = new String(header);
140 assertTrue(headerStr.contains("Header: "), headerStr);
141 assertTrue(headerStr.contains("Java version "), headerStr);
142 assertTrue(headerStr.contains("(build "), headerStr);
143 assertTrue(headerStr.contains(" from "), headerStr);
144 assertTrue(headerStr.contains(" architecture: "), headerStr);
145 assertFalse(headerStr.contains("%d{UNIX}"), headerStr);
149 assertTrue(headerStr, headerStr.contains("Header: "));
150 assertTrue(headerStr, headerStr.contains("Java version "));
151 assertTrue(headerStr, headerStr.contains("(build "));
152 assertTrue(headerStr, headerStr.contains(" from "));
153 assertTrue(headerStr, headerStr.contains(" architecture: "));
154 assertFalse(headerStr, headerStr.contains("%d{UNIX}"));
146155 //
147156 final byte[] footer = layout.getFooter();
148 assertNotNull(footer, "No footer");
157 assertNotNull("No footer", footer);
149158 final String footerStr = new String(footer);
150 assertTrue(footerStr.contains("Footer: "), footerStr);
151 assertTrue(footerStr.contains("Java version "), footerStr);
152 assertTrue(footerStr.contains("(build "), footerStr);
153 assertTrue(footerStr.contains(" from "), footerStr);
154 assertTrue(footerStr.contains(" architecture: "), footerStr);
155 assertFalse(footerStr.contains("%d{UNIX}"), footerStr);
159 assertTrue(footerStr, footerStr.contains("Footer: "));
160 assertTrue(footerStr, footerStr.contains("Java version "));
161 assertTrue(footerStr, footerStr.contains("(build "));
162 assertTrue(footerStr, footerStr.contains(" from "));
163 assertTrue(footerStr, footerStr.contains(" architecture: "));
164 assertFalse(footerStr, footerStr.contains("%d{UNIX}"));
156165 }
157166
158167 /**
164173 final PatternLayout layout = PatternLayout.newBuilder().withConfiguration(ctx.getConfiguration())
165174 .withHeader("${main:0}").withFooter("${main:2}").build();
166175 final byte[] header = layout.getHeader();
167 assertNotNull(header, "No header");
176 assertNotNull("No header", header);
168177 final String headerStr = new String(header);
169 assertTrue(headerStr.contains("value0"), headerStr);
178 assertTrue(headerStr, headerStr.contains("value0"));
170179 //
171180 final byte[] footer = layout.getFooter();
172 assertNotNull(footer, "No footer");
181 assertNotNull("No footer", footer);
173182 final String footerStr = new String(footer);
174 assertTrue(footerStr.contains("value2"), footerStr);
183 assertTrue(footerStr, footerStr.contains("value2"));
175184 }
176185
177186 @Test
182191 ThreadContext.put("header", "Hello world Header");
183192 ThreadContext.put("footer", "Hello world Footer");
184193 final byte[] header = layout.getHeader();
185 assertNotNull(header, "No header");
186 assertEquals("Hello world Header", new String(header),
187 "expected \"Hello world Header\", actual " + Strings.dquote(new String(header)));
194 assertNotNull("No header", header);
195 assertTrue("expected \"Hello world Header\", actual " + Strings.dquote(new String(header)),
196 new String(header).equals(new String("Hello world Header")));
188197 }
189198
190199 private void testMdcPattern(final String patternStr, final String expectedStr, final boolean useThreadContext)
248257 .setMessage(new SimpleMessage("entry")).build();
249258 final String result1 = new FauxLogger().formatEvent(event1, layout);
250259 final String expectPattern1 = String.format(".*====== PatternLayoutTest.testPatternSelector:\\d+ entry ======%n");
251 assertTrue(result1.matches(expectPattern1), "Unexpected result: " + result1);
260 assertTrue("Unexpected result: " + result1, result1.matches(expectPattern1));
252261 final LogEvent event2 = Log4jLogEvent.newBuilder() //
253262 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
254263 .setLevel(Level.INFO) //
255264 .setMessage(new SimpleMessage("Hello, world 1!")).build();
256265 final String result2 = new String(layout.toByteArray(event2));
257266 final String expectSuffix2 = String.format("Hello, world 1!%n");
258 assertTrue(result2.endsWith(expectSuffix2), "Unexpected result: " + result2);
267 assertTrue("Unexpected result: " + result2, result2.endsWith(expectSuffix2));
259268 }
260269
261270 @Test
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import static org.junit.Assert.assertTrue;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.MarkerManager;
2022 import org.apache.logging.log4j.core.Layout;
2224 import org.apache.logging.log4j.core.LoggerContext;
2325 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2426 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
27 import org.junit.Test;
2828
2929 public class PatternSelectorTest {
3030
31 public static class FauxLogger {
31 public class FauxLogger {
3232 public String formatEvent(final LogEvent event, final Layout<?> layout) {
3333 return new String(layout.toByteArray(event));
3434 }
3737 LoggerContext ctx = LoggerContext.getContext();
3838
3939 @Test
40 public void testMarkerPatternSelector() throws Exception {
40 public void testPatternSelector() throws Exception {
4141 final PatternMatch[] patterns = new PatternMatch[1];
4242 patterns[0] = new PatternMatch("FLOW", "%d %-5p [%t]: ====== %C{1}.%M:%L %m ======%n");
4343 final PatternSelector selector = MarkerPatternSelector.createSelector(patterns, "%d %-5p [%t]: %m%n", true, true, ctx.getConfiguration());
5050 .setIncludeLocation(true)
5151 .setMessage(new SimpleMessage("entry")).build();
5252 final String result1 = new FauxLogger().formatEvent(event1, layout);
53 final String expectSuffix1 = String.format("====== PatternSelectorTest.testMarkerPatternSelector:53 entry ======%n");
54 assertTrue(result1.endsWith(expectSuffix1), "Unexpected result: " + result1);
53 final String expectSuffix1 = String.format("====== PatternSelectorTest.testPatternSelector:53 entry ======%n");
54 assertTrue("Unexpected result: " + result1, result1.endsWith(expectSuffix1));
5555 final LogEvent event2 = Log4jLogEvent.newBuilder() //
5656 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
5757 .setLevel(Level.INFO) //
5858 .setMessage(new SimpleMessage("Hello, world 1!")).build();
5959 final String result2 = new String(layout.toByteArray(event2));
6060 final String expectSuffix2 = String.format("Hello, world 1!%n");
61 assertTrue(result2.endsWith(expectSuffix2), "Unexpected result: " + result2);
62 }
63
64
65 @Test
66 public void testLevelPatternSelector() throws Exception {
67 final PatternMatch[] patterns = new PatternMatch[1];
68 patterns[0] = new PatternMatch("TRACE", "%d %-5p [%t]: ====== %C{1}.%M:%L %m ======%n");
69 final PatternSelector selector = LevelPatternSelector.createSelector(patterns, "%d %-5p [%t]: %m%n", true, true, ctx.getConfiguration());
70 final PatternLayout layout = PatternLayout.newBuilder().withPatternSelector(selector)
71 .withConfiguration(ctx.getConfiguration()).build();
72 final LogEvent event1 = Log4jLogEvent.newBuilder() //
73 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.layout.PatternSelectorTest$FauxLogger")
74 .setLevel(Level.TRACE) //
75 .setIncludeLocation(true)
76 .setMessage(new SimpleMessage("entry")).build();
77 final String result1 = new FauxLogger().formatEvent(event1, layout);
78 final String expectSuffix1 = String.format("====== PatternSelectorTest.testLevelPatternSelector:78 entry ======%n");
79 assertTrue(result1.endsWith(expectSuffix1), "Unexpected result: " + result1);
80 final LogEvent event2 = Log4jLogEvent.newBuilder() //
81 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
82 .setLevel(Level.INFO) //
83 .setMessage(new SimpleMessage("Hello, world 1!")).build();
84 final String result2 = new String(layout.toByteArray(event2));
85 final String expectSuffix2 = String.format("Hello, world 1!%n");
86 assertTrue(result2.endsWith(expectSuffix2), "Unexpected result: " + result2);
61 assertTrue("Unexpected result: " + result2, result2.endsWith(expectSuffix2));
8762 }
8863
8964 }
3030 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3131 import org.apache.logging.log4j.core.net.Facility;
3232 import org.apache.logging.log4j.core.util.KeyValuePair;
33 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
33 import org.apache.logging.log4j.junit.ThreadContextRule;
3434 import org.apache.logging.log4j.message.StructuredDataCollectionMessage;
3535 import org.apache.logging.log4j.message.StructuredDataMessage;
3636 import org.apache.logging.log4j.status.StatusLogger;
3737 import org.apache.logging.log4j.test.appender.ListAppender;
3838 import org.apache.logging.log4j.util.ProcessIdUtil;
3939 import org.apache.logging.log4j.util.Strings;
40 import org.junit.jupiter.api.AfterAll;
41 import org.junit.jupiter.api.BeforeAll;
42 import org.junit.jupiter.api.Test;
43
44 import static org.junit.jupiter.api.Assertions.*;
45
46 @UsingAnyThreadContext
40 import org.junit.AfterClass;
41 import org.junit.Assert;
42 import org.junit.BeforeClass;
43 import org.junit.Rule;
44 import org.junit.Test;
45
46 import static org.junit.Assert.*;
47
4748 public class Rfc5424LayoutTest {
4849 LoggerContext ctx = LoggerContext.getContext();
4950 Logger root = ctx.getRootLogger();
7071
7172 static ConfigurationFactory cf = new BasicConfigurationFactory();
7273
73 @BeforeAll
74 @Rule
75 public final ThreadContextRule threadContextRule = new ThreadContextRule();
76
77 @BeforeClass
7478 public static void setupClass() {
7579 StatusLogger.getLogger().setLevel(Level.OFF);
7680 ConfigurationFactory.setConfigurationFactory(cf);
7882 ctx.reconfigure();
7983 }
8084
81 @AfterAll
85 @AfterClass
8286 public static void cleanupClass() {
8387 ConfigurationFactory.removeConfigurationFactory(cf);
8488 }
125129
126130 List<String> list = appender.getMessages();
127131
128 assertTrue(list.get(0).endsWith(line1), "Expected line 1 to end with: " + line1 + " Actual " + list.get(0));
129 assertTrue(list.get(1).endsWith(line2), "Expected line 2 to end with: " + line2 + " Actual " + list.get(1));
130 assertTrue(list.get(2).endsWith(line3), "Expected line 3 to end with: " + line3 + " Actual " + list.get(2));
131 assertTrue(list.get(3).endsWith(line4), "Expected line 4 to end with: " + line4 + " Actual " + list.get(3));
132 assertTrue("Expected line 1 to end with: " + line1 + " Actual " + list.get(0), list.get(0).endsWith(line1));
133 assertTrue("Expected line 2 to end with: " + line2 + " Actual " + list.get(1), list.get(1).endsWith(line2));
134 assertTrue("Expected line 3 to end with: " + line3 + " Actual " + list.get(2), list.get(2).endsWith(line3));
135 assertTrue("Expected line 4 to end with: " + line4 + " Actual " + list.get(3), list.get(3).endsWith(line4));
132136
133137 for (final String frame : list) {
134138 int length = -1;
141145 assertEquals(frameLength, messageLength.length() + length);
142146 }
143147 catch (final NumberFormatException e) {
144 fail("Not a valid RFC 5425 frame");
148 assertTrue("Not a valid RFC 5425 frame", false);
145149 }
146150 }
147151
152156 root.debug("This is a test");
153157
154158 list = appender.getMessages();
155 assertTrue(list.isEmpty(), "No messages expected, found " + list.size());
156 } finally {
159 assertTrue("No messages expected, found " + list.size(), list.isEmpty());
160 } finally {
161 ThreadContext.clearMap();
157162 root.removeAppender(appender);
158163 appender.stop();
159164 }
196201
197202 root.info(MarkerManager.getMarker("EVENT"), collectionMessage);
198203
199 List<String> list = appender.getMessages();
200 String result = list.get(0);
201 assertTrue(
202 result.contains(collectionLine1), "Expected line to contain " + collectionLine1 + ", Actual " + result);
203 assertTrue(
204 result.contains(collectionLine2), "Expected line to contain " + collectionLine2 + ", Actual " + result);
205 assertTrue(
206 result.contains(collectionLine3), "Expected line to contain " + collectionLine3 + ", Actual " + result);
207 assertTrue(
208 result.endsWith(collectionEndOfLine),
209 "Expected line to end with: " + collectionEndOfLine + " Actual " + result);
204 final List<String> list = appender.getMessages();
205 final String result = list.get(0);
206 assertTrue("Expected line to contain " + collectionLine1 + ", Actual " + result,
207 result.contains(collectionLine1));
208 assertTrue("Expected line to contain " + collectionLine2 + ", Actual " + result,
209 result.contains(collectionLine2));
210 assertTrue("Expected line to contain " + collectionLine3 + ", Actual " + result,
211 result.contains(collectionLine3));
212 assertTrue("Expected line to end with: " + collectionEndOfLine + " Actual " + result,
213 result.endsWith(collectionEndOfLine));
210214
211215 for (final String frame : list) {
212216 int length = -1;
219223 assertEquals(frameLength, messageLength.length() + length);
220224 }
221225 catch (final NumberFormatException e) {
222 fail("Not a valid RFC 5425 frame");
226 assertTrue("Not a valid RFC 5425 frame", false);
223227 }
224228 }
225229
226230 appender.clear();
227231 } finally {
232 ThreadContext.clearMap();
228233 root.removeAppender(appender);
229234 appender.stop();
230235 }
271276
272277 List<String> list = appender.getMessages();
273278
274 assertTrue(list.get(0).endsWith(line1), "Expected line 1 to end with: " + line1 + " Actual " + list.get(0));
275 assertTrue(list.get(1).endsWith(line2), "Expected line 2 to end with: " + line2 + " Actual " + list.get(1));
276 assertTrue(list.get(2).endsWith(lineEscaped3),
277 "Expected line 3 to end with: " + lineEscaped3 + " Actual " + list.get(2));
278 assertTrue(list.get(3).endsWith(lineEscaped4),
279 "Expected line 4 to end with: " + lineEscaped4 + " Actual " + list.get(3));
279 assertTrue("Expected line 1 to end with: " + line1 + " Actual " + list.get(0), list.get(0).endsWith(line1));
280 assertTrue("Expected line 2 to end with: " + line2 + " Actual " + list.get(1), list.get(1).endsWith(line2));
281 assertTrue("Expected line 3 to end with: " + lineEscaped3 + " Actual " + list.get(2), list.get(2).endsWith(lineEscaped3));
282 assertTrue("Expected line 4 to end with: " + lineEscaped4 + " Actual " + list.get(3), list.get(3).endsWith(lineEscaped4));
280283
281284 appender.clear();
282285
285288 root.debug("This is a test");
286289
287290 list = appender.getMessages();
288 assertTrue(list.isEmpty(), "No messages expected, found " + list.size());
291 assertTrue("No messages expected, found " + list.size(), list.isEmpty());
289292 } finally {
290293 root.removeAppender(appender);
291294 appender.stop();
319322
320323 final List<String> list = appender.getMessages();
321324
322 assertTrue(list.size() > 1, "Not enough list entries");
325 assertTrue("Not enough list entries", list.size() > 1);
323326 final String string = list.get(1);
324 assertTrue(string.contains("IllegalArgumentException"), "No Exception in " + string);
327 assertTrue("No Exception in " + string, string.contains("IllegalArgumentException"));
325328
326329 appender.clear();
327330 } finally {
360363 try {
361364
362365 final List<String> list = appender.getMessages();
363 assertTrue(list.size() > 0, "Not enough list entries");
364 assertTrue(list.get(0).contains("Rfc5424LayoutTest.testMDCLoggerFields"), "No class/method");
366 assertTrue("Not enough list entries", list.size() > 0);
367 assertTrue("No class/method", list.get(0).contains("Rfc5424LayoutTest.testMDCLoggerFields"));
365368
366369 appender.clear();
367370 } finally {
404407 try {
405408
406409 final List<String> list = appender.getMessages();
407 assertTrue(list.size() > 0, "Not enough list entries");
410 assertTrue("Not enough list entries", list.size() > 0);
408411 final String message = list.get(0);
409 assertTrue(message.contains("Rfc5424LayoutTest.testLoggerFields"), "No class/method");
412 assertTrue("No class/method", message.contains("Rfc5424LayoutTest.testLoggerFields"));
410413 for (final String value : expectedToContain) {
411 assertTrue(message.contains(value), "Message expected to contain " + value + " but did not");
414 Assert.assertTrue("Message expected to contain " + value + " but did not", message.contains(value));
412415 }
413416 appender.clear();
414417 } finally {
451454 try {
452455
453456 final List<String> list = appender.getMessages();
454 assertTrue(list.size() > 0, "Not enough list entries");
457 assertTrue("Not enough list entries", list.size() > 0);
455458 final String message = list.get(0);
456 assertFalse(message.contains("SD-ID"), "SD-ID should have been discarded");
457 assertTrue(message.contains("BAZ"), "BAZ should have been included");
458 assertTrue(message.contains(mdcId), mdcId + "should have been included");
459 Assert.assertTrue("SD-ID should have been discarded", !message.contains("SD-ID"));
460 Assert.assertTrue("BAZ should have been included", message.contains("BAZ"));
461 Assert.assertTrue(mdcId + "should have been included", message.contains(mdcId));
459462 appender.clear();
460463 } finally {
461464 root.removeAppender(appender);
485488
486489 try {
487490 final List<String> list = appender.getMessages();
488 assertTrue(list.size() > 0, "Not enough list entries");
491 assertTrue("Not enough list entries", list.size() > 0);
489492 final String message = list.get(0);
490 assertTrue(message.contains(expectedToContain), "Not the expected message received");
493 Assert.assertTrue("Not the expected message received", message.contains(expectedToContain));
491494 appender.clear();
492495 } finally {
493496 root.removeAppender(appender);
513516 root.info("Hello {}", "World");
514517 try {
515518 final List<String> list = appender.getMessages();
516 assertTrue(list.size() > 0, "Not enough list entries");
519 assertTrue("Not enough list entries", list.size() > 0);
517520 final String message = list.get(0);
518 assertTrue(message.contains("Hello World"),
519 "Incorrect message. Expected - Hello World, Actual - " + message);
521 assertTrue("Incorrect message. Expected - Hello World, Actual - " + message, message.contains("Hello World"));
520522 } finally {
521523 root.removeAppender(appender);
522524 appender.stop();
176176 testSerialization();
177177 final File file = new File(DAT_PATH);
178178 final FileInputStream fis = new FileInputStream(file);
179 try (ObjectInputStream ois = useObjectInputStream ? new ObjectInputStream(fis) :
180 new FilteredObjectInputStream(fis)) {
179 final ObjectInputStream ois = useObjectInputStream ? new ObjectInputStream(fis) :
180 new FilteredObjectInputStream(fis);
181 try {
181182 final LogEvent event = (LogEvent) ois.readObject();
182183 assertNotNull(event);
184 } finally {
185 ois.close();
183186 }
184187 }
185188 }
1818 import java.nio.charset.Charset;
1919 import java.nio.charset.StandardCharsets;
2020
21 import org.junit.jupiter.api.Test;
22
23 import static org.junit.jupiter.api.Assertions.*;
21 import org.junit.Test;
22
23 import static org.junit.Assert.*;
2424
2525 /**
2626 * Tests the {@code TextEncoderHelper} class.
3434 final SpyByteBufferDestination destination = new SpyByteBufferDestination(17, 17);
3535 helper.encode(text, destination);
3636
37 assertEquals(0, destination.drainPoints.size(), "drained");
38 assertEquals(text.length(), destination.buffer.position(), "destination.buf.pos");
37 assertEquals("drained", 0, destination.drainPoints.size());
38 assertEquals("destination.buf.pos", text.length(), destination.buffer.position());
3939
4040 for (int i = 0; i < text.length(); i++) {
41 assertEquals((byte) text.charAt(i), destination.buffer.get(i), "char at " + i);
41 assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(i));
4242 }
4343 }
4444
4949 final SpyByteBufferDestination destination = new SpyByteBufferDestination(14, 15);
5050 helper.encode(text, destination);
5151
52 assertEquals(1, destination.drainPoints.size(), "drained");
53 assertEquals(0, destination.drainPoints.get(0).position, "drained[0].from");
54 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(0).limit, "drained[0].to");
55 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(0).length(), "drained[0].length");
56 assertEquals(text.length() - destination.buffer.capacity(),
57 destination.buffer.position(), "destination.buf.pos");
52 assertEquals("drained", 1, destination.drainPoints.size());
53 assertEquals("drained[0].from", 0, destination.drainPoints.get(0).position);
54 assertEquals("drained[0].to", destination.buffer.capacity(), destination.drainPoints.get(0).limit);
55 assertEquals("drained[0].length", destination.buffer.capacity(), destination.drainPoints.get(0).length());
56 assertEquals("destination.buf.pos", text.length() - destination.buffer.capacity(),
57 destination.buffer.position());
5858
5959 for (int i = 0; i < destination.buffer.capacity(); i++) {
60 assertEquals((byte) text.charAt(i), destination.drained.get(i), "char at " + i);
60 assertEquals("char at " + i, (byte) text.charAt(i), destination.drained.get(i));
6161 }
6262 for (int i = destination.buffer.capacity(); i < text.length(); i++) {
6363 final int bufIx = i - destination.buffer.capacity();
64 assertEquals((byte) text.charAt(i), destination.buffer.get(bufIx), "char at " + i);
64 assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(bufIx));
6565 }
6666 }
6767
7272 final SpyByteBufferDestination destination = new SpyByteBufferDestination(4, 20);
7373 helper.encode(text, destination);
7474
75 assertEquals(3, destination.drainPoints.size(), "drained");
76 assertEquals(0, destination.drainPoints.get(0).position, "drained[0].from");
77 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(0).limit, "drained[0].to");
78 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(0).length(), "drained[0].length");
79 assertEquals(0, destination.drainPoints.get(1).position, "drained[1].from");
80 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(1).limit, "drained[1].to");
81 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(1).length(), "drained[1].length");
82 assertEquals(0, destination.drainPoints.get(2).position, "drained[2].from");
83 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(2).limit, "drained[2].to");
84 assertEquals(destination.buffer.capacity(), destination.drainPoints.get(2).length(), "drained[2].length");
85 assertEquals(text.length() - 3 * destination.buffer.capacity(),
86 destination.buffer.position(), "destination.buf.pos");
75 assertEquals("drained", 3, destination.drainPoints.size());
76 assertEquals("drained[0].from", 0, destination.drainPoints.get(0).position);
77 assertEquals("drained[0].to", destination.buffer.capacity(), destination.drainPoints.get(0).limit);
78 assertEquals("drained[0].length", destination.buffer.capacity(), destination.drainPoints.get(0).length());
79 assertEquals("drained[1].from", 0, destination.drainPoints.get(1).position);
80 assertEquals("drained[1].to", destination.buffer.capacity(), destination.drainPoints.get(1).limit);
81 assertEquals("drained[1].length", destination.buffer.capacity(), destination.drainPoints.get(1).length());
82 assertEquals("drained[2].from", 0, destination.drainPoints.get(2).position);
83 assertEquals("drained[2].to", destination.buffer.capacity(), destination.drainPoints.get(2).limit);
84 assertEquals("drained[2].length", destination.buffer.capacity(), destination.drainPoints.get(2).length());
85 assertEquals("destination.buf.pos", text.length() - 3 * destination.buffer.capacity(),
86 destination.buffer.position());
8787
8888 for (int i = 0; i < 3 * destination.buffer.capacity(); i++) {
89 assertEquals((byte) text.charAt(i), destination.drained.get(i), "char at " + i);
89 assertEquals("char at " + i, (byte) text.charAt(i), destination.drained.get(i));
9090 }
9191 for (int i = 3 * destination.buffer.capacity(); i < text.length(); i++) {
9292 final int bufIx = i - 3 * destination.buffer.capacity();
93 assertEquals((byte) text.charAt(i), destination.buffer.get(bufIx), "char at " + i);
93 assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(bufIx));
9494 }
9595 }
9696
101101 final SpyByteBufferDestination destination = new SpyByteBufferDestination(17, 17);
102102 helper.encode(text, destination);
103103
104 assertEquals(0, destination.drainPoints.size(), "drained");
105 assertEquals(text.length(), destination.buffer.position(), "destination.buf.pos");
104 assertEquals("drained", 0, destination.drainPoints.size());
105 assertEquals("destination.buf.pos", text.length(), destination.buffer.position());
106106
107107 for (int i = 0; i < text.length(); i++) {
108 assertEquals((byte) text.charAt(i), destination.buffer.get(i), "char at " + i);
108 assertEquals("char at " + i, (byte) text.charAt(i), destination.buffer.get(i));
109109 }
110110 }
111111
117117 final SpyByteBufferDestination destination = new SpyByteBufferDestination(50, 50);
118118 helper.encode(text, destination);
119119
120 assertEquals(0, destination.drainPoints.size(), "drained");
120 assertEquals("drained", 0, destination.drainPoints.size());
121121 destination.drain(destination.getByteBuffer());
122122
123123 final byte[] utf8 = text.toString().getBytes(StandardCharsets.UTF_8);
124124 for (int i = 0; i < utf8.length; i++) {
125 assertEquals(utf8[i], destination.drained.get(i), "byte at " + i);
125 assertEquals("byte at " + i, utf8[i], destination.drained.get(i));
126126 }
127127 }
128128
135135 final SpyByteBufferDestination destination = new SpyByteBufferDestination(50, 50);
136136 helper.encode(text, destination);
137137
138 assertEquals(0, destination.drainPoints.size(), "drained");
138 assertEquals("drained", 0, destination.drainPoints.size());
139139 destination.drain(destination.getByteBuffer());
140140
141141 final byte[] bytes = text.toString().getBytes(SHIFT_JIS);
142142 for (int i = 0; i < bytes.length; i++) {
143 assertEquals(bytes[i], destination.drained.get(i), "byte at " + i);
143 assertEquals("byte at " + i, bytes[i], destination.drained.get(i));
144144 }
145145 }
146146
151151 final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 17);
152152 helper.encode(text, destination);
153153
154 assertEquals(4, destination.drainPoints.size(), "drained");
155 assertEquals(3, destination.buffer.position(), "destination.buf.pos");
154 assertEquals("drained", 4, destination.drainPoints.size());
155 assertEquals("destination.buf.pos", 3, destination.buffer.position());
156156
157157 for (int i = 0; i < text.length() - 3; i++) {
158 assertEquals((byte) text.charAt(i), destination.drained.get(i), "char at " + i);
158 assertEquals("char at " + i, (byte) text.charAt(i), destination.drained.get(i));
159159 }
160160 for (int i = 0; i < 3; i++) {
161 assertEquals((byte) text.charAt(12 + i), destination.buffer.get(i), "char at " + (12 + i));
161 assertEquals("char at " + (12 + i), (byte) text.charAt(12 + i), destination.buffer.get(i));
162162 }
163163 }
164164
170170 final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 50);
171171 helper.encode(text, destination);
172172
173 assertEquals(7, destination.drainPoints.size(), "drained");
173 assertEquals("drained", 7, destination.drainPoints.size());
174174 destination.drain(destination.getByteBuffer());
175175
176176 final byte[] utf8 = text.toString().getBytes(StandardCharsets.UTF_8);
177177 for (int i = 0; i < utf8.length; i++) {
178 assertEquals(utf8[i], destination.drained.get(i), "byte at " + i);
178 assertEquals("byte at " + i, utf8[i], destination.drained.get(i));
179179 }
180180 }
181181
187187 final SpyByteBufferDestination destination = new SpyByteBufferDestination(3, 50);
188188 helper.encode(text, destination);
189189
190 assertEquals(15, destination.drainPoints.size(), "drained");
190 assertEquals("drained", 15, destination.drainPoints.size());
191191 destination.drain(destination.getByteBuffer());
192192
193193 final byte[] utf8 = text.toString().getBytes(StandardCharsets.UTF_8);
194194 for (int i = 0; i < utf8.length; i++) {
195 assertEquals(utf8[i], destination.drained.get(i), "byte at " + i);
195 assertEquals("byte at " + i, utf8[i], destination.drained.get(i));
196196 }
197197 }
198198
209209
210210 final byte[] bytes = text.toString().getBytes(SHIFT_JIS);
211211 for (int i = 0; i < bytes.length; i++) {
212 assertEquals(bytes[i], destination.drained.get(i), "byte at " + i);
212 assertEquals("byte at " + i, bytes[i], destination.drained.get(i));
213213 }
214214 }
215215
226226
227227 final byte[] bytes = text.toString().getBytes(SHIFT_JIS);
228228 for (int i = 0; i < bytes.length; i++) {
229 assertEquals(bytes[i], destination.drained.get(i), "byte at " + i);
229 assertEquals("byte at " + i, bytes[i], destination.drained.get(i));
230230 }
231231 }
232232
235235 final CharBuffer buff = CharBuffer.wrap(new char[16]);
236236 final StringBuilder text = createText(15);
237237 final int length = TextEncoderHelper.copy(text, 0, buff);
238 assertEquals(text.length(), length, "everything fits");
239 for (int i = 0; i < length; i++) {
240 assertEquals(text.charAt(i), buff.get(i), "char at " + i);
241 }
242 assertEquals(text.length(), buff.position(), "position moved by length");
238 assertEquals("everything fits", text.length(), length);
239 for (int i = 0; i < length; i++) {
240 assertEquals("char at " + i, text.charAt(i), buff.get(i));
241 }
242 assertEquals("position moved by length", text.length(), buff.position());
243243 }
244244
245245 @Test
247247 final CharBuffer buff = CharBuffer.wrap(new char[3]);
248248 final StringBuilder text = createText(15);
249249 final int length = TextEncoderHelper.copy(text, 0, buff);
250 assertEquals(buff.capacity(), length, "partial copy");
251 for (int i = 0; i < length; i++) {
252 assertEquals(text.charAt(i), buff.get(i), "char at " + i);
253 }
254 assertEquals(0, buff.remaining(), "no space remaining");
255 assertEquals(buff.capacity(), buff.position(), "position at end");
250 assertEquals("partial copy", buff.capacity(), length);
251 for (int i = 0; i < length; i++) {
252 assertEquals("char at " + i, text.charAt(i), buff.get(i));
253 }
254 assertEquals("no space remaining", 0, buff.remaining());
255 assertEquals("position at end", buff.capacity(), buff.position());
256256 }
257257
258258 @Test
259259 public void testCopyDoesNotWriteBeyondStringText() throws Exception {
260260 final CharBuffer buff = CharBuffer.wrap(new char[5]);
261 assertEquals(0, buff.position(), "initial buffer position");
261 assertEquals("initial buffer position", 0, buff.position());
262262 final StringBuilder text = createText(2);
263263 final int length = TextEncoderHelper.copy(text, 0, buff);
264 assertEquals(text.length(), length, "full copy");
265 for (int i = 0; i < length; i++) {
266 assertEquals(text.charAt(i), buff.get(i), "char at " + i);
267 }
268 assertEquals(text.length(), buff.position(), "resulting buffer position");
264 assertEquals("full copy", text.length(), length);
265 for (int i = 0; i < length; i++) {
266 assertEquals("char at " + i, text.charAt(i), buff.get(i));
267 }
268 assertEquals("resulting buffer position", text.length(), buff.position());
269269 for (int i = length; i < buff.capacity(); i++) {
270 assertEquals(0, buff.get(i), "unset char at " + i);
270 assertEquals("unset char at " + i, 0, buff.get(i));
271271 }
272272 }
273273
278278 buff.position(START_POSITION); // set start position
279279 final StringBuilder text = createText(15);
280280 final int length = TextEncoderHelper.copy(text, 0, buff);
281 assertEquals(buff.capacity() - START_POSITION, length, "partial copy");
282 for (int i = 0; i < length; i++) {
283 assertEquals(text.charAt(i), buff.get(START_POSITION + i), "char at " + i);
284 }
285 assertEquals(buff.capacity(), buff.position(), "buffer position at end");
281 assertEquals("partial copy", buff.capacity() - START_POSITION, length);
282 for (int i = 0; i < length; i++) {
283 assertEquals("char at " + i, text.charAt(i), buff.get(START_POSITION + i));
284 }
285 assertEquals("buffer position at end", buff.capacity(), buff.position());
286286 }
287287
288288 @Test
2727 import org.apache.logging.log4j.core.LoggerContext;
2828 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2929 import org.apache.logging.log4j.core.net.Facility;
30 import org.apache.logging.log4j.junit.UsingAnyThreadContext;
30 import org.apache.logging.log4j.junit.ThreadContextRule;
3131 import org.apache.logging.log4j.message.StructuredDataMessage;
3232 import org.apache.logging.log4j.test.appender.ListAppender;
33 import org.junit.jupiter.api.AfterAll;
34 import org.junit.jupiter.api.BeforeAll;
35 import org.junit.jupiter.api.Test;
33 import org.junit.AfterClass;
34 import org.junit.BeforeClass;
35 import org.junit.Rule;
36 import org.junit.Test;
3637
37 import static org.junit.jupiter.api.Assertions.*;
38 import static org.junit.Assert.*;
3839
39 @UsingAnyThreadContext
40 /**
41 *
42 */
4043 public class SyslogLayoutTest {
4144 LoggerContext ctx = LoggerContext.getContext();
4245 Logger root = ctx.getRootLogger();
5053
5154 static ConfigurationFactory cf = new BasicConfigurationFactory();
5255
53 @BeforeAll
56 @Rule
57 public final ThreadContextRule threadContextRule = new ThreadContextRule();
58
59 @BeforeClass
5460 public static void setupClass() {
5561 ConfigurationFactory.setConfigurationFactory(cf);
5662 final LoggerContext ctx = LoggerContext.getContext();
5763 ctx.reconfigure();
5864 }
5965
60 @AfterAll
66 @AfterClass
6167 public static void cleanupClass() {
6268 ConfigurationFactory.removeConfigurationFactory(cf);
6369 }
108114
109115 final List<String> list = appender.getMessages();
110116
111 assertTrue(list.get(0).endsWith(line1), "Expected line 1 to end with: " + line1 + " Actual " + list.get(0));
112 assertTrue(list.get(1).endsWith(line2), "Expected line 2 to end with: " + line2 + " Actual " + list.get(1));
113 assertTrue(list.get(2).endsWith(line3), "Expected line 3 to end with: " + line3 + " Actual " + list.get(2));
114 assertTrue(list.get(3).endsWith(line4), "Expected line 4 to end with: " + line4 + " Actual " + list.get(3));
117 assertTrue("Expected line 1 to end with: " + line1 + " Actual " + list.get(0), list.get(0).endsWith(line1));
118 assertTrue("Expected line 2 to end with: " + line2 + " Actual " + list.get(1), list.get(1).endsWith(line2));
119 assertTrue("Expected line 3 to end with: " + line3 + " Actual " + list.get(2), list.get(2).endsWith(line3));
120 assertTrue("Expected line 4 to end with: " + line4 + " Actual " + list.get(3), list.get(3).endsWith(line4));
115121 }
116122 }
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import static org.hamcrest.CoreMatchers.equalTo;
1918 import static org.junit.Assert.assertEquals;
2019 import static org.junit.Assert.assertFalse;
2120 import static org.junit.Assert.assertNull;
22 import static org.junit.Assert.assertThat;
2321 import static org.junit.Assert.assertTrue;
2422
2523 import java.nio.charset.StandardCharsets;
2624 import java.util.List;
2725 import java.util.Map;
2826
29 import com.fasterxml.jackson.databind.JsonNode;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
3227 import org.apache.logging.log4j.Level;
3328 import org.apache.logging.log4j.ThreadContext;
3429 import org.apache.logging.log4j.categories.Layouts;
313308 .setIncludeStacktrace(false)
314309 .setAdditionalFields(new KeyValuePair[] {
315310 new KeyValuePair("KEY1", "VALUE1"),
316 new KeyValuePair("KEY2", "${java:runtime}"), })
311 new KeyValuePair("KEY2", "${java:hw}"), })
317312 .setCharset(StandardCharsets.UTF_8)
318313 .setConfiguration(ctx.getConfiguration())
319314 .build();
320315 final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
321 final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
322 JsonNode node = mapper.readTree(str);
323 assertThat(getJSONChildNodeValueAsText(node, "KEY1"), equalTo("VALUE1"));
324 assertThat(getJSONChildNodeValueAsText(node, "KEY2"), equalTo(new JavaLookup().getRuntime()));
325 }
326
327 private String getJSONChildNodeValueAsText(final JsonNode parentNode, final String key) {
328 JsonNode childNode = parentNode.get(key);
329 if (childNode != null) {
330 return childNode.asText();
331 } else {
332 return Strings.EMPTY;
333 }
316 assertTrue(str, str.contains("KEY1: \"VALUE1\""));
317 assertTrue(str, str.contains("KEY2: \"" + new JavaLookup().getHardware() + "\""));
334318 }
335319
336320 @Test
+0
-40
log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/CaseLookupTest.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.logging.log4j.core.lookup;
17
18 import org.junit.jupiter.api.Test;
19
20 import static org.junit.jupiter.api.Assertions.*;
21
22 public class CaseLookupTest {
23
24
25 @Test
26 public void testLookup() {
27 final String testStr = "JabberWocky";
28 final String lower = "jabberwocky";
29 final String upper = "JABBERWOCKY";
30 StrLookup lookup = new LowerLookup();
31 String value = lookup.lookup(null, testStr);
32 assertNotNull(value);
33 assertEquals(lower, value);
34 lookup = new UpperLookup();
35 value = lookup.lookup(null, testStr);
36 assertNotNull(value);
37 assertEquals(upper, value);
38 }
39 }
2424 import org.junit.Rule;
2525 import org.junit.Test;
2626 import org.junit.rules.RuleChain;
27 import org.junit.rules.TestRule;
28 import org.junit.runner.Description;
2729 import org.junit.runners.model.Statement;
2830
2931 import static org.junit.Assert.*;
3032
33 /**
34 *
35 */
3136 public class ContextMapLookupTest {
3237
3338 private static final String TESTKEY = "TestKey";
3641 private final LoggerContextRule context = new LoggerContextRule("ContextMapLookupTest.xml");
3742
3843 @Rule
39 public RuleChain chain = RuleChain.outerRule((base, description) -> new Statement() {
44 public RuleChain chain = RuleChain.outerRule(new TestRule() {
4045 @Override
41 public void evaluate() throws Throwable {
42 final File logFile = new File("target",
43 description.getClassName() + '.' + description.getMethodName() + ".log");
44 ThreadContext.put("testClassName", description.getClassName());
45 ThreadContext.put("testMethodName", description.getMethodName());
46 try {
47 base.evaluate();
48 } finally {
49 ThreadContext.remove("testClassName");
50 ThreadContext.remove("testMethodName");
51 if (logFile.exists()) {
52 logFile.deleteOnExit();
46 public Statement apply(final Statement base, final Description description) {
47 return new Statement() {
48 @Override
49 public void evaluate() throws Throwable {
50 final File logFile = new File("target",
51 description.getClassName() + '.' + description.getMethodName() + ".log");
52 ThreadContext.put("testClassName", description.getClassName());
53 ThreadContext.put("testMethodName", description.getMethodName());
54 try {
55 base.evaluate();
56 } finally {
57 ThreadContext.remove("testClassName");
58 ThreadContext.remove("testMethodName");
59 if (logFile.exists()) {
60 logFile.deleteOnExit();
61 }
62 }
5363 }
54 }
64 };
5565 }
5666 }).around(context);
5767
1919
2020 import org.apache.logging.log4j.core.AbstractLogEvent;
2121 import org.apache.logging.log4j.core.LogEvent;
22 import org.junit.jupiter.api.Test;
22 import org.junit.Test;
2323
24 import static org.junit.jupiter.api.Assertions.*;
24 import static org.junit.Assert.*;
2525
26 /**
27 *
28 */
2629 public class DateLookupTest {
2730
2831
3538 assertEquals("12/30/2011", value);
3639 }
3740
38 private static class MyLogEvent extends AbstractLogEvent {
41 private class MyLogEvent extends AbstractLogEvent {
3942 /**
4043 * Generated serial version ID.
4144 */
4447 @Override
4548 public long getTimeMillis() {
4649 final Calendar cal = Calendar.getInstance();
47 cal.set(2011, Calendar.DECEMBER, 30, 10, 56, 35);
50 cal.set(2011, 11, 30, 10, 56, 35);
4851 return cal.getTimeInMillis();
4952 }
5053
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
22 /**
23 *
24 */
2225 public class EnvironmentLookupTest {
26
2327
2428 @Test
2529 public void testLookup() {
+0
-116
log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/EventLookupTest.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.logging.log4j.core.lookup;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Marker;
20 import org.apache.logging.log4j.MarkerManager;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
23 import org.apache.logging.log4j.message.SimpleMessage;
24 import org.junit.jupiter.api.Test;
25
26 import static org.junit.jupiter.api.Assertions.*;
27
28 /**
29 * Tests {@link MarkerLookup}.
30 *
31 * @since 2.4
32 */
33 public class EventLookupTest {
34
35 private static final String ABSENT_MARKER_NAME = "NONE";
36 private final String markerName = "EventLookupTest";
37 private final StrLookup strLookup = new EventLookup();
38
39 @Test
40 public void testLookupEventMarker() {
41 final Marker marker = MarkerManager.getMarker(markerName);
42 final LogEvent event = Log4jLogEvent.newBuilder() //
43 .setLoggerName(this.getClass().getName()) //
44 .setMarker(marker) //
45 .setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
46 .setLevel(Level.INFO) //
47 .setMessage(new SimpleMessage("Hello, world!")).build();
48 final String value = strLookup.lookup(event, "Marker");
49 assertEquals(markerName, value);
50 }
51
52 @Test
53 public void testLookupEventMessage() {
54 String msg = "Hello, world!";
55 final LogEvent event = Log4jLogEvent.newBuilder() //
56 .setLoggerName(this.getClass().getName()) //
57 .setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
58 .setLevel(Level.INFO) //
59 .setMessage(new SimpleMessage(msg)).build();
60 final String value = strLookup.lookup(event, "Message");
61 assertEquals(msg, value);
62 }
63
64 @Test
65 public void testLookupEventLevel() {
66 String msg = "Hello, world!";
67 final LogEvent event = Log4jLogEvent.newBuilder() //
68 .setLoggerName(this.getClass().getName()) //
69 .setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
70 .setLevel(Level.INFO) //
71 .setMessage(new SimpleMessage(msg)).build();
72 final String value = strLookup.lookup(event, "Level");
73 assertEquals(Level.INFO.toString(), value);
74 }
75
76 @Test
77 public void testLookupEventTimestamp() {
78 String msg = "Hello, world!";
79 long now = System.currentTimeMillis();
80 final LogEvent event = Log4jLogEvent.newBuilder() //
81 .setLoggerName(this.getClass().getName()) //
82 .setTimeMillis(now)
83 .setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
84 .setLevel(Level.INFO) //
85 .setMessage(new SimpleMessage(msg)).build();
86 final String value = strLookup.lookup(event, "Timestamp");
87 assertEquals(Long.toString(now), value);
88 }
89
90 @Test
91 public void testLookupEventLogger() {
92 String msg = "Hello, world!";
93 final LogEvent event = Log4jLogEvent.newBuilder() //
94 .setLoggerName(this.getClass().getName()) //
95 .setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
96 .setLevel(Level.INFO) //
97 .setMessage(new SimpleMessage(msg)).build();
98 final String value = strLookup.lookup(event, "Logger");
99 assertEquals(this.getClass().getName(), value);
100 }
101
102 @Test
103 public void testLookupEventThreadName() {
104 String msg = "Hello, world!";
105 final LogEvent event = Log4jLogEvent.newBuilder() //
106 .setLoggerName(this.getClass().getName()) //
107 .setThreadName("Main")
108 .setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
109 .setLevel(Level.INFO) //
110 .setMessage(new SimpleMessage(msg)).build();
111 final String value = strLookup.lookup(event, "ThreadName");
112 assertEquals("Main", value);
113 }
114
115 }
2121 import java.util.Map;
2222
2323 import org.apache.logging.log4j.ThreadContext;
24 import org.apache.logging.log4j.junit.JndiRule;
25 import org.junit.BeforeClass;
2624 import org.junit.ClassRule;
2725 import org.junit.Test;
2826 import org.junit.rules.ExternalResource;
3937 private static final String TESTKEY2 = "TestKey2";
4038 private static final String TESTVAL = "TestValue";
4139
42 private static final String TEST_CONTEXT_RESOURCE_NAME = "logging/context-name";
43 private static final String TEST_CONTEXT_NAME = "app-1";
44
4540 @ClassRule
4641 public static RuleChain rules = RuleChain.outerRule(new ExternalResource() {
4742 @Override
5752 System.clearProperty(TESTKEY2);
5853 System.clearProperty("log4j2.enableJndiLookup");
5954 }
60 }).around(new JndiRule(
61 JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_CONTEXT_RESOURCE_NAME, TEST_CONTEXT_NAME));
55 });
6256
6357 @Test
6458 public void testLookup() {
7973 ThreadContext.clearMap();
8074 value = lookup.lookup("ctx:" + TESTKEY);
8175 assertEquals(TESTVAL, value);
82 value = lookup.lookup("jndi:" + TEST_CONTEXT_RESOURCE_NAME);
83 assertEquals(TEST_CONTEXT_NAME, value);
8476 }
8577
8678 private void assertLookupNotEmpty(final StrLookup lookup, final String key) {
9789 assertEquals(TESTVAL, value);
9890 value = lookup.lookup("env:PATH");
9991 assertNotNull(value);
100 value = lookup.lookup("jndi:" + TEST_CONTEXT_RESOURCE_NAME);
101 assertEquals(TEST_CONTEXT_NAME, value);
10292 value = lookup.lookup("date:yyyy-MM-dd");
10393 assertNotNull("No Date", value);
10494 final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import static org.junit.jupiter.api.Assertions.assertThrows;
19
18 import org.apache.logging.log4j.test.JUnit5Bridge;
2019 import org.junit.Test;
2120
2221 /**
2827
2928 @Test
3029 public void testLookup() {
31 assertThrows(IllegalStateException.class, JndiLookup::new);
30 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
31 @Override
32 public void run() {
33 new JndiLookup();
34 }
35 });
3236 }
3337 }
+0
-36
log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiExploit.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.logging.log4j.core.lookup;
17
18 import javax.naming.Context;
19 import javax.naming.Name;
20 import javax.naming.spi.ObjectFactory;
21 import java.util.Hashtable;
22
23 import static org.junit.jupiter.api.Assertions.fail;
24
25 /**
26 * Test LDAP object
27 */
28 public class JndiExploit implements ObjectFactory {
29 @Override
30 public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
31 throws Exception {
32 fail("getObjectInstance must not be allowed");
33 return null;
34 }
35 }
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNull;
20
1821 import java.util.Arrays;
1922 import java.util.Collection;
2023 import java.util.HashMap;
2124 import java.util.Map;
2225
2326 import org.apache.logging.log4j.junit.JndiRule;
27 import org.junit.AfterClass;
2428 import org.junit.BeforeClass;
2529 import org.junit.Rule;
2630 import org.junit.Test;
27
28 import static org.junit.Assert.*;
2931
3032 /**
3133 * JndiLookupTest
4143
4244 @Rule
4345 public JndiRule jndiRule = new JndiRule(createBindings());
46
47 @AfterClass
48 public static void afterClass() {
49 System.clearProperty("log4j2.enableJndiLookup");
50 }
4451
4552 @BeforeClass
4653 public static void beforeClass() {
7885 final String collectionValue = lookup.lookup(TEST_STRINGS_NAME);
7986 assertEquals(String.valueOf(TEST_STRINGS_COLLECTION), collectionValue);
8087 }
88
8189 }
1414 */
1515 package org.apache.logging.log4j.core.lookup;
1616
17 import java.io.File;
18 import java.net.URISyntaxException;
19
1720 import org.apache.logging.log4j.core.LoggerContext;
1821 import org.apache.logging.log4j.core.config.Configuration;
1922 import org.apache.logging.log4j.core.config.ConfigurationAware;
2023 import org.apache.logging.log4j.core.config.ConfigurationSource;
2124 import org.apache.logging.log4j.core.impl.ContextAnchor;
22 import org.junit.jupiter.api.AfterEach;
23 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.extension.ExtendWith;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
2629 import org.mockito.Mock;
27 import org.mockito.junit.jupiter.MockitoExtension;
28
29 import java.io.File;
30 import org.mockito.runners.MockitoJUnitRunner;
3031
3132 import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_LOCATION;
3233 import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_PARENT_LOCATION;
33 import static org.junit.jupiter.api.Assertions.assertEquals;
34 import static org.junit.Assert.*;
3435 import static org.mockito.BDDMockito.given;
3536
36 @ExtendWith(MockitoExtension.class)
37 /**
38 *
39 */
40 @RunWith(MockitoJUnitRunner.class)
3741 public class Log4jLookupTest {
3842
3943 private final static File EXPECT = new File(System.getProperty("user.home"), "/a/b/c/d/e/log4j2.xml");
4549 @Mock
4650 private ConfigurationSource configSrc;
4751
48 @BeforeEach
49 public void setup() {
52 @Before
53 public void setup() throws URISyntaxException {
5054 ContextAnchor.THREAD_CONTEXT.set(mockCtx);
5155 given(config.getConfigurationSource()).willReturn(configSrc);
5256 given(configSrc.getFile()).willReturn(EXPECT);
5357 }
5458
55 @AfterEach
59 @After
5660 public void cleanup() {
5761 ContextAnchor.THREAD_CONTEXT.set(null);
5862 }
1414 */
1515 package org.apache.logging.log4j.core.lookup;
1616
17 import java.io.File;
18 import java.net.MalformedURLException;
19 import java.net.URISyntaxException;
20
1721 import org.apache.logging.log4j.core.LoggerContext;
1822 import org.apache.logging.log4j.core.config.Configuration;
1923 import org.apache.logging.log4j.core.config.ConfigurationAware;
2024 import org.apache.logging.log4j.core.config.ConfigurationSource;
2125 import org.apache.logging.log4j.core.impl.ContextAnchor;
22 import org.junit.jupiter.api.AfterEach;
23 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.junit.After;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
2630 import org.mockito.Mock;
27 import org.mockito.junit.jupiter.MockitoExtension;
28
29 import java.io.File;
31 import org.mockito.runners.MockitoJUnitRunner;
3032
3133 import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_LOCATION;
3234 import static org.apache.logging.log4j.core.lookup.Log4jLookup.KEY_CONFIG_PARENT_LOCATION;
33 import static org.junit.jupiter.api.Assertions.assertEquals;
35 import static org.junit.Assert.*;
3436 import static org.mockito.BDDMockito.given;
3537
36 @ExtendWith(MockitoExtension.class)
38 /**
39 *
40 */
41 @RunWith(MockitoJUnitRunner.class)
3742 public class Log4jLookupWithSpacesTest {
3843
3944 private final static File EXPECT = new File(System.getProperty("user.home"), "/a a/b b/c c/d d/e e/log4j2 file.xml");
4449 @Mock
4550 private ConfigurationSource configSrc;
4651
47 @BeforeEach
48 public void setup() {
52 @Before
53 public void setup() throws URISyntaxException, MalformedURLException {
4954 ContextAnchor.THREAD_CONTEXT.set(mockCtx);
5055 given(config.getConfigurationSource()).willReturn(configSrc);
5156 given(configSrc.getFile()).willReturn(EXPECT);
5257 }
5358
54 @AfterEach
59 @After
5560 public void cleanup() {
5661 ContextAnchor.THREAD_CONTEXT.set(null);
5762 }
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import org.junit.jupiter.api.Test;
18 import static org.junit.Assert.assertEquals;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import org.junit.Test;
2121
2222 /**
2323 * Tests {@link JmxRuntimeInputArgumentsLookup} from the command line, not a JUnit test.
3535 @Test
3636 public void testMap() {
3737 final JmxRuntimeInputArgumentsLookup lookup = JmxRuntimeInputArgumentsLookup.JMX_SINGLETON;
38 assertNull(lookup.lookup(null));
39 assertNull(lookup.lookup("X"));
40 assertNull(lookup.lookup("foo.txt"));
38 assertEquals(null, lookup.lookup(null));
39 assertEquals(null, lookup.lookup("X"));
40 assertEquals(null, lookup.lookup("foo.txt"));
4141 }
4242
4343 public void callFromMain() {
4444 final JmxRuntimeInputArgumentsLookup lookup = JmxRuntimeInputArgumentsLookup.JMX_SINGLETON;
45 assertNull(lookup.lookup(null));
46 assertNull(lookup.lookup("X"));
45 assertEquals(null, lookup.lookup(null));
46 assertEquals(null, lookup.lookup("X"));
4747 // Eclipse adds -Dfile.encoding=Cp1252
4848 // assertEquals("--file", lookup.lookup("0"));
4949 // assertEquals("foo.txt", lookup.lookup("1"));
+0
-41
log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsLookupApp.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.logging.log4j.core.lookup;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.config.Configurator;
21
22 /**
23 * Tests {@link org.apache.logging.log4j.core.lookup.MainMapLookup#MAIN_SINGLETON} from the command line, not a real
24 * JUnit test.
25 *
26 * From an IDE or CLI: --file foo.txt
27 *
28 * @since 2.4
29 */
30 public class MainInputArgumentsLookupApp {
31
32 public static void main(final String[] args) {
33 MainMapLookup.setMainArguments(args);
34 try (final LoggerContext ctx = Configurator.initialize(MainInputArgumentsLookupApp.class.getName(),
35 "target/test-classes/log4j-lookup-main.xml")) {
36 LogManager.getLogger().error("this is an error message");
37 }
38 }
39
40 }
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.LogManager;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.config.Configurator;
21
22 /**
23 * Tests {@link org.apache.logging.log4j.core.lookup.MainMapLookup#MAIN_SINGLETON} from the command line, not a real
24 * JUnit test.
25 *
26 * From an IDE or CLI: --file foo.txt
27 *
28 * @since 2.4
29 */
30 public class MainInputArgumentsLookupTest {
31
32 public static void main(final String[] args) {
33 MainMapLookup.setMainArguments(args);
34 try (final LoggerContext ctx = Configurator.initialize(MainInputArgumentsLookupTest.class.getName(),
35 "target/test-classes/log4j-lookup-main.xml")) {
36 LogManager.getLogger().error("this is an error message");
37 }
38 }
39
40 }
3333 final StackTraceElement[] stackTraceElements = entry.getValue();
3434 entry.getKey();
3535 // Can't use the thread name to look for "main" since anyone can set it.
36 // Can't use thread ID since it can be any positive value, and is likely vendor dependent. Oracle seems to
36 // Can't use thread ID since it can be any positive value, and is likely vender dependent. Oracle seems to
3737 // use 1.
3838 // We are left to look for "main" at the top of the stack
3939 if (stackTraceElements != null) {
+0
-56
log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainLookupTest.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.logging.log4j.core.lookup;
17
18 import org.junit.jupiter.api.Test;
19
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import static org.junit.jupiter.api.Assertions.*;
24
25 /**
26 * Tests MainLookup.
27 */
28 public class MainLookupTest {
29
30 @Test
31 public void testMainArgs(){
32 MainMapLookup.setMainArguments("--file", "foo.txt", "--verbose", "-x", "bar");
33 String str ="${key} ${main:-1} ${main:0} ${main:1} ${main:2} ${main:3} ${main:4} ${main:\\--file} ${main:foo.txt} ${main:\\--verbose} ${main:\\-x} ${main:bar} ${main:\\--quiet:-true}";
34 Map<String, String> properties = new HashMap<>();
35 properties.put("key", "value");
36 properties.put("bar", "default_bar_value");
37 Interpolator lookup = new Interpolator(properties);
38 StrSubstitutor substitutor = new StrSubstitutor(lookup);
39 String replacedValue = substitutor.replace(null, str);
40 String[] values = replacedValue.split(" ");
41 assertEquals("value", values[0], "Item 0 is incorrect ");
42 assertEquals("1", values[1], "Item 1 is incorrect ");
43 assertEquals("--file", values[2], "Item 2 is incorrect");
44 assertEquals("foo.txt", values[3], "Item 3 is incorrect");
45 assertEquals("--verbose", values[4], "Item 4 is incorrect");
46 assertEquals("-x", values[5], "Item 5 is incorrect");
47 assertEquals("bar", values[6], "Iten 6 is incorrect");
48 assertEquals("foo.txt", values[7], "Item 7 is incorrect");
49 assertEquals("--verbose", values[8], "Item 8 is incorrect");
50 assertEquals("-x", values[9], "Item 9 is incorrect");
51 assertEquals("bar", values[10], "Item 10 is incorrect");
52 assertEquals("default_bar_value", values[11], "Item 11 is incorrect");
53 assertEquals("true", values[12], "Item 12 is incorrect");
54 }
55 }
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import static org.junit.Assert.assertEquals;
19
1820 import java.util.HashMap;
1921
2022 import org.apache.logging.log4j.core.LogEvent;
2123 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2224 import org.apache.logging.log4j.message.MapMessage;
2325 import org.apache.logging.log4j.message.StringMapMessage;
24 import org.junit.jupiter.api.Test;
25
26 import static org.junit.jupiter.api.Assertions.*;
26 import org.junit.Test;
2727
2828 /**
2929 * Tests {@link MapLookup}.
3333 @Test
3434 public void testEmptyMap() {
3535 final MapLookup lookup = new MapLookup(new HashMap<String, String>());
36 assertNull(lookup.lookup(null));
37 assertNull(lookup.lookup("X"));
36 assertEquals(null, lookup.lookup(null));
37 assertEquals(null, lookup.lookup("X"));
3838 }
3939
4040 @Test
4242 final HashMap<String, String> map = new HashMap<>();
4343 map.put("A", "B");
4444 final MapLookup lookup = new MapLookup(map);
45 assertNull(lookup.lookup(null));
45 assertEquals(null, lookup.lookup(null));
4646 assertEquals("B", lookup.lookup("A"));
4747 }
4848
4949 @Test
5050 public void testNullMap() {
5151 final MapLookup lookup = new MapLookup();
52 assertNull(lookup.lookup(null));
53 assertNull(lookup.lookup("X"));
52 assertEquals(null, lookup.lookup(null));
53 assertEquals(null, lookup.lookup("X"));
5454 }
5555
5656 @Test
5757 public void testMainMap() {
58 MainMapLookup.setMainArguments("--file", "foo.txt");
58 MapLookup.setMainArguments(new String[] {
59 "--file",
60 "foo.txt" });
5961 final MapLookup lookup = MainMapLookup.MAIN_SINGLETON;
60 assertNull(lookup.lookup(null));
61 assertNull(lookup.lookup("X"));
62 assertEquals(null, lookup.lookup(null));
63 assertEquals(null, lookup.lookup("X"));
6264 assertEquals("--file", lookup.lookup("0"));
6365 assertEquals("foo.txt", lookup.lookup("1"));
6466 assertEquals("foo.txt", lookup.lookup("--file"));
65 assertNull(lookup.lookup("foo.txt"));
67 assertEquals(null, lookup.lookup("foo.txt"));
6668 }
6769
6870 @Test
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import java.io.File;
19 import java.io.IOException;
20
1821 import org.apache.commons.io.FileUtils;
1922 import org.apache.logging.log4j.LogManager;
2023 import org.apache.logging.log4j.Logger;
2124 import org.apache.logging.log4j.Marker;
2225 import org.apache.logging.log4j.MarkerManager;
23 import org.apache.logging.log4j.junit.LoggerContextSource;
24 import org.junit.jupiter.api.Tag;
25 import org.junit.jupiter.api.Test;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.nio.charset.StandardCharsets;
30
31 import static org.junit.jupiter.api.Assertions.assertFalse;
32 import static org.junit.jupiter.api.Assertions.assertTrue;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.Assert;
28 import org.junit.ClassRule;
29 import org.junit.Test;
3330
3431 /**
3532 * Tests {@link MarkerLookup} with a configuration file.
3633 *
3734 * @since 2.4
3835 */
39 @LoggerContextSource("log4j-marker-lookup.yaml")
40 @Tag("yaml")
4136 public class MarkerLookupConfigTest {
4237
38 @ClassRule
39 public static LoggerContextRule context = new LoggerContextRule("log4j-marker-lookup.yaml");
4340 public static final Marker PAYLOAD = MarkerManager.getMarker("PAYLOAD");
4441 private static final String PAYLOAD_LOG = "Message in payload.log";
4542
5653 logger.info(PAYLOAD, PAYLOAD_LOG);
5754 logger.info(PERFORMANCE, PERFORMANCE_LOG);
5855 {
59 final String log = FileUtils.readFileToString(new File("target/logs/sql.log"), StandardCharsets.UTF_8);
60 assertTrue(log.contains(SQL_LOG));
61 assertFalse(log.contains(PAYLOAD_LOG));
62 assertFalse(log.contains(PERFORMANCE_LOG));
56 final String log = FileUtils.readFileToString(new File("target/logs/sql.log"));
57 Assert.assertTrue(log.contains(SQL_LOG));
58 Assert.assertFalse(log.contains(PAYLOAD_LOG));
59 Assert.assertFalse(log.contains(PERFORMANCE_LOG));
6360 }
6461 {
65 final String log = FileUtils.readFileToString(new File("target/logs/payload.log"), StandardCharsets.UTF_8);
66 assertFalse(log.contains(SQL_LOG));
67 assertTrue(log.contains(PAYLOAD_LOG));
68 assertFalse(log.contains(PERFORMANCE_LOG));
62 final String log = FileUtils.readFileToString(new File("target/logs/payload.log"));
63 Assert.assertFalse(log.contains(SQL_LOG));
64 Assert.assertTrue(log.contains(PAYLOAD_LOG));
65 Assert.assertFalse(log.contains(PERFORMANCE_LOG));
6966 }
7067 {
71 final String log = FileUtils.readFileToString(new File("target/logs/performance.log"), StandardCharsets.UTF_8);
72 assertFalse(log.contains(SQL_LOG));
73 assertFalse(log.contains(PAYLOAD_LOG));
74 assertTrue(log.contains(PERFORMANCE_LOG));
68 final String log = FileUtils.readFileToString(new File("target/logs/performance.log"));
69 Assert.assertFalse(log.contains(SQL_LOG));
70 Assert.assertFalse(log.contains(PAYLOAD_LOG));
71 Assert.assertTrue(log.contains(PERFORMANCE_LOG));
7572 }
7673 }
7774 }
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNull;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.Marker;
2023 import org.apache.logging.log4j.MarkerManager;
2124 import org.apache.logging.log4j.core.LogEvent;
2225 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2326 import org.apache.logging.log4j.message.SimpleMessage;
24 import org.junit.jupiter.api.Test;
25
26 import static org.junit.jupiter.api.Assertions.*;
27 import org.junit.Test;
2728
2829 /**
2930 * Tests {@link MarkerLookup}.
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Assert;
19 import org.junit.Test;
1920
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertNull;
22
21 /**
22 *
23 */
2324 public class ResourceBundleLookupTest {
2425
2526 @Test
2627 public void testLookup() {
2728 final StrLookup lookup = new ResourceBundleLookup();
2829 lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle_en:KeyA");
29 assertEquals("ValueA", lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA"));
30 Assert.assertEquals("ValueA", lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA"));
3031 }
3132
3233 @Test
3334 public void testLookupWithLocale() {
3435 final StrLookup lookup = new ResourceBundleLookup();
3536 lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA");
36 assertEquals("ValueA", lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA"));
37 Assert.assertEquals("ValueA", lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA"));
3738 }
3839
3940 public void testMissingKey() {
4041 final StrLookup lookup = new ResourceBundleLookup();
41 assertNull(lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyUnkown"));
42 Assert.assertNull(lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyUnkown"));
4243 }
4344
4445 @Test
4546 public void testBadFormatBundleOnly() {
4647 final StrLookup lookup = new ResourceBundleLookup();
47 assertNull(lookup.lookup("X"));
48 Assert.assertNull(lookup.lookup("X"));
4849 }
4950 }
2020
2121 import org.apache.logging.log4j.ThreadContext;
2222 import org.apache.logging.log4j.core.LogEvent;
23 import org.junit.jupiter.api.AfterAll;
24 import org.junit.jupiter.api.BeforeAll;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
23 import org.junit.AfterClass;
24 import org.junit.BeforeClass;
25 import org.junit.Test;
26
27 import static org.junit.Assert.*;
2828
2929 public class StrSubstitutorTest {
3030
3232 private static final String TESTVAL = "TestValue";
3333
3434
35 @BeforeAll
35 @BeforeClass
3636 public static void before() {
3737 System.setProperty(TESTKEY, TESTVAL);
3838 }
3939
40 @AfterAll
40 @AfterClass
4141 public static void after() {
4242 System.clearProperty(TESTKEY);
4343 }
4545
4646 @Test
4747 public void testLookup() {
48 final Map<String, String> map = new HashMap<>();
48 final Map<String, String> map = new HashMap<String, String>();
4949 map.put(TESTKEY, TESTVAL);
5050 final StrLookup lookup = new Interpolator(new MapLookup(map));
5151 final StrSubstitutor subst = new StrSubstitutor(lookup);
6565
6666 @Test
6767 public void testDefault() {
68 final Map<String, String> map = new HashMap<>();
68 final Map<String, String> map = new HashMap<String, String>();
6969 map.put(TESTKEY, TESTVAL);
7070 final StrLookup lookup = new Interpolator(new MapLookup(map));
7171 final StrSubstitutor subst = new StrSubstitutor(lookup);
7777
7878 @Test
7979 public void testDefaultReferencesLookupValue() {
80 final Map<String, String> map = new HashMap<>();
80 final Map<String, String> map = new HashMap<String, String>();
8181 map.put(TESTKEY, "${java:version}");
8282 final StrLookup lookup = new Interpolator(new MapLookup(map));
8383 final StrSubstitutor subst = new StrSubstitutor(lookup);
8888
8989 @Test
9090 public void testInfiniteSubstitutionOnString() {
91 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<>()));
91 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<String, String>()));
9292 final StrSubstitutor subst = new StrSubstitutor(lookup);
9393 subst.setRecursiveEvaluationAllowed(true);
9494 String infiniteSubstitution = "${${::-${::-$${::-j}}}}";
9797
9898 @Test
9999 public void testInfiniteSubstitutionOnStringBuilder() {
100 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<>()));
100 final StrLookup lookup = new Interpolator(new MapLookup(new HashMap<String, String>()));
101101 final StrSubstitutor subst = new StrSubstitutor(lookup);
102102 subst.setRecursiveEvaluationAllowed(true);
103103 String infiniteSubstitution = "${${::-${::-$${::-j}}}}";
106106
107107 @Test
108108 public void testRecursiveSubstitution() {
109 final Map<String, String> map = new HashMap<>();
109 final Map<String, String> map = new HashMap<String, String>();
110110 map.put("first", "${ctx:first}");
111111 map.put("second", "secondValue");
112112 final StrLookup lookup = new Interpolator(new MapLookup(map));
117117
118118 @Test
119119 public void testRecursiveWithDefault() {
120 final Map<String, String> map = new HashMap<>();
120 final Map<String, String> map = new HashMap<String, String>();
121121 map.put("first", "${ctx:first:-default}");
122122 final StrLookup lookup = new Interpolator(new MapLookup(map));
123123 final StrSubstitutor subst = new StrSubstitutor(lookup);
127127
128128 @Test
129129 public void testRecursiveWithRecursiveDefault() {
130 final Map<String, String> map = new HashMap<>();
130 final Map<String, String> map = new HashMap<String, String>();
131131 map.put("first", "${ctx:first:-${ctx:first}}");
132132 final StrLookup lookup = new Interpolator(new MapLookup(map));
133133 final StrSubstitutor subst = new StrSubstitutor(lookup);
137137
138138 @Test
139139 public void testNestedSelfReferenceWithRecursiveEvaluation() {
140 final Map<String, String> map = new HashMap<>();
140 final Map<String, String> map = new HashMap<String, String>();
141141 map.put("first", "${${ctx:first}}");
142142 final StrLookup lookup = new Interpolator(new MapLookup(map));
143143 final StrSubstitutor subst = new StrSubstitutor(lookup);
147147
148148 @Test
149149 public void testRandomWithRecursiveDefault() {
150 final Map<String, String> map = new HashMap<>();
150 final Map<String, String> map = new HashMap<String, String>();
151151 map.put("first", "${env:RANDOM:-${ctx:first}}");
152152 final StrLookup lookup = new Interpolator(new MapLookup(map));
153153 final StrSubstitutor subst = new StrSubstitutor(lookup);
157157
158158 @Test
159159 public void testNoRecursiveEvaluationWithDefault() {
160 final Map<String, String> map = new HashMap<>();
160 final Map<String, String> map = new HashMap<String, String>();
161161 map.put("first", "${java:version}");
162162 map.put("second", "${java:runtime}");
163163 final StrLookup lookup = new Interpolator(new MapLookup(map));
168168
169169 @Test
170170 public void testNoRecursiveEvaluationWithDepthOne() {
171 final Map<String, String> map = new HashMap<>();
171 final Map<String, String> map = new HashMap<String, String>();
172172 map.put("first", "${java:version}");
173173 final StrLookup lookup = new Interpolator(new MapLookup(map));
174174 final StrSubstitutor subst = new StrSubstitutor(lookup);
175175 subst.setRecursiveEvaluationAllowed(false);
176176 assertEquals("${java:version}", subst.replace("${ctx:first}"));
177 }
178
179 @Test
180 public void testLookupsNestedWithoutRecursiveEvaluation() {
181 final Map<String, String> map = new HashMap<>();
182 map.put("first", "${java:version}");
183 final StrLookup lookup = new Interpolator(new MapLookup(map));
184 final StrSubstitutor subst = new StrSubstitutor(lookup);
185 subst.setRecursiveEvaluationAllowed(false);
186 assertEquals("${java:version}", subst.replace("${${lower:C}t${lower:X}:first}"));
187177 }
188178
189179 @Test
2020 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2121 import org.apache.logging.log4j.message.Message;
2222 import org.apache.logging.log4j.message.StructuredDataMessage;
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
27 /**
28 *
29 */
2730 public class StructuredDataLookupTest {
2831
2932 private static final String TESTKEY = "type";
1515 */
1616 package org.apache.logging.log4j.core.lookup;
1717
18 import org.junit.jupiter.api.AfterAll;
19 import org.junit.jupiter.api.BeforeAll;
20 import org.junit.jupiter.api.Test;
18 import org.junit.AfterClass;
19 import org.junit.BeforeClass;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2323
24 /**
25 *
26 */
2427 public class SystemPropertiesLookupTest {
2528
2629 private static final String TESTKEY = "TestKey";
2730 private static final String TESTVAL = "TestValue";
2831
29 @BeforeAll
32 @BeforeClass
3033 public static void before() {
3134 System.setProperty(TESTKEY, TESTVAL);
3235 }
3336
34 @AfterAll
37 @AfterClass
3538 public static void after() {
3639 System.clearProperty(TESTKEY);
3740 }
1616 package org.apache.logging.log4j.core.message;
1717
1818 import org.apache.logging.log4j.message.ThreadDumpMessage;
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * Tests that ThreadDumpMessage uses ExtendedThreadInformation when available.
3030
3131 final String message = msg.getFormattedMessage();
3232 //System.out.print(message);
33 assertTrue(message.contains(" Id="), "No header");
33 assertTrue("No header", message.contains(" Id="));
3434 }
3535 }
1616
1717 package org.apache.logging.log4j.core.net;
1818
19 import static org.junit.jupiter.api.Assertions.assertFalse;
20 import static org.junit.jupiter.api.Assertions.assertThrows;
19 import static org.junit.Assert.assertFalse;
2120
2221 import java.util.Properties;
2322
24 import org.junit.jupiter.api.Test;
23 import org.apache.logging.log4j.test.JUnit5Bridge;
24 import org.junit.Test;
2525
2626 /**
2727 * Tests {@link JndiManager}.
4747 public void testIsJndiLookupEnabled() {
4848 assertFalse(JndiManager.isJndiLookupEnabled());
4949 }
50
50
5151 @Test
5252 public void testNoInstanceByDefault() {
53 assertThrows(IllegalStateException.class, () -> JndiManager.getDefaultManager());
54 assertThrows(IllegalStateException.class, () -> JndiManager.getDefaultManager(null));
55 assertThrows(IllegalStateException.class, () -> JndiManager.getDefaultManager("A"));
56 assertThrows(IllegalStateException.class, () -> JndiManager.getJndiManager(null));
57 assertThrows(IllegalStateException.class, () -> JndiManager.getJndiManager(new Properties()));
58 assertThrows(IllegalStateException.class, () -> JndiManager.getJndiManager(null, null, null, null, null, null));
59 assertThrows(IllegalStateException.class, () -> JndiManager.getJndiManager("A", "A", "A", "A", "A", new Properties()));
53 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
54 @Override
55 public void run() {
56 JndiManager.getDefaultManager();
57 }
58 });
59 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
60 @Override
61 public void run() {
62 JndiManager.getDefaultManager(null);
63 }
64 });
65 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
66 @Override
67 public void run() {
68 JndiManager.getDefaultManager("A");
69 }
70 });
71 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
72 @Override
73 public void run() {
74 JndiManager.getJndiManager(null);
75 }
76 });
77 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
78 @Override
79 public void run() {
80 JndiManager.getJndiManager(new Properties());
81 }
82 });
83 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
84 @Override
85 public void run() {
86 JndiManager.getJndiManager(null, null, null, null, null, null);
87 }
88 });
89 JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
90 @Override
91 public void run() {
92 JndiManager.getJndiManager("A", "A", "A", "A", "A", new Properties());
93 }
94 });
6095 }
61
62
96
6397 }
1616 package org.apache.logging.log4j.core.net;
1717
1818 import org.apache.logging.log4j.Level;
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
23 /**
24 *
25 */
2326 public class PriorityTest {
2427
2528 @Test
2629 public void testP1() {
2730 final int p = Priority.getPriority(Facility.AUTH, Level.INFO);
28 assertEquals(38, p, "Expected priority value is 38, got " + p);
31 assertTrue("Expected priority value is 38, got "+ p, p == 38);
2932 }
3033 }
+0
-85
log4j-core/src/test/java/org/apache/logging/log4j/core/net/SmtpManagerTest.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
17 package org.apache.logging.log4j.core.net;
18
19 import static org.hamcrest.CoreMatchers.instanceOf;
20 import static org.hamcrest.CoreMatchers.is;
21 import static org.hamcrest.MatcherAssert.assertThat;
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.async.RingBufferLogEvent;
26 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
27 import org.apache.logging.log4j.core.impl.MementoMessage;
28 import org.apache.logging.log4j.core.impl.MutableLogEvent;
29 import org.apache.logging.log4j.core.util.ClockFactory;
30 import org.apache.logging.log4j.core.util.DummyNanoClock;
31 import org.apache.logging.log4j.message.ReusableMessage;
32 import org.apache.logging.log4j.message.ReusableSimpleMessage;
33 import org.junit.jupiter.api.Test;
34
35 /**
36 * Unit tests for {@link SmtpManager}.
37 */
38 class SmtpManagerTest {
39
40 @Test
41 void testCreateManagerName() {
42 String managerName = SmtpManager.createManagerName("to", "cc", null, "from", null, "LOG4J2-3107",
43 "proto", "smtp.log4j.com", 4711, "username", false, "filter");
44 assertEquals("SMTP:to:cc::from::LOG4J2-3107:proto:smtp.log4j.com:4711:username::filter", managerName);
45 }
46
47 private void testAdd(LogEvent event) {
48 SmtpManager smtpManager = SmtpManager.getSmtpManager(null, "to", "cc", "bcc", "from", "replyTo", "subject", "protocol", "host", 0, "username", "password", false, "filterName", 10, null);
49 smtpManager.removeAllBufferedEvents(); // in case this smtpManager is reused
50 smtpManager.add(event);
51
52 LogEvent[] bufferedEvents = smtpManager.removeAllBufferedEvents();
53 assertThat("unexpected number of buffered events", bufferedEvents.length, is(1));
54 assertThat("expected the immutable version of the event to be buffered", bufferedEvents[0].getMessage(), is(instanceOf(MementoMessage.class)));
55 }
56
57 // LOG4J2-3172: make sure existing protections are not violated
58 @Test
59 void testAdd_WhereLog4jLogEventWithReusableMessage() {
60 LogEvent event = new Log4jLogEvent.Builder().setMessage(getReusableMessage("test message")).build();
61 testAdd(event);
62 }
63
64 // LOG4J2-3172: make sure existing protections are not violated
65 @Test
66 void testAdd_WhereMutableLogEvent() {
67 MutableLogEvent event = new MutableLogEvent(new StringBuilder("test message"), null);
68 testAdd(event);
69 }
70
71 // LOG4J2-3172
72 @Test
73 void testAdd_WhereRingBufferLogEvent() {
74 RingBufferLogEvent event = new RingBufferLogEvent();
75 event.setValues(null, null, null, null, null, getReusableMessage("test message"), null, null, null, 0, null, 0, null, ClockFactory.getClock(), new DummyNanoClock());
76 testAdd(event);
77 }
78
79 private ReusableMessage getReusableMessage(String text) {
80 ReusableSimpleMessage message = new ReusableSimpleMessage();
81 message.set(text);
82 return message;
83 }
84 }
+0
-419
log4j-core/src/test/java/org/apache/logging/log4j/core/net/SocketAppenderReconnectTest.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.logging.log4j.core.net;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
23 import org.apache.logging.log4j.core.config.Configuration;
24 import org.apache.logging.log4j.core.config.Configurator;
25 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
26 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
27 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
28 import org.apache.logging.log4j.core.net.TcpSocketManager.HostResolver;
29 import org.apache.logging.log4j.status.StatusLogger;
30 import org.apache.logging.log4j.util.PropertiesUtil;
31 import org.junit.jupiter.api.Test;
32
33 import java.io.BufferedReader;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import java.net.InetSocketAddress;
38 import java.net.ServerSocket;
39 import java.net.Socket;
40 import java.net.SocketException;
41 import java.nio.charset.StandardCharsets;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.List;
45 import java.util.concurrent.BlockingQueue;
46 import java.util.concurrent.LinkedBlockingQueue;
47 import java.util.concurrent.TimeUnit;
48 import java.util.concurrent.TimeoutException;
49 import java.util.stream.Collectors;
50 import java.util.stream.IntStream;
51
52 import static org.awaitility.Awaitility.await;
53 import static org.junit.jupiter.api.Assertions.*;
54
55 /**
56 * Tests reconnection support of {@link org.apache.logging.log4j.core.appender.SocketAppender}.
57 */
58 class SocketAppenderReconnectTest {
59
60 private static final Logger LOGGER = StatusLogger.getLogger();
61
62 /**
63 * Tests if failures are propagated when reconnection fails.
64 *
65 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-2829">LOG4J2-2829</a>
66 */
67 @Test
68 void repeating_reconnect_failures_should_be_propagated() throws Exception {
69 try (final LineReadingTcpServer server = new LineReadingTcpServer()) {
70
71 // Start the server.
72 server.start("Main", 0);
73 final int port = server.serverSocket.getLocalPort();
74
75 // Initialize the logger context.
76 final LoggerContext loggerContext = initContext(port);
77 try {
78
79 // Verify the initial working state.
80 verifyLoggingSuccess(server);
81
82 // Stop the server, and verify the logging failure.
83 server.close();
84 verifyLoggingFailure();
85
86 // Start the server again, and verify the logging success.
87 server.start("Main", port);
88 verifyLoggingSuccess(server);
89
90 }
91
92 // Shutdown the logger context.
93 finally {
94 Configurator.shutdown(loggerContext);
95 }
96
97 }
98 }
99
100 /**
101 * Tests if all the {@link InetSocketAddress}es returned by an {@link HostResolver} is used for fallback on reconnect attempts.
102 */
103 @Test
104 void reconnect_should_fallback_when_there_are_multiple_resolved_hosts() throws Exception {
105 try (final LineReadingTcpServer primaryServer = new LineReadingTcpServer();
106 final LineReadingTcpServer secondaryServer = new LineReadingTcpServer()) {
107
108 // Start servers.
109 primaryServer.start("Primary", 0);
110 secondaryServer.start("Secondary", 0);
111
112 // Mock the host resolver.
113 final FixedHostResolver hostResolver = FixedHostResolver.ofServers(primaryServer, secondaryServer);
114 TcpSocketManager.setHostResolver(hostResolver);
115 try {
116
117 // Initialize the logger context.
118 final LoggerContext loggerContext = initContext(
119 // Passing an invalid port, since the resolution is supposed to be performed by the mocked host resolver anyway.
120 0);
121 try {
122
123 // Verify the initial working state on the primary server.
124 verifyLoggingSuccess(primaryServer);
125
126 // Stop the primary server, and verify the logging success due to fallback on to the secondary server.
127 primaryServer.close();
128 verifyLoggingSuccess(secondaryServer);
129
130 }
131
132 // Shutdown the logger context.
133 finally {
134 Configurator.shutdown(loggerContext);
135 }
136
137 } finally {
138 // Reset the host resolver.
139 TcpSocketManager.setHostResolver(new HostResolver());
140 }
141
142 }
143 }
144
145 private static LoggerContext initContext(final int port) {
146
147 // Create the configuration builder.
148 final ConfigurationBuilder<BuiltConfiguration> configBuilder = ConfigurationBuilderFactory
149 .newConfigurationBuilder()
150 .setStatusLevel(Level.ERROR)
151 .setConfigurationName(SocketAppenderReconnectTest.class.getSimpleName());
152
153 // Create the configuration.
154 final String appenderName = "Socket";
155 final Configuration config = configBuilder
156 .add(configBuilder
157 .newAppender(appenderName, "SOCKET")
158 .addAttribute("host", "localhost")
159 .addAttribute("port", String.valueOf(port))
160 .addAttribute("protocol", Protocol.TCP)
161 .addAttribute("ignoreExceptions", false)
162 .addAttribute("reconnectionDelayMillis", 10)
163 .addAttribute("immediateFlush", true)
164 .add(configBuilder
165 .newLayout("PatternLayout")
166 .addAttribute("pattern", "%m%n")))
167 .add(configBuilder.newLogger("org.apache.logging.log4j", Level.DEBUG))
168 .add(configBuilder
169 .newRootLogger(Level.ERROR)
170 .add(configBuilder.newAppenderRef(appenderName)))
171 .build(false);
172
173 // Initialize the configuration.
174 return Configurator.initialize(config);
175
176 }
177
178 private static void verifyLoggingSuccess(final LineReadingTcpServer server) throws Exception {
179 final int messageCount = 100;
180 // noinspection ConstantConditions
181 assertTrue(messageCount > 1, "was expecting messageCount to be bigger than 1 due to LOG4J2-2829, found: " + messageCount);
182 final List<String> expectedMessages = IntStream
183 .range(0, messageCount)
184 .mapToObj(messageIndex -> String.format("m%02d", messageIndex))
185 .collect(Collectors.toList());
186 final Logger logger = LogManager.getLogger();
187 for (int messageIndex = 0; messageIndex < expectedMessages.size(); messageIndex++) {
188 final String message = expectedMessages.get(messageIndex);
189 // Due to socket initialization, the first write() might need some extra effort.
190 if (messageIndex == 0) {
191 awaitUntilSucceeds(() -> logger.info(message));
192 } else {
193 logger.info(message);
194 }
195 }
196 expectedMessages.forEach(logger::info);
197 final List<String> actualMessages = server.pollLines(messageCount);
198 assertEquals(expectedMessages, actualMessages);
199 }
200
201 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 }
215 await()
216 .pollInterval(pollIntervalMillis, TimeUnit.MILLISECONDS)
217 .atMost(timeoutSeconds, TimeUnit.SECONDS)
218 .until(() -> {
219 runnable.run();
220 return true;
221 });
222 }
223
224 private static void verifyLoggingFailure() {
225 final Logger logger = LogManager.getLogger();
226 int retryCount = 3;
227 // noinspection ConstantConditions
228 assertTrue(retryCount > 1, "was expecting retryCount to be bigger than 1 due to LOG4J2-2829, found: " + retryCount);
229 for (int i = 0; i < retryCount; i++) {
230 try {
231 logger.info("should fail #" + i);
232 fail("should have failed #" + i);
233 } catch (final AppenderLoggingException ignored) {}
234 }
235 }
236
237 /**
238 * A simple TCP server implementation reading the accepted connection's input stream into a blocking queue of lines.
239 * <p>
240 * The implementation is thread-safe, yet connections are handled sequentially, i.e., no parallelization.
241 * The input stream of the connection is decoded in UTF-8.
242 * </p>
243 */
244 private static final class LineReadingTcpServer implements AutoCloseable {
245
246 private volatile boolean running = false;
247
248 private ServerSocket serverSocket = null;
249
250 private Socket clientSocket = null;
251
252 private Thread readerThread = null;
253
254 private final BlockingQueue<String> lines = new LinkedBlockingQueue<>();
255
256 private LineReadingTcpServer() {}
257
258 private synchronized void start(final String name, final int port) throws IOException {
259 if (!running) {
260 running = true;
261 serverSocket = createServerSocket(port);
262 readerThread = createReaderThread(name);
263 }
264 }
265
266 private ServerSocket createServerSocket(final int port) throws IOException {
267 final ServerSocket serverSocket = new ServerSocket(port);
268 serverSocket.setReuseAddress(true);
269 serverSocket.setSoTimeout(0); // Zero indicates accept() will block indefinitely.
270 return serverSocket;
271 }
272
273 private Thread createReaderThread(final String name) {
274 final String threadName = "LineReadingTcpSocketServerReader-" + name;
275 final Thread thread = new Thread(this::acceptClients, threadName);
276 thread.setDaemon(true); // Avoid blocking JVM exit.
277 thread.setUncaughtExceptionHandler((ignored, error) ->
278 LOGGER.error("uncaught reader thread exception", error));
279 thread.start();
280 return thread;
281 }
282
283 private void acceptClients() {
284 try {
285 while (running) {
286 acceptClient();
287 }
288 } catch (final Exception error) {
289 LOGGER.error("failed accepting client connections", error);
290 }
291 }
292
293 private void acceptClient() throws Exception {
294
295 // Accept the client connection.
296 final Socket clientSocket;
297 try {
298 clientSocket = serverSocket.accept();
299 } catch (SocketException ignored) {
300 return;
301 }
302 clientSocket.setSoLinger(true, 0); // Enable immediate forceful close.
303 synchronized (this) {
304 if (running) {
305 this.clientSocket = clientSocket;
306 }
307 }
308
309 // Read from the client.
310 try (final InputStream clientInputStream = clientSocket.getInputStream();
311 final InputStreamReader clientReader = new InputStreamReader(clientInputStream, StandardCharsets.UTF_8);
312 final BufferedReader clientBufferedReader = new BufferedReader(clientReader)) {
313 while (running) {
314 final String line = clientBufferedReader.readLine();
315 if (line == null) {
316 break;
317 }
318 lines.put(line);
319 }
320 }
321
322 // Ignore connection failures.
323 catch (final SocketException ignored) {}
324
325 // Clean up the client connection.
326 finally {
327 try {
328 synchronized (this) {
329 if (!clientSocket.isClosed()) {
330 clientSocket.shutdownOutput();
331 clientSocket.close();
332 }
333 this.clientSocket = null;
334 }
335 } catch (final Exception error) {
336 LOGGER.error("failed closing client socket", error);
337 }
338 }
339
340 }
341
342 @Override
343 public void close() throws Exception {
344
345 // Stop the reader, if running.
346 Thread stoppedReaderThread = null;
347 synchronized (this) {
348 if (running) {
349 running = false;
350 // acceptClient() might have closed the client socket due to a connection failure and haven't created a new one yet.
351 // Hence, here we double-check if the client connection is in place.
352 if (clientSocket != null && !clientSocket.isClosed()) {
353 // Interrupting a thread is not sufficient to unblock operations waiting on socket I/O: https://stackoverflow.com/a/4426050/1278899
354 // Hence, here we close the client socket to unblock the read from the client socket.
355 clientSocket.close();
356 }
357 serverSocket.close();
358 stoppedReaderThread = readerThread;
359 clientSocket = null;
360 serverSocket = null;
361 readerThread = null;
362 }
363 }
364
365 // We wait for the termination of the reader thread outside the synchronized block.
366 // Otherwise, there is a chance of deadlock with this join() and the synchronized block inside the acceptClient().
367 if (stoppedReaderThread != null) {
368 stoppedReaderThread.join();
369 }
370
371 }
372
373 private List<String> pollLines(@SuppressWarnings("SameParameterValue") final int count) throws InterruptedException, TimeoutException {
374 final List<String> polledLines = new ArrayList<>(count);
375 for (int i = 0; i < count; i++) {
376 final String polledLine = pollLine();
377 polledLines.add(polledLine);
378 }
379 return polledLines;
380 }
381
382 private String pollLine() throws InterruptedException, TimeoutException {
383 final String line = lines.poll(2, TimeUnit.SECONDS);
384 if (line == null) {
385 throw new TimeoutException();
386 }
387 return line;
388 }
389
390 }
391
392 /**
393 * {@link HostResolver} implementation always resolving to the given list of {@link #addresses}.
394 */
395 private static final class FixedHostResolver extends HostResolver {
396
397 private final List<InetSocketAddress> addresses;
398
399 private FixedHostResolver(List<InetSocketAddress> addresses) {
400 this.addresses = addresses;
401 }
402
403 private static FixedHostResolver ofServers(LineReadingTcpServer... servers) {
404 List<InetSocketAddress> addresses = Arrays
405 .stream(servers)
406 .map(server -> (InetSocketAddress) server.serverSocket.getLocalSocketAddress())
407 .collect(Collectors.toList());
408 return new FixedHostResolver(addresses);
409 }
410
411 @Override
412 public List<InetSocketAddress> resolveHost(String ignoredHost, int ignoredPort) {
413 return addresses;
414 }
415
416 }
417
418 }
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.net;
17
18 import java.io.BufferedReader;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.net.ServerSocket;
23 import java.net.Socket;
24 import java.util.concurrent.Callable;
25 import java.util.concurrent.ExecutorService;
26 import java.util.concurrent.Executors;
27 import java.util.concurrent.Future;
28
29 import org.apache.logging.log4j.Logger;
30 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
31 import org.apache.logging.log4j.junit.LoggerContextRule;
32 import org.apache.logging.log4j.test.AvailablePortFinder;
33 import org.junit.ClassRule;
34 import org.junit.Ignore;
35 import org.junit.Test;
36
37 import static org.junit.Assert.*;
38
39 @Ignore("Currently needs better port choosing support")
40 public class SocketMessageLossTest {
41 private static final int SOCKET_PORT = AvailablePortFinder.getNextAvailable();
42
43 private static final String CONFIG = "log4j-socket2.xml";
44
45 @ClassRule
46 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
47
48 @Test
49 public void testSocket() throws Exception {
50 TestSocketServer testServer;
51 ExecutorService executor = null;
52 Future<InputStream> futureIn;
53
54 try {
55 executor = Executors.newSingleThreadExecutor();
56 System.err.println("Initializing server");
57 testServer = new TestSocketServer();
58 futureIn = executor.submit(testServer);
59
60 //System.err.println("Initializing logger");
61 final Logger logger = context.getLogger();
62
63 String message = "Log #1";
64 logger.error(message);
65
66 final BufferedReader reader = new BufferedReader(new InputStreamReader(futureIn.get()));
67 assertEquals(message, reader.readLine());
68
69 //System.err.println("Closing server");
70 closeQuietly(testServer);
71 assertTrue("Server not shutdown", testServer.server.isClosed());
72
73 //System.err.println("Sleeping to ensure no race conditions");
74 Thread.sleep(1000);
75
76 message = "Log #2";
77 try {
78 logger.error(message);
79 fail("Expected exception not thrown");
80 } catch (final AppenderLoggingException e) {
81 // An exception is expected.
82 }
83
84 message = "Log #3";
85 try {
86 logger.error(message);
87 fail("Expected exception not thrown");
88 } catch (final AppenderLoggingException e) {
89 // An exception is expected.
90 }
91 } finally {
92 closeQuietly(executor);
93 }
94 }
95
96
97 private static class TestSocketServer implements Callable<InputStream> {
98 private final ServerSocket server;
99 private Socket client;
100
101 public TestSocketServer() throws Exception {
102 server = new ServerSocket(SOCKET_PORT);
103 }
104
105 @Override
106 public InputStream call() throws Exception {
107 client = server.accept();
108 return client.getInputStream();
109 }
110
111 public void close() {
112 closeQuietly(client);
113 closeQuietly(server);
114 }
115
116 private static void closeQuietly(final ServerSocket socket) {
117 if (null != socket) {
118 try {
119 socket.close();
120 } catch (final IOException ignore) {
121 }
122 }
123 }
124
125 private static void closeQuietly(final Socket socket) {
126 if (null != socket) {
127 try {
128 socket.setSoLinger(true, 0);
129 socket.close();
130 } catch (final IOException ignore) {
131 }
132 }
133 }
134 }
135
136 private static void closeQuietly(final ExecutorService executor) {
137 if (null != executor) {
138 executor.shutdownNow();
139 }
140 }
141
142 private static void closeQuietly(final TestSocketServer testServer) {
143 if (null != testServer) {
144 testServer.close();
145 }
146 }
147 }
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.net;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
22 import org.apache.logging.log4j.core.config.Configurator;
23 import org.apache.logging.log4j.test.AvailablePortFinder;
24 import org.apache.logging.log4j.util.Strings;
25 import org.junit.After;
26 import org.junit.AfterClass;
27 import org.junit.BeforeClass;
28 import org.junit.Test;
29
30 import java.io.BufferedReader;
31 import java.io.IOException;
32 import java.io.InputStreamReader;
33 import java.net.InetAddress;
34 import java.net.InetSocketAddress;
35 import java.net.ServerSocket;
36 import java.net.Socket;
37 import java.net.SocketException;
38 import java.net.UnknownHostException;
39 import java.util.ArrayList;
40 import java.util.List;
41
42 import static org.junit.Assert.*;
43
44 //@Ignore("Currently needs better port choosing support")
45 public class SocketReconnectTest {
46 private static final int SOCKET_PORT1 = AvailablePortFinder.getNextAvailable();
47 private static final int SOCKET_PORT2 = AvailablePortFinder.getNextAvailable();
48
49 private static final String CONFIG = "log4j-socket.xml";
50
51 private static final String SHUTDOWN = "Shutdown" + Strings.LINE_SEPARATOR +
52 "................................................................" + Strings.LINE_SEPARATOR +
53 "................................................................" + Strings.LINE_SEPARATOR +
54 "................................................................" + Strings.LINE_SEPARATOR +
55 "................................................................" + Strings.LINE_SEPARATOR;
56
57 public static LocalHostResolver resolver = new LocalHostResolver();
58
59 private static LoggerContext loggerContext;
60
61 private static final List<String> list = new ArrayList<>();
62 private static int[] ports;
63 private static TestSocketServer server1;
64 private static TestSocketServer server2;
65 private static Logger logger;
66
67
68 @BeforeClass
69 public static void beforeClass() throws IOException, InterruptedException {
70 server1 = new TestSocketServer(0);
71 server2 = new TestSocketServer(0);
72 server1.start();
73 server2.start();
74 Thread.sleep(100);
75 ports = new int[] { server1.getPort(), server2.getPort()};
76 resolver.ports = ports;
77 TcpSocketManager.setHostResolver(resolver);
78 loggerContext = Configurator.initialize("SocketReconnectTest", SocketReconnectTest.class.getClassLoader(),
79 CONFIG);
80 logger = LogManager.getLogger(SocketReconnectTest.class);
81 server1.shutdown();
82 server1.join();
83 server2.shutdown();
84 server2.join();
85 server1 = null;
86 server2 = null;
87 Thread.sleep(100);
88 list.clear();
89 }
90
91 @AfterClass
92 public static void afterClass() {
93 Configurator.shutdown(loggerContext);
94 }
95
96 @After
97 public void after() throws InterruptedException {
98 if (server1 != null) {
99 server1.shutdown();
100 server1.join();
101 }
102 if (server2 != null) {
103 server2.shutdown();
104 server2.join();
105 }
106 server1 = null;
107 server2 = null;
108 Thread.sleep(300);
109 }
110
111 @Test
112 public void testReconnect() throws Exception {
113 list.clear();
114 resolver.ports = new int[] {ports[0]};
115 server1 = new TestSocketServer(ports[0]);
116 server1.start();
117 Thread.sleep(200);
118 String message = "Log #1";
119 String msg = null;
120 for (int i = 0; i < 5; ++i) {
121 logger.error(message);
122 Thread.sleep(100);
123 if (list.size() > 0) {
124 msg = list.get(0);
125 if (msg != null) {
126 break;
127 }
128 }
129 }
130 assertNotNull("No message", msg);
131 assertEquals(message, msg);
132
133 logger.error(SHUTDOWN);
134 server1.join();
135
136 list.clear();
137
138 message = "Log #2";
139 boolean exceptionCaught = false;
140
141 for (int i = 0; i < 100; ++i) {
142 try {
143 logger.error(message);
144 } catch (final AppenderLoggingException e) {
145 exceptionCaught = true;
146 break;
147 // System.err.println("Caught expected exception");
148 }
149 }
150 assertTrue("No Exception thrown", exceptionCaught);
151 message = "Log #3";
152
153
154 server1 = new TestSocketServer(ports[0]);
155 server1.start();
156 Thread.sleep(300);
157
158 msg = null;
159 for (int i = 0; i < 5; ++i) {
160 logger.error(message);
161 Thread.sleep(100);
162 if (list.size() > 0) {
163 msg = list.get(0);
164 if (msg != null) {
165 break;
166 }
167 }
168 }
169 assertNotNull("No message", msg);
170 assertEquals(message, msg);
171 logger.error(SHUTDOWN);
172 server1.join();
173 }
174
175 @Test
176 public void testFailover() throws Exception {
177 list.clear();
178 server1 = new TestSocketServer(ports[0]);
179 server2 = new TestSocketServer(ports[1]);
180 resolver.ports = ports;
181 server1.start();
182 server2.start();
183 Thread.sleep(100);
184
185 String message = "Log #1";
186
187 String msg = null;
188 for (int i = 0; i < 5; ++i) {
189 logger.error(message);
190 Thread.sleep(100);
191 if (list.size() > 0) {
192 msg = list.get(0);
193 if (msg != null) {
194 break;
195 }
196 }
197 }
198 assertNotNull("No message", msg);
199 assertEquals(message, msg);
200
201 server1.shutdown();
202 server1.join();
203
204 list.clear();
205
206 message = "Log #2";
207 for (int i = 0; i < 5; ++i) {
208 logger.error(message);
209 Thread.sleep(100);
210 if (list.size() > 0) {
211 msg = list.get(0);
212 if (msg != null) {
213 break;
214 }
215 }
216 }
217 assertNotNull("No message", msg);
218 assertEquals(message, msg);
219
220 server2.shutdown();
221 server2.join();
222 }
223
224
225 private static class TestSocketServer extends Thread {
226 private volatile boolean shutdown = false;
227 private volatile boolean started = false;
228 private volatile Socket client;
229 private final int port;
230 private ServerSocket server;
231
232 public TestSocketServer(int port) throws IOException {
233 this.port = port;
234 server = new ServerSocket(port);
235 }
236
237 public int getPort() {
238 return port == 0 ? server.getLocalPort() : port;
239 }
240
241 public void shutdown() {
242 if (!shutdown) {
243 shutdown = true;
244 if (server != null && server.isBound()) {
245 try {
246 if (client != null) {
247 Socket serverClient = client;
248 client = null;
249 serverClient.shutdownInput();
250 serverClient.shutdownOutput();
251 serverClient.setSoLinger(true, 0);
252 serverClient.close();
253 }
254 ServerSocket serverSocket = server;
255 server = null;
256 serverSocket.close();
257 } catch (Exception ex) {
258 System.out.println("Unable to send shutdown message");
259 ex.printStackTrace();
260 }
261 }
262 return;
263 }
264 }
265
266 @Override
267 public void run() {
268 client = null;
269 try {
270 client = server.accept();
271 started = true;
272 while (!shutdown) {
273 final BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
274 final String line = reader.readLine();
275 if (line == null || line.equals("Shutdown")) {
276 shutdown = true;
277 } else {
278 list.add(line);
279 }
280 }
281 } catch (final SocketException ex) {
282 if (!shutdown) {
283 ex.printStackTrace();
284 }
285 } catch (final Exception ex) {
286 ex.printStackTrace();
287 } finally {
288 if (client != null && !client.isClosed()) {
289 try {
290 client.setSoLinger(true, 0);
291 client.shutdownOutput();
292 client.close();
293 } catch (final Exception ex) {
294 System.out.println("Unable to close socket: " + ex.getMessage());
295 }
296 }
297 if (server != null && !server.isClosed()) {
298 try {
299 server.close();
300 } catch (final Exception ex) {
301 System.out.println("Unable to close server socket: " + ex.getMessage());
302 }
303 }
304 }
305 }
306 }
307
308 private static class LocalHostResolver extends TcpSocketManager.HostResolver {
309 public volatile int[] ports;
310
311 @Override
312 public List<InetSocketAddress> resolveHost(String host, int port) throws UnknownHostException {
313 int[] socketPorts = ports;
314 List<InetSocketAddress> socketAddresses = new ArrayList<>(ports.length);
315 InetAddress addr = InetAddress.getLocalHost();
316 for (int i = 0; i < socketPorts.length; ++i){
317 socketAddresses.add(new InetSocketAddress(addr, socketPorts[i]));
318 }
319 return socketAddresses;
320 }
321 }
322 }
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.net;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.ServerSocket;
21 import java.net.Socket;
22 import java.util.concurrent.Callable;
23
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.apache.logging.log4j.test.AvailablePortFinder;
28 import org.junit.ClassRule;
29 import org.junit.Ignore;
30 import org.junit.Test;
31
32 import static org.junit.Assert.*;
33
34 @Ignore("Currently needs better port choosing support")
35 public class SocketTest {
36 private static final int SOCKET_PORT = AvailablePortFinder.getNextAvailable();
37
38 private static final String CONFIG = "log4j-socket.xml";
39
40 @ClassRule
41 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
42
43 @Test
44 public void testConnect() throws Exception {
45 // TODO: there's a JUnit rule that simplifies this (matt)
46 System.err.println("Initializing logger");
47 Logger logger = null;
48 try {
49 logger = context.getLogger();
50 } catch (final NullPointerException e) {
51 fail("Unexpected exception; should not occur until first logging statement " + e.getMessage());
52 }
53
54 final String message = "Log #1";
55 try {
56 logger.error(message);
57 fail("Expected exception not thrown");
58 } catch (final AppenderLoggingException e) {
59 //System.err.println("Expected exception here, but already errored out when initializing logger");
60 }
61 }
62
63 private static class TestSocketServer implements Callable<InputStream> {
64 private ServerSocket server;
65 private Socket client;
66
67 @Override
68 public InputStream call() throws Exception {
69 server = new ServerSocket(SOCKET_PORT);
70 client = server.accept();
71 return client.getInputStream();
72 }
73
74 public void close() {
75 closeQuietly(client);
76 closeQuietly(server);
77 }
78
79 private static void closeQuietly(final ServerSocket socket) {
80 if (null != socket) {
81 try {
82 socket.close();
83 } catch (final IOException ignore) {
84 }
85 }
86 }
87
88 private static void closeQuietly(final Socket socket) {
89 if (null != socket) {
90 try {
91 socket.close();
92 } catch (final IOException ignore) {
93 }
94 }
95 }
96 }
97
98 }
5858 while (!shutdown) {
5959 try {
6060 final byte[] buffer = new byte[4096];
61 try (Socket socket = socketServer.accept()) {
61 Socket socket = null;
62 try {
63 socket = socketServer.accept();
6264 socket.setSoLinger(true, 0);
6365 final InputStream in = socket.getInputStream();
6466 int i = in.read(buffer, 0, buffer.length);
7577 }
7678 } catch (final BindException be) {
7779 be.printStackTrace();
80 } finally {
81 if (socket != null) {
82 socket.close();
83 }
7884 }
7985 } catch (final Exception ex) {
8086 if (!shutdown) {
2727 import org.apache.logging.log4j.core.net.ssl.TlsSyslogInputStreamReader;
2828 import org.apache.logging.log4j.core.net.ssl.TlsSyslogInputStreamReaderBase;
2929 import org.apache.logging.log4j.core.net.ssl.TlsSyslogMessageFormat;
30 import org.apache.logging.log4j.util.Strings;
3031
3132 public class MockTlsSyslogServer extends MockSyslogServer {
3233 private final SSLServerSocket serverSocket;
125126 try {
126127 int count = 0;
127128 while (!shutdown) {
128 String message;
129 String message = Strings.EMPTY;
129130 message = syslogReader.read();
130131 messageList.add(message);
131132 count++;
1414 * limitations under the license.
1515 */
1616
17 import org.junit.jupiter.api.Test;
17 import org.junit.Test;
1818
19 import static org.junit.jupiter.api.Assertions.*;
19 import static org.junit.Assert.*;
2020
2121 public class EnvironmentPasswordProviderTest {
2222
23 @Test
23 @Test(expected = NullPointerException.class)
2424 public void testConstructorDisallowsNull() {
25 assertThrows(NullPointerException.class, () -> new EnvironmentPasswordProvider(null));
25 new EnvironmentPasswordProvider(null);
2626 }
2727
2828 @Test
1818 import java.nio.file.Files;
1919 import java.nio.file.NoSuchFileException;
2020 import java.nio.file.Path;
21 import org.junit.Test;
2122
22 import org.junit.jupiter.api.Test;
23
24 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2524
2625 public class FilePasswordProviderTest {
2726
3635 assertArrayEquals(PASSWORD.toCharArray(), actual);
3736 }
3837
39 @Test
38 @Test(expected = NullPointerException.class)
4039 public void testConstructorDisallowsNull() throws Exception {
41 assertThrows(NullPointerException.class, () -> new FilePasswordProvider(null));
40 new FilePasswordProvider(null);
4241 }
4342
44 @Test
43 @Test(expected = NoSuchFileException.class)
4544 public void testConstructorFailsIfFileDoesNotExist() throws Exception {
46 assertThrows(NoSuchFileException.class, () -> new FilePasswordProvider("nosuchfile"));
45 new FilePasswordProvider("nosuchfile");
4746 }
4847 }
1515 */
1616 package org.apache.logging.log4j.core.net.ssl;
1717
18 import org.junit.jupiter.api.Test;
19
2018 import java.security.KeyStore;
2119
22 import static org.junit.jupiter.api.Assertions.*;
20 import org.junit.Assert;
21 import org.junit.Test;
2322
2423 public class KeyStoreConfigurationTest {
25 @SuppressWarnings("deprecation")
26 @Test
27 public void loadEmptyConfigurationDeprecated() {
28 assertThrows(StoreConfigurationException.class,
29 () -> new KeyStoreConfiguration(null, TestConstants.NULL_PWD, null, null));
24 @Test(expected = StoreConfigurationException.class)
25 public void loadEmptyConfigurationDeprecated() throws StoreConfigurationException {
26 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(null, TestConstants.NULL_PWD, null, null);
27 final KeyStore ks = ksc.getKeyStore();
28 Assert.assertTrue(ks == null);
3029 }
31
32 @Test
33 public void loadEmptyConfiguration() {
34 assertThrows(StoreConfigurationException.class,
35 () -> new KeyStoreConfiguration(null, new MemoryPasswordProvider(TestConstants.NULL_PWD), null, null));
30 @Test(expected = StoreConfigurationException.class)
31 public void loadEmptyConfiguration() throws StoreConfigurationException {
32 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(null, new MemoryPasswordProvider(TestConstants.NULL_PWD), null, null);
33 final KeyStore ks = ksc.getKeyStore();
34 Assert.assertTrue(ks == null);
3635 }
3736
3837 @Test
3938 public void loadNotEmptyConfigurationDeprecated() throws StoreConfigurationException {
40 @SuppressWarnings("deprecation") final KeyStoreConfiguration ksc =
41 new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, TestConstants.KEYSTORE_PWD(),
42 TestConstants.KEYSTORE_TYPE, null);
39 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, TestConstants.KEYSTORE_PWD(),
40 TestConstants.KEYSTORE_TYPE, null);
4341 final KeyStore ks = ksc.getKeyStore();
44 assertNotNull(ks);
42 Assert.assertTrue(ks != null);
4543 }
4644
4745 @Test
4947 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD()),
5048 TestConstants.KEYSTORE_TYPE, null);
5149 final KeyStore ks = ksc.getKeyStore();
52 assertNotNull(ks);
50 Assert.assertTrue(ks != null);
5351 }
5452
5553 @Test
5654 public void returnTheSameKeyStoreAfterMultipleLoadsDeprecated() throws StoreConfigurationException {
57 @SuppressWarnings("deprecation") final KeyStoreConfiguration ksc =
58 new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, TestConstants.KEYSTORE_PWD(),
59 TestConstants.KEYSTORE_TYPE, null);
55 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, TestConstants.KEYSTORE_PWD(),
56 TestConstants.KEYSTORE_TYPE, null);
6057 final KeyStore ks = ksc.getKeyStore();
6158 final KeyStore ks2 = ksc.getKeyStore();
62 assertSame(ks, ks2);
59 Assert.assertTrue(ks == ks2);
6360 }
6461
6562 @Test
6865 TestConstants.KEYSTORE_TYPE, null);
6966 final KeyStore ks = ksc.getKeyStore();
7067 final KeyStore ks2 = ksc.getKeyStore();
71 assertSame(ks, ks2);
68 Assert.assertTrue(ks == ks2);
7269 }
7370
74 @SuppressWarnings("deprecation")
75 @Test
76 public void wrongPasswordDeprecated() {
77 assertThrows(StoreConfigurationException.class,
78 () -> new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, "wrongPassword!", null, null));
71 @Test(expected = StoreConfigurationException.class)
72 public void wrongPasswordDeprecated() throws StoreConfigurationException {
73 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, "wrongPassword!", null, null);
74 ksc.getKeyStore();
7975 }
8076
81 @Test
82 public void wrongPassword() {
83 assertThrows(StoreConfigurationException.class, () -> new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE,
84 new MemoryPasswordProvider("wrongPassword!".toCharArray()), null, null));
77 @Test(expected = StoreConfigurationException.class)
78 public void wrongPassword() throws StoreConfigurationException {
79 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, new MemoryPasswordProvider("wrongPassword!".toCharArray()), null, null);
80 ksc.getKeyStore();
8581 }
8682 }
1616
1717 import java.util.Arrays;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 public class MemoryPasswordProviderTest {
2424 @Test
2525 public void testConstructorAllowsNull() {
26 assertNull(new MemoryPasswordProvider(null).getPassword());
26 assertEquals(null, new MemoryPasswordProvider(null).getPassword());
2727 }
2828
2929 @Test
2222 import javax.net.ssl.SSLSocket;
2323 import javax.net.ssl.SSLSocketFactory;
2424
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
25 import org.junit.Assert;
26 import org.junit.Test;
2827
2928 public class SslConfigurationTest {
3029
3130 private static final String TLS_TEST_HOST = "login.yahoo.com";
3231 private static final int TLS_TEST_PORT = 443;
3332
34 @SuppressWarnings("deprecation")
3533 public static SslConfiguration createTestSslConfigurationResourcesDeprecated() throws StoreConfigurationException {
3634 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE_RESOURCE,
3735 TestConstants.KEYSTORE_PWD(), TestConstants.KEYSTORE_TYPE, null);
4846 return SslConfiguration.createSSLConfiguration(null, ksc, tsc);
4947 }
5048
51 @SuppressWarnings("deprecation")
5249 public static SslConfiguration createTestSslConfigurationFilesDeprecated() throws StoreConfigurationException {
5350 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE,
5451 TestConstants.KEYSTORE_PWD(), TestConstants.KEYSTORE_TYPE, null);
6764
6865 @Test
6966 public void testGettersFromScratchFiles() throws StoreConfigurationException {
70 assertNotNull(createTestSslConfigurationFiles().getProtocol());
71 assertNotNull(createTestSslConfigurationFiles().getKeyStoreConfig());
72 assertNotNull(createTestSslConfigurationFiles().getSslContext());
73 assertNotNull(createTestSslConfigurationFiles().getSslSocketFactory());
74 assertNotNull(createTestSslConfigurationFiles().getTrustStoreConfig());
67 Assert.assertNotNull(createTestSslConfigurationFiles().getProtocol());
68 Assert.assertNotNull(createTestSslConfigurationFiles().getKeyStoreConfig());
69 Assert.assertNotNull(createTestSslConfigurationFiles().getSslContext());
70 Assert.assertNotNull(createTestSslConfigurationFiles().getSslSocketFactory());
71 Assert.assertNotNull(createTestSslConfigurationFiles().getTrustStoreConfig());
7572 }
7673
7774 @Test
7875 public void testGettersFromScratchResources() throws StoreConfigurationException {
79 assertNotNull(createTestSslConfigurationResources().getProtocol());
80 assertNotNull(createTestSslConfigurationResources().getKeyStoreConfig());
81 assertNotNull(createTestSslConfigurationResources().getSslContext());
82 assertNotNull(createTestSslConfigurationResources().getSslSocketFactory());
83 assertNotNull(createTestSslConfigurationResources().getTrustStoreConfig());
76 Assert.assertNotNull(createTestSslConfigurationResources().getProtocol());
77 Assert.assertNotNull(createTestSslConfigurationResources().getKeyStoreConfig());
78 Assert.assertNotNull(createTestSslConfigurationResources().getSslContext());
79 Assert.assertNotNull(createTestSslConfigurationResources().getSslSocketFactory());
80 Assert.assertNotNull(createTestSslConfigurationResources().getTrustStoreConfig());
8481 }
8582
8683 @Test
8784 public void equals() {
88 assertEquals(SslConfiguration.createSSLConfiguration(null, null, null), SslConfiguration.createSSLConfiguration(null, null, null));
85 Assert.assertEquals(SslConfiguration.createSSLConfiguration(null, null, null), SslConfiguration.createSSLConfiguration(null, null, null));
8986 }
9087
9188 @Test
9289 public void emptyConfigurationDoesntCauseNullSSLSocketFactory() {
9390 final SslConfiguration sc = SslConfiguration.createSSLConfiguration(null, null, null);
9491 final SSLSocketFactory factory = sc.getSslSocketFactory();
95 assertNotNull(factory);
92 Assert.assertNotNull(factory);
9693 }
9794
9895 @Test
10198 final SSLSocketFactory factory = sc.getSslSocketFactory();
10299 try {
103100 try (final SSLSocket clientSocket = (SSLSocket) factory.createSocket(TLS_TEST_HOST, TLS_TEST_PORT)) {
104 assertNotNull(clientSocket);
101 Assert.assertNotNull(clientSocket);
102 clientSocket.close();
105103 }
106104 } catch (final UnknownHostException offline) {
107105 // this exception is thrown on Windows when offline
117115 try {
118116 try (final SSLSocket clientSocket = (SSLSocket) factory.createSocket(TLS_TEST_HOST, TLS_TEST_PORT)) {
119117 try (final OutputStream os = clientSocket.getOutputStream()) {
120 assertThrows(IOException.class, () -> os.write("GET config/login_verify2?".getBytes()));
118 os.write("GET config/login_verify2?".getBytes());
119 Assert.fail("Expected IOException");
120 } catch (final IOException e) {
121 // Expected, do nothing.
121122 }
122123 }
123124 } catch (final UnknownHostException offline) {
131132 new MemoryPasswordProvider(TestConstants.NULL_PWD), null, null);
132133 final SslConfiguration sslConf = SslConfiguration.createSSLConfiguration(null, ksc, null);
133134 final SSLSocketFactory factory = sslConf.getSslSocketFactory();
134 assertNotNull(factory);
135 Assert.assertNotNull(factory);
135136 }
136137 }
1515 */
1616 package org.apache.logging.log4j.core.net.ssl;
1717
18 import org.junit.jupiter.api.Disabled;
19 import org.junit.jupiter.api.Test;
18 import org.junit.Ignore;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
23 @Disabled
23 @Ignore
2424 public class StoreConfigurationTest<T extends StoreConfiguration<?>> {
2525
2626 @Test
3030 final StoreConfiguration<Object> a = new StoreConfiguration<>(location, password);
3131 final StoreConfiguration<Object> b = new StoreConfiguration<>(location, password);
3232
33 assertEquals(b, a);
34 assertEquals(a, b);
33 assertTrue(a.equals(b));
34 assertTrue(b.equals(a));
3535 }
3636
3737 @Test
5050 final StoreConfiguration<Object> a = new StoreConfiguration<>(null, new MemoryPasswordProvider(null));
5151 final StoreConfiguration<Object> b = new StoreConfiguration<>(null, new MemoryPasswordProvider(null));
5252
53 assertEquals(b, a);
54 assertEquals(a, b);
53 assertTrue(a.equals(b));
54 assertTrue(b.equals(a));
5555 }
5656 }
1515 */
1616 package org.apache.logging.log4j.core.net.ssl;
1717
18 import org.junit.jupiter.api.Test;
19
2018 import java.security.KeyStore;
2119
22 import static org.junit.jupiter.api.Assertions.*;
20 import org.junit.Assert;
21 import org.junit.Test;
2322
2423 public class TrustStoreConfigurationTest {
25 @SuppressWarnings("deprecation")
26 @Test
27 public void loadEmptyConfigurationDeprecated() {
28 assertThrows(StoreConfigurationException.class, () -> new TrustStoreConfiguration(null, TestConstants.NULL_PWD, null, null));
24 @Test(expected = StoreConfigurationException.class)
25 public void loadEmptyConfigurationDeprecated() throws StoreConfigurationException {
26 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(null, TestConstants.NULL_PWD, null, null);
27 final KeyStore ks = ksc.getKeyStore();
28 Assert.assertTrue(ks == null);
2929 }
30
31 @Test
32 public void loadEmptyConfiguration() {
33 assertThrows(StoreConfigurationException.class, () -> new TrustStoreConfiguration(null, new MemoryPasswordProvider(TestConstants.NULL_PWD), null, null));
30 @Test(expected = StoreConfigurationException.class)
31 public void loadEmptyConfiguration() throws StoreConfigurationException {
32 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(null, new MemoryPasswordProvider(TestConstants.NULL_PWD), null, null);
33 final KeyStore ks = ksc.getKeyStore();
34 Assert.assertTrue(ks == null);
3435 }
3536
3637 @Test
3738 public void loadConfigurationDeprecated() throws StoreConfigurationException {
38 @SuppressWarnings("deprecation") final TrustStoreConfiguration ksc =
39 new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, TestConstants.TRUSTSTORE_PWD(), null, null);
39 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, TestConstants.TRUSTSTORE_PWD(), null, null);
4040 final KeyStore ks = ksc.getKeyStore();
41 assertNotNull(ks);
41 Assert.assertNotNull(ks);
4242 }
4343
4444 @Test
4545 public void loadConfiguration() throws StoreConfigurationException {
4646 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD()), null, null);
4747 final KeyStore ks = ksc.getKeyStore();
48 assertNotNull(ks);
48 Assert.assertNotNull(ks);
4949 }
5050
5151 @Test
5252 public void returnTheSameKeyStoreAfterMultipleLoadsDeprecated() throws StoreConfigurationException {
53 @SuppressWarnings("deprecation") final TrustStoreConfiguration ksc =
54 new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, TestConstants.TRUSTSTORE_PWD(), null, null);
53 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, TestConstants.TRUSTSTORE_PWD(), null, null);
5554 final KeyStore ks = ksc.getKeyStore();
5655 final KeyStore ks2 = ksc.getKeyStore();
57 assertSame(ks, ks2);
56 Assert.assertTrue(ks == ks2);
5857 }
5958
6059 @Test
6261 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD()), null, null);
6362 final KeyStore ks = ksc.getKeyStore();
6463 final KeyStore ks2 = ksc.getKeyStore();
65 assertSame(ks, ks2);
64 Assert.assertTrue(ks == ks2);
6665 }
6766
68 @SuppressWarnings("deprecation")
69 @Test
70 public void wrongPasswordDeprecated() {
71 assertThrows(StoreConfigurationException.class, () -> new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, "wrongPassword!".toCharArray(), null, null));
67 @Test(expected = StoreConfigurationException.class)
68 public void wrongPasswordDeprecated() throws StoreConfigurationException {
69 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, "wrongPassword!".toCharArray(), null, null);
70 ksc.getKeyStore();
71 Assert.assertTrue(false);
7272 }
7373
74 @Test
75 public void wrongPassword() {
76 assertThrows(StoreConfigurationException.class, () -> new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, new MemoryPasswordProvider("wrongPassword!".toCharArray()), null, null));
74 @Test(expected = StoreConfigurationException.class)
75 public void wrongPassword() throws StoreConfigurationException {
76 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, new MemoryPasswordProvider("wrongPassword!".toCharArray()), null, null);
77 ksc.getKeyStore();
78 Assert.assertTrue(false);
7779 }
7880 }
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2422 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.Test;
23 import org.junit.ClassRule;
24 import org.junit.Test;
2625
27 import static org.junit.jupiter.api.Assertions.*;
26 import static org.junit.Assert.*;
2827
29 @LoggerContextSource("log4j2-calling-class.xml")
3028 public class CallerInformationTest {
3129
30 @ClassRule
31 public static LoggerContextRule context = new LoggerContextRule("log4j2-calling-class.xml");
32
3233 @Test
33 public void testClassLogger(final LoggerContext context, @Named("Class") final ListAppender app) {
34 app.clear();
34 public void testClassLogger() throws Exception {
35 final ListAppender app = context.getListAppender("Class").clear();
3536 final Logger logger = context.getLogger("ClassLogger");
3637 logger.info("Ignored message contents.");
3738 logger.warn("Verifying the caller class is still correct.");
3839 logger.error("Hopefully nobody breaks me!");
3940 final List<String> messages = app.getMessages();
40 assertEquals(3, messages.size(), "Incorrect number of messages.");
41 assertEquals("Incorrect number of messages.", 3, messages.size());
4142 for (final String message : messages) {
42 assertEquals(this.getClass().getName(), message, "Incorrect caller class name.");
43 assertEquals("Incorrect caller class name.", this.getClass().getName(), message);
4344 }
4445 }
4546
4647 @Test
47 public void testMethodLogger(final LoggerContext context, @Named("Method") final ListAppender app) {
48 app.clear();
48 public void testMethodLogger() throws Exception {
49 final ListAppender app = context.getListAppender("Method").clear();
4950 final Logger logger = context.getLogger("MethodLogger");
5051 logger.info("More messages.");
5152 logger.warn("CATASTROPHE INCOMING!");
5354 logger.fatal("brains~~~");
5455 logger.info("Itchy. Tasty.");
5556 final List<String> messages = app.getMessages();
56 assertEquals(5, messages.size(), "Incorrect number of messages.");
57 assertEquals("Incorrect number of messages.", 5, messages.size());
5758 for (final String message : messages) {
58 assertEquals("testMethodLogger", message, "Incorrect caller method name.");
59 assertEquals("Incorrect caller method name.", "testMethodLogger", message);
5960 }
6061 }
6162 }
101101 field.setBoolean(null, threadLocalEnabled.booleanValue());
102102 }
103103
104 private static Date date(final int year, final int month, final int date) {
104 private Date date(final int year, final int month, final int date) {
105105 final Calendar cal = Calendar.getInstance();
106106 cal.set(year, month, date, 14, 15, 16);
107107 cal.set(Calendar.MILLISECOND, 123);
118118
119119 @Test
120120 public void testFormatDateStringBuilderDefaultPattern() {
121 assertDatePattern(null, date(2001, 1, 1), "2001-02-01 14:15:16,123");
121 final DatePatternConverter converter = DatePatternConverter.newInstance(null);
122 final StringBuilder sb = new StringBuilder();
123 converter.format(date(2001, 1, 1), sb);
124
125 final String expected = "2001-02-01 14:15:16,123";
126 assertEquals(expected, sb.toString());
122127 }
123128
124129 @Test
133138
134139 @Test
135140 public void testFormatDateStringBuilderIso8601BasicWithPeriod() {
136 assertDatePattern(FixedDateFormat.FixedFormat.ISO8601_BASIC_PERIOD.name(), date(2001, 1, 1), "20010201T141516.123");
141 final String[] pattern = {FixedDateFormat.FixedFormat.ISO8601_BASIC_PERIOD.name()};
142 final DatePatternConverter converter = DatePatternConverter.newInstance(pattern);
143 final StringBuilder sb = new StringBuilder();
144 converter.format(date(2001, 1, 1), sb);
145
146 final String expected = "20010201T141516.123";
147 assertEquals(expected, sb.toString());
137148 }
138149
139150 @Test
140151 public void testFormatDateStringBuilderIso8601WithPeriod() {
141 assertDatePattern(FixedDateFormat.FixedFormat.ISO8601_PERIOD.name(), date(2001, 1, 1), "2001-02-01T14:15:16.123");
142 }
143
144 @Test
145 public void testFormatDateStringBuilderIso8601WithPeriodMicroseconds() {
146 final String[] pattern = {FixedDateFormat.FixedFormat.ISO8601_PERIOD_MICROS.name(), "Z"};
152 final String[] pattern = {FixedDateFormat.FixedFormat.ISO8601_PERIOD.name()};
147153 final DatePatternConverter converter = DatePatternConverter.newInstance(pattern);
148154 final StringBuilder sb = new StringBuilder();
149 MutableInstant instant = new MutableInstant();
150 instant.initFromEpochMilli(
151 1577225134559L,
152 // One microsecond
153 1000);
154 converter.format(instant, sb);
155
156 final String expected = "2019-12-24T22:05:34.559001";
155 converter.format(date(2001, 1, 1), sb);
156
157 final String expected = "2001-02-01T14:15:16.123";
157158 assertEquals(expected, sb.toString());
158159 }
159160
160161 @Test
161162 public void testFormatDateStringBuilderOriginalPattern() {
162 assertDatePattern("yyyy/MM/dd HH-mm-ss.SSS", date(2001, 1, 1), "2001/02/01 14-15-16.123");
163 final String[] pattern = {"yyyy/MM/dd HH-mm-ss.SSS"};
164 final DatePatternConverter converter = DatePatternConverter.newInstance(pattern);
165 final StringBuilder sb = new StringBuilder();
166 converter.format(date(2001, 1, 1), sb);
167
168 final String expected = "2001/02/01 14-15-16.123";
169 assertEquals(expected, sb.toString());
163170 }
164171
165172 @Test
181188 converter.format(event, sb);
182189
183190 final String expected = "2011-12-30T10:56:35,987";
184 assertEquals(expected, sb.toString());
185 }
186
187 @Test
188 public void testFormatAmericanPatterns() {
189 Date date = date(2011, 2, 11);
190 assertDatePattern("US_MONTH_DAY_YEAR4_TIME", date, "11/03/2011 14:15:16.123");
191 assertDatePattern("US_MONTH_DAY_YEAR2_TIME", date, "11/03/11 14:15:16.123");
192 assertDatePattern("dd/MM/yyyy HH:mm:ss.SSS", date, "11/03/2011 14:15:16.123");
193 assertDatePattern("dd/MM/yyyy HH:mm:ss.nnnnnn", date, "11/03/2011 14:15:16.123000");
194 assertDatePattern("dd/MM/yy HH:mm:ss.SSS", date, "11/03/11 14:15:16.123");
195 assertDatePattern("dd/MM/yy HH:mm:ss.nnnnnn", date, "11/03/11 14:15:16.123000");
196 }
197
198 private static void assertDatePattern(final String format, final Date date, final String expected) {
199 DatePatternConverter converter = DatePatternConverter.newInstance(new String[] {format});
200 StringBuilder sb = new StringBuilder();
201 converter.format(date, sb);
202
203191 assertEquals(expected, sb.toString());
204192 }
205193
314302
315303 @Test
316304 public void testGetPatternReturnsDefaultForEmptyOptionsArray() {
317 assertEquals(DEFAULT_PATTERN, DatePatternConverter.newInstance(Strings.EMPTY_ARRAY).getPattern());
305 assertEquals(DEFAULT_PATTERN, DatePatternConverter.newInstance(new String[0]).getPattern());
318306 }
319307
320308 @Test
372360 final String precisePattern;
373361 if (foundIndex < 0) {
374362 precisePattern = pattern;
363 preciseConverter = DatePatternConverter.newInstance(new String[] { precisePattern });
375364 } else {
376365 final String subPattern = pattern.substring(0, foundIndex);
377366 final String remainder = pattern.substring(foundIndex + search.length());
378367 precisePattern = subPattern + "nnnnnnnnn" + "n" + remainder; // nanos too long
368 preciseConverter = DatePatternConverter.newInstance(new String[] { precisePattern });
379369 }
380 preciseConverter = DatePatternConverter.newInstance(new String[] { precisePattern });
381370 preciseConverter.format(event, preciseBuilder);
382371
383372 final String[] milliOptions = { pattern };
411400 final StringBuilder milliBuilder = new StringBuilder();
412401 final LogEvent event = new MyLogEvent();
413402
414 for (final String timeZone : new String[]{"PST", null}) { // Pacific Standard Time=UTC-8:00
403 for (final String timeZone : new String[]{"PDT", null}) { // Pacific Daylight Time=UTC-8:00
415404 for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
416405 for (int i = 1; i <= 9; i++) {
417406 final String pattern = format.getPattern();
461450 @Test
462451 public void testPredefinedFormatWithTimezone() {
463452 for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
464 final String[] options = {format.name(), "PST"}; // Pacific Standard Time=UTC-8:00
453 final String[] options = {format.name(), "PDT"}; // Pacific Daylight Time=UTC-8:00
465454 final DatePatternConverter converter = DatePatternConverter.newInstance(options);
466455 assertEquals(format.getPattern(), converter.getPattern());
467456 }
1616 package org.apache.logging.log4j.core.pattern;
1717
1818 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
19 import org.apache.logging.log4j.junit.LoggerContextRule;
2220 import org.apache.logging.log4j.test.appender.ListAppender;
2321 import org.apache.logging.log4j.util.Strings;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
22 import org.junit.Before;
23 import org.junit.Rule;
24 import org.junit.Test;
2625
2726 import java.util.List;
2827
29 import static org.junit.jupiter.api.Assertions.*;
28 import static org.junit.Assert.*;
3029
31 @LoggerContextSource("log4j2-console-disableAnsi.xml")
3230 public class DisableAnsiTest {
3331
3432 private static final String EXPECTED =
3533 "ERROR LoggerTest o.a.l.l.c.p.DisableAnsiTest org.apache.logging.log4j.core.pattern.DisableAnsiTest"
3634 + Strings.LINE_SEPARATOR;
3735
36 @Rule
37 public LoggerContextRule init = new LoggerContextRule("log4j2-console-disableAnsi.xml");
38
3839 private Logger logger;
3940 private ListAppender app;
4041
41 @BeforeEach
42 public void setUp(final LoggerContext context, @Named("List") final ListAppender app) {
43 this.logger = context.getLogger("LoggerTest");
44 this.app = app.clear();
42 @Before
43 public void setUp() throws Exception {
44 this.logger = this.init.getLogger("LoggerTest");
45 this.app = this.init.getListAppender("List").clear();
4546 }
4647
4748 @Test
5051
5152 final List<String> msgs = app.getMessages();
5253 assertNotNull(msgs);
53 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
54 assertTrue(msgs.get(0).endsWith(EXPECTED),
55 "Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0));
54 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
55 assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
5656 }
5757
5858 }
1818 import org.apache.logging.log4j.Level;
1919 import org.apache.logging.log4j.core.LogEvent;
2020 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2321 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2422 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2624
27 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2826
27 /**
28 *
29 */
2930 public class EncodingPatternConverterTest {
3031
3132 @Test
4041 final String[] options = new String[]{"%msg"};
4142 final EncodingPatternConverter converter = EncodingPatternConverter
4243 .newInstance(ctx.getConfiguration(), options);
43 assertNotNull(converter, "Error creating converter");
44 assertNotNull("Error creating converter", converter);
4445 converter.format(event, sb);
4546 assertEquals(
4647 "Test \\r\\n&lt;div class=&quot;test&quot;&gt;this&lt;&#x2F;div&gt; &amp; &lt;div class=&apos;test&apos;&gt;that&lt;&#x2F;div&gt;",
4849 }
4950
5051 @Test
51 public void testJsonEscaping() {
52 public void testJsonEscaping() throws Exception {
5253 final LogEvent event = Log4jLogEvent.newBuilder()
5354 .setLoggerName(getClass().getName())
5455 .setLevel(Level.DEBUG)
6061 final String[] options = new String[]{"%msg", "JSON"};
6162 final EncodingPatternConverter converter = EncodingPatternConverter.newInstance(ctx.getConfiguration(), options);
6263
63 assertNotNull(converter, "Error creating converter");
64 assertNotNull("Error creating converter", converter);
6465 converter.format(event, sb);
6566
6667 assertEquals(expected, sb.toString());
7879 final String[] options = new String[]{"%msg", "CRLF"};
7980 final EncodingPatternConverter converter = EncodingPatternConverter
8081 .newInstance(ctx.getConfiguration(), options);
81 assertNotNull(converter, "Error creating converter");
82 assertNotNull("Error creating converter", converter);
8283 converter.format(event, sb);
8384 assertEquals(
8485 "Test \\r\\n<div class=\"test\">this\\r</div> & \\n<div class='test'>that</div>",
9798 final String[] options = new String[]{"%msg", "XML"};
9899 final EncodingPatternConverter converter = EncodingPatternConverter
99100 .newInstance(ctx.getConfiguration(), options);
100 assertNotNull(converter, "Error creating converter");
101 assertNotNull("Error creating converter", converter);
101102 converter.format(event, sb);
102103 assertEquals(
103104 "Test \r\n&lt;div class=&quot;test&quot;&gt;this&lt;/div&gt; &amp; &lt;div class=&apos;test&apos;&gt;that&lt;/div&gt;",
104105 sb.toString());
105106 }
106107
107 @Test
108 public void testHandlesThrowable() {
109 final Configuration configuration = new DefaultConfiguration();
110 assertFalse(EncodingPatternConverter.newInstance(configuration, new String[]{"%msg", "XML"})
111 .handlesThrowable());
112 assertTrue(EncodingPatternConverter.newInstance(configuration, new String[]{"%xThrowable{full}", "JSON"})
113 .handlesThrowable());
114 assertTrue(EncodingPatternConverter.newInstance(configuration, new String[]{"%ex", "XML"})
115 .handlesThrowable());
116 }
117108 }
1717
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.Assert.assertEquals;
2323
2424 public class EndOfBatchPatternConverterTest {
2525
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.core.LogEvent;
2022 import org.apache.logging.log4j.core.LoggerContext;
2123 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2224 import org.apache.logging.log4j.message.SimpleMessage;
2325 import org.apache.logging.log4j.util.Strings;
24 import org.junit.jupiter.api.Test;
26 import org.junit.Test;
2527
26 import static org.junit.jupiter.api.Assertions.*;
27
28 /**
29 *
30 */
2831 public class EqualsIgnoreCaseReplacementConverterTest {
2932
3033 @Test
5356 final String[] options = new String[] { "aaa[" + tag + "]zzz", "AAA[]ZZZ", expectedValue };
5457 final EqualsIgnoreCaseReplacementConverter converter = EqualsIgnoreCaseReplacementConverter
5558 .newInstance(ctx.getConfiguration(), options);
56 assertNotNull(converter);
5759 converter.format(event, sb);
5860 assertEquals(expectedValue, sb.toString());
5961 }
2121 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2222 import org.apache.logging.log4j.message.SimpleMessage;
2323 import org.apache.logging.log4j.util.Strings;
24 import org.junit.jupiter.api.Test;
24 import org.junit.Test;
2525
26 import static org.junit.jupiter.api.Assertions.*;
26 import static org.junit.Assert.*;
2727
28 /**
29 *
30 */
2831 public class EqualsReplacementConverterTest {
2932
3033 private static final String TEST_MESSAGE = "This is a test";
6467 final LoggerContext ctx = LoggerContext.getContext();
6568 final EqualsReplacementConverter converter = EqualsReplacementConverter.newInstance(ctx.getConfiguration(),
6669 options);
67 assertNotNull(converter);
6870 converter.format(event, sb);
6971 assertEquals(expectedValue, sb.toString());
7072 }
101103 new String[]{"[%marker]", "[]", substitution});
102104
103105 final StringBuilder sb = new StringBuilder();
104 assertNotNull(converter);
105106 converter.parseSubstitution(event, sb);
106107 final String actual = sb.toString();
107108 assertEquals(expected, actual);
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22
1823 import java.io.PrintWriter;
1924 import java.io.StringWriter;
2025 import java.util.List;
2732 import org.apache.logging.log4j.core.impl.ThrowableProxy;
2833 import org.apache.logging.log4j.message.SimpleMessage;
2934 import org.apache.logging.log4j.util.Strings;
30 import org.junit.jupiter.api.Test;
35 import org.junit.Test;
3136
32 import static org.junit.jupiter.api.Assertions.*;
33
37 /**
38 *
39 */
3440 public class ExtendedThrowablePatternConverterTest {
3541
3642 @Test
5056 final StringBuilder sb = new StringBuilder();
5157 converter.format(event, sb);
5258 final String result = sb.toString();
53 assertTrue(result.contains("test suffix"), "No suffix");
59 assertTrue("No suffix", result.contains("test suffix"));
5460 }
5561
5662 @Test
6975 final StringBuilder sb = new StringBuilder();
7076 converter.format(event, sb);
7177 final String result = sb.toString();
72 assertTrue(result.contains("test suffix"), "No suffix");
78 assertTrue("No suffix", result.contains("test suffix"));
7379 }
7480
7581 @Test
8894 final StringBuilder sb = new StringBuilder();
8995 converter.format(event, sb);
9096 final String result = sb.toString();
91 assertFalse(result.contains("inner suffix"), "Has unexpected suffix");
97 assertFalse("Has unexpected suffix", result.contains("inner suffix"));
9298 }
9399
94100 @Test
108114 final StringBuilder sb = new StringBuilder();
109115 converter.format(event, sb);
110116 final String result = sb.toString();
111 assertTrue(result.contains(originalThrowable.getMessage()), result);
112 assertTrue(result.contains(originalThrowable.getStackTrace()[0].getMethodName()), result);
117 assertTrue(result, result.contains(originalThrowable.getMessage()));
118 assertTrue(result, result.contains(originalThrowable.getStackTrace()[0].getMethodName()));
113119 }
114120
115121 @Test
128134 final StringBuilder sb = new StringBuilder();
129135 converter.format(event, sb);
130136 final String result = sb.toString();
131 assertTrue(result.contains(" suppressed "), "No suppressed lines");
137 assertTrue("No suppressed lines", result.contains(" suppressed "));
132138 }
133139
134140 @Test
161167 final List<String> ignorePackages = options.getIgnorePackages();
162168 assertNotNull(ignorePackages);
163169 final String ignorePackagesString = ignorePackages.toString();
164 assertTrue(ignorePackages.contains("org.junit"), ignorePackagesString);
165 assertTrue(ignorePackages.contains("org.eclipse"), ignorePackagesString);
170 assertTrue(ignorePackagesString, ignorePackages.contains("org.junit"));
171 assertTrue(ignorePackagesString, ignorePackages.contains("org.eclipse"));
166172 assertEquals("|", options.getSeparator());
167173 }
168174
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2422 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
23 import org.junit.Before;
24 import org.junit.ClassRule;
25 import org.junit.Test;
2726
28 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.*;
2928
30 @LoggerContextSource("log4j-throwablefilter.xml")
29 /**
30 *
31 */
3132 public class ExtendedThrowableTest {
3233 private ListAppender app;
3334
34 @BeforeEach
35 public void setUp(@Named("List") final ListAppender app) throws Exception {
36 this.app = app.clear();
35 @ClassRule
36 public static LoggerContextRule context = new LoggerContextRule("log4j-throwablefilter.xml");
37
38 @Before
39 public void setUp() throws Exception {
40 this.app = context.getListAppender("List").clear();
3741 }
3842
3943 @Test
40 public void testException(final LoggerContext context) {
44 public void testException() {
4145 final Logger logger = context.getLogger("LoggerTest");
4246 final Throwable cause = new NullPointerException("null pointer");
4347 final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
4448 logger.error("Exception", parent);
4549 final List<String> msgs = app.getMessages();
4650 assertNotNull(msgs);
47 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
48 assertTrue(msgs.get(0).contains("suppressed"), "No suppressed lines");
51 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
52 assertTrue("No suppressed lines", msgs.get(0).contains("suppressed"));
4953 }
5054 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import org.junit.jupiter.api.Test;
18 import static org.junit.Assert.assertEquals;
1919
20 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import org.junit.Test;
2121
2222 /**
2323 * Testing FormattingInfo.
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2020 import org.apache.logging.log4j.message.SimpleMessage;
21 import org.junit.jupiter.api.Test;
21 import org.junit.Assert;
22 import org.junit.Test;
2223
23 import static org.junit.jupiter.api.Assertions.*;
24
25 import static org.junit.Assert.*;
2426
2527 /**
2628 * Tests the HighlightConverter.
3133 public void testAnsiEmpty() {
3234 final String[] options = {"", PatternParser.NO_CONSOLE_NO_ANSI + "=false, " + PatternParser.DISABLE_ANSI + "=false"};
3335 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
34 assertNotNull(converter);
3536
3637 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
3738 new SimpleMessage("message in a bottle")).build();
4445 public void testAnsiNonEmpty() {
4546 final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, " + PatternParser.DISABLE_ANSI + "=false"};
4647 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
47 assertNotNull(converter);
4848
4949 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
5050 new SimpleMessage("message in a bottle")).build();
5959 final String[] options = { "%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
6060 + PatternParser.DISABLE_ANSI + "=false, " + "BAD_LEVEL_A=" + colorName + ", BAD_LEVEL_B=" + colorName };
6161 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
62 assertNotNull(converter);
63 assertNotNull(converter.getLevelStyle(Level.TRACE));
64 assertNotNull(converter.getLevelStyle(Level.DEBUG));
62 Assert.assertNotNull(converter);
63 Assert.assertNotNull(converter.getLevelStyle(Level.TRACE));
64 Assert.assertNotNull(converter.getLevelStyle(Level.DEBUG));
6565 }
6666
6767 @Test
7070 final String[] options = { "%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
7171 + PatternParser.DISABLE_ANSI + "=false, " + "DEBUG=" + colorName + ", TRACE=" + colorName };
7272 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
73 assertNotNull(converter);
74 assertEquals(AnsiEscape.createSequence(colorName), converter.getLevelStyle(Level.TRACE));
75 assertEquals(AnsiEscape.createSequence(colorName), converter.getLevelStyle(Level.DEBUG));
73 Assert.assertNotNull(converter);
74 Assert.assertEquals(AnsiEscape.createSequence(colorName), converter.getLevelStyle(Level.TRACE));
75 Assert.assertEquals(AnsiEscape.createSequence(colorName), converter.getLevelStyle(Level.DEBUG));
7676 }
7777
7878 @Test
8181 final String[] options = { "%level", PatternParser.NO_CONSOLE_NO_ANSI + "=false, " + PatternParser.DISABLE_ANSI
8282 + "=false, " + "DEBUG=" + colorName + ", CUSTOM1=" + colorName };
8383 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
84 assertNotNull(converter);
85 assertNotNull(converter.getLevelStyle(Level.INFO));
86 assertNotNull(converter.getLevelStyle(Level.DEBUG));
87 assertNotNull(converter.getLevelStyle(Level.forName("CUSTOM1", 412)));
88 assertNull(converter.getLevelStyle(Level.forName("CUSTOM2", 512)));
84 Assert.assertNotNull(converter);
85 Assert.assertNotNull(converter.getLevelStyle(Level.INFO));
86 Assert.assertNotNull(converter.getLevelStyle(Level.DEBUG));
87 Assert.assertNotNull(converter.getLevelStyle(Level.forName("CUSTOM1", 412)));
88 Assert.assertNull(converter.getLevelStyle(Level.forName("CUSTOM2", 512)));
8989
9090 assertArrayEquals(new byte[] { 27, '[', '3', '4', 'm', 'D', 'E', 'B', 'U', 'G', 27, '[', 'm' },
9191 toFormattedCharSeq(converter, Level.DEBUG).toString().getBytes());
102102 final String[] options = { "%-5level: %msg",
103103 PatternParser.NO_CONSOLE_NO_ANSI + "=false, " + PatternParser.DISABLE_ANSI + "=false" };
104104 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
105 assertNotNull(converter);
106 assertNotNull(converter.getLevelStyle(Level.TRACE));
107 assertNotNull(converter.getLevelStyle(Level.DEBUG));
105 Assert.assertNotNull(converter);
106 Assert.assertNotNull(converter.getLevelStyle(Level.TRACE));
107 Assert.assertNotNull(converter.getLevelStyle(Level.DEBUG));
108108 }
109109
110110 @Test
111111 public void testNoAnsiEmpty() {
112112 final String[] options = {"", PatternParser.DISABLE_ANSI + "=true"};
113113 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
114 assertNotNull(converter);
115114
116115 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
117116 new SimpleMessage("message in a bottle")).build();
124123 public void testNoAnsiNonEmpty() {
125124 final String[] options = {"%-5level: %msg", PatternParser.DISABLE_ANSI + "=true"};
126125 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
127 assertNotNull(converter);
128126
129127 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
130128 new SimpleMessage("message in a bottle")).build();
2020 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2121 import org.apache.logging.log4j.message.Message;
2222 import org.apache.logging.log4j.message.SimpleMessage;
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
27 /**
28 *
29 */
2730 public class LevelPatternConverterTest {
2831
2932 private void testLevelLength(final int length, final String debug, final String warn) {
1616
1717 package org.apache.logging.log4j.core.pattern;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * Tests the LiteralPatternConverter.
1717
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.assertEquals;
2323
2424 public class LoggerFqcnPatternConverterTest {
2525
2020 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2121 import org.apache.logging.log4j.message.MapMessage;
2222 import org.apache.logging.log4j.message.StringMapMessage;
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
27 /**
28 *
29 */
2730 public class MapPatternConverterTest {
2831
2932 @Test
4346 converter.format(event, sb);
4447 final String str = sb.toString();
4548 String expected = "subject=I";
46 assertTrue(str.contains(expected), "Missing or incorrect subject. Expected " + expected + ", actual " + str);
49 assertTrue("Missing or incorrect subject. Expected " + expected + ", actual " + str, str.contains(expected));
4750 expected = "verb=love";
48 assertTrue(str.contains(expected), "Missing or incorrect verb");
51 assertTrue("Missing or incorrect verb", str.contains(expected));
4952 expected = "object=Log4j";
50 assertTrue(str.contains(expected), "Missing or incorrect object");
53 assertTrue("Missing or incorrect object", str.contains(expected));
5154
5255 assertEquals("{object=Log4j, subject=I, verb=love}", str);
5356 }
8992 converter.format(event, sb);
9093 final String str = sb.toString();
9194 String expected = "subject=\"I\"";
92 assertTrue(str.contains(expected), "Missing or incorrect subject. Expected " + expected + ", actual " + str);
95 assertTrue("Missing or incorrect subject. Expected " + expected + ", actual " + str, str.contains(expected));
9396 expected = "verb=\"love\"";
94 assertTrue(str.contains(expected), "Missing or incorrect verb");
97 assertTrue("Missing or incorrect verb", str.contains(expected));
9598 expected = "object=\"Log4j\"";
96 assertTrue(str.contains(expected), "Missing or incorrect object");
99 assertTrue("Missing or incorrect object", str.contains(expected));
97100
98101 assertEquals("{object=\"Log4j\", subject=\"I\", verb=\"love\"}", str);
99102 }
2222 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2323 import org.apache.logging.log4j.message.Message;
2424 import org.apache.logging.log4j.message.StructuredDataMessage;
25 import org.junit.jupiter.api.Test;
25 import org.junit.Test;
2626
27 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.*;
2828
2929 /**
3030 * Tests {@link MarkerPatternConverter}.
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.Marker;
2022 import org.apache.logging.log4j.MarkerManager;
2224 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2325 import org.apache.logging.log4j.message.Message;
2426 import org.apache.logging.log4j.message.StructuredDataMessage;
25 import org.junit.jupiter.api.Test;
26
27 import static org.junit.jupiter.api.Assertions.*;
27 import org.junit.Test;
2828
2929 /**
3030 * Tests {@link MarkerSimpleNamePatternConverter}.
2121 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2222 import org.apache.logging.log4j.message.Message;
2323 import org.apache.logging.log4j.message.SimpleMessage;
24 import org.junit.jupiter.api.Test;
24 import org.junit.Test;
2525
26 import static org.junit.jupiter.api.Assertions.*;
26 import static org.junit.Assert.*;
2727
28 /**
29 *
30 */
2831 public class MaxLengthConverterTest {
2932
30 private static final MaxLengthConverter converter = MaxLengthConverter.newInstance(null, new String[]{"%m", "10"});
33 private static MaxLengthConverter converter = MaxLengthConverter.newInstance(null, new String[]{"%m", "10"});
3134
3235 @Test
33 public void testUnderMaxLength() {
36 public void testUnderMaxLength() throws Exception {
3437 final Message message = new SimpleMessage("0123456789");
3538 final LogEvent event = Log4jLogEvent.newBuilder()
3639 .setLoggerName("MyLogger")
4346 }
4447
4548 @Test
46 public void testOverMaxLength() {
49 public void testOverMaxLength() throws Exception {
4750 final Message message = new SimpleMessage("01234567890123456789");
4851 final LogEvent event = Log4jLogEvent.newBuilder()
4952 .setLoggerName("MyLogger")
5457 converter.format(event, sb);
5558 assertEquals("0123456789", sb.toString());
5659 }
57
5860 @Test
59 public void testOverMaxLength21WithEllipsis() {
61 public void testOverMaxLength21WithEllipsis() throws Exception {
6062 final Message message = new SimpleMessage("012345678901234567890123456789");
6163 final LogEvent event = Log4jLogEvent.newBuilder()
6264 .setLoggerName("MyLogger")
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertTrue;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.ThreadContext;
2023 import org.apache.logging.log4j.core.LogEvent;
2124 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
22 import org.apache.logging.log4j.junit.UsingThreadContextMap;
25 import org.apache.logging.log4j.junit.ThreadContextMapRule;
2326 import org.apache.logging.log4j.message.Message;
2427 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
27
28 import static org.junit.jupiter.api.Assertions.*;
29
30 @UsingThreadContextMap
28 import org.junit.Before;
29 import org.junit.Rule;
30 import org.junit.Test;
31
32 /**
33 *
34 */
3135 public class MdcPatternConverterTest {
3236
33 @BeforeEach
37 @Rule
38 public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
39
40 @Before
3441 public void setup() {
3542 ThreadContext.put("subject", "I");
3643 ThreadContext.put("verb", "love");
5057 converter.format(event, sb);
5158 final String str = sb.toString();
5259 final String expected = "{object=Log4j, subject=I, verb=love}";
53 assertEquals(expected, str, "Incorrect result. Expected " + expected + ", actual " + str);
60 assertTrue("Incorrect result. Expected " + expected + ", actual " + str, str.equals(expected));
5461 }
5562
5663 @Test
6774 converter.format(event, sb);
6875 final String str = sb.toString();
6976 final String expected = "prefix {object=Log4j, subject=I, verb=love}";
70 assertEquals(expected, str, "Incorrect result. Expected " + expected + ", actual " + str);
71 }
72
77 assertTrue("Incorrect result. Expected " + expected + ", actual " + str, str.equals(expected));
78 }
7379 @Test
7480 public void testConverterFullEmpty() {
7581 ThreadContext.clearMap();
8490 converter.format(event, sb);
8591 final String str = sb.toString();
8692 final String expected = "{}";
87 assertEquals(expected, str, "Incorrect result. Expected " + expected + ", actual " + str);
93 assertTrue("Incorrect result. Expected " + expected + ", actual " + str, str.equals(expected));
8894 }
8995
9096 @Test
102108 converter.format(event, sb);
103109 final String str = sb.toString();
104110 final String expected = "{foo=bar}";
105 assertEquals(expected, str, "Incorrect result. Expected " + expected + ", actual " + str);
111 assertTrue("Incorrect result. Expected " + expected + ", actual " + str, str.equals(expected));
106112 }
107113
108114 @Test
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2422 import org.apache.logging.log4j.test.appender.ListAppender;
2523 import org.apache.logging.log4j.util.Strings;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
2827
29 import static org.junit.jupiter.api.Assertions.*;
28 import static org.junit.Assert.*;
3029
31 @LoggerContextSource("log4j-message-ansi.xml")
30 /**
31 *
32 */
3233 public class MessageJansiConverterTest {
3334
3435 private static final String EXPECTED = "\u001B[31;1mWarning!\u001B[m Pants on \u001B[31mfire!\u001B[m"
3536 + Strings.LINE_SEPARATOR;
3637
38 @Rule
39 public LoggerContextRule init = new LoggerContextRule("log4j-message-ansi.xml");
40
3741 private Logger logger;
3842 private ListAppender app;
3943
40 @BeforeEach
41 public void setUp(final LoggerContext context, @Named("List") final ListAppender app) {
42 this.logger = context.getLogger("LoggerTest");
43 this.app = app.clear();
44 @Before
45 public void setUp() throws Exception {
46 this.logger = this.init.getLogger("LoggerTest");
47 this.app = this.init.getListAppender("List").clear();
4448 }
4549
4650 @Test
5054
5155 final List<String> msgs = app.getMessages();
5256 assertNotNull(msgs);
53 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
54 assertTrue(
55 msgs.get(0).endsWith(EXPECTED), "Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0));
56 // System.out.println(msgs.get(0));
57 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
58 assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0),
59 msgs.get(0).endsWith(EXPECTED));
5760 }
5861 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.core.LogEvent;
2023 import org.apache.logging.log4j.core.config.Configuration;
2124 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2225 import org.apache.logging.log4j.core.config.builder.impl.DefaultConfigurationBuilder;
2326 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
27 import org.apache.logging.log4j.core.util.Constants;
2428 import org.apache.logging.log4j.message.Message;
2529 import org.apache.logging.log4j.message.ParameterizedMessage;
2630 import org.apache.logging.log4j.message.SimpleMessage;
2731 import org.apache.logging.log4j.message.StringMapMessage;
2832 import org.apache.logging.log4j.message.StructuredDataMessage;
29 import org.junit.jupiter.api.Test;
33 import org.junit.Test;
3034
31 import static org.junit.jupiter.api.Assertions.*;
32
35 /**
36 *
37 */
3338 public class MessagePatternConverterTest {
3439
3540 @Test
36 public void testPattern() {
41 public void testPattern() throws Exception {
3742 final MessagePatternConverter converter = MessagePatternConverter.newInstance(null, null);
3843 Message msg = new SimpleMessage("Hello!");
3944 LogEvent event = Log4jLogEvent.newBuilder() //
4247 .setMessage(msg).build();
4348 StringBuilder sb = new StringBuilder();
4449 converter.format(event, sb);
45 assertEquals("Hello!", sb.toString(), "Unexpected result");
50 assertEquals("Unexpected result", "Hello!", sb.toString());
4651 event = Log4jLogEvent.newBuilder() //
4752 .setLoggerName("MyLogger") //
4853 .setLevel(Level.DEBUG) //
4954 .setMessage(null).build();
5055 sb = new StringBuilder();
5156 converter.format(event, sb);
52 assertEquals(0, sb.length(), "Incorrect length: " + sb);
57 assertEquals("Incorrect length: " + sb, 0, sb.length());
5358 msg = new SimpleMessage(null);
5459 event = Log4jLogEvent.newBuilder() //
5560 .setLoggerName("MyLogger") //
5762 .setMessage(msg).build();
5863 sb = new StringBuilder();
5964 converter.format(event, sb);
60 assertEquals(4, sb.length(), "Incorrect length: " + sb);
65 assertEquals("Incorrect length: " + sb, 4, sb.length());
6166 }
6267
6368 @Test
64 public void testPatternAndParameterizedMessageDateLookup() {
69 public void testPatternAndParameterizedMessageDateLookup() throws Exception {
6570 final MessagePatternConverter converter = MessagePatternConverter.newInstance(null, null);
6671 final Message msg = new ParameterizedMessage("${date:now:buhu}");
6772 final LogEvent event = Log4jLogEvent.newBuilder() //
7075 .setMessage(msg).build();
7176 final StringBuilder sb = new StringBuilder();
7277 converter.format(event, sb);
73 assertEquals("${date:now:buhu}", sb.toString(), "Unexpected result");
74 }
75
76 @Test
77 public void testDefaultDisabledLookup() {
78 final Configuration config = new DefaultConfigurationBuilder()
79 .addProperty("foo", "bar")
80 .build(true);
81 final MessagePatternConverter converter = MessagePatternConverter.newInstance(config, null);
82 final Message msg = new ParameterizedMessage("${foo}");
83 final LogEvent event = Log4jLogEvent.newBuilder() //
84 .setLoggerName("MyLogger") //
85 .setLevel(Level.DEBUG) //
86 .setMessage(msg).build();
87 final StringBuilder sb = new StringBuilder();
88 converter.format(event, sb);
89 assertEquals("${foo}", sb.toString(), "Unexpected result");
78 assertEquals("Unexpected result", "${date:now:buhu}", sb.toString());
9079 }
9180
9281 @Test
10392 .setMessage(msg).build();
10493 final StringBuilder sb = new StringBuilder();
10594 converter.format(event, sb);
106 assertEquals("${foo}", sb.toString(), "Expected the raw pattern string without lookup");
95 assertEquals("Expected the raw pattern string without lookup", "${foo}", sb.toString());
10796 }
10897
10998 @Test
110 public void testLookup() {
111 final Configuration config = new DefaultConfigurationBuilder()
112 .addProperty("foo", "bar")
113 .build(true);
114 final MessagePatternConverter converter =
115 MessagePatternConverter.newInstance(config, new String[] {"lookups"});
116 final Message msg = new ParameterizedMessage("${foo}");
117 final LogEvent event = Log4jLogEvent.newBuilder() //
118 .setLoggerName("MyLogger") //
119 .setLevel(Level.DEBUG) //
120 .setMessage(msg).build();
121 final StringBuilder sb = new StringBuilder();
122 converter.format(event, sb);
123 assertEquals("${foo}", sb.toString(), "Unexpected result");
124 }
125
126 @Test
127 public void testPatternWithConfiguration() {
99 public void testPatternWithConfiguration() throws Exception {
128100 final Configuration config = new DefaultConfiguration();
129101 final MessagePatternConverter converter = MessagePatternConverter.newInstance(config, null);
130102 Message msg = new SimpleMessage("Hello!");
134106 .setMessage(msg).build();
135107 StringBuilder sb = new StringBuilder();
136108 converter.format(event, sb);
137 assertEquals("Hello!", sb.toString(), "Unexpected result");
109 assertEquals("Unexpected result", "Hello!", sb.toString());
138110 event = Log4jLogEvent.newBuilder() //
139111 .setLoggerName("MyLogger") //
140112 .setLevel(Level.DEBUG) //
141113 .setMessage(null).build();
142114 sb = new StringBuilder();
143115 converter.format(event, sb);
144 assertEquals(0, sb.length(), "Incorrect length: " + sb);
116 assertEquals("Incorrect length: " + sb, 0, sb.length());
145117 msg = new SimpleMessage(null);
146118 event = Log4jLogEvent.newBuilder() //
147119 .setLoggerName("MyLogger") //
149121 .setMessage(msg).build();
150122 sb = new StringBuilder();
151123 converter.format(event, sb);
152 assertEquals(4, sb.length(), "Incorrect length: " + sb);
124 assertEquals("Incorrect length: " + sb, 4, sb.length());
153125 }
154126
155127 @Test
156 public void testMapMessageFormatJson() {
128 public void testMapMessageFormatJson() throws Exception {
157129 final MessagePatternConverter converter = MessagePatternConverter.newInstance(null, new String[]{"json"});
158130 final Message msg = new StringMapMessage()
159131 .with("key", "val");
163135 .setMessage(msg).build();
164136 final StringBuilder sb = new StringBuilder();
165137 converter.format(event, sb);
166 assertEquals("{\"key\":\"val\"}", sb.toString(), "Unexpected result");
138 assertEquals("Unexpected result", "{\"key\":\"val\"}", sb.toString());
167139 }
168140
169141 @Test
170 public void testMapMessageFormatXml() {
142 public void testMapMessageFormatXml() throws Exception {
171143 final MessagePatternConverter converter = MessagePatternConverter.newInstance(null, new String[]{"xml"});
172144 final Message msg = new StringMapMessage()
173145 .with("key", "val");
177149 .setMessage(msg).build();
178150 final StringBuilder sb = new StringBuilder();
179151 converter.format(event, sb);
180 assertEquals("<Map>\n <Entry key=\"key\">val</Entry>\n</Map>", sb.toString(), "Unexpected result");
152 assertEquals("Unexpected result", "<Map>\n <Entry key=\"key\">val</Entry>\n</Map>", sb.toString());
181153 }
182154
183155 @Test
184 public void testMapMessageFormatDefault() {
156 public void testMapMessageFormatDefault() throws Exception {
185157 final MessagePatternConverter converter = MessagePatternConverter.newInstance(null, null);
186158 final Message msg = new StringMapMessage()
187159 .with("key", "val");
191163 .setMessage(msg).build();
192164 final StringBuilder sb = new StringBuilder();
193165 converter.format(event, sb);
194 assertEquals("key=\"val\"", sb.toString(), "Unexpected result");
166 assertEquals("Unexpected result", "key=\"val\"", sb.toString());
195167 }
196168
197169 @Test
198 public void testStructuredDataFormatFull() {
170 public void testStructuredDataFormatFull() throws Exception {
199171 final MessagePatternConverter converter = MessagePatternConverter.newInstance(null, new String[]{"FULL"});
200172 final Message msg = new StructuredDataMessage("id", "message", "type")
201173 .with("key", "val");
205177 .setMessage(msg).build();
206178 final StringBuilder sb = new StringBuilder();
207179 converter.format(event, sb);
208 assertEquals("type [id key=\"val\"] message", sb.toString(), "Unexpected result");
180 assertEquals("Unexpected result", "type [id key=\"val\"] message", sb.toString());
209181 }
210182 }
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2422 import org.apache.logging.log4j.test.appender.ListAppender;
2523 import org.apache.logging.log4j.util.Strings;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
2827
29 import static org.junit.jupiter.api.Assertions.*;
28 import static org.junit.Assert.*;
3029
31 @LoggerContextSource("log4j-message-styled.xml")
30 /**
31 *
32 */
3233 public class MessageStyledConverterTest {
3334
3435 private static final String EXPECTED = "\u001B[31;1mWarning!\u001B[m Pants on \u001B[31;1mfire!\u001B[m"
3536 + Strings.LINE_SEPARATOR;
3637
38 @Rule
39 public LoggerContextRule init = new LoggerContextRule("log4j-message-styled.xml");
40
3741 private Logger logger;
3842 private ListAppender app;
3943
40 @BeforeEach
41 public void setUp(final LoggerContext context, @Named("List") final ListAppender app) {
42 this.logger = context.getLogger("LoggerTest");
43 this.app = app.clear();
44 @Before
45 public void setUp() throws Exception {
46 this.logger = this.init.getLogger("LoggerTest");
47 this.app = this.init.getListAppender("List").clear();
4448 }
4549
4650 @Test
5054
5155 final List<String> msgs = app.getMessages();
5256 assertNotNull(msgs);
53 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
54 assertTrue(
55 msgs.get(0).endsWith(EXPECTED), "Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0));
57 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
58 assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0),
59 msgs.get(0).endsWith(EXPECTED));
5660 }
5761 }
4949 { "3", "core.pattern.NameAbbreviatorTest" },
5050 { "1.", "o.a.l.l.c.p.NameAbbreviatorTest" },
5151 { "1.1.~", "o.a.~.~.~.~.NameAbbreviatorTest" },
52 { "1.1.1.*", "o.a.l.log4j.core.pattern.NameAbbreviatorTest" },
5352 { ".", "......NameAbbreviatorTest" }
5453 }
5554 );
1717
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2323
24 /**
25 *
26 */
2427 public class NanoTimePatternConverterTest {
2528
2629 @Test
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.ThreadContext;
2022 import org.apache.logging.log4j.core.LogEvent;
2123 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
22 import org.apache.logging.log4j.junit.UsingThreadContextStack;
24 import org.apache.logging.log4j.junit.ThreadContextStackRule;
2325 import org.apache.logging.log4j.message.Message;
2426 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.junit.jupiter.api.Test;
27 import org.junit.Rule;
28 import org.junit.Test;
2629
27 import static org.junit.jupiter.api.Assertions.*;
30 public class NdcPatternConverterTest {
2831
29 @UsingThreadContextStack
30 public class NdcPatternConverterTest {
32 @Rule
33 public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
3134
3235 @Test
3336 public void testEmpty() {
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import java.util.List;
19
1820 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2222 import org.apache.logging.log4j.test.appender.ListAppender;
2323 import org.apache.logging.log4j.util.Strings;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
2627
27 import java.util.List;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertNotNull;
30 import static org.junit.Assert.assertTrue;
2831
29 import static org.junit.jupiter.api.Assertions.*;
30
31 @LoggerContextSource("log4j2-console-noConsoleNoAnsi.xml")
3232 public class NoConsoleNoAnsiTest {
3333
3434 private static final String EXPECTED =
3535 "ERROR LoggerTest o.a.l.l.c.p.NoConsoleNoAnsiTest org.apache.logging.log4j.core.pattern.NoConsoleNoAnsiTest"
3636 + Strings.LINE_SEPARATOR;
3737
38 @Rule
39 public LoggerContextRule init = new LoggerContextRule("log4j2-console-noConsoleNoAnsi.xml");
40
3841 private Logger logger;
3942 private ListAppender app;
4043
41 @BeforeEach
42 public void setUp(final LoggerContext context, @Named("List") final ListAppender app) {
43 this.logger = context.getLogger("LoggerTest");
44 this.app = app.clear();
44 @Before
45 public void setUp() throws Exception {
46 this.logger = this.init.getLogger("LoggerTest");
47 this.app = this.init.getListAppender("List").clear();
4548 }
4649
4750 @Test
5053
5154 final List<String> msgs = app.getMessages();
5255 assertNotNull(msgs);
53 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
54 assertTrue(msgs.get(0).endsWith(EXPECTED),
55 "Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0));
56 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
57 assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
5658 }
5759
5860 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
1822 import java.util.Calendar;
1923 import java.util.List;
2024
3337 import org.apache.logging.log4j.message.SimpleMessage;
3438 import org.apache.logging.log4j.util.StringMap;
3539 import org.apache.logging.log4j.util.Strings;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38
39 import static org.junit.jupiter.api.Assertions.*;
40
40 import org.junit.Before;
41 import org.junit.Test;
42
43 /**
44 *
45 */
4146 public class PatternParserTest {
4247
4348 static String OUTPUT_FILE = "output/PatternParser";
6368 private static final String KEY = "Converter";
6469 private PatternParser parser;
6570
66 @BeforeEach
71 @Before
6772 public void setup() {
6873 parser = new PatternParser(KEY);
6974 }
7075
7176 private void validateConverter(final List<PatternFormatter> formatter, final int index, final String name) {
7277 final PatternConverter pc = formatter.get(index).getConverter();
73 assertEquals(
74 pc.getName(), name, "Incorrect converter " + pc.getName() + " at index " + index + " expected " + name);
78 assertEquals("Incorrect converter " + pc.getName() + " at index " + index + " expected " + name,
79 pc.getName(), name);
7580 }
7681
7782 /**
8186 public void defaultPattern() {
8287 final List<PatternFormatter> formatters = parser.parse(msgPattern);
8388 assertNotNull(formatters);
84 assertEquals(formatters.size(), 2);
89 assertTrue(formatters.size() == 2);
8590 validateConverter(formatters, 0, "Message");
8691 validateConverter(formatters, 1, "Line Sep");
8792 }
112117 formatter.format(event, buf);
113118 }
114119 final String str = buf.toString();
115 final String expected = "INFO [PatternParserTest :99 ] - Hello, world" + Strings.LINE_SEPARATOR;
116 assertTrue(str.endsWith(expected), "Expected to end with: " + expected + ". Actual: " + str);
120 final String expected = "INFO [PatternParserTest :104 ] - Hello, world" + Strings.LINE_SEPARATOR;
121 assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
117122 }
118123
119124 @Test
134139 }
135140 final String str = buf.toString();
136141 final String expected = "INFO rTest Hello, world" + Strings.LINE_SEPARATOR;
137 assertTrue(str.endsWith(expected), "Expected to end with: " + expected + ". Actual: " + str);
142 assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
138143 }
139144
140145 @Test
155160 }
156161 final String str = buf.toString();
157162 final String expected = "INFO org.a Hello, world" + Strings.LINE_SEPARATOR;
158 assertTrue(str.endsWith(expected), "Expected to end with: " + expected + ". Actual: " + str);
163 assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
159164 }
160165
161166 @Test
186191
187192 // eats all characters until the closing '}' character
188193 final String expected = "[2001-02-03 04:05:06,789] - Hello, world";
189 assertTrue(str.startsWith(expected), "Expected to start with: " + expected + ". Actual: " + str);
194 assertTrue("Expected to start with: " + expected + ". Actual: " + str, str.startsWith(expected));
190195 }
191196
192197 @Test
220225 }
221226 final String str = buf.toString();
222227 final String expectedEnd = String.format("] %-5s: Hello, world%s\u001B[m", level, Strings.LINE_SEPARATOR);
223 assertTrue(str.startsWith(expectedStart), "Expected to start with: " + expectedStart + ". Actual: " + str);
224 assertTrue(str.endsWith(expectedEnd), "Expected to end with: \"" + expectedEnd + "\". Actual: \"" + str);
228 assertTrue("Expected to start with: " + expectedStart + ". Actual: " + str, str.startsWith(expectedStart));
229 assertTrue("Expected to end with: \"" + expectedEnd + "\". Actual: \"" + str, str.endsWith(expectedEnd));
225230 }
226231
227232 @Test
295300 final List<PatternFormatter> formatters = parser.parse(pattern);
296301 assertNotNull(formatters);
297302 final String msg = formatters.toString();
298 assertEquals(1, formatters.size(), msg);
299 assertTrue(checkClass.isInstance(formatters.get(0).getConverter()), msg);
303 assertEquals(msg, 1, formatters.size());
304 assertTrue(msg, checkClass.isInstance(formatters.get(0).getConverter()));
300305 }
301306
302307 @Test
361366 assertNotNull(formatters);
362367 assertEquals(2, formatters.size());
363368
364 validateConverter(formatters, 0, "SimpleLiteral");
369 validateConverter(formatters, 0, "Literal");
365370 validateConverter(formatters, 1, "Date");
366371 }
367372
395400 final List<String> ignorePackages = options.getIgnorePackages();
396401 assertNotNull(ignorePackages);
397402 final String ignorePackagesString = ignorePackages.toString();
398 assertTrue(ignorePackages.contains("org.junit"), ignorePackagesString);
399 assertTrue(ignorePackages.contains("org.eclipse"), ignorePackagesString);
403 assertTrue(ignorePackagesString, ignorePackages.contains("org.junit"));
404 assertTrue(ignorePackagesString, ignorePackages.contains("org.eclipse"));
400405 assertEquals("|", options.getSeparator());
401406 }
402407
405410 public void testMapPatternConverter() {
406411 final List<PatternFormatter> formatters = parser.parse("%K");
407412 assertNotNull(formatters);
408 assertEquals(formatters.size(), 1);
413 assertTrue(formatters.size() == 1);
409414 PatternFormatter formatter = formatters.get(0);
410 assertTrue(formatter.getConverter() instanceof MapPatternConverter, "Expected a MapPatternConverter");
415 assertTrue("Expected a MapPatternConverter", formatter.getConverter() instanceof MapPatternConverter);
411416 }
412417 }
2020 import java.util.Date;
2121 import java.util.List;
2222
23 import org.junit.jupiter.api.Test;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
27 /**
28 *
29 */
2730 public class PatternParserTest2 {
2831
2932 @Test
0 /*
0 package org.apache.logging.log4j.core.pattern;/*
11 * Licensed to the Apache Software Foundation (ASF) under one or more
22 * contributor license agreements. See the NOTICE file distributed with
33 * this work for additional information regarding copyright ownership.
1313 * See the license for the specific language governing permissions and
1414 * limitations under the license.
1515 */
16 package org.apache.logging.log4j.core.pattern;
1716
18 import org.junit.jupiter.api.Test;
17 import org.junit.Test;
1918
20 import static org.junit.jupiter.api.Assertions.*;
19 import static org.junit.Assert.*;
2120
2221 /**
2322 * Tests that process ID succeeds.
2423 */
2524 public class ProcessIdPatternConverterTest {
2625 @Test
27 public void getProcessId() {
26 public void getProcessId() throws Exception {
2827 final String[] defaultValue = {"???"};
2928 final String actual = ProcessIdPatternConverter.newInstance(defaultValue).getProcessId();
3029 assertNotEquals("???", actual);
2222 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2323 import org.apache.logging.log4j.message.SimpleMessage;
2424 import org.apache.logging.log4j.util.Strings;
25 import org.junit.jupiter.api.Test;
25 import org.junit.Test;
2626
27 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.*;
2828
29 /**
30 *
31 */
2932 public class RegexReplacementConverterTest {
3033
3134 @Test
4346 };
4447 final RegexReplacementConverter converter = RegexReplacementConverter.newInstance(ctx.getConfiguration(),
4548 options);
46 assertNotNull(converter);
4749 converter.format(event, sb);
4850 assertEquals("org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest This is a test" +
4951 Strings.LINE_SEPARATOR, sb.toString());
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.jupiter.api.Assertions.assertEquals;
19 import static org.junit.jupiter.api.Assertions.assertNotNull;
20 import static org.junit.jupiter.api.Assertions.assertTrue;
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
2121
2222 import java.util.List;
2323
2424 import org.apache.logging.log4j.ThreadContext;
25 import org.apache.logging.log4j.core.LoggerContext;
26 import org.apache.logging.log4j.junit.LoggerContextSource;
27 import org.apache.logging.log4j.junit.Named;
28 import org.apache.logging.log4j.junit.UsingThreadContextMap;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
26 import org.apache.logging.log4j.junit.ThreadContextMapRule;
2927 import org.apache.logging.log4j.test.appender.ListAppender;
3028 import org.apache.logging.log4j.util.Strings;
31 import org.junit.jupiter.api.Test;
29 import org.junit.Before;
30 import org.junit.ClassRule;
31 import org.junit.Rule;
32 import org.junit.Test;
3233
33 @LoggerContextSource("log4j-replace.xml")
34 @UsingThreadContextMap
34 /**
35 *
36 */
3537 public class RegexReplacementTest {
36 private final ListAppender app;
37 private final ListAppender app2;
38 private final org.apache.logging.log4j.Logger logger;
39 private final org.apache.logging.log4j.Logger logger2;
38 private static final String CONFIG = "log4j-replace.xml";
39 private static ListAppender app;
40 private static ListAppender app2;
4041
4142 private static final String EXPECTED = "/RegexReplacementTest" + Strings.LINE_SEPARATOR;
4243
43 public RegexReplacementTest(
44 final LoggerContext context, @Named("List") final ListAppender app, @Named("List2") final ListAppender app2) {
45 logger = context.getLogger("LoggerTest");
46 logger2 = context.getLogger("ReplacementTest");
47 this.app = app.clear();
48 this.app2 = app2.clear();
44 @ClassRule
45 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
46
47 @Rule
48 public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
49
50 @Before
51 public void setUp() throws Exception {
52 app = context.getListAppender("List").clear();
53 app2 = context.getListAppender("List2").clear();
4954 }
55
56 org.apache.logging.log4j.Logger logger = context.getLogger("LoggerTest");
57 org.apache.logging.log4j.Logger logger2 = context.getLogger("ReplacementTest");
5058
5159 @Test
5260 public void testReplacement() {
5361 logger.error(this.getClass().getName());
5462 List<String> msgs = app.getMessages();
5563 assertNotNull(msgs);
56 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
57 assertTrue(
58 msgs.get(0).endsWith(EXPECTED), "Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0));
59
60 }
61
62 @Test
63 public void testMessageReplacement() {
64 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
65 assertTrue("Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0),
66 msgs.get(0).endsWith(EXPECTED));
67 app.clear();
6468 ThreadContext.put("MyKey", "Apache");
6569 logger.error("This is a test for ${ctx:MyKey}");
66 List<String> msgs = app.getMessages();
70 msgs = app.getMessages();
6771 assertNotNull(msgs);
68 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
69 assertEquals("LoggerTest This is a test for ${ctx:MyKey}" + Strings.LINE_SEPARATOR, msgs.get(0));
72 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
73 assertEquals("LoggerTest This is a test for ${ctx:MyKey}\n", msgs.get(0));
7074 }
71
72 @Test
75 @Test
7376 public void testConverter() {
7477 logger2.error(this.getClass().getName());
7578 final List<String> msgs = app2.getMessages();
7679 assertNotNull(msgs);
77 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
78 assertTrue(
79 msgs.get(0).endsWith(EXPECTED), "Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0));
80 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
81 assertTrue("Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0),
82 msgs.get(0).endsWith(EXPECTED));
8083 }
8184 }
+0
-51
log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/RepeatPatternConverterTest.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.logging.log4j.core.pattern;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
21 import org.apache.logging.log4j.message.SimpleMessage;
22 import org.junit.jupiter.api.Test;
23
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26
27 /**
28 * Tests that process ID succeeds.
29 */
30 public class RepeatPatternConverterTest {
31 @Test
32 public void repeat() {
33 final String[] args = {"*", "10"};
34 final String expected = "**********";
35 PatternConverter converter = RepeatPatternConverter.newInstance(null, args);
36 assertNotNull(converter, "No RepeatPatternConverter returned");
37 StringBuilder sb = new StringBuilder();
38 converter.format(null, sb);
39 assertEquals(expected, sb.toString());
40 sb.setLength(0);
41 LogEvent event = Log4jLogEvent.newBuilder() //
42 .setLoggerName("MyLogger") //
43 .setLevel(Level.DEBUG) //
44 .setMessage(new SimpleMessage("Hello")).build();
45 converter.format(event, sb);
46 assertEquals(expected, sb.toString());
47 }
48
49
50 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertTrue;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.ThreadContext;
2023 import org.apache.logging.log4j.core.LogEvent;
2124 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2225 import org.apache.logging.log4j.message.SimpleMessage;
23 import org.junit.jupiter.api.Test;
26 import org.junit.Test;
2427
25 import static org.junit.jupiter.api.Assertions.*;
26
28 /**
29 *
30 */
2731 public class RootThrowablePatternConverterTest {
2832
2933 @Test
4246 final StringBuilder sb = new StringBuilder();
4347 converter.format(event, sb);
4448 final String result = sb.toString();
45 assertTrue(result.contains("test suffix"), "No suffix");
49 assertTrue("No suffix", result.contains("test suffix"));
4650 }
4751
4852 @Test
6266 final StringBuilder sb = new StringBuilder();
6367 converter.format(event, sb);
6468 final String result = sb.toString();
65 assertTrue(result.contains("test suffix"), "No suffix");
69 assertTrue("No suffix", result.contains("test suffix"));
6670 }
6771
6872 @Test
8185 final StringBuilder sb = new StringBuilder();
8286 converter.format(event, sb);
8387 final String result = sb.toString();
84 assertFalse(result.contains("inner suffix"), "Has unexpected suffix");
88 assertFalse("Has unexpected suffix", result.contains("inner suffix"));
8589 }
8690
8791 @Test
99103 converter.format(event, sb);
100104 final String result = sb.toString();
101105 // System.out.print(result);
102 assertTrue(
103 result.contains("Wrapped by: java.lang.IllegalArgumentException: IllegalArgument"), "Missing Exception");
104 assertTrue(result.startsWith("java.lang.NullPointerException: null pointer"), "Incorrect start of msg");
106 assertTrue("Missing Exception",
107 result.contains("Wrapped by: java.lang.IllegalArgumentException: IllegalArgument"));
108 assertTrue("Incorrect start of msg", result.startsWith("java.lang.NullPointerException: null pointer"));
105109 }
106110
107111 /**
131135 converter.format(event, sb);
132136 final String result = sb.toString();
133137 // System.out.print(result);
134 assertTrue(
135 result.contains("Wrapped by: java.lang.IllegalArgumentException: IllegalArgument"), "Missing Exception");
136 assertTrue(result.startsWith("java.lang.NullPointerException: null pointer"), "Incorrect start of msg");
138 assertTrue("Missing Exception",
139 result.contains("Wrapped by: java.lang.IllegalArgumentException: IllegalArgument"));
140 assertTrue("Incorrect start of msg", result.startsWith("java.lang.NullPointerException: null pointer"));
137141 }
138142 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Test;
24
2518 import java.util.List;
2619
27 import static org.junit.jupiter.api.Assertions.*;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.Before;
24 import org.junit.ClassRule;
25 import org.junit.Test;
2826
29 @LoggerContextSource("log4j-rootthrowablefilter.xml")
27 import static org.junit.Assert.*;
28
29 /**
30 *
31 */
3032 public class RootThrowableTest {
33 private static final String CONFIG = "log4j-rootthrowablefilter.xml";
34 private static ListAppender app;
35
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
38
39 @Before
40 public void setUp() throws Exception {
41 app = context.getListAppender("List").clear();
42 }
43
3144 @Test
32 public void testException(final LoggerContext context, @Named("List") final ListAppender app) {
33 app.clear();
45 public void testException() {
3446 final Logger logger = context.getLogger("LoggerTest");
3547 final Throwable cause = new NullPointerException("null pointer");
3648 final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
3749 logger.error("Exception", parent);
3850 final List<String> msgs = app.getMessages();
3951 assertNotNull(msgs);
40 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
41 assertTrue(msgs.get(0).contains("suppressed"), "No suppressed lines");
52 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
53 assertTrue("No suppressed lines", msgs.get(0).contains("suppressed"));
4254 app.clear();
4355 }
4456 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Test;
24
2518 import java.util.List;
2619
27 import static org.hamcrest.MatcherAssert.assertThat;
28 import static org.hamcrest.Matchers.contains;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.ClassRule;
24 import org.junit.Test;
2925
30 @LoggerContextSource("SequenceNumberPatternConverterTest.yml")
26 import static org.hamcrest.Matchers.*;
27 import static org.junit.Assert.*;
28
29 /**
30 *
31 */
3132 public class SequenceNumberPatternConverterTest {
3233
34 @ClassRule
35 public static LoggerContextRule ctx = new LoggerContextRule("SequenceNumberPatternConverterTest.yml");
36
3337 @Test
34 public void testSequenceIncreases(final LoggerContext context, @Named("List") final ListAppender app) {
35 app.clear();
36 final Logger logger = context.getLogger(getClass().getName());
38 public void testSequenceIncreases() throws Exception {
39 final Logger logger = ctx.getLogger();
3740 logger.info("Message 1");
3841 logger.info("Message 2");
3942 logger.info("Message 3");
4043 logger.info("Message 4");
4144 logger.info("Message 5");
4245
46 final ListAppender app = ctx.getListAppender("List");
4347 final List<String> messages = app.getMessages();
4448 assertThat(messages, contains("1", "2", "3", "4", "5"));
4549 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.jupiter.api.Test;
24
2518 import java.util.List;
2619
27 import static org.hamcrest.MatcherAssert.assertThat;
28 import static org.hamcrest.Matchers.contains;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.Test;
2924
30 @LoggerContextSource("SequenceNumberPatternConverterZeroPaddedTest.yml")
25 import static org.hamcrest.Matchers.*;
26 import static org.junit.Assert.*;
27 import org.junit.Before;
28 import org.junit.ClassRule;
29
30 /**
31 *
32 */
3133 public class SequenceNumberPatternConverterZeroPaddedTest {
3234
35 @ClassRule
36 public static LoggerContextRule ctx = new LoggerContextRule("SequenceNumberPatternConverterZeroPaddedTest.yml");
37
38 @Before
39 public void before() {
40 ctx.getListAppender("Padded").clear();
41 }
42
3343 @Test
34 public void testPaddedSequence(final LoggerContext context, @Named("Padded") final ListAppender app) {
35 app.clear();
36 final Logger logger = context.getLogger(getClass().getName());
44 public void testPaddedSequence() throws Exception {
45 final Logger logger = ctx.getLogger();
3746 logger.info("Message 1");
3847 logger.info("Message 2");
3948 logger.info("Message 3");
4049 logger.info("Message 4");
4150 logger.info("Message 5");
4251
52 final ListAppender app = ctx.getListAppender("Padded");
4353 final List<String> messages = app.getMessages();
44 // System.out.println("Written messages "+messages);
54 System.out.println("Written messages "+messages);
4555 assertThat(messages, contains("001", "002", "003", "004", "005"));
4656 }
4757 }
+0
-47
log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/SimpleLiteralPatternConverterTest.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
17 package org.apache.logging.log4j.core.pattern;
18
19 import org.junit.jupiter.api.Test;
20
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22
23 public class SimpleLiteralPatternConverterTest {
24
25 @Test
26 public void testConvertBackslashes() {
27 String literal = "ABC\\tDEF\\nGHI\\rJKL\\'MNO\\f \\b \\\\DROPPED:\\x";
28 LogEventPatternConverter converter = SimpleLiteralPatternConverter.of(literal, true);
29 String actual = literal(converter);
30 assertEquals("ABC\tDEF\nGHI\rJKL\'MNO\f \b \\DROPPED:x", actual);
31 }
32
33 @Test
34 public void testDontConvertBackslashes() {
35 String literal = "ABC\\tDEF\\nGHI\\rJKL\\'MNO\\f \\b \\\\DROPPED:\\x";
36 LogEventPatternConverter converter = SimpleLiteralPatternConverter.of(literal, false);
37 String actual = literal(converter);
38 assertEquals(literal, actual);
39 }
40
41 private static String literal(LogEventPatternConverter converter) {
42 StringBuilder buffer = new StringBuilder();
43 converter.format(null, buffer);
44 return buffer.toString();
45 }
46 }
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2422 import org.apache.logging.log4j.test.appender.ListAppender;
2523 import org.apache.logging.log4j.util.Strings;
26 import org.junit.jupiter.api.BeforeAll;
27 import org.junit.jupiter.api.Test;
24 import org.junit.Assert;
25 import org.junit.Before;
26 import org.junit.BeforeClass;
27 import org.junit.Rule;
28 import org.junit.Test;
2829
29 import static org.junit.jupiter.api.Assertions.*;
30 import static org.junit.Assert.*;
3031
32 /**
33 *
34 */
3135 public class StyleConverterTest {
3236
3337 private static final String EXPECTED =
3438 "\u001B[1;31mERROR\u001B[m \u001B[1;36mLoggerTest\u001B[m o.a.l.l.c.p.StyleConverterTest org.apache.logging.log4j.core.pattern.StyleConverterTest"
3539 + Strings.LINE_SEPARATOR;
3640
37 @BeforeAll
41 @BeforeClass
3842 public static void beforeClass() {
3943 System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
4044 }
4145
46 @Rule
47 public LoggerContextRule init = new LoggerContextRule("log4j-style.xml");
48
49 private Logger logger;
50 private ListAppender app;
51
52 @Before
53 public void setUp() throws Exception {
54 this.logger = this.init.getLogger("LoggerTest");
55 this.app = this.init.getListAppender("List").clear();
56 }
57
4258 @Test
43 @LoggerContextSource("log4j-style.xml")
44 public void testReplacement(final LoggerContext context, @Named("List") final ListAppender app) {
45 final Logger logger = context.getLogger("LoggerTest");
59 public void testReplacement() {
4660 logger.error(this.getClass().getName());
4761
4862 final List<String> msgs = app.getMessages();
4963 assertNotNull(msgs);
50 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
51 assertTrue(msgs.get(0).endsWith(EXPECTED),
52 "Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0));
64 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
65 assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
5366 }
5467
5568 @Test
5669 public void testNull() {
57 assertNull(StyleConverter.newInstance(null, null));
70 Assert.assertNull(StyleConverter.newInstance(null, null));
5871 }
5972 }
1717
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2323
24 /**
25 *
26 */
2427 public class ThreadIdPatternConverterTest {
2528
2629 @Test
1717
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2323
24 /**
25 *
26 */
2427 public class ThreadNamePatternConverterTest {
2528
2629 @Test
1717
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.junit.jupiter.api.Test;
20 import org.junit.Test;
2121
22 import static org.junit.jupiter.api.Assertions.*;
22 import static org.junit.Assert.*;
2323
24 /**
25 *
26 */
2427 public class ThreadPriorityPatternConverterTest {
2528
2629 @Test
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertTrue;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.core.LogEvent;
2023 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2124 import org.apache.logging.log4j.message.SimpleMessage;
2225 import org.apache.logging.log4j.util.Strings;
23 import org.junit.jupiter.api.Test;
24
25 import static org.junit.jupiter.api.Assertions.*;
26 import org.junit.Test;
2627
2728 public class ThrowablePatternConverterTest {
2829
4950 /**
5051 * TODO: Needs better a better exception? NumberFormatException is NOT helpful.
5152 */
52 @Test
53 @Test(expected = Exception.class)
5354 public void testBadShortOption() {
5455 final String[] options = { "short.UNKNOWN" };
55 assertThrows(NumberFormatException.class, () -> ThrowablePatternConverter.newInstance(null, options));
56 ThrowablePatternConverter.newInstance(null, options);
5657 }
5758
5859 @Test
7980 converter.format(event, sb);
8081 final String result = sb.toString();
8182 // System.out.print(result);
82 assertTrue(result.startsWith("java.lang.IllegalArgumentException: IllegalArgument"), "Incorrect start of msg");
83 assertTrue(result.contains("java.lang.NullPointerException: null pointer"), "Missing nested exception");
83 assertTrue("Incorrect start of msg", result.startsWith("java.lang.IllegalArgumentException: IllegalArgument"));
84 assertTrue("Missing nested exception", result.contains("java.lang.NullPointerException: null pointer"));
8485 }
8586
8687 @Test
99100 final StringBuilder sb = new StringBuilder();
100101 converter.format(event, sb);
101102 final String result = sb.toString();
102 assertEquals(packageName + "ThrowablePatternConverterTest", result, "The class names should be same");
103 assertEquals("The class names should be same", packageName + "ThrowablePatternConverterTest", result);
103104 }
104105
105106 @Test
117118 final StringBuilder sb = new StringBuilder();
118119 converter.format(event, sb);
119120 final String result = sb.toString();
120 assertEquals("ThrowablePatternConverterTest.java", result, "The file names should be same");
121 assertEquals("The file names should be same", "ThrowablePatternConverterTest.java", result);
121122 }
122123
123124 @Test
138139 final StringBuilder sb = new StringBuilder();
139140 converter.format(event, sb);
140141 final String result = sb.toString();
141 assertEquals(Integer.parseInt(result), expectedLineNumber, "The line numbers should be same");
142 assertTrue("The line numbers should be same", expectedLineNumber == Integer.parseInt(result));
142143 }
143144
144145 @Test
155156 final StringBuilder sb = new StringBuilder();
156157 converter.format(event, sb);
157158 final String result = sb.toString();
158 assertEquals("I am localized.", result, "The messages should be same");
159 assertEquals("The messages should be same", "I am localized.", result);
159160 }
160161
161162 @Test
173174 final StringBuilder sb = new StringBuilder();
174175 converter.format(event, sb);
175176 final String result = sb.toString();
176 assertEquals("IllegalArgument", result, "The messages should be same");
177 assertEquals("The messages should be same", "IllegalArgument", result);
177178 }
178179
179180 @Test
191192 final StringBuilder sb = new StringBuilder();
192193 converter.format(event, sb);
193194 final String result = sb.toString();
194 assertEquals("testShortMethodName", result, "The method names should be same");
195 assertEquals("The method names should be same", "testShortMethodName", result);
195196 }
196197
197198 @Test
217218 final StringBuilder sb = new StringBuilder();
218219 converter.format(event, sb);
219220 final String result = sb.toString();
220 assertTrue(everyLineEndsWith(result, "test suffix"),
221 "Each line of full stack trace should end with the specified suffix");
221 assertTrue("Each line of full stack trace should end with the specified suffix", everyLineEndsWith(result, "test suffix"));
222222 }
223223
224224 @Test
237237 final StringBuilder sb = new StringBuilder();
238238 converter.format(event, sb);
239239 final String result = sb.toString();
240 assertTrue(everyLineEndsWith(result, "test suffix"), "Each line should end with suffix");
240 assertTrue("Each line should end with suffix", everyLineEndsWith(result, "test suffix"));
241241 }
242242
243243 }
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.junit.LoggerContextSource;
23 import org.apache.logging.log4j.junit.Named;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
2422 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
23 import org.junit.Before;
24 import org.junit.ClassRule;
25 import org.junit.Test;
2726
28 import static org.junit.jupiter.api.Assertions.*;
27 import static org.junit.Assert.*;
2928
3029 /**
3130 * Unit tests for {@code throwable} pattern.
3231 */
33 @LoggerContextSource("log4j-throwable.xml")
3432 public class ThrowableTest {
35 private ListAppender app;
36 private Logger logger;
33 private static final String CONFIG = "log4j-throwable.xml";
34 private static ListAppender app;
3735
38 @BeforeEach
39 public void setUp(final LoggerContext context, @Named("List") final ListAppender app) {
40 this.logger = context.getLogger("LoggerTest");
41 this.app = app.clear();
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
38
39 @Before
40 public void setUp() throws Exception {
41 app = context.getListAppender("List").clear();
4242 }
43
44 Logger logger = context.getLogger("LoggerTest");
4345
4446 @Test
4547 public void testException() {
4850 logger.error("Exception", parent);
4951 final List<String> msgs = app.getMessages();
5052 assertNotNull(msgs);
51 assertEquals(1, msgs.size(), "Incorrect number of messages. Should be 1 is " + msgs.size());
52 assertFalse(msgs.get(0).contains("suppressed"), "No suppressed lines");
53 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
54 assertFalse("No suppressed lines", msgs.get(0).contains("suppressed"));
5355 }
5456 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.core.LogEvent;
2022 import org.apache.logging.log4j.core.LoggerContext;
2123 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2224 import org.apache.logging.log4j.message.SimpleMessage;
2325 import org.apache.logging.log4j.util.Strings;
24 import org.junit.jupiter.api.Test;
26 import org.junit.Test;
2527
26 import static org.junit.jupiter.api.Assertions.*;
27
28 /**
29 *
30 */
2831 public class VariablesNotEmptyReplacementConverterTest {
2932
3033 @Test
6871 final String[] options = new String[] { "[" + tag + "]" };
6972 final VariablesNotEmptyReplacementConverter converter = VariablesNotEmptyReplacementConverter
7073 .newInstance(ctx.getConfiguration(), options);
71 assertNotNull(converter);
7274 converter.format(event, sb);
7375 assertEquals(expectedValue, sb.toString());
7476 }
+0
-55
log4j-core/src/test/java/org/apache/logging/log4j/core/selector/BasicContextSelectorTest.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.logging.log4j.core.selector;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.core.LifeCycle;
20 import org.apache.logging.log4j.core.util.Constants;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.junit.AfterClass;
23 import org.junit.BeforeClass;
24 import org.junit.Test;
25
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28
29 public final class BasicContextSelectorTest {
30
31 @BeforeClass
32 public static void beforeClass() {
33 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
34 BasicContextSelector.class.getName());
35 }
36
37 @AfterClass
38 public static void afterClass() {
39 System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
40 }
41
42 @Test
43 public void testLogManagerShutdown() {
44 LoggerContext context = (LoggerContext) LogManager.getContext();
45 assertEquals(LifeCycle.State.STARTED, context.getState());
46 LogManager.shutdown();
47 assertEquals(LifeCycle.State.STOPPED, context.getState());
48 }
49
50 @Test
51 public void testNotDependentOnClassLoader() {
52 assertFalse(LogManager.getFactory().isClassLoaderDependent());
53 }
54 }
1919
2020 import org.apache.logging.log4j.core.Logger;
2121 import org.apache.logging.log4j.core.util.ReflectionUtil;
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.Test;
22 import org.junit.Before;
23 import org.junit.Test;
2424
25 import static org.junit.jupiter.api.Assertions.*;
25 import static org.junit.Assert.*;
2626
2727 public class ClassLoaderContextSelectorTest {
2828
3030
3131 private ClassLoader loader1, loader2, loader3;
3232
33 @BeforeEach
33 @Before
3434 public void setUp() throws Exception {
3535 loader1 = new TestClassLoader();
3636 loader2 = new TestClassLoader();
1616 package org.apache.logging.log4j.core.time;
1717
1818 import org.apache.logging.log4j.core.time.internal.FixedPreciseClock;
19 import org.junit.jupiter.api.Test;
20
21 import java.time.ZoneId;
22 import java.time.format.DateTimeFormatter;
23
24 import static org.junit.jupiter.api.Assertions.*;
25
26 class MutableInstantTest {
27
28 @Test
29 void testGetEpochSecond() {
30 MutableInstant instant = new MutableInstant();
31 assertEquals(0, instant.getEpochSecond(), "initial");
19 import org.junit.Test;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotEquals;
23
24 public class MutableInstantTest {
25
26 @Test
27 public void testGetEpochSecond() {
28 final MutableInstant instant = new MutableInstant();
29 assertEquals("initial", 0, instant.getEpochSecond());
3230
3331 instant.initFromEpochSecond(123, 456);
34 assertEquals(123, instant.getEpochSecond(), "returns directly set value");
35
36 instant.initFromEpochMilli(123456, 789012);
37 assertEquals(123, instant.getEpochSecond(), "returns converted value when initialized from milllis");
38
39 MutableInstant other = new MutableInstant();
32 assertEquals("returns directly set value", 123, instant.getEpochSecond());
33
34 instant.initFromEpochMilli(123456, 789012);
35 assertEquals("returns converted value when initialized from milllis", 123, instant.getEpochSecond());
36
37 final MutableInstant other = new MutableInstant();
4038 other.initFromEpochSecond(788, 456);
4139 instant.initFrom(other);
4240
43 assertEquals(788, instant.getEpochSecond(), "returns ref value when initialized from instant");
44 }
45
46 @Test
47 void testGetNanoOfSecond() {
48 MutableInstant instant = new MutableInstant();
49 assertEquals(0, instant.getNanoOfSecond(), "initial");
41 assertEquals("returns ref value when initialized from instant", 788, instant.getEpochSecond());
42 }
43
44 @Test
45 public void testGetNanoOfSecond() {
46 final MutableInstant instant = new MutableInstant();
47 assertEquals("initial", 0, instant.getNanoOfSecond());
5048
5149 instant.initFromEpochSecond(123, 456);
52 assertEquals(456, instant.getNanoOfSecond(), "returns directly set value");
53
54 instant.initFromEpochMilli(123456, 789012);
55 assertEquals(456789012, instant.getNanoOfSecond(), "returns converted value when initialized from milllis");
56
57 MutableInstant other = new MutableInstant();
50 assertEquals("returns directly set value", 456, instant.getNanoOfSecond());
51
52 instant.initFromEpochMilli(123456, 789012);
53 assertEquals("returns converted value when initialized from milllis", 456789012, instant.getNanoOfSecond());
54
55 final MutableInstant other = new MutableInstant();
5856 other.initFromEpochSecond(788, 456);
5957 instant.initFrom(other);
6058
61 assertEquals(456, instant.getNanoOfSecond(), "returns ref value when initialized from instant");
62 }
63
64 @Test
65 void testGetEpochMillisecond() {
66 MutableInstant instant = new MutableInstant();
67 assertEquals(0, instant.getEpochMillisecond(), "initial");
59 assertEquals("returns ref value when initialized from instant", 456, instant.getNanoOfSecond());
60 }
61
62 @Test
63 public void testGetEpochMillisecond() {
64 final MutableInstant instant = new MutableInstant();
65 assertEquals("initial", 0, instant.getEpochMillisecond());
6866
6967 instant.initFromEpochMilli(123, 456);
70 assertEquals(123, instant.getEpochMillisecond(), "returns directly set value");
71
72 instant.initFromEpochSecond(123, 456789012);
73 assertEquals(123456, instant.getEpochMillisecond(), "returns converted value when initialized from seconds");
74
75 MutableInstant other = new MutableInstant();
68 assertEquals("returns directly set value", 123, instant.getEpochMillisecond());
69
70 instant.initFromEpochSecond(123, 456789012);
71 assertEquals("returns converted value when initialized from seconds", 123456, instant.getEpochMillisecond());
72
73 final MutableInstant other = new MutableInstant();
7674 other.initFromEpochMilli(788, 456);
7775 instant.initFrom(other);
7876
79 assertEquals(788, instant.getEpochMillisecond(), "returns ref value when initialized from instant");
80 }
81
82 @Test
83 void getGetNanoOfMillisecond() {
84 MutableInstant instant = new MutableInstant();
85 assertEquals(0, instant.getNanoOfMillisecond(), "initial");
77 assertEquals("returns ref value when initialized from instant", 788, instant.getEpochMillisecond());
78 }
79
80 @Test
81 public void getGetNanoOfMillisecond() {
82 final MutableInstant instant = new MutableInstant();
83 assertEquals("initial", 0, instant.getNanoOfMillisecond());
8684
8785 instant.initFromEpochMilli(123, 456);
88 assertEquals(456, instant.getNanoOfMillisecond(), "returns directly set value");
89
90 instant.initFromEpochSecond(123, 456789012);
91 assertEquals(789012, instant.getNanoOfMillisecond(), "returns converted value when initialized from milllis");
92
93 MutableInstant other = new MutableInstant();
86 assertEquals("returns directly set value", 456, instant.getNanoOfMillisecond());
87
88 instant.initFromEpochSecond(123, 456789012);
89 assertEquals("returns converted value when initialized from milllis", 789012, instant.getNanoOfMillisecond());
90
91 final MutableInstant other = new MutableInstant();
9492 other.initFromEpochMilli(788, 456);
9593 instant.initFrom(other);
9694
97 assertEquals(456, instant.getNanoOfMillisecond(), "returns ref value when initialized from instant");
98 }
99
100 @Test
101 void testInitFromInstantRejectsNull() {
102 assertThrows(NullPointerException.class, () -> new MutableInstant().initFrom((Instant) null));
103 }
104
105 @Test
106 void testInitFromInstantCopiesValues() {
107 MutableInstant other = new MutableInstant();
95 assertEquals("returns ref value when initialized from instant", 456, instant.getNanoOfMillisecond());
96 }
97
98 @Test(expected = NullPointerException.class)
99 public void testInitFromInstantRejectsNull() {
100 new MutableInstant().initFrom((Instant) null);
101 }
102
103 @Test
104 public void testInitFromInstantCopiesValues() {
105 final MutableInstant other = new MutableInstant();
108106 other.initFromEpochSecond(788, 456);
109 assertEquals(788, other.getEpochSecond(), "epochSec");
110 assertEquals(456, other.getNanoOfSecond(), "NanosOfSec");
111
112 MutableInstant instant = new MutableInstant();
113 instant.initFrom(other);
114
115 assertEquals(788, instant.getEpochSecond(), "epochSec");
116 assertEquals(456, instant.getNanoOfSecond(), "NanoOfSec");
117 }
118
119 @Test
120 void testInitFromEpochMillis() {
121 MutableInstant instant = new MutableInstant();
122 instant.initFromEpochMilli(123456, 789012);
123 assertEquals(123, instant.getEpochSecond(), "epochSec");
124 assertEquals(456789012, instant.getNanoOfSecond(), "NanoOfSec");
125 assertEquals(123456, instant.getEpochMillisecond(), "epochMilli");
126 assertEquals(789012, instant.getNanoOfMillisecond(), "NanoOfMilli");
127 }
128
129 @Test
130 void testInitFromEpochMillisRejectsNegativeNanoOfMilli() {
131 MutableInstant instant = new MutableInstant();
132 assertThrows(IllegalArgumentException.class, () -> instant.initFromEpochMilli(123456, -1));
133 }
134
135 @Test
136 void testInitFromEpochMillisRejectsTooLargeNanoOfMilli() {
137 MutableInstant instant = new MutableInstant();
138 assertThrows(IllegalArgumentException.class, () -> instant.initFromEpochMilli(123456, 1000_000));
139 }
140
141 @Test
142 void testInitFromEpochMillisAcceptsTooMaxNanoOfMilli() {
143 MutableInstant instant = new MutableInstant();
107 assertEquals("epochSec", 788, other.getEpochSecond());
108 assertEquals("NanosOfSec", 456, other.getNanoOfSecond());
109
110 final MutableInstant instant = new MutableInstant();
111 instant.initFrom(other);
112
113 assertEquals("epochSec", 788, instant.getEpochSecond());
114 assertEquals("NanoOfSec", 456, instant.getNanoOfSecond());
115 }
116
117 @Test
118 public void testInitFromEpochMillis() {
119 final MutableInstant instant = new MutableInstant();
120 instant.initFromEpochMilli(123456, 789012);
121 assertEquals("epochSec", 123, instant.getEpochSecond());
122 assertEquals("NanoOfSec", 456789012, instant.getNanoOfSecond());
123 assertEquals("epochMilli", 123456, instant.getEpochMillisecond());
124 assertEquals("NanoOfMilli", 789012, instant.getNanoOfMillisecond());
125 }
126
127 @Test(expected = IllegalArgumentException.class)
128 public void testInitFromEpochMillisRejectsNegativeNanoOfMilli() {
129 final MutableInstant instant = new MutableInstant();
130 instant.initFromEpochMilli(123456, -1);
131 }
132
133 @Test(expected = IllegalArgumentException.class)
134 public void testInitFromEpochMillisRejectsTooLargeNanoOfMilli() {
135 final MutableInstant instant = new MutableInstant();
136 instant.initFromEpochMilli(123456, 1000_000);
137 }
138
139 @Test
140 public void testInitFromEpochMillisAcceptsTooMaxNanoOfMilli() {
141 final MutableInstant instant = new MutableInstant();
144142 instant.initFromEpochMilli(123456, 999_999);
145 assertEquals(999_999, instant.getNanoOfMillisecond(), "NanoOfMilli");
146 }
147
148 @Test
149 void testInitFromEpochSecond() {
150 MutableInstant instant = new MutableInstant();
151 instant.initFromEpochSecond(123, 456789012);
152 assertEquals(123, instant.getEpochSecond(), "epochSec");
153 assertEquals(456789012, instant.getNanoOfSecond(), "NanoOfSec");
154 assertEquals(123456, instant.getEpochMillisecond(), "epochMilli");
155 assertEquals(789012, instant.getNanoOfMillisecond(), "NanoOfMilli");
156 }
157
158 @Test
159 void testInitFromEpochSecondRejectsNegativeNanoOfMilli() {
160 MutableInstant instant = new MutableInstant();
161 assertThrows(IllegalArgumentException.class, () -> instant.initFromEpochSecond(123456, -1));
162 }
163
164 @Test
165 void testInitFromEpochSecondRejectsTooLargeNanoOfMilli() {
166 MutableInstant instant = new MutableInstant();
167 assertThrows(IllegalArgumentException.class, () -> instant.initFromEpochSecond(123456, 1000_000_000));
168 }
169
170 @Test
171 void testInitFromEpochSecondAcceptsTooMaxNanoOfMilli() {
172 MutableInstant instant = new MutableInstant();
143 assertEquals("NanoOfMilli", 999_999, instant.getNanoOfMillisecond());
144 }
145
146 @Test
147 public void testInitFromEpochSecond() {
148 final MutableInstant instant = new MutableInstant();
149 instant.initFromEpochSecond(123, 456789012);
150 assertEquals("epochSec", 123, instant.getEpochSecond());
151 assertEquals("NanoOfSec", 456789012, instant.getNanoOfSecond());
152 assertEquals("epochMilli", 123456, instant.getEpochMillisecond());
153 assertEquals("NanoOfMilli", 789012, instant.getNanoOfMillisecond());
154 }
155
156 @Test(expected = IllegalArgumentException.class)
157 public void testInitFromEpochSecondRejectsNegativeNanoOfMilli() {
158 final MutableInstant instant = new MutableInstant();
159 instant.initFromEpochSecond(123456, -1);
160 }
161
162 @Test(expected = IllegalArgumentException.class)
163 public void testInitFromEpochSecondRejectsTooLargeNanoOfMilli() {
164 final MutableInstant instant = new MutableInstant();
165 instant.initFromEpochSecond(123456, 1000_000_000);
166 }
167
168 @Test
169 public void testInitFromEpochSecondAcceptsTooMaxNanoOfMilli() {
170 final MutableInstant instant = new MutableInstant();
173171 instant.initFromEpochSecond(123456, 999_999_999);
174 assertEquals(999_999_999, instant.getNanoOfSecond(), "NanoOfSec");
175 }
176
177 @Test
178 void testInstantToMillisAndNanos() {
179 long[] values = new long[2];
172 assertEquals("NanoOfSec", 999_999_999, instant.getNanoOfSecond());
173 }
174
175 @Test
176 public void testInstantToMillisAndNanos() {
177 final long[] values = new long[2];
180178 MutableInstant.instantToMillisAndNanos(123456, 999_999_999, values);
181179 assertEquals(123456_999, values[0]);
182180 assertEquals(999_999, values[1]);
183181 }
184182
185183 @Test
186 void testInitFromClock() {
187 MutableInstant instant = new MutableInstant();
188
189 PreciseClock clock = new FixedPreciseClock(123456, 789012);
184 public void testInitFromClock() {
185 final MutableInstant instant = new MutableInstant();
186
187 final PreciseClock clock = new FixedPreciseClock(123456, 789012);
190188 instant.initFrom(clock);
191189
192190 assertEquals(123456, instant.getEpochMillisecond());
196194 }
197195
198196 @Test
199 void testEquals() {
200 MutableInstant instant = new MutableInstant();
201 instant.initFromEpochSecond(123, 456789012);
202
203 MutableInstant instant2 = new MutableInstant();
197 public void testEquals() {
198 final MutableInstant instant = new MutableInstant();
199 instant.initFromEpochSecond(123, 456789012);
200
201 final MutableInstant instant2 = new MutableInstant();
204202 instant2.initFromEpochMilli(123456, 789012);
205203
206204 assertEquals(instant, instant2);
207205 }
208206
209207 @Test
210 void testHashCode() {
211 MutableInstant instant = new MutableInstant();
212 instant.initFromEpochSecond(123, 456789012);
213
214 MutableInstant instant2 = new MutableInstant();
208 public void testHashCode() {
209 final MutableInstant instant = new MutableInstant();
210 instant.initFromEpochSecond(123, 456789012);
211
212 final MutableInstant instant2 = new MutableInstant();
215213 instant2.initFromEpochMilli(123456, 789012);
216214
217215 assertEquals(instant.hashCode(), instant2.hashCode());
222220 }
223221
224222 @Test
225 void testToString() {
226 MutableInstant instant = new MutableInstant();
223 public void testToString() {
224 final MutableInstant instant = new MutableInstant();
227225 instant.initFromEpochSecond(123, 456789012);
228226 assertEquals("MutableInstant[epochSecond=123, nano=456789012]", instant.toString());
229227
230228 instant.initFromEpochMilli(123456, 789012);
231229 assertEquals("MutableInstant[epochSecond=123, nano=456789012]", instant.toString());
232230 }
233
234 @Test
235 void testTemporalAccessor() {
236 java.time.Instant javaInstant = java.time.Instant.parse("2020-05-10T22:09:04.123456789Z");
237 MutableInstant log4jInstant = new MutableInstant();
238 log4jInstant.initFromEpochSecond(javaInstant.getEpochSecond(), javaInstant.getNano());
239 DateTimeFormatter formatter = DateTimeFormatter
240 .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z'")
241 .withZone(ZoneId.of("UTC"));
242 assertEquals(formatter.format(javaInstant), formatter.format(log4jInstant));
243 }
244
245 }
231 }
2323 import java.nio.charset.Charset;
2424 import java.util.ArrayList;
2525 import java.util.Arrays;
26 import java.util.Collections;
2726 import java.util.List;
2827 import java.util.Locale;
2928
4140 import org.apache.logging.log4j.message.MessageFactory;
4241 import org.apache.logging.log4j.util.MessageSupplier;
4342 import org.apache.logging.log4j.util.Supplier;
44 import org.junit.jupiter.api.BeforeAll;
45 import org.junit.jupiter.api.Tag;
46 import org.junit.jupiter.api.Test;
43 import org.junit.BeforeClass;
44 import org.junit.Test;
4745
48 import static org.junit.jupiter.api.Assertions.*;
46 import static org.junit.Assert.*;
4947
50 @Tag("functional")
5148 public class GenerateCustomLoggerTest {
52
53 @BeforeAll
49
50 @BeforeClass
5451 public static void beforeClass() {
5552 System.setProperty("log4j2.loggerContextFactory", "org.apache.logging.log4j.TestLoggerContextFactory");
5653 }
7471 final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
7572 final List<String> errors = new ArrayList<>();
7673 try (final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null)) {
77 final Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(
78 Collections.singletonList(f));
74 final Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays
75 .asList(f));
7976
8077 // compile generated source
8178 compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();
8784 }
8885 }
8986 }
90 assertTrue(errors.isEmpty(), errors.toString());
87 assertTrue(errors.toString(), errors.isEmpty());
9188
9289 // load the compiled class
9390 final Class<?> cls = Class.forName(CLASSNAME);
9491
9592 // check that all factory methods exist and are static
96 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create").getModifiers()));
97 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", Class.class).getModifiers()));
98 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", Object.class).getModifiers()));
99 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", String.class).getModifiers()));
93 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[0]).getModifiers()));
94 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[] { Class.class }).getModifiers()));
95 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[] { Object.class }).getModifiers()));
96 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[] { String.class }).getModifiers()));
10097 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", Class.class, MessageFactory.class).getModifiers()));
10198 assertTrue(Modifier
10299 .isStatic(cls.getDeclaredMethod("create", Object.class, MessageFactory.class).getModifiers()));
106103 // check that all log methods exist
107104 final String[] logMethods = { "defcon1", "defcon2", "defcon3" };
108105 for (final String name : logMethods) {
109 assertDoesNotThrow(() -> {
110 cls.getDeclaredMethod(name, Marker.class, Message.class, Throwable.class);
111 cls.getDeclaredMethod(name, Marker.class, Object.class, Throwable.class);
112 cls.getDeclaredMethod(name, Marker.class, String.class, Throwable.class);
113 cls.getDeclaredMethod(name, Marker.class, Message.class);
114 cls.getDeclaredMethod(name, Marker.class, Object.class);
115 cls.getDeclaredMethod(name, Marker.class, String.class);
116 cls.getDeclaredMethod(name, Message.class);
117 cls.getDeclaredMethod(name, Object.class);
118 cls.getDeclaredMethod(name, String.class);
119 cls.getDeclaredMethod(name, Message.class, Throwable.class);
120 cls.getDeclaredMethod(name, Object.class, Throwable.class);
121 cls.getDeclaredMethod(name, String.class, Throwable.class);
122 cls.getDeclaredMethod(name, String.class, Object[].class);
123 cls.getDeclaredMethod(name, Marker.class, String.class, Object[].class);
106 cls.getDeclaredMethod(name, Marker.class, Message.class, Throwable.class);
107 cls.getDeclaredMethod(name, Marker.class, Object.class, Throwable.class);
108 cls.getDeclaredMethod(name, Marker.class, String.class, Throwable.class);
109 cls.getDeclaredMethod(name, Marker.class, Message.class);
110 cls.getDeclaredMethod(name, Marker.class, Object.class);
111 cls.getDeclaredMethod(name, Marker.class, String.class);
112 cls.getDeclaredMethod(name, Message.class);
113 cls.getDeclaredMethod(name, Object.class);
114 cls.getDeclaredMethod(name, String.class);
115 cls.getDeclaredMethod(name, Message.class, Throwable.class);
116 cls.getDeclaredMethod(name, Object.class, Throwable.class);
117 cls.getDeclaredMethod(name, String.class, Throwable.class);
118 cls.getDeclaredMethod(name, String.class, Object[].class);
119 cls.getDeclaredMethod(name, Marker.class, String.class, Object[].class);
124120
125 // 2.4 lambda support
126 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class);
127 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class, Throwable.class);
128 cls.getDeclaredMethod(name, Marker.class, String.class, Supplier[].class);
129 cls.getDeclaredMethod(name, Marker.class, Supplier.class);
130 cls.getDeclaredMethod(name, Marker.class, Supplier.class, Throwable.class);
131 cls.getDeclaredMethod(name, MessageSupplier.class);
132 cls.getDeclaredMethod(name, MessageSupplier.class, Throwable.class);
133 cls.getDeclaredMethod(name, String.class, Supplier[].class);
134 cls.getDeclaredMethod(name, Supplier.class);
135 cls.getDeclaredMethod(name, Supplier.class, Throwable.class);
136 });
121 // 2.4 lambda support
122 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class);
123 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class, Throwable.class);
124 cls.getDeclaredMethod(name, Marker.class, String.class, Supplier[].class);
125 cls.getDeclaredMethod(name, Marker.class, Supplier.class);
126 cls.getDeclaredMethod(name, Marker.class, Supplier.class, Throwable.class);
127 cls.getDeclaredMethod(name, MessageSupplier.class);
128 cls.getDeclaredMethod(name, MessageSupplier.class, Throwable.class);
129 cls.getDeclaredMethod(name, String.class, Supplier[].class);
130 cls.getDeclaredMethod(name, Supplier.class);
131 cls.getDeclaredMethod(name, Supplier.class, Throwable.class);
137132 }
138133
139134 // now see if it actually works...
140 final Method create = cls.getDeclaredMethod("create", String.class);
135 final Method create = cls.getDeclaredMethod("create", new Class[] { String.class });
141136 final Object customLogger = create.invoke(null, "X.Y.Z");
142137 int n = 0;
143138 for (final String name : logMethods) {
2323 import java.nio.charset.Charset;
2424 import java.util.ArrayList;
2525 import java.util.Arrays;
26 import java.util.Collections;
2726 import java.util.List;
2827 import java.util.Locale;
2928
3736 import org.apache.logging.log4j.LogManager;
3837 import org.apache.logging.log4j.Marker;
3938 import org.apache.logging.log4j.TestLogger;
39 import org.apache.logging.log4j.core.tools.Generate;
4040 import org.apache.logging.log4j.message.Message;
4141 import org.apache.logging.log4j.message.MessageFactory;
4242 import org.apache.logging.log4j.spi.ExtendedLogger;
4343 import org.apache.logging.log4j.util.MessageSupplier;
4444 import org.apache.logging.log4j.util.Supplier;
45 import org.junit.jupiter.api.BeforeAll;
46 import org.junit.jupiter.api.Tag;
47 import org.junit.jupiter.api.Test;
45 import org.junit.BeforeClass;
46 import org.junit.Test;
4847
49 import static org.junit.jupiter.api.Assertions.*;
48 import static org.junit.Assert.*;
5049
51 @Tag("functional")
5250 public class GenerateExtendedLoggerTest {
53
54 @BeforeAll
51
52 @BeforeClass
5553 public static void beforeClass() {
5654 System.setProperty("log4j2.loggerContextFactory", "org.apache.logging.log4j.TestLoggerContextFactory");
5755 }
7674 final List<String> errors = new ArrayList<>();
7775 try (final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null)) {
7876 final Iterable<? extends JavaFileObject> compilationUnits = fileManager
79 .getJavaFileObjectsFromFiles(Collections.singletonList(f));
77 .getJavaFileObjectsFromFiles(Arrays.asList(f));
8078
8179 // compile generated source
8280 compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();
8886 }
8987 }
9088 }
91 assertTrue(errors.isEmpty(), errors.toString());
89 assertTrue(errors.toString(), errors.isEmpty());
9290
9391 // load the compiled class
9492 final Class<?> cls = Class.forName(CLASSNAME);
9593
9694 // check that all factory methods exist and are static
97 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create").getModifiers()));
98 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", Class.class).getModifiers()));
99 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", Object.class).getModifiers()));
100 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", String.class).getModifiers()));
95 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[0]).getModifiers()));
96 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[] { Class.class }).getModifiers()));
97 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[] { Object.class }).getModifiers()));
98 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", new Class[] { String.class }).getModifiers()));
10199 assertTrue(Modifier.isStatic(cls.getDeclaredMethod("create", Class.class, MessageFactory.class).getModifiers()));
102100 assertTrue(Modifier
103101 .isStatic(cls.getDeclaredMethod("create", Object.class, MessageFactory.class).getModifiers()));
107105 // check that the extended log methods exist
108106 final String[] extendedMethods = { "diag", "notice", "verbose" };
109107 for (final String name : extendedMethods) {
110 assertDoesNotThrow(() -> {
111 cls.getDeclaredMethod(name, Marker.class, Message.class, Throwable.class);
112 cls.getDeclaredMethod(name, Marker.class, Object.class, Throwable.class);
113 cls.getDeclaredMethod(name, Marker.class, String.class, Throwable.class);
114 cls.getDeclaredMethod(name, Marker.class, Message.class);
115 cls.getDeclaredMethod(name, Marker.class, Object.class);
116 cls.getDeclaredMethod(name, Marker.class, String.class);
117 cls.getDeclaredMethod(name, Message.class);
118 cls.getDeclaredMethod(name, Object.class);
119 cls.getDeclaredMethod(name, String.class);
120 cls.getDeclaredMethod(name, Message.class, Throwable.class);
121 cls.getDeclaredMethod(name, Object.class, Throwable.class);
122 cls.getDeclaredMethod(name, String.class, Throwable.class);
123 cls.getDeclaredMethod(name, String.class, Object[].class);
124 cls.getDeclaredMethod(name, Marker.class, String.class, Object[].class);
108 cls.getDeclaredMethod(name, Marker.class, Message.class, Throwable.class);
109 cls.getDeclaredMethod(name, Marker.class, Object.class, Throwable.class);
110 cls.getDeclaredMethod(name, Marker.class, String.class, Throwable.class);
111 cls.getDeclaredMethod(name, Marker.class, Message.class);
112 cls.getDeclaredMethod(name, Marker.class, Object.class);
113 cls.getDeclaredMethod(name, Marker.class, String.class);
114 cls.getDeclaredMethod(name, Message.class);
115 cls.getDeclaredMethod(name, Object.class);
116 cls.getDeclaredMethod(name, String.class);
117 cls.getDeclaredMethod(name, Message.class, Throwable.class);
118 cls.getDeclaredMethod(name, Object.class, Throwable.class);
119 cls.getDeclaredMethod(name, String.class, Throwable.class);
120 cls.getDeclaredMethod(name, String.class, Object[].class);
121 cls.getDeclaredMethod(name, Marker.class, String.class, Object[].class);
125122
126 // 2.4 lambda support
127 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class);
128 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class, Throwable.class);
129 cls.getDeclaredMethod(name, Marker.class, String.class, Supplier[].class);
130 cls.getDeclaredMethod(name, Marker.class, Supplier.class);
131 cls.getDeclaredMethod(name, Marker.class, Supplier.class, Throwable.class);
132 cls.getDeclaredMethod(name, MessageSupplier.class);
133 cls.getDeclaredMethod(name, MessageSupplier.class, Throwable.class);
134 cls.getDeclaredMethod(name, String.class, Supplier[].class);
135 cls.getDeclaredMethod(name, Supplier.class);
136 cls.getDeclaredMethod(name, Supplier.class, Throwable.class);
137 });
123 // 2.4 lambda support
124 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class);
125 cls.getDeclaredMethod(name, Marker.class, MessageSupplier.class, Throwable.class);
126 cls.getDeclaredMethod(name, Marker.class, String.class, Supplier[].class);
127 cls.getDeclaredMethod(name, Marker.class, Supplier.class);
128 cls.getDeclaredMethod(name, Marker.class, Supplier.class, Throwable.class);
129 cls.getDeclaredMethod(name, MessageSupplier.class);
130 cls.getDeclaredMethod(name, MessageSupplier.class, Throwable.class);
131 cls.getDeclaredMethod(name, String.class, Supplier[].class);
132 cls.getDeclaredMethod(name, Supplier.class);
133 cls.getDeclaredMethod(name, Supplier.class, Throwable.class);
138134 }
139135
140136 // now see if it actually works...
141 final Method create = cls.getDeclaredMethod("create", String.class);
137 final Method create = cls.getDeclaredMethod("create", new Class[] { String.class });
142138 final Object extendedLogger = create.invoke(null, "X.Y.Z");
143139 int n = 0;
144140 for (final String name : extendedMethods) {
145141 final Method method = cls.getDeclaredMethod(name, String.class);
146142 method.invoke(extendedLogger, "This is message " + n++);
147143 }
148
144
149145 // This logger extends o.a.l.log4j.spi.ExtendedLogger,
150146 // so all the standard logging methods can be used as well
151147 final ExtendedLogger logger = (ExtendedLogger) extendedLogger;
161157 for (int i = 0; i < lines.size() - 6; i++) {
162158 assertEquals(" " + levels.get(i).name + " This is message " + i, lines.get(i));
163159 }
164
160
165161 // test that the standard logging methods still work
166162 int i = lines.size() - 6;
167163 assertEquals(" TRACE trace message", lines.get(i++));
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import static org.junit.jupiter.api.Assertions.assertEquals;
19
2018 import java.util.ArrayList;
2119 import java.util.Collections;
2220 import java.util.HashMap;
2321
24 import org.junit.jupiter.params.ParameterizedTest;
25 import org.junit.jupiter.params.provider.MethodSource;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.Parameterized;
2625
26 import static org.junit.Assert.*;
27
28 /**
29 *
30 */
31 @RunWith(Parameterized.class)
2732 public class AssertTest {
2833
34 private final Object value;
35 private final boolean isEmpty;
36
37 @Parameterized.Parameters
2938 public static Object[][] data() {
3039 return new Object[][]{
3140 // value, isEmpty
3241 {null, true},
3342 {"", true},
34 {org.apache.logging.log4j.util.Constants.EMPTY_OBJECT_ARRAY, true},
43 {new Object[0], true},
3544 {new ArrayList<>(), true},
3645 {new HashMap<>(), true},
3746 {0, false},
4554 };
4655 }
4756
48 @ParameterizedTest
49 @MethodSource("data")
50 public void isEmpty(Object value, boolean isEmpty) throws Exception {
57 public AssertTest(final Object value, final boolean isEmpty) {
58 this.value = value;
59 this.isEmpty = isEmpty;
60 }
61
62 @Test
63 public void isEmpty() throws Exception {
5164 assertEquals(isEmpty, Assert.isEmpty(value));
5265 }
5366
54 }
67 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.lang.reflect.Field;
19
1820 import org.apache.commons.lang3.reflect.FieldUtils;
1921 import org.apache.logging.log4j.core.async.AsyncLogger;
2022 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
21 import org.junit.jupiter.api.BeforeEach;
22 import org.junit.jupiter.api.Test;
23 import org.junit.jupiter.api.condition.EnabledOnJre;
24 import org.junit.jupiter.api.condition.JRE;
23 import org.junit.Before;
24 import org.junit.Test;
2525
26 import java.lang.reflect.Field;
26 import static org.junit.Assert.*;
2727
28 import static org.junit.jupiter.api.Assertions.*;
29
30 // as of Java 12, final fields can no longer be overwritten via reflection
31 @EnabledOnJre({ JRE.JAVA_8, JRE.JAVA_9, JRE.JAVA_10, JRE.JAVA_11 })
3228 public class ClockFactoryTest {
3329
3430 public static void resetClocks() throws IllegalAccessException {
3935 public static void resetClock(final Class<?> clazz) throws IllegalAccessException {
4036 System.clearProperty(ClockFactory.PROPERTY_NAME);
4137 final Field field = FieldUtils.getField(clazz, "CLOCK", true);
42 FieldUtils.removeFinalModifier(field);
38 FieldUtils.removeFinalModifier(field, true);
4339 FieldUtils.writeStaticField(field, ClockFactory.getClock(), false);
4440 }
4541
46 @BeforeEach
42 @Before
4743 public void setUp() throws Exception {
4844 resetClocks();
4945 }
+0
-71
log4j-core/src/test/java/org/apache/logging/log4j/core/util/ContextDataProviderTest.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.logging.log4j.core.util;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.ThreadContext;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.ConfigurationFactory;
23 import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
24 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.jupiter.api.BeforeAll;
26 import org.junit.jupiter.api.Tag;
27 import org.junit.jupiter.api.Test;
28
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32
33 import static org.junit.jupiter.api.Assertions.*;
34
35 @Tag("functional")
36 public class ContextDataProviderTest {
37
38 private static Logger logger;
39 private static ListAppender appender;
40
41 @BeforeAll
42 public static void beforeClass() {
43 ThreadContextDataInjector.contextDataProviders.add(new TestContextDataProvider());
44 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "log4j-contextData.xml");
45 LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
46 logger = loggerContext.getLogger(ContextDataProviderTest.class.getName());
47 appender = loggerContext.getConfiguration().getAppender("List");
48 assertNotNull(appender, "No List appender");
49 }
50
51 @Test
52 public void testContextProvider() {
53 ThreadContext.put("loginId", "jdoe");
54 logger.debug("This is a test");
55 List<String> messages = appender.getMessages();
56 assertEquals(1, messages.size(), "Incorrect number of messages");
57 assertTrue(messages.get(0).contains("testKey=testValue"), "Context data missing");
58 }
59
60 private static class TestContextDataProvider implements ContextDataProvider {
61
62 @Override
63 public Map<String, String> supplyContextData() {
64 Map<String, String> contextData = new HashMap<>();
65 contextData.put("testKey", "testValue");
66 return contextData;
67 }
68
69 }
70 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import java.text.SimpleDateFormat;
21 import java.util.Calendar;
2220 import java.util.Date;
2321 import java.util.GregorianCalendar;
2422
25 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2624
2725 /**
2826 * Class Description goes here.
3634 final Date date = new GregorianCalendar(2015, 11, 2).getTime();
3735 final Date fireDate = parser.getNextValidTimeAfter(date);
3836 final Date expected = new GregorianCalendar(2015, 11, 2, 7, 0, 0).getTime();
39 assertEquals(expected, fireDate, "Dates not equal.");
37 assertEquals("Dates not equal.", expected, fireDate);
4038 }
4139
4240 @Test
4543 final Date date = new GregorianCalendar(2015, 11, 2).getTime();
4644 final Date fireDate = parser.getNextValidTimeAfter(date);
4745 final Date expected = new GregorianCalendar(2015, 11, 4, 7, 0, 0).getTime();
48 assertEquals(expected, fireDate, "Dates not equal.");
46 assertEquals("Dates not equal.", expected, fireDate);
4947 }
5048
5149 @Test
5452 final Date date = new GregorianCalendar(2015, 11, 2).getTime();
5553 final Date fireDate = parser.getNextValidTimeAfter(date);
5654 final Date expected = new GregorianCalendar(2016, 0, 1, 7, 0, 0).getTime();
57 assertEquals(expected, fireDate, "Dates not equal.");
55 assertEquals("Dates not equal.", expected, fireDate);
5856 }
5957
6058 @Test
6361 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
6462 final Date fireDate = parser.getNextValidTimeAfter(date);
6563 final Date expected = new GregorianCalendar(2015, 10, 30, 7, 0, 0).getTime();
66 assertEquals(expected, fireDate, "Dates not equal.");
64 assertEquals("Dates not equal.", expected, fireDate);
6765 }
6866
6967 @Test
7270 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
7371 final Date fireDate = parser.getNextValidTimeAfter(date);
7472 final Date expected = new GregorianCalendar(2015, 10, 3, 0, 0, 0).getTime();
75 assertEquals(expected, fireDate, "Dates not equal.");
73 assertEquals("Dates not equal.", expected, fireDate);
7674 }
7775
7876 @Test
8179 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
8280 final Date fireDate = parser.getPrevFireTime(date);
8381 final Date expected = new GregorianCalendar(2015, 9, 31, 17, 45, 0).getTime();
84 assertEquals(expected, fireDate, "Dates not equal.");
82 assertEquals("Dates not equal.", expected, fireDate);
8583 }
8684
8785 @Test
9088 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
9189 final Date fireDate = parser.getPrevFireTime(date);
9290 final Date expected = new GregorianCalendar(2015, 10, 1, 18, 55, 0).getTime();
93 assertEquals(expected, fireDate, "Dates not equal.");
91 assertEquals("Dates not equal.", expected, fireDate);
9492 }
9593
9694 /**
97 * 35,45, and 55 minutes past the hour every hour.
95 * 35,45, and 55 minutes past the hour evern hour.
9896 */
9997 @Test
10098 public void testPrevFireTime3() throws Exception {
102100 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
103101 final Date fireDate = parser.getPrevFireTime(date);
104102 final Date expected = new GregorianCalendar(2015, 10, 1, 23, 55, 0).getTime();
105 assertEquals(expected, fireDate, "Dates not equal.");
103 assertEquals("Dates not equal.", expected, fireDate);
106104 }
107105
108106 /**
115113 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
116114 final Date fireDate = parser.getPrevFireTime(date);
117115 final Date expected = new GregorianCalendar(2015, 10, 1, 10, 15, 0).getTime();
118 assertEquals(expected, fireDate, "Dates not equal.");
116 assertEquals("Dates not equal.", expected, fireDate);
119117 }
120118
121119 /**
127125 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
128126 final Date fireDate = parser.getPrevFireTime(date);
129127 final Date expected = new GregorianCalendar(2015, 10, 1, 14, 59, 0).getTime();
130 assertEquals(expected, fireDate, "Dates not equal.");
128 assertEquals("Dates not equal.", expected, fireDate);
131129 }
132130
133131 /**
139137 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
140138 final Date fireDate = parser.getPrevFireTime(date);
141139 final Date expected = new GregorianCalendar(2015, 2, 25, 14, 44, 0).getTime();
142 assertEquals(expected, fireDate, "Dates not equal.");
140 assertEquals("Dates not equal.", expected, fireDate);
143141 }
144142
145143 /**
151149 final Date date = new GregorianCalendar(2015, 10, 2).getTime();
152150 final Date fireDate = parser.getPrevFireTime(date);
153151 final Date expected = new GregorianCalendar(2015, 9, 16, 10, 15, 0).getTime();
154 assertEquals(expected, fireDate, "Dates not equal.");
155 }
156
157 /*
158 * Input time with milliseconds will correctly return the next
159 * scheduled time.
160 */
161 @Test
162 public void testTimeBeforeMilliseconds() throws Exception {
163 final CronExpression parser = new CronExpression("0 0 0 * * ?");
164 final GregorianCalendar cal = new GregorianCalendar(2015, 10, 2, 0, 0, 0);
165 cal.set(Calendar.MILLISECOND, 100);
166 final Date date = cal.getTime();
167 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
168 System.err.println(sdf.format(date));
169 final Date fireDate = parser.getTimeBefore(date);
170 System.err.println(sdf.format(fireDate));
171 final Date expected = new GregorianCalendar(2015, 10, 1, 0, 0, 0).getTime();
172 assertEquals(expected, fireDate, "Dates not equal.");
152 assertEquals("Dates not equal.", expected, fireDate);
173153 }
174154
175155 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import org.junit.jupiter.api.Test;
18 import static org.junit.Assert.assertArrayEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
1921
20 import static org.junit.jupiter.api.Assertions.*;
22 import org.junit.Test;
2123
2224 public class CyclicBufferTest {
2325
2931 buffer.add(1);
3032 assertTrue(buffer.isEmpty());
3133 Integer[] items = buffer.removeAll();
32 assertEquals(0, items.length, "Incorrect number of items");
34 assertTrue("Incorrect number of items", items.length == 0);
3335
3436 assertTrue(buffer.isEmpty());
3537 buffer.add(1);
3739 buffer.add(3);
3840 buffer.add(4);
3941 items = buffer.removeAll();
40 assertEquals(0, items.length, "Incorrect number of items");
42 assertTrue("Incorrect number of items", items.length == 0);
4143 assertTrue(buffer.isEmpty());
4244 }
4345
4951 buffer.add(1);
5052 assertFalse(buffer.isEmpty());
5153 Integer[] items = buffer.removeAll();
52 assertEquals(1, items.length, "Incorrect number of items");
54 assertTrue("Incorrect number of items", items.length == 1);
5355
5456 assertTrue(buffer.isEmpty());
5557 buffer.add(1);
5759 buffer.add(3);
5860 buffer.add(4);
5961 items = buffer.removeAll();
60 assertEquals(1, items.length, "Incorrect number of items");
62 assertTrue("Incorrect number of items", items.length == 1);
6163 assertArrayEquals(new Integer[] { 4 }, items);
6264 assertTrue(buffer.isEmpty());
6365 }
7072 buffer.add(1);
7173 assertFalse(buffer.isEmpty());
7274 Integer[] items = buffer.removeAll();
73 assertEquals(1, items.length, "Incorrect number of items");
75 assertTrue("Incorrect number of items", items.length == 1);
7476
7577 assertTrue(buffer.isEmpty());
7678 buffer.add(1);
7880 buffer.add(3);
7981 buffer.add(4);
8082 items = buffer.removeAll();
81 assertEquals(3, items.length, "Incorrect number of items");
83 assertTrue("Incorrect number of items", items.length == 3);
8284 assertArrayEquals(new Integer[] { 2, 3, 4 }, items);
8385 assertTrue(buffer.isEmpty());
8486 }
8587
86 @Test
88 @Test(expected = IllegalArgumentException.class)
8789 public void testSizeNegative() {
88 assertThrows(IllegalArgumentException.class, () -> new CyclicBuffer<>(Integer.class, -1));
90 final CyclicBuffer<Integer> buffer = new CyclicBuffer<>(Integer.class, -1);
8991 }
9092
9193 }
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
17 package org.apache.logging.log4j.core.util;
18
19 import org.junit.jupiter.api.Test;
20
21 import static org.junit.jupiter.api.Assertions.*;
22
23 /**
24 * Tests the DummyNanoClock.
25 */
26 public class DummyNanoClockTest {
27
28 @Test
29 public void testReturnsZeroByDefault() {
30 assertEquals(0, new DummyNanoClock().nanoTime());
31 }
32
33 @Test
34 public void testReturnsConstructorValue() {
35 assertEquals(123, new DummyNanoClock(123).nanoTime());
36 }
37
38 }
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
17 package org.apache.logging.log4j.core.util;
18
19 import org.junit.Test;
20
21 import static org.junit.Assert.*;
22
23 /**
24 * Tests the DummyNanoClock.
25 */
26 public class DummyNanoClockTest {
27
28 @Test
29 public void testReturnsZeroByDefault() {
30 assertEquals(0, new DummyNanoClock().nanoTime());
31 }
32
33 @Test
34 public void testReturnsConstructorValue() {
35 assertEquals(123, new DummyNanoClock(123).nanoTime());
36 }
37
38 }
1616
1717 package org.apache.logging.log4j.core.util;
1818
19 import org.junit.jupiter.api.Test;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
2024
2125 import java.io.File;
2226 import java.net.URI;
2327
24 import static org.junit.jupiter.api.Assertions.*;
28 import org.junit.Test;
2529
2630 /**
2731 * Tests the FileUtils class.
3640 final URI uri = new URI(config);
3741 final File file = FileUtils.fileFromUri(uri);
3842 assertEquals(LOG4J_CONFIG_WITH_PLUS, file.getName());
39 assertTrue(file.exists(), "file exists");
40 }
41
42 @Test
43 public void testAbsoluteFileFromUriWithPlusCharactersInName() throws Exception {
44 final String config = "target/test-classes/log4j+config+with+plus+characters.xml";
45 final URI uri = new File(config).toURI();
46 final File file = FileUtils.fileFromUri(uri);
47 assertEquals(LOG4J_CONFIG_WITH_PLUS, file.getName());
48 assertTrue(file.exists(), "file exists");
49 }
50
51 @Test
52 public void testAbsoluteFileFromUriWithSpacesInName() throws Exception {
53 final String config = "target/test-classes/s p a c e s/log4j+config+with+plus+characters.xml";
54 final URI uri = new File(config).toURI();
55 final File file = FileUtils.fileFromUri(uri);
56 assertEquals(LOG4J_CONFIG_WITH_PLUS, file.getName());
57 assertTrue(file.exists(), "file exists");
58 }
59
60 @Test
61 public void testAbsoluteFileFromJBossVFSUri() throws Exception {
62 final String config = "target/test-classes/log4j+config+with+plus+characters.xml";
63 final String uriStr = new File(config).toURI().toString().replaceAll("^file:", "vfsfile:");
64 assertTrue(uriStr.startsWith("vfsfile:"));
65 final URI uri = URI.create(uriStr);
66 final File file = FileUtils.fileFromUri(uri);
67 assertEquals(LOG4J_CONFIG_WITH_PLUS, file.getName());
68 assertTrue(file.exists(), "file exists");
43 assertTrue("file exists", file.exists());
6944 }
7045
7146 @Test
7449 final URI uri = new URI(config);
7550 final File file = FileUtils.fileFromUri(uri);
7651 assertEquals(LOG4J_CONFIG_WITH_PLUS, file.getName());
77 assertTrue(file.exists(), "file exists");
52 assertTrue("file exists", file.exists());
53 }
54
55 /**
56 * Helps figure out why {@link #testFileFromUriWithPlusCharactersInName()} fails in Jenkins but asserting different
57 * parts of the implementation of {@link FileUtils#fileFromUri(URI)}.
58 */
59 @Test
60 public void testFileExistsWithPlusCharactersInName() throws Exception {
61 final String config = "target/test-classes/log4j+config+with+plus+characters.xml";
62 final File file = new File(config);
63 assertEquals(LOG4J_CONFIG_WITH_PLUS, file.getName());
64 assertTrue("file exists", file.exists());
65 //
66 final URI uri1 = new URI(config);
67 assertNull(uri1.getScheme());
68 //
69 final URI uri2 = new File(uri1.getPath()).toURI();
70 assertNotNull(uri2);
71 assertTrue("URI \"" + uri2 + "\" does not end with \"" + LOG4J_CONFIG_WITH_PLUS + "\"", uri2.toString()
72 .endsWith(LOG4J_CONFIG_WITH_PLUS));
73 //
74 final String fileName = uri2.toURL().getFile();
75 assertTrue("File name \"" + fileName + "\" does not end with \"" + LOG4J_CONFIG_WITH_PLUS + "\"",
76 fileName.endsWith(LOG4J_CONFIG_WITH_PLUS));
77 }
78
79 @Test
80 public void testFileFromUriWithPlusCharactersConvertedToSpacesIfFileDoesNotExist() throws Exception {
81 final String config = "NON-EXISTING-PATH/this+file+does+not+exist.xml";
82 final URI uri = new URI(config);
83 final File file = FileUtils.fileFromUri(uri);
84 assertEquals("this file does not exist.xml", file.getName());
85 assertFalse("file does not exist", file.exists());
7886 }
7987
8088 }
+0
-43
log4j-core/src/test/java/org/apache/logging/log4j/core/util/InitTest.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.logging.log4j.core.util;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.util.Timer;
21 import org.junit.jupiter.api.Disabled;
22 import org.junit.jupiter.api.Test;
23
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25
26 /**
27 * Test initialization.
28 */
29 @Disabled
30 public class InitTest {
31
32 @Test
33 public void initTest() {
34 Timer timer = new Timer("Log4j Initialization");
35 timer.start();
36 Logger logger = LogManager.getLogger();
37 timer.stop();
38 long elapsed = timer.getElapsedNanoTime();
39 System.out.println(timer.toString());
40 assertTrue(elapsed < 1000000000, "Initialization time exceeded threshold; elapsed " + elapsed);
41 }
42 }
1616
1717 package org.apache.logging.log4j.core.util;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * Tests the Integers class.
1616
1717 package org.apache.logging.log4j.core.util;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * This class is borrowed from <a href="https://github.com/FasterXML/jackson-core">Jackson</a>.
1616
1717 package org.apache.logging.log4j.core.util;
1818
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
21 import static org.junit.jupiter.api.Assertions.*;
21 import static org.junit.Assert.*;
2222
2323 /**
2424 * Tests the Loader class.
2727
2828 @Test
2929 public void testLoadClassWithNullClassloaderReturnNull() throws Exception {
30 assertNull(
31 Loader.loadClass(Loader.class.getCanonicalName(), null), "Expect null return value for null ClassLoader.");
30 assertNull("Expect null return value for null ClassLoader.",
31 Loader.loadClass(Loader.class.getCanonicalName(), null));
3232 }
3333
3434 @Test
3535 public void testLoadClassReturnClassForExistingClass() throws Exception {
36 assertEquals(Loader.class,
37 Loader.loadClass(Loader.class.getCanonicalName(), Loader.getClassLoader()),
38 "Expect Class return value for null ClassLoader.");
36 assertEquals("Expect Class return value for null ClassLoader.", Loader.class,
37 Loader.loadClass(Loader.class.getCanonicalName(), Loader.getClassLoader()));
3938 }
4039 }
1616
1717 package org.apache.logging.log4j.core.util;
1818
19 import org.junit.jupiter.api.Test;
20 import org.junit.jupiter.api.condition.EnabledOnOs;
21 import org.junit.jupiter.api.condition.OS;
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
2221
2322 import java.net.URI;
23 import java.net.URISyntaxException;
2424
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
25 import org.apache.logging.log4j.util.PropertiesUtil;
26 import org.junit.Assume;
27 import org.junit.Test;
2728
2829 public class NetUtilsTest {
2930
31 private static final boolean IS_WINDOWS = PropertiesUtil.getProperties().isOsWindows();
32
3033 @Test
31 public void testToUriWithoutBackslashes() {
34 public void testToUriWithoutBackslashes() throws URISyntaxException {
3235 final String config = "file:///path/to/something/on/unix";
3336 final URI uri = NetUtils.toURI(config);
3437
35 assertNotNull(uri, "The URI should not be null.");
36 assertEquals("file:///path/to/something/on/unix", uri.toString(), "The URI is not correct.");
38 assertNotNull("The URI should not be null.", uri);
39 assertEquals("The URI is not correct.", "file:///path/to/something/on/unix", uri.toString());
3740 }
3841
3942 @Test
40 @EnabledOnOs(OS.WINDOWS)
41 public void testToUriWindowsWithBackslashes() {
43 public void testToUriWindowsWithBackslashes() throws URISyntaxException {
44 Assume.assumeTrue(IS_WINDOWS);
4245 final String config = "file:///D:\\path\\to\\something/on/windows";
4346 final URI uri = NetUtils.toURI(config);
4447
45 assertNotNull(uri, "The URI should not be null.");
46 assertEquals("file:///D:/path/to/something/on/windows", uri.toString(), "The URI is not correct.");
48 assertNotNull("The URI should not be null.", uri);
49 assertEquals("The URI is not correct.", "file:///D:/path/to/something/on/windows", uri.toString());
4750 }
4851
4952 @Test
50 @EnabledOnOs(OS.WINDOWS)
51 public void testToUriWindowsAbsolutePath() {
53 public void testToUriWindowsAbsolutePath() throws URISyntaxException {
54 Assume.assumeTrue(IS_WINDOWS);
5255 final String config = "D:\\path\\to\\something\\on\\windows";
5356 final URI uri = NetUtils.toURI(config);
5457
55 assertNotNull(uri, "The URI should not be null.");
56 assertEquals("file:/D:/path/to/something/on/windows", uri.toString(), "The URI is not correct.");
58 assertNotNull("The URI should not be null.", uri);
59 assertEquals("The URI is not correct.", "file:/D:/path/to/something/on/windows", uri.toString());
5760 }
5861
5962 }
2323 import org.apache.logging.log4j.core.LoggerContext;
2424 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
2525 import org.apache.logging.log4j.core.selector.ContextSelector;
26 import org.apache.logging.log4j.junit.LoggerContextSource;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
2727 import org.apache.logging.log4j.status.StatusLogger;
28 import org.junit.jupiter.api.AfterAll;
29 import org.junit.jupiter.api.BeforeAll;
30 import org.junit.jupiter.api.Test;
28 import org.junit.AfterClass;
29 import org.junit.BeforeClass;
30 import org.junit.Rule;
31 import org.junit.Test;
3132
32 import static org.hamcrest.MatcherAssert.*;
3333 import static org.hamcrest.Matchers.hasItem;
3434 import static org.hamcrest.Matchers.hasSize;
3535 import static org.hamcrest.Matchers.not;
36 import static org.junit.jupiter.api.Assertions.*;
36 import static org.junit.Assert.*;
3737
3838 public class ShutdownCallbackRegistryTest {
3939
40 @BeforeAll
41 public static void setUpClass() {
40 @Rule
41 public final LoggerContextRule ctx = new LoggerContextRule("ShutdownCallbackRegistryTest.xml");
42
43 @BeforeClass
44 public static void setUpClass() throws Exception {
4245 System.setProperty("log4j2.is.webapp", "false");
4346 System.setProperty(ShutdownCallbackRegistry.SHUTDOWN_CALLBACK_REGISTRY, Registry.class.getName());
4447 }
4548
46 @AfterAll
49 @AfterClass
4750 public static void afterClass() {
4851 System.clearProperty(ShutdownCallbackRegistry.SHUTDOWN_CALLBACK_REGISTRY);
4952 System.clearProperty("log4j2.is.webapp");
5053 }
5154
5255 @Test
53 @LoggerContextSource("ShutdownCallbackRegistryTest.xml")
54 public void testShutdownCallbackRegistry(final LoggerContext context) {
55 assertTrue(context.isStarted(), "LoggerContext should be started");
56 public void testShutdownCallbackRegistry() throws Exception {
57 final LoggerContext context = ctx.getLoggerContext();
58 assertTrue("LoggerContext should be started", context.isStarted());
5659 assertThat(Registry.CALLBACKS, hasSize(1));
5760 Registry.shutdown();
58 assertTrue(context.isStopped(), "LoggerContext should be stopped");
61 assertTrue("LoggerContext should be stopped", context.isStopped());
5962 assertThat(Registry.CALLBACKS, hasSize(0));
6063 final ContextSelector selector = ((Log4jContextFactory) LogManager.getFactory()).getSelector();
6164 assertThat(selector.getLoggerContexts(), not(hasItem(context)));
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import org.junit.jupiter.api.Test;
18 import org.junit.Test;
1919
20 import static org.junit.jupiter.api.Assertions.*;
20 import static org.junit.Assert.*;
2121
2222 public class SystemClockTest {
2323
2828
2929 final long diff = sysMillis - millis1;
3030
31 assertTrue(diff <= 1, "diff too large: " + diff);
31 assertTrue("diff too large: " + diff, diff <= 1);
3232 }
3333
3434 @Test
3939
4040 final long diff = sysMillis - millis1;
4141
42 assertTrue(diff <= 1, "diff too large: " + diff);
42 assertTrue("diff too large: " + diff, diff <= 1);
4343 }
4444
4545 }
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
17 package org.apache.logging.log4j.core.util;
18
19 import org.junit.jupiter.api.Test;
20
21 import java.util.concurrent.TimeUnit;
22
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24
25 /**
26 * Tests the SystemNanoClock.
27 */
28 public class SystemNanoClockTest {
29
30 @Test
31 public void testReturnsSystemNanoTime() {
32 final NanoClock clock = new SystemNanoClock();
33 final long expected = System.nanoTime();
34 final long actual = clock.nanoTime();
35 assertTrue(actual - expected < TimeUnit.SECONDS.toNanos(1), "smal difference");
36 }
37
38 }
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
17 package org.apache.logging.log4j.core.util;
18
19 import java.util.concurrent.TimeUnit;
20
21 import org.junit.Test;
22
23 import static org.junit.Assert.*;
24
25 /**
26 * Tests the SystemNanoClock.
27 */
28 public class SystemNanoClockTest {
29
30 @Test
31 public void testReturnsSystemNanoTime() {
32 final NanoClock clock = new SystemNanoClock();
33 final long expected = System.nanoTime();
34 final long actual = clock.nanoTime();
35 assertTrue("smal difference", actual - expected < TimeUnit.SECONDS.toNanos(1));
36 }
37
38 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import org.junit.jupiter.api.Test;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
18 import org.junit.Test;
2219
2320 public class ThrowablesTest {
2421
2522 @Test
26 public void testGetRootCauseNone() {
23 public void testGetRootCauseNone() throws Exception {
2724 final NullPointerException throwable = new NullPointerException();
28 assertEquals(throwable, Throwables.getRootCause(throwable));
25 org.junit.Assert.assertEquals(throwable, Throwables.getRootCause(throwable));
2926 }
3027
3128 @Test
32 public void testGetRootCauseDepth1() {
33 final Throwable cause = new NullPointerException();
34 final Throwable error = new UnsupportedOperationException(cause);
35 assertEquals(cause, Throwables.getRootCause(error));
29 public void testGetRootCauseDepth1() throws Exception {
30 final NullPointerException throwable = new NullPointerException();
31 org.junit.Assert.assertEquals(throwable, Throwables.getRootCause(new UnsupportedOperationException(throwable)));
3632 }
3733
3834 @Test
39 public void testGetRootCauseDepth2() {
40 final Throwable rootCause = new NullPointerException();
41 final Throwable cause = new UnsupportedOperationException(rootCause);
42 final Throwable error = new IllegalArgumentException(cause);
43 assertEquals(rootCause, Throwables.getRootCause(error));
35 public void testGetRootCauseDepth2() throws Exception {
36 final NullPointerException throwable = new NullPointerException();
37 org.junit.Assert.assertEquals(throwable,
38 Throwables.getRootCause(new IllegalArgumentException(new UnsupportedOperationException(throwable))));
4439 }
4540
46 @SuppressWarnings("ThrowableNotThrown")
47 @Test
48 public void testGetRootCauseLoop() {
49 final Throwable cause1 = new RuntimeException();
50 final Throwable cause2 = new RuntimeException(cause1);
51 final Throwable cause3 = new RuntimeException(cause2);
52 cause1.initCause(cause3);
53 assertThrows(IllegalArgumentException.class, () -> Throwables.getRootCause(cause3));
41 @Test(expected = NullPointerException.class)
42 public void testRethrowRuntimeException() throws Exception {
43 Throwables.rethrow(new NullPointerException());
5444 }
5545
56 @Test
57 public void testRethrowRuntimeException() {
58 assertThrows(NullPointerException.class, () -> Throwables.rethrow(new NullPointerException()));
46 @Test(expected = UnknownError.class)
47 public void testRethrowError() throws Exception {
48 Throwables.rethrow(new UnknownError());
5949 }
6050
61 @Test
62 public void testRethrowError() {
63 assertThrows(UnknownError.class, () -> Throwables.rethrow(new UnknownError()));
64 }
65
66 @Test
67 public void testRethrowCheckedException() {
68 assertThrows(NoSuchMethodException.class, () -> Throwables.rethrow(new NoSuchMethodException()));
51 @Test(expected = NoSuchMethodException.class)
52 public void testRethrowCheckedException() throws Exception {
53 Throwables.rethrow(new NoSuchMethodException());
6954 }
7055 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import org.junit.jupiter.api.Test;
19
2018 import java.util.UUID;
2119
22 import static org.junit.jupiter.api.Assertions.*;
20 import org.junit.Test;
2321
22 import static org.junit.Assert.*;
23 /**
24 *
25 */
2426 public class UuidTest {
2527
2628 private static final int COUNT = 200;
3436 //final UUID uuid2 = UuidUtil.getTimeBasedUUID(); // unused
3537 final long current = (System.currentTimeMillis() * 10000) + NUM_100NS_INTERVALS_SINCE_UUID_EPOCH;
3638 final long time = uuid.timestamp();
37 assertTrue(current + 10000 - time > 0, "Incorrect time");
39 assertTrue("Incorrect time", current + 10000 - time > 0);
3840 final UUID[] uuids = new UUID[COUNT];
3941 final long start = System.nanoTime();
4042 for (int i=0; i < COUNT; ++i) {
5153 }
5254 }
5355 }
54 assertEquals(0, errors, errors + " duplicate UUIDS");
56 assertEquals(errors + " duplicate UUIDS", 0, errors);
5557 final int variant = uuid.variant();
56 assertEquals(2, variant, "Incorrect variant. Expected 2 got " + variant);
58 assertEquals("Incorrect variant. Expected 2 got " + variant, 2, variant);
5759 final int version = uuid.version();
58 assertEquals(1, version, "Incorrect version. Expected 1 got " + version);
60 assertEquals("Incorrect version. Expected 1 got " + version, 1, version);
5961 final long node = uuid.node();
60 assertTrue(node != 0, "Invalid node");
61 }
62
63 @Test
64 public void testInitialize() {
65 // Test if no ArrayIndexOutOfBoundsException is thrown when Mac address array is null
66 UuidUtil.initialize(null);
67
68 // Test if no ArrayIndexOutOfBoundsException is thrown for different Mac address lengths
69 for (int i=0; i < 10; i++) {
70 // Create MAC address byte array with i as size
71 byte[] mac = new byte[i];
72 for(int j=0; j < i; j++) {
73 mac[j] = (byte)j;
74 }
75 UuidUtil.initialize(mac);
76 }
62 assertTrue("Invalid node", node != 0);
7763 }
7864
7965 @Test
10389 }
10490 }
10591 }
106 assertEquals(0, errors, errors + " duplicate UUIDS");
92 assertEquals(errors + " duplicate UUIDS", 0, errors);
10793 }
10894
10995
3434 import org.apache.logging.log4j.core.net.ssl.TestConstants;
3535 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
3636 import org.apache.logging.log4j.util.PropertiesUtil;
37 import org.junit.After;
3738 import org.junit.Assume;
39 import org.junit.Before;
3840 import org.junit.BeforeClass;
3941 import org.junit.Rule;
4042 import org.junit.Test;
152154 }
153155 }
154156
155 private static class TestConfigurationListener implements ConfigurationListener {
157 private class TestConfigurationListener implements ConfigurationListener {
156158 private final Queue<String> queue;
157159 private final String name;
158160
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertNull;
20
1821 import java.io.File;
1922 import java.io.FileOutputStream;
2023 import java.nio.file.Files;
2730 import java.util.concurrent.TimeUnit;
2831
2932 import org.apache.logging.log4j.core.config.ConfigurationScheduler;
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.api.condition.DisabledOnOs;
32 import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
33 import org.junit.jupiter.api.condition.OS;
34
35 import static org.junit.jupiter.api.Assertions.*;
33 import org.apache.logging.log4j.util.PropertiesUtil;
34 import org.junit.Assume;
35 import org.junit.Test;
3636
3737 /**
3838 * Test the WatchManager
3939 */
40 @DisabledOnOs(OS.WINDOWS)
41 @EnabledIfSystemProperty(named = "WatchManagerTest.forceRun", matches = "true")
4240 public class WatchManagerTest {
4341
42 private static final String FORCE_RUN_KEY = WatchManagerTest.class.getSimpleName() + ".forceRun";
4443 private final String testFile = "target/testWatchFile";
4544 private final String originalFile = "target/test-classes/log4j-test1.xml";
4645 private final String newFile = "target/test-classes/log4j-test1.yaml";
4746
47 private static final boolean IS_WINDOWS = PropertiesUtil.getProperties().isOsWindows();
48
4849 @Test
4950 public void testWatchManager() throws Exception {
51 Assume.assumeTrue(!IS_WINDOWS || Boolean.getBoolean(FORCE_RUN_KEY));
5052 final ConfigurationScheduler scheduler = new ConfigurationScheduler();
5153 scheduler.incrementScheduledItems();
5254 final WatchManager watchManager = new WatchManager(scheduler);
6870 Files.copy(source, Paths.get(targetFile.toURI()), StandardCopyOption.REPLACE_EXISTING);
6971 Thread.sleep(1000);
7072 final File f = queue.poll(1, TimeUnit.SECONDS);
71 assertNotNull(f, "File change not detected");
73 assertNotNull("File change not detected", f);
7274 } finally {
7375 watchManager.stop();
7476 scheduler.stop();
7779
7880 @Test
7981 public void testWatchManagerReset() throws Exception {
82 Assume.assumeTrue(!IS_WINDOWS || Boolean.getBoolean(FORCE_RUN_KEY));
8083 final ConfigurationScheduler scheduler = new ConfigurationScheduler();
8184 scheduler.incrementScheduledItems();
8285 final WatchManager watchManager = new WatchManager(scheduler);
101104 watchManager.start();
102105 Thread.sleep(1000);
103106 final File f = queue.poll(1, TimeUnit.SECONDS);
104 assertNull(f, "File change detected");
107 assertNull("File change detected", f);
105108 } finally {
106109 watchManager.stop();
107110 scheduler.stop();
110113
111114 @Test
112115 public void testWatchManagerResetFile() throws Exception {
116 Assume.assumeTrue(!IS_WINDOWS || Boolean.getBoolean(FORCE_RUN_KEY));
113117 final ConfigurationScheduler scheduler = new ConfigurationScheduler();
114118 scheduler.incrementScheduledItems();
115119 final WatchManager watchManager = new WatchManager(scheduler);
134138 watchManager.start();
135139 Thread.sleep(1000);
136140 final File f = queue.poll(1, TimeUnit.SECONDS);
137 assertNull(f, "File change detected");
141 assertNull("File change detected", f);
138142 } finally {
139143 watchManager.stop();
140144 scheduler.stop();
141145 }
142146 }
143147
144 private static class TestWatcher implements FileWatcher {
148 private class TestWatcher implements FileWatcher {
145149
146150 private final Queue<File> queue;
147151
120120 this.valid = valid;
121121 }
122122
123 @Test
124 public void testOriginal() throws Exception {
125 checkParse(input);
126 }
127
128 @Test
129 public void testOriginalPP() throws Exception {
130 checkParsePosition(input);
131 }
132
133 @Test
134 public void testUpperCase() throws Exception {
135 checkParse(input.toUpperCase(locale));
136 }
137
138 @Test
139 public void testUpperCasePP() throws Exception {
140 checkParsePosition(input.toUpperCase(locale));
141 }
142
143 @Test
144 public void testLowerCase() throws Exception {
145 checkParse(input.toLowerCase(locale));
146 }
147
148 @Test
149 public void testLowerCasePP() throws Exception {
150 checkParsePosition(input.toLowerCase(locale));
151 }
152
123153 private void checkParse(final String formattedDate) {
124154 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
125155 sdf.setTimeZone(timeZone);
160190 assertEquals(locale.toString()+" "+formattedDate + " expected same Exception ", sdfE, fdfE);
161191 }
162192 }
163
164193 private void checkParsePosition(final String formattedDate) {
165194 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
166195 sdf.setTimeZone(timeZone);
199228 sdferrorIndex - fdferrorIndex <= 4);
200229 }
201230 }
202
203 @Test
204 public void testLowerCase() throws Exception {
205 checkParse(input.toLowerCase(locale));
206 }
207
208 @Test
209 public void testLowerCasePP() throws Exception {
210 checkParsePosition(input.toLowerCase(locale));
211 }
212
213 @Test
214 public void testOriginal() throws Exception {
215 checkParse(input);
216 }
217
218 @Test
219 public void testOriginalPP() throws Exception {
220 checkParsePosition(input);
221 }
222
223 @Test
224 public void testUpperCase() throws Exception {
225 checkParse(input.toUpperCase(locale));
226 }
227 @Test
228 public void testUpperCasePP() throws Exception {
229 checkParsePosition(input.toUpperCase(locale));
230 }
231231 }
4242 * Copied from Apache Commons Lang 3 on 2016-11-16.
4343 */
4444 public class FastDateParserTest {
45 private static enum Expected1806 {
46 India(INDIA, "+05", "+0530", "+05:30", true),
47 Greenwich(GMT, "Z", "Z", "Z", false),
48 NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
49
50 final TimeZone zone;
51
52 final String one;
53 final String two;
54 final String three;
55 final long offset;
56 private Expected1806(final TimeZone zone, final String one, final String two, final String three, final boolean hasHalfHourOffset) {
57 this.zone = zone;
58 this.one = one;
59 this.two = two;
60 this.three = three;
61 this.offset = hasHalfHourOffset ?30*60*1000 :0;
62 }
63 }
6445 private static final String SHORT_FORMAT_NOERA = "y/M/d/h/a/m/s/E";
6546 private static final String LONG_FORMAT_NOERA = "yyyy/MMMM/dddd/hhhh/mmmm/ss/aaaa/EEEE";
6647 private static final String SHORT_FORMAT = "G/" + SHORT_FORMAT_NOERA;
67
6848 private static final String LONG_FORMAT = "GGGG/" + LONG_FORMAT_NOERA;
49
6950 private static final String yMdHmsSZ = "yyyy-MM-dd'T'HH:mm:ss.SSS Z";
7051 private static final String DMY_DOT = "dd.MM.yyyy";
7152 private static final String YMD_SLASH = "yyyy/MM/dd";
7253 private static final String MDY_DASH = "MM-DD-yyyy";
73
7454 private static final String MDY_SLASH = "MM/DD/yyyy";
55
7556 private static final TimeZone REYKJAVIK = TimeZone.getTimeZone("Atlantic/Reykjavik");
7657 private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York");
7758 private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
78
7959 private static final TimeZone INDIA = TimeZone.getTimeZone("Asia/Calcutta");
8060
8161 private static final Locale SWEDEN = new Locale("sv", "SE");
8262
83 private static Calendar initializeCalendar(final TimeZone tz) {
84 final Calendar cal = Calendar.getInstance(tz);
85 cal.set(Calendar.YEAR, 2001);
86 cal.set(Calendar.MONTH, 1); // not daylight savings
87 cal.set(Calendar.DAY_OF_MONTH, 4);
88 cal.set(Calendar.HOUR_OF_DAY, 12);
89 cal.set(Calendar.MINUTE, 8);
90 cal.set(Calendar.SECOND, 56);
91 cal.set(Calendar.MILLISECOND, 235);
92 return cal;
93 }
94
95 private void checkParse(final Locale locale, final Calendar cal, final SimpleDateFormat sdf, final DateParser fdf) throws ParseException {
96 final String formattedDate= sdf.format(cal.getTime());
97 checkParse(locale, sdf, fdf, formattedDate);
98 checkParse(locale, sdf, fdf, formattedDate.toLowerCase(locale));
99 checkParse(locale, sdf, fdf, formattedDate.toUpperCase(locale));
100 }
101
102 private void checkParse(final Locale locale, final SimpleDateFormat sdf, final DateParser fdf, final String formattedDate) throws ParseException {
103 final Date expectedTime = sdf.parse(formattedDate);
104 final Date actualTime = fdf.parse(formattedDate);
105 assertEquals(locale.toString()+" "+formattedDate +"\n",expectedTime, actualTime);
63 DateParser getInstance(final String format) {
64 return getInstance(format, TimeZone.getDefault(), Locale.getDefault());
10665 }
10766
10867 private DateParser getDateInstance(final int dateStyle, final Locale locale) {
10968 return getInstance(FormatCache.getPatternForStyle(Integer.valueOf(dateStyle), null, locale), TimeZone.getDefault(), Locale.getDefault());
110 }
111
112 private Calendar getEraStart(int year, final TimeZone zone, final Locale locale) {
113 final Calendar cal = Calendar.getInstance(zone, locale);
114 cal.clear();
115
116 // http://docs.oracle.com/javase/6/docs/technotes/guides/intl/calendar.doc.html
117 if (locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
118 if(year < 1868) {
119 cal.set(Calendar.ERA, 0);
120 cal.set(Calendar.YEAR, 1868-year);
121 }
122 }
123 else {
124 if (year < 0) {
125 cal.set(Calendar.ERA, GregorianCalendar.BC);
126 year= -year;
127 }
128 cal.set(Calendar.YEAR, year/100 * 100);
129 }
130 return cal;
131 }
132
133 DateParser getInstance(final String format) {
134 return getInstance(format, TimeZone.getDefault(), Locale.getDefault());
13569 }
13670
13771 private DateParser getInstance(final String format, final Locale locale) {
180114 }
181115
182116 @Test
183 public void test1806() throws ParseException {
184 final String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
185 final String dateStub = "2001-02-04T12:08:56.235";
186
187 for (final Expected1806 trial : Expected1806.values()) {
188 final Calendar cal = initializeCalendar(trial.zone);
189
190 final String message = trial.zone.getDisplayName()+";";
191
192 DateParser parser = getInstance(formatStub+"X", trial.zone);
193 assertEquals(message+trial.one, cal.getTime().getTime(), parser.parse(dateStub+trial.one).getTime()-trial.offset);
194
195 parser = getInstance(formatStub+"XX", trial.zone);
196 assertEquals(message+trial.two, cal.getTime(), parser.parse(dateStub+trial.two));
197
198 parser = getInstance(formatStub+"XXX", trial.zone);
199 assertEquals(message+trial.three, cal.getTime(), parser.parse(dateStub+trial.three));
200 }
201 }
202
203 @Test(expected = IllegalArgumentException.class)
204 public void test1806Argument() {
205 getInstance("XXXX");
206 }
207
117 public void testParseZone() throws ParseException {
118 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
119 cal.clear();
120 cal.set(2003, Calendar.JULY, 10, 16, 33, 20);
121
122 final DateParser fdf = getInstance(yMdHmsSZ, NEW_YORK, Locale.US);
123
124 assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 -0500"));
125 assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 GMT-05:00"));
126 assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 Eastern Daylight Time"));
127 assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 EDT"));
128
129 cal.setTimeZone(TimeZone.getTimeZone("GMT-3"));
130 cal.set(2003, Calendar.FEBRUARY, 10, 9, 0, 0);
131
132 assertEquals(cal.getTime(), fdf.parse("2003-02-10T09:00:00.000 -0300"));
133
134 cal.setTimeZone(TimeZone.getTimeZone("GMT+5"));
135 cal.set(2003, Calendar.FEBRUARY, 10, 15, 5, 6);
136
137 assertEquals(cal.getTime(), fdf.parse("2003-02-10T15:05:06.000 +0500"));
138 }
139
140 @Test
141 public void testParseLongShort() throws ParseException {
142 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
143 cal.clear();
144 cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
145 cal.set(Calendar.MILLISECOND, 989);
146 cal.setTimeZone(NEW_YORK);
147
148 DateParser fdf = getInstance("yyyy GGGG MMMM dddd aaaa EEEE HHHH mmmm ssss SSSS ZZZZ", NEW_YORK, Locale.US);
149
150 assertEquals(cal.getTime(), fdf.parse("2003 AD February 0010 PM Monday 0015 0033 0020 0989 GMT-05:00"));
151 cal.set(Calendar.ERA, GregorianCalendar.BC);
152
153 final Date parse = fdf.parse("2003 BC February 0010 PM Saturday 0015 0033 0020 0989 GMT-05:00");
154 assertEquals(cal.getTime(), parse);
155
156 fdf = getInstance("y G M d a E H m s S Z", NEW_YORK, Locale.US);
157 assertEquals(cal.getTime(), fdf.parse("03 BC 2 10 PM Sat 15 33 20 989 -0500"));
158
159 cal.set(Calendar.ERA, GregorianCalendar.AD);
160 assertEquals(cal.getTime(), fdf.parse("03 AD 2 10 PM Saturday 15 33 20 989 -0500"));
161 }
208162
209163 @Test
210164 public void testAmPm() throws ParseException {
241195 assertEquals(cal.getTime(), H.parse("2010-08-01 12:33:20"));
242196 }
243197
244 @Test
245 public void testDayNumberOfWeek() throws ParseException {
246 final DateParser parser = getInstance("u");
247 final Calendar calendar = Calendar.getInstance();
248
249 calendar.setTime(parser.parse("1"));
250 Assert.assertEquals(Calendar.MONDAY, calendar.get(Calendar.DAY_OF_WEEK));
251
252 calendar.setTime(parser.parse("6"));
253 Assert.assertEquals(Calendar.SATURDAY, calendar.get(Calendar.DAY_OF_WEEK));
254
255 calendar.setTime(parser.parse("7"));
256 Assert.assertEquals(Calendar.SUNDAY, calendar.get(Calendar.DAY_OF_WEEK));
257 }
258
259 @Test
260 public void testDayOf() throws ParseException {
261 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
198 private Calendar getEraStart(int year, final TimeZone zone, final Locale locale) {
199 final Calendar cal = Calendar.getInstance(zone, locale);
200 cal.clear();
201
202 // http://docs.oracle.com/javase/6/docs/technotes/guides/intl/calendar.doc.html
203 if (locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
204 if(year < 1868) {
205 cal.set(Calendar.ERA, 0);
206 cal.set(Calendar.YEAR, 1868-year);
207 }
208 }
209 else {
210 if (year < 0) {
211 cal.set(Calendar.ERA, GregorianCalendar.BC);
212 year= -year;
213 }
214 cal.set(Calendar.YEAR, year/100 * 100);
215 }
216 return cal;
217 }
218
219 private void validateSdfFormatFdpParseEquality(final String format, final Locale locale, final TimeZone tz, final DateParser fdp, final Date in, final int year, final Date cs) throws ParseException {
220 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
221 sdf.setTimeZone(tz);
222 if (format.equals(SHORT_FORMAT)) {
223 sdf.set2DigitYearStart( cs );
224 }
225 final String fmt = sdf.format(in);
226 try {
227 final Date out = fdp.parse(fmt);
228 assertEquals(locale.toString()+" "+in+" "+ format+ " "+tz.getID(), in, out);
229 } catch (final ParseException pe) {
230 if (year >= 1868 || !locale.getCountry().equals("JP")) {// LANG-978
231 throw pe;
232 }
233 }
234 }
235
236 @Test
237 // Check that all Locales can parse the formats we use
238 public void testParses() throws Exception {
239 for(final String format : new String[]{LONG_FORMAT, SHORT_FORMAT}) {
240 for(final Locale locale : Locale.getAvailableLocales()) {
241 for(final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK, GMT}) {
242 for(final int year : new int[]{2003, 1940, 1868, 1867, 1, -1, -1940}) {
243 final Calendar cal= getEraStart(year, tz, locale);
244 final Date centuryStart= cal.getTime();
245
246 cal.set(Calendar.MONTH, 1);
247 cal.set(Calendar.DAY_OF_MONTH, 10);
248 final Date in= cal.getTime();
249
250 final FastDateParser fdp= new FastDateParser(format, tz, locale, centuryStart);
251 validateSdfFormatFdpParseEquality(format, locale, tz, fdp, in, year, centuryStart);
252 }
253 }
254 }
255 }
256 }
257
258 // we cannot use historic dates to test timezone parsing, some timezones have second offsets
259 // as well as hours and minutes which makes the z formats a low fidelity round trip
260 @Test
261 public void testTzParses() throws Exception {
262 // Check that all Locales can parse the time formats we use
263 for(final Locale locale : Locale.getAvailableLocales()) {
264 final FastDateParser fdp= new FastDateParser("yyyy/MM/dd z", TimeZone.getDefault(), locale);
265
266 for(final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK, GMT}) {
267 final Calendar cal= Calendar.getInstance(tz, locale);
268 cal.clear();
269 cal.set(Calendar.YEAR, 2000);
270 cal.set(Calendar.MONTH, 1);
271 cal.set(Calendar.DAY_OF_MONTH, 10);
272 final Date expected= cal.getTime();
273
274 final Date actual = fdp.parse("2000/02/10 "+tz.getDisplayName(locale));
275 Assert.assertEquals("tz:"+tz.getID()+" locale:"+locale.getDisplayName(), expected, actual);
276 }
277 }
278 }
279
280
281 @Test
282 public void testLocales_Long_AD() throws Exception {
283 testLocales(LONG_FORMAT, false);
284 }
285
286 @Test
287 public void testLocales_Long_BC() throws Exception {
288 testLocales(LONG_FORMAT, true);
289 }
290
291 @Test
292 public void testLocales_Short_AD() throws Exception {
293 testLocales(SHORT_FORMAT, false);
294 }
295
296 @Test
297 public void testLocales_Short_BC() throws Exception {
298 testLocales(SHORT_FORMAT, true);
299 }
300
301 @Test
302 public void testLocales_LongNoEra_AD() throws Exception {
303 testLocales(LONG_FORMAT_NOERA, false);
304 }
305
306 @Test
307 public void testLocales_LongNoEra_BC() throws Exception {
308 testLocales(LONG_FORMAT_NOERA, true);
309 }
310
311 @Test
312 public void testLocales_ShortNoEra_AD() throws Exception {
313 testLocales(SHORT_FORMAT_NOERA, false);
314 }
315
316 @Test
317 public void testLocales_ShortNoEra_BC() throws Exception {
318 testLocales(SHORT_FORMAT_NOERA, true);
319 }
320
321 private void testLocales(final String format, final boolean eraBC) throws Exception {
322
323 final Calendar cal= Calendar.getInstance(GMT);
262324 cal.clear();
263325 cal.set(2003, Calendar.FEBRUARY, 10);
264
265 final DateParser fdf = getInstance("W w F D y", NEW_YORK, Locale.US);
266 assertEquals(cal.getTime(), fdf.parse("3 7 2 41 03"));
267 }
268
269 @Test
270 public void testEquals() {
271 final DateParser parser1= getInstance(YMD_SLASH);
272 final DateParser parser2= getInstance(YMD_SLASH);
273
274 assertEquals(parser1, parser2);
275 assertEquals(parser1.hashCode(), parser2.hashCode());
276
277 assertFalse(parser1.equals(new Object()));
326 if (eraBC) {
327 cal.set(Calendar.ERA, GregorianCalendar.BC);
328 }
329
330 for(final Locale locale : Locale.getAvailableLocales() ) {
331 // ja_JP_JP cannot handle dates before 1868 properly
332 if (eraBC && locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
333 continue;
334 }
335 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
336 final DateParser fdf = getInstance(format, locale);
337
338 try {
339 checkParse(locale, cal, sdf, fdf);
340 } catch(final ParseException ex) {
341 Assert.fail("Locale "+locale+ " failed with "+format+" era "+(eraBC?"BC":"AD")+"\n" + trimMessage(ex.toString()));
342 }
343 }
278344 }
279345
280346 @Test
299365 }
300366 }
301367
302 @Test
303 public void testLANG_831() throws Exception {
304 testSdfAndFdp("M E","3 Tue", true);
368 private String trimMessage(final String msg) {
369 if (msg.length() < 100) {
370 return msg;
371 }
372 final int gmt = msg.indexOf("(GMT");
373 if (gmt > 0) {
374 return msg.substring(0, gmt+4)+"...)";
375 }
376 return msg.substring(0, 100)+"...";
377 }
378
379 private void checkParse(final Locale locale, final Calendar cal, final SimpleDateFormat sdf, final DateParser fdf) throws ParseException {
380 final String formattedDate= sdf.format(cal.getTime());
381 checkParse(locale, sdf, fdf, formattedDate);
382 checkParse(locale, sdf, fdf, formattedDate.toLowerCase(locale));
383 checkParse(locale, sdf, fdf, formattedDate.toUpperCase(locale));
384 }
385
386 private void checkParse(final Locale locale, final SimpleDateFormat sdf, final DateParser fdf, final String formattedDate) throws ParseException {
387 final Date expectedTime = sdf.parse(formattedDate);
388 final Date actualTime = fdf.parse(formattedDate);
389 assertEquals(locale.toString()+" "+formattedDate +"\n",expectedTime, actualTime);
390 }
391
392 @Test
393 public void testParseNumerics() throws ParseException {
394 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
395 cal.clear();
396 cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
397 cal.set(Calendar.MILLISECOND, 989);
398
399 final DateParser fdf = getInstance("yyyyMMddHHmmssSSS", NEW_YORK, Locale.US);
400 assertEquals(cal.getTime(), fdf.parse("20030210153320989"));
401 }
402
403 @Test
404 public void testQuotes() throws ParseException {
405 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
406 cal.clear();
407 cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
408 cal.set(Calendar.MILLISECOND, 989);
409
410 final DateParser fdf = getInstance("''yyyyMMdd'A''B'HHmmssSSS''", NEW_YORK, Locale.US);
411 assertEquals(cal.getTime(), fdf.parse("'20030210A'B153320989'"));
412 }
413
414 @Test
415 public void testSpecialCharacters() throws Exception {
416 testSdfAndFdp("q" ,"", true); // bad pattern character (at present)
417 testSdfAndFdp("Q" ,"", true); // bad pattern character
418 testSdfAndFdp("$" ,"$", false); // OK
419 testSdfAndFdp("?.d" ,"?.12", false); // OK
420 testSdfAndFdp("''yyyyMMdd'A''B'HHmmssSSS''", "'20030210A'B153320989'", false); // OK
421 testSdfAndFdp("''''yyyyMMdd'A''B'HHmmssSSS''", "''20030210A'B153320989'", false); // OK
422 testSdfAndFdp("'$\\Ed'" ,"$\\Ed", false); // OK
423
424 // quoted charaters are case sensitive
425 testSdfAndFdp("'QED'", "QED", false);
426 testSdfAndFdp("'QED'", "qed", true);
427 // case sensitive after insensitive Month field
428 testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 QED", false);
429 testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 qed", true);
305430 }
306431
307432 @Test
311436 }
312437
313438 @Test
314 public void testLang1121() throws ParseException {
315 final TimeZone kst = TimeZone.getTimeZone("KST");
316 final DateParser fdp = getInstance("yyyyMMdd", kst, Locale.KOREA);
439 public void testLANG_831() throws Exception {
440 testSdfAndFdp("M E","3 Tue", true);
441 }
442
443 private void testSdfAndFdp(final String format, final String date, final boolean shouldFail)
444 throws Exception {
445 Date dfdp = null;
446 Date dsdf = null;
447 Throwable f = null;
448 Throwable s = null;
317449
318450 try {
319 fdp.parse("2015");
320 Assert.fail("expected parse exception");
321 } catch (final ParseException pe) {
322 // expected parse exception
323 }
324
325 // Wed Apr 29 00:00:00 KST 2015
326 Date actual = fdp.parse("20150429");
327 final Calendar cal = Calendar.getInstance(kst, Locale.KOREA);
328 cal.clear();
329 cal.set(2015, 3, 29);
330 Date expected = cal.getTime();
331 Assert.assertEquals(expected, actual);
332
333 final SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd", Locale.KOREA);
334 df.setTimeZone(kst);
335 expected = df.parse("20150429113100");
336
337 // Thu Mar 16 00:00:00 KST 81724
338 actual = fdp.parse("20150429113100");
339 Assert.assertEquals(expected, actual);
340 }
341
342 @Test
343 public void testLang303() throws ParseException {
344 DateParser parser = getInstance(YMD_SLASH);
451 final SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
452 sdf.setTimeZone(NEW_YORK);
453 dsdf = sdf.parse(date);
454 if (shouldFail) {
455 Assert.fail("Expected SDF failure, but got " + dsdf + " for ["+format+","+date+"]");
456 }
457 } catch (final Exception e) {
458 s = e;
459 if (!shouldFail) {
460 throw e;
461 }
462 }
463
464 try {
465 final DateParser fdp = getInstance(format, NEW_YORK, Locale.US);
466 dfdp = fdp.parse(date);
467 if (shouldFail) {
468 Assert.fail("Expected FDF failure, but got " + dfdp + " for ["+format+","+date+"]");
469 }
470 } catch (final Exception e) {
471 f = e;
472 if (!shouldFail) {
473 throw e;
474 }
475 }
476 // SDF and FDF should produce equivalent results
477 assertTrue("Should both or neither throw Exceptions", (f==null)==(s==null));
478 assertEquals("Parsed dates should be equal", dsdf, dfdp);
479 }
480
481 @Test
482 public void testDayOf() throws ParseException {
483 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
484 cal.clear();
485 cal.set(2003, Calendar.FEBRUARY, 10);
486
487 final DateParser fdf = getInstance("W w F D y", NEW_YORK, Locale.US);
488 assertEquals(cal.getTime(), fdf.parse("3 7 2 41 03"));
489 }
490
491 /**
492 * Test case for {@link FastDateParser#FastDateParser(String, TimeZone, Locale)}.
493 * @throws ParseException so we don't have to catch it
494 */
495 @Test
496 public void testShortDateStyleWithLocales() throws ParseException {
497 DateParser fdf = getDateInstance(FastDateFormat.SHORT, Locale.US);
345498 final Calendar cal = Calendar.getInstance();
346 cal.set(2004, Calendar.DECEMBER, 31);
347
348 final Date date = parser.parse("2004/11/31");
349
350 parser = SerializationUtils.deserialize(SerializationUtils.serialize((Serializable) parser));
351 assertEquals(date, parser.parse("2004/11/31"));
352 }
353
354 @Test
355 public void testLang538() throws ParseException {
356 final DateParser parser = getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", GMT);
357
358 final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-8"));
359 cal.clear();
360 cal.set(2009, Calendar.OCTOBER, 16, 8, 42, 16);
361
362 assertEquals(cal.getTime(), parser.parse("2009-10-16T16:42:16.000Z"));
363 }
364
365 @Test
366 public void testLang996() throws ParseException {
367 final Calendar expected = Calendar.getInstance(NEW_YORK, Locale.US);
368 expected.clear();
369 expected.set(2014, Calendar.MAY, 14);
370
371 final DateParser fdp = getInstance("ddMMMyyyy", NEW_YORK, Locale.US);
372 assertEquals(expected.getTime(), fdp.parse("14may2014"));
373 assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
374 assertEquals(expected.getTime(), fdp.parse("14May2014"));
375 }
376
377 @Test
378 public void testLocaleMatches() {
379 final DateParser parser= getInstance(yMdHmsSZ, SWEDEN);
380 assertEquals(SWEDEN, parser.getLocale());
381 }
382
383 private void testLocales(final String format, final boolean eraBC) throws Exception {
384
385 final Calendar cal= Calendar.getInstance(GMT);
386 cal.clear();
387 cal.set(2003, Calendar.FEBRUARY, 10);
388 if (eraBC) {
389 cal.set(Calendar.ERA, GregorianCalendar.BC);
390 }
391
392 for(final Locale locale : Locale.getAvailableLocales() ) {
393 // ja_JP_JP cannot handle dates before 1868 properly
394 if (eraBC && locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
395 continue;
396 }
397 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
398 final DateParser fdf = getInstance(format, locale);
399
400 try {
401 checkParse(locale, cal, sdf, fdf);
402 } catch(final ParseException ex) {
403 Assert.fail("Locale "+locale+ " failed with "+format+" era "+(eraBC?"BC":"AD")+"\n" + trimMessage(ex.toString()));
404 }
405 }
406 }
407
408 @Test
409 public void testLocales_Long_AD() throws Exception {
410 testLocales(LONG_FORMAT, false);
411 }
412
413 @Test
414 public void testLocales_Long_BC() throws Exception {
415 testLocales(LONG_FORMAT, true);
416 }
417
418 @Test
419 public void testLocales_LongNoEra_AD() throws Exception {
420 testLocales(LONG_FORMAT_NOERA, false);
421 }
422
423 @Test
424 public void testLocales_LongNoEra_BC() throws Exception {
425 testLocales(LONG_FORMAT_NOERA, true);
426 }
427
428 @Test
429 public void testLocales_Short_AD() throws Exception {
430 testLocales(SHORT_FORMAT, false);
431 }
432
433 @Test
434 public void testLocales_Short_BC() throws Exception {
435 testLocales(SHORT_FORMAT, true);
436 }
437
438 @Test
439 public void testLocales_ShortNoEra_AD() throws Exception {
440 testLocales(SHORT_FORMAT_NOERA, false);
441 }
442
443 @Test
444 public void testLocales_ShortNoEra_BC() throws Exception {
445 testLocales(SHORT_FORMAT_NOERA, true);
499 cal.clear();
500
501 cal.set(2004, Calendar.FEBRUARY, 3);
502 assertEquals(cal.getTime(), fdf.parse("2/3/04"));
503
504 fdf = getDateInstance(FastDateFormat.SHORT, SWEDEN);
505 assertEquals(cal.getTime(), fdf.parse("2004-02-03"));
446506 }
447507
448508 /**
476536 }
477537
478538 @Test
479 public void testParseLongShort() throws ParseException {
480 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
481 cal.clear();
482 cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
483 cal.set(Calendar.MILLISECOND, 989);
484 cal.setTimeZone(NEW_YORK);
485
486 DateParser fdf = getInstance("yyyy GGGG MMMM dddd aaaa EEEE HHHH mmmm ssss SSSS ZZZZ", NEW_YORK, Locale.US);
487
488 assertEquals(cal.getTime(), fdf.parse("2003 AD February 0010 PM Monday 0015 0033 0020 0989 GMT-05:00"));
489 cal.set(Calendar.ERA, GregorianCalendar.BC);
490
491 final Date parse = fdf.parse("2003 BC February 0010 PM Saturday 0015 0033 0020 0989 GMT-05:00");
492 assertEquals(cal.getTime(), parse);
493
494 fdf = getInstance("y G M d a E H m s S Z", NEW_YORK, Locale.US);
495 assertEquals(cal.getTime(), fdf.parse("03 BC 2 10 PM Sat 15 33 20 989 -0500"));
496
497 cal.set(Calendar.ERA, GregorianCalendar.AD);
498 assertEquals(cal.getTime(), fdf.parse("03 AD 2 10 PM Saturday 15 33 20 989 -0500"));
499 }
500
501 @Test
502 public void testParseNumerics() throws ParseException {
503 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
504 cal.clear();
505 cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
506 cal.set(Calendar.MILLISECOND, 989);
507
508 final DateParser fdf = getInstance("yyyyMMddHHmmssSSS", NEW_YORK, Locale.US);
509 assertEquals(cal.getTime(), fdf.parse("20030210153320989"));
539 public void testLang303() throws ParseException {
540 DateParser parser = getInstance(YMD_SLASH);
541 final Calendar cal = Calendar.getInstance();
542 cal.set(2004, Calendar.DECEMBER, 31);
543
544 final Date date = parser.parse("2004/11/31");
545
546 parser = SerializationUtils.deserialize(SerializationUtils.serialize((Serializable) parser));
547 assertEquals(date, parser.parse("2004/11/31"));
548 }
549
550 @Test
551 public void testLang538() throws ParseException {
552 final DateParser parser = getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", GMT);
553
554 final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-8"));
555 cal.clear();
556 cal.set(2009, Calendar.OCTOBER, 16, 8, 42, 16);
557
558 assertEquals(cal.getTime(), parser.parse("2009-10-16T16:42:16.000Z"));
559 }
560
561 @Test
562 public void testEquals() {
563 final DateParser parser1= getInstance(YMD_SLASH);
564 final DateParser parser2= getInstance(YMD_SLASH);
565
566 assertEquals(parser1, parser2);
567 assertEquals(parser1.hashCode(), parser2.hashCode());
568
569 assertFalse(parser1.equals(new Object()));
570 }
571
572 @Test
573 public void testToStringContainsName() {
574 final DateParser parser= getInstance(YMD_SLASH);
575 assertTrue(parser.toString().startsWith("FastDate"));
576 }
577
578 @Test
579 public void testPatternMatches() {
580 final DateParser parser= getInstance(yMdHmsSZ);
581 assertEquals(yMdHmsSZ, parser.getPattern());
582 }
583
584 @Test
585 public void testLocaleMatches() {
586 final DateParser parser= getInstance(yMdHmsSZ, SWEDEN);
587 assertEquals(SWEDEN, parser.getLocale());
588 }
589
590 @Test
591 public void testTimeZoneMatches() {
592 final DateParser parser= getInstance(yMdHmsSZ, REYKJAVIK);
593 assertEquals(REYKJAVIK, parser.getTimeZone());
594 }
595
596 @Test
597 public void testLang996() throws ParseException {
598 final Calendar expected = Calendar.getInstance(NEW_YORK, Locale.US);
599 expected.clear();
600 expected.set(2014, Calendar.MAY, 14);
601
602 final DateParser fdp = getInstance("ddMMMyyyy", NEW_YORK, Locale.US);
603 assertEquals(expected.getTime(), fdp.parse("14may2014"));
604 assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
605 assertEquals(expected.getTime(), fdp.parse("14May2014"));
606 }
607
608 @Test(expected = IllegalArgumentException.class)
609 public void test1806Argument() {
610 getInstance("XXXX");
611 }
612
613 private static Calendar initializeCalendar(final TimeZone tz) {
614 final Calendar cal = Calendar.getInstance(tz);
615 cal.set(Calendar.YEAR, 2001);
616 cal.set(Calendar.MONTH, 1); // not daylight savings
617 cal.set(Calendar.DAY_OF_MONTH, 4);
618 cal.set(Calendar.HOUR_OF_DAY, 12);
619 cal.set(Calendar.MINUTE, 8);
620 cal.set(Calendar.SECOND, 56);
621 cal.set(Calendar.MILLISECOND, 235);
622 return cal;
623 }
624
625 private static enum Expected1806 {
626 India(INDIA, "+05", "+0530", "+05:30", true),
627 Greenwich(GMT, "Z", "Z", "Z", false),
628 NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
629
630 private Expected1806(final TimeZone zone, final String one, final String two, final String three, final boolean hasHalfHourOffset) {
631 this.zone = zone;
632 this.one = one;
633 this.two = two;
634 this.three = three;
635 this.offset = hasHalfHourOffset ?30*60*1000 :0;
636 }
637
638 final TimeZone zone;
639 final String one;
640 final String two;
641 final String three;
642 final long offset;
643 }
644
645 @Test
646 public void test1806() throws ParseException {
647 final String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
648 final String dateStub = "2001-02-04T12:08:56.235";
649
650 for (final Expected1806 trial : Expected1806.values()) {
651 final Calendar cal = initializeCalendar(trial.zone);
652
653 final String message = trial.zone.getDisplayName()+";";
654
655 DateParser parser = getInstance(formatStub+"X", trial.zone);
656 assertEquals(message+trial.one, cal.getTime().getTime(), parser.parse(dateStub+trial.one).getTime()-trial.offset);
657
658 parser = getInstance(formatStub+"XX", trial.zone);
659 assertEquals(message+trial.two, cal.getTime(), parser.parse(dateStub+trial.two));
660
661 parser = getInstance(formatStub+"XXX", trial.zone);
662 assertEquals(message+trial.three, cal.getTime(), parser.parse(dateStub+trial.three));
663 }
664 }
665
666 @Test
667 public void testLang1121() throws ParseException {
668 final TimeZone kst = TimeZone.getTimeZone("KST");
669 final DateParser fdp = getInstance("yyyyMMdd", kst, Locale.KOREA);
670
671 try {
672 fdp.parse("2015");
673 Assert.fail("expected parse exception");
674 } catch (final ParseException pe) {
675 // expected parse exception
676 }
677
678 // Wed Apr 29 00:00:00 KST 2015
679 Date actual = fdp.parse("20150429");
680 final Calendar cal = Calendar.getInstance(kst, Locale.KOREA);
681 cal.clear();
682 cal.set(2015, 3, 29);
683 Date expected = cal.getTime();
684 Assert.assertEquals(expected, actual);
685
686 final SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd", Locale.KOREA);
687 df.setTimeZone(kst);
688 expected = df.parse("20150429113100");
689
690 // Thu Mar 16 00:00:00 KST 81724
691 actual = fdp.parse("20150429113100");
692 Assert.assertEquals(expected, actual);
510693 }
511694
512695 @Test
521704 }
522705
523706 @Test
524 // Check that all Locales can parse the formats we use
525 public void testParses() throws Exception {
526 for(final String format : new String[]{LONG_FORMAT, SHORT_FORMAT}) {
527 for(final Locale locale : Locale.getAvailableLocales()) {
528 for(final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK, GMT}) {
529 for(final int year : new int[]{2003, 1940, 1868, 1867, 1, -1, -1940}) {
530 final Calendar cal= getEraStart(year, tz, locale);
531 final Date centuryStart= cal.getTime();
532
533 cal.set(Calendar.MONTH, 1);
534 cal.set(Calendar.DAY_OF_MONTH, 10);
535 final Date in= cal.getTime();
536
537 final FastDateParser fdp= new FastDateParser(format, tz, locale, centuryStart);
538 validateSdfFormatFdpParseEquality(format, locale, tz, fdp, in, year, centuryStart);
539 }
540 }
541 }
542 }
543 }
544
545 @Test
546 public void testParseZone() throws ParseException {
547 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
548 cal.clear();
549 cal.set(2003, Calendar.JULY, 10, 16, 33, 20);
550
551 final DateParser fdf = getInstance(yMdHmsSZ, NEW_YORK, Locale.US);
552
553 assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 -0500"));
554 assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 GMT-05:00"));
555 assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 Eastern Daylight Time"));
556 assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 EDT"));
557
558 cal.setTimeZone(TimeZone.getTimeZone("GMT-3"));
559 cal.set(2003, Calendar.FEBRUARY, 10, 9, 0, 0);
560
561 assertEquals(cal.getTime(), fdf.parse("2003-02-10T09:00:00.000 -0300"));
562
563 cal.setTimeZone(TimeZone.getTimeZone("GMT+5"));
564 cal.set(2003, Calendar.FEBRUARY, 10, 15, 5, 6);
565
566 assertEquals(cal.getTime(), fdf.parse("2003-02-10T15:05:06.000 +0500"));
567 }
568
569 @Test
570 public void testPatternMatches() {
571 final DateParser parser= getInstance(yMdHmsSZ);
572 assertEquals(yMdHmsSZ, parser.getPattern());
573 }
574
575 @Test
576 public void testQuotes() throws ParseException {
577 final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
578 cal.clear();
579 cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
580 cal.set(Calendar.MILLISECOND, 989);
581
582 final DateParser fdf = getInstance("''yyyyMMdd'A''B'HHmmssSSS''", NEW_YORK, Locale.US);
583 assertEquals(cal.getTime(), fdf.parse("'20030210A'B153320989'"));
584 }
585
586 private void testSdfAndFdp(final String format, final String date, final boolean shouldFail)
587 throws Exception {
588 Date dfdp = null;
589 Date dsdf = null;
590 Throwable f = null;
591 Throwable s = null;
592
593 try {
594 final SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
595 sdf.setTimeZone(NEW_YORK);
596 dsdf = sdf.parse(date);
597 if (shouldFail) {
598 Assert.fail("Expected SDF failure, but got " + dsdf + " for ["+format+","+date+"]");
599 }
600 } catch (final Exception e) {
601 s = e;
602 if (!shouldFail) {
603 throw e;
604 }
605 }
606
607 try {
608 final DateParser fdp = getInstance(format, NEW_YORK, Locale.US);
609 dfdp = fdp.parse(date);
610 if (shouldFail) {
611 Assert.fail("Expected FDF failure, but got " + dfdp + " for ["+format+","+date+"]");
612 }
613 } catch (final Exception e) {
614 f = e;
615 if (!shouldFail) {
616 throw e;
617 }
618 }
619 // SDF and FDF should produce equivalent results
620 assertTrue("Should both or neither throw Exceptions", (f==null)==(s==null));
621 assertEquals("Parsed dates should be equal", dsdf, dfdp);
622 }
623
624 /**
625 * Test case for {@link FastDateParser#FastDateParser(String, TimeZone, Locale)}.
626 * @throws ParseException so we don't have to catch it
627 */
628 @Test
629 public void testShortDateStyleWithLocales() throws ParseException {
630 DateParser fdf = getDateInstance(FastDateFormat.SHORT, Locale.US);
631 final Calendar cal = Calendar.getInstance();
632 cal.clear();
633
634 cal.set(2004, Calendar.FEBRUARY, 3);
635 assertEquals(cal.getTime(), fdf.parse("2/3/04"));
636
637 fdf = getDateInstance(FastDateFormat.SHORT, SWEDEN);
638 assertEquals(cal.getTime(), fdf.parse("2004-02-03"));
639 }
640
641 @Test
642 public void testSpecialCharacters() throws Exception {
643 testSdfAndFdp("q" ,"", true); // bad pattern character (at present)
644 testSdfAndFdp("Q" ,"", true); // bad pattern character
645 testSdfAndFdp("$" ,"$", false); // OK
646 testSdfAndFdp("?.d" ,"?.12", false); // OK
647 testSdfAndFdp("''yyyyMMdd'A''B'HHmmssSSS''", "'20030210A'B153320989'", false); // OK
648 testSdfAndFdp("''''yyyyMMdd'A''B'HHmmssSSS''", "''20030210A'B153320989'", false); // OK
649 testSdfAndFdp("'$\\Ed'" ,"$\\Ed", false); // OK
650
651 // quoted charaters are case sensitive
652 testSdfAndFdp("'QED'", "QED", false);
653 testSdfAndFdp("'QED'", "qed", true);
654 // case sensitive after insensitive Month field
655 testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 QED", false);
656 testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 qed", true);
657 }
658
659 @Test
660 public void testTimeZoneMatches() {
661 final DateParser parser= getInstance(yMdHmsSZ, REYKJAVIK);
662 assertEquals(REYKJAVIK, parser.getTimeZone());
663 }
664
665 @Test
666 public void testToStringContainsName() {
667 final DateParser parser= getInstance(YMD_SLASH);
668 assertTrue(parser.toString().startsWith("FastDate"));
669 }
670
671 // we cannot use historic dates to test timezone parsing, some timezones have second offsets
672 // as well as hours and minutes which makes the z formats a low fidelity round trip
673 @Test
674 public void testTzParses() throws Exception {
675 // Check that all Locales can parse the time formats we use
676 for(final Locale locale : Locale.getAvailableLocales()) {
677 final FastDateParser fdp= new FastDateParser("yyyy/MM/dd z", TimeZone.getDefault(), locale);
678
679 for(final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK, GMT}) {
680 final Calendar cal= Calendar.getInstance(tz, locale);
681 cal.clear();
682 cal.set(Calendar.YEAR, 2000);
683 cal.set(Calendar.MONTH, 1);
684 cal.set(Calendar.DAY_OF_MONTH, 10);
685 final Date expected= cal.getTime();
686
687 final Date actual = fdp.parse("2000/02/10 "+tz.getDisplayName(locale));
688 Assert.assertEquals("tz:"+tz.getID()+" locale:"+locale.getDisplayName(), expected, actual);
689 }
690 }
691 }
692
693 private String trimMessage(final String msg) {
694 if (msg.length() < 100) {
695 return msg;
696 }
697 final int gmt = msg.indexOf("(GMT");
698 if (gmt > 0) {
699 return msg.substring(0, gmt+4)+"...)";
700 }
701 return msg.substring(0, 100)+"...";
702 }
703
704 private void validateSdfFormatFdpParseEquality(final String format, final Locale locale, final TimeZone tz, final DateParser fdp, final Date in, final int year, final Date cs) throws ParseException {
705 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
706 sdf.setTimeZone(tz);
707 if (format.equals(SHORT_FORMAT)) {
708 sdf.set2DigitYearStart( cs );
709 }
710 final String fmt = sdf.format(in);
711 try {
712 final Date out = fdp.parse(fmt);
713 assertEquals(locale.toString()+" "+in+" "+ format+ " "+tz.getID(), in, out);
714 } catch (final ParseException pe) {
715 if (year >= 1868 || !locale.getCountry().equals("JP")) {// LANG-978
716 throw pe;
717 }
718 }
707 public void testDayNumberOfWeek() throws ParseException {
708 final DateParser parser = getInstance("u");
709 final Calendar calendar = Calendar.getInstance();
710
711 calendar.setTime(parser.parse("1"));
712 Assert.assertEquals(Calendar.MONDAY, calendar.get(Calendar.DAY_OF_WEEK));
713
714 calendar.setTime(parser.parse("6"));
715 Assert.assertEquals(Calendar.SATURDAY, calendar.get(Calendar.DAY_OF_WEEK));
716
717 calendar.setTime(parser.parse("7"));
718 Assert.assertEquals(Calendar.SUNDAY, calendar.get(Calendar.DAY_OF_WEEK));
719719 }
720720 }
3232 private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York");
3333
3434 @Test
35 public void testInputHasLessCharacters() {
36 final FastDateParser parser = new FastDateParser("MM/dd/yyy", TimeZone.getDefault(), Locale.getDefault());
37 final ParsePosition parsePosition = new ParsePosition(0);
38 Assert.assertNull(parser.parse("03/23", parsePosition));
39 Assert.assertEquals(5, parsePosition.getErrorIndex());
40 }
41
42 @Test
43 public void testInputHasMoreCharacters() {
44 final FastDateParser parser = new FastDateParser("MM/dd", TimeZone.getDefault(), Locale.getDefault());
45 final ParsePosition parsePosition = new ParsePosition(0);
46 final Date date = parser.parse("3/23/61", parsePosition);
47 Assert.assertEquals(4, parsePosition.getIndex());
48
49 final Calendar calendar = Calendar.getInstance();
50 calendar.setTime(date);
51 Assert.assertEquals(2, calendar.get(Calendar.MONTH));
52 Assert.assertEquals(23, calendar.get(Calendar.DATE));
53 }
54
55 @Test
5635 public void testInputHasPrecedingCharacters() {
5736 final FastDateParser parser = new FastDateParser("MM/dd", TimeZone.getDefault(), Locale.getDefault());
5837 final ParsePosition parsePosition = new ParsePosition(0);
7857 }
7958
8059 @Test
60 public void testInputHasMoreCharacters() {
61 final FastDateParser parser = new FastDateParser("MM/dd", TimeZone.getDefault(), Locale.getDefault());
62 final ParsePosition parsePosition = new ParsePosition(0);
63 final Date date = parser.parse("3/23/61", parsePosition);
64 Assert.assertEquals(4, parsePosition.getIndex());
65
66 final Calendar calendar = Calendar.getInstance();
67 calendar.setTime(date);
68 Assert.assertEquals(2, calendar.get(Calendar.MONTH));
69 Assert.assertEquals(23, calendar.get(Calendar.DATE));
70 }
71
72 @Test
8173 public void testInputHasWrongCharacters() {
8274 final FastDateParser parser = new FastDateParser("MM-dd-yyy", TimeZone.getDefault(), Locale.getDefault());
8375 final ParsePosition parsePosition = new ParsePosition(0);
8678 }
8779
8880 @Test
89 public void testInputHasWrongDay() {
90 final FastDateParser parser = new FastDateParser("EEEE, MM/dd/yyy", NEW_YORK, Locale.US);
91 final String input = "Thursday, 03/23/61";
81 public void testInputHasLessCharacters() {
82 final FastDateParser parser = new FastDateParser("MM/dd/yyy", TimeZone.getDefault(), Locale.getDefault());
9283 final ParsePosition parsePosition = new ParsePosition(0);
93 Assert.assertNotNull(parser.parse(input, parsePosition));
94 Assert.assertEquals(input.length(), parsePosition.getIndex());
95
96 parsePosition.setIndex(0);
97 Assert.assertNull(parser.parse( "Thorsday, 03/23/61", parsePosition));
98 Assert.assertEquals(0, parsePosition.getErrorIndex());
84 Assert.assertNull(parser.parse("03/23", parsePosition));
85 Assert.assertEquals(5, parsePosition.getErrorIndex());
9986 }
10087
10188 @Test
11198 Assert.assertNull(parser.parse( "11:23 Pacific Standard ", parsePosition));
11299 Assert.assertEquals(6, parsePosition.getErrorIndex());
113100 }
101
102 @Test
103 public void testInputHasWrongDay() {
104 final FastDateParser parser = new FastDateParser("EEEE, MM/dd/yyy", NEW_YORK, Locale.US);
105 final String input = "Thursday, 03/23/61";
106 final ParsePosition parsePosition = new ParsePosition(0);
107 Assert.assertNotNull(parser.parse(input, parsePosition));
108 Assert.assertEquals(input.length(), parsePosition.getIndex());
109
110 parsePosition.setIndex(0);
111 Assert.assertNull(parser.parse( "Thorsday, 03/23/61", parsePosition));
112 Assert.assertEquals(0, parsePosition.getErrorIndex());
113 }
114114 }
3030 public class FastDateParser_TimeZoneStrategyTest {
3131
3232 @Test
33 public void testLang1219() throws ParseException {
34 final FastDateParser parser = new FastDateParser("dd.MM.yyyy HH:mm:ss z", TimeZone.getDefault(), Locale.GERMAN);
35
36 final Date summer = parser.parse("26.10.2014 02:00:00 MESZ");
37 final Date standard = parser.parse("26.10.2014 02:00:00 MEZ");
38 Assert.assertNotEquals(summer.getTime(), standard.getTime());
39 }
40
41 @Test
4233 public void testTimeZoneStrategyPattern() {
4334 for(final Locale locale : Locale.getAvailableLocales()) {
4435 final FastDateParser parser = new FastDateParser("z", TimeZone.getDefault(), locale);
6556 }
6657 }
6758 }
59
60 @Test
61 public void testLang1219() throws ParseException {
62 final FastDateParser parser = new FastDateParser("dd.MM.yyyy HH:mm:ss z", TimeZone.getDefault(), Locale.GERMAN);
63
64 final Date summer = parser.parse("26.10.2014 02:00:00 MESZ");
65 final Date standard = parser.parse("26.10.2014 02:00:00 MEZ");
66 Assert.assertNotEquals(summer.getTime(), standard.getTime());
67 }
6868 }
3030 import java.util.concurrent.TimeUnit;
3131
3232 import org.apache.logging.log4j.core.util.datetime.FixedDateFormat.FixedFormat;
33 import org.apache.logging.log4j.util.Strings;
3433 import org.junit.Test;
3534
3635 /**
3837 */
3938 public class FixedDateFormatTest {
4039
41 private boolean containsNanos(final FixedFormat fixedFormat) {
42 final String pattern = fixedFormat.getPattern();
43 return pattern.endsWith("n") || pattern.matches(".+n+X*") || pattern.matches(".+n+Z*");
44 }
45
46 @Test(expected = NullPointerException.class)
47 public void testConstructorDisallowsNullFormat() {
48 new FixedDateFormat(null, TimeZone.getDefault());
49 }
50
51 @Test(expected = NullPointerException.class)
52 public void testConstructorDisallowsNullTimeZone() {
53 new FixedDateFormat(FixedFormat.ABSOLUTE, null);
54 }
55
56 @Test
57 public void testCreateIfSupported_customTimeZoneIfOptionsArrayWithTimeZoneElement() {
58 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(DEFAULT.getPattern(), "+08:00", "");
59 assertEquals(DEFAULT.getPattern(), fmt.getFormat());
60 assertEquals(TimeZone.getTimeZone("+08:00"), fmt.getTimeZone());
61 }
62
63 @Test
64 public void testCreateIfSupported_defaultIfOptionsArrayEmpty() {
65 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(Strings.EMPTY_ARRAY);
66 assertEquals(DEFAULT.getPattern(), fmt.getFormat());
40 @Test
41 public void testFixedFormat_getDatePatternNullIfNoDateInPattern() {
42 assertNull(FixedFormat.ABSOLUTE.getDatePattern());
43 assertNull(FixedFormat.ABSOLUTE_PERIOD.getDatePattern());
44 }
45
46 @Test
47 public void testFixedFormat_getDatePatternLengthZeroIfNoDateInPattern() {
48 assertEquals(0, FixedFormat.ABSOLUTE.getDatePatternLength());
49 assertEquals(0, FixedFormat.ABSOLUTE_PERIOD.getDatePatternLength());
50 }
51
52 @Test
53 public void testFixedFormat_getFastDateFormatNullIfNoDateInPattern() {
54 assertNull(FixedFormat.ABSOLUTE.getFastDateFormat());
55 assertNull(FixedFormat.ABSOLUTE_PERIOD.getFastDateFormat());
56 }
57
58 @Test
59 public void testFixedFormat_getDatePatternReturnsDatePatternIfExists() {
60 assertEquals("yyyyMMdd", FixedFormat.COMPACT.getDatePattern());
61 assertEquals("yyyy-MM-dd ", DEFAULT.getDatePattern());
62 }
63
64 @Test
65 public void testFixedFormat_getDatePatternLengthReturnsDatePatternLength() {
66 assertEquals("yyyyMMdd".length(), FixedFormat.COMPACT.getDatePatternLength());
67 assertEquals("yyyy-MM-dd ".length(), DEFAULT.getDatePatternLength());
68 }
69
70 @Test
71 public void testFixedFormat_getFastDateFormatNonNullIfDateInPattern() {
72 assertNotNull(FixedFormat.COMPACT.getFastDateFormat());
73 assertNotNull(DEFAULT.getFastDateFormat());
74 assertEquals("yyyyMMdd", FixedFormat.COMPACT.getFastDateFormat().getPattern());
75 assertEquals("yyyy-MM-dd ", DEFAULT.getFastDateFormat().getPattern());
76 }
77
78 @Test
79 public void testCreateIfSupported_nonNullIfNameMatches() {
80 for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
81 final String[] options = {format.name()};
82 assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
83 }
84 }
85
86 @Test
87 public void testCreateIfSupported_nonNullIfPatternMatches() {
88 for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
89 final String[] options = {format.getPattern()};
90 assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
91 }
92 }
93
94 @Test
95 public void testCreateIfSupported_nullIfNameDoesNotMatch() {
96 final String[] options = {"DEFAULT3"};
97 assertNull("DEFAULT3", FixedDateFormat.createIfSupported(options));
98 }
99
100 @Test
101 public void testCreateIfSupported_nullIfPatternDoesNotMatch() {
102 final String[] options = {"y M d H m s"};
103 assertNull("y M d H m s", FixedDateFormat.createIfSupported(options));
67104 }
68105
69106 @Test
70107 public void testCreateIfSupported_defaultIfOptionsArrayNull() {
71108 final FixedDateFormat fmt = FixedDateFormat.createIfSupported((String[]) null);
109 assertEquals(DEFAULT.getPattern(), fmt.getFormat());
110 }
111
112 @Test
113 public void testCreateIfSupported_defaultIfOptionsArrayEmpty() {
114 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[0]);
72115 assertEquals(DEFAULT.getPattern(), fmt.getFormat());
73116 }
74117
81124
82125 @Test
83126 public void testCreateIfSupported_defaultTimeZoneIfOptionsArrayWithSecondNullElement() {
84 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(DEFAULT.getPattern(), null, "");
127 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[] {DEFAULT.getPattern(), null, ""});
85128 assertEquals(DEFAULT.getPattern(), fmt.getFormat());
86129 assertEquals(TimeZone.getDefault(), fmt.getTimeZone());
87130 }
88131
89132 @Test
90 public void testCreateIfSupported_nonNullIfNameMatches() {
91 for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
92 final String[] options = {format.name()};
93 assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
94 }
95 }
96
97 @Test
98 public void testCreateIfSupported_nonNullIfPatternMatches() {
99 for (final FixedDateFormat.FixedFormat format : FixedDateFormat.FixedFormat.values()) {
100 final String[] options = {format.getPattern()};
101 assertNotNull(format.name(), FixedDateFormat.createIfSupported(options));
102 }
103 }
104
105 @Test
106 public void testCreateIfSupported_nullIfNameDoesNotMatch() {
107 final String[] options = {"DEFAULT3"};
108 assertNull("DEFAULT3", FixedDateFormat.createIfSupported(options));
109 }
110
111 @Test
112 public void testCreateIfSupported_nullIfPatternDoesNotMatch() {
113 final String[] options = {"y M d H m s"};
114 assertNull("y M d H m s", FixedDateFormat.createIfSupported(options));
133 public void testCreateIfSupported_customTimeZoneIfOptionsArrayWithTimeZoneElement() {
134 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[] {DEFAULT.getPattern(), "+08:00", ""});
135 assertEquals(DEFAULT.getPattern(), fmt.getFormat());
136 assertEquals(TimeZone.getTimeZone("+08:00"), fmt.getTimeZone());
137 }
138
139 @Test(expected = NullPointerException.class)
140 public void testConstructorDisallowsNullFormat() {
141 new FixedDateFormat(null, TimeZone.getDefault());
142 }
143
144 @Test(expected = NullPointerException.class)
145 public void testConstructorDisallowsNullTimeZone() {
146 new FixedDateFormat(FixedFormat.ABSOLUTE, null);
147 }
148
149 @Test
150 public void testGetFormatReturnsConstructorFixedFormatPattern() {
151 final FixedDateFormat format = new FixedDateFormat(FixedDateFormat.FixedFormat.ABSOLUTE, TimeZone.getDefault());
152 assertSame(FixedDateFormat.FixedFormat.ABSOLUTE.getPattern(), format.getFormat());
153 }
154
155 @Test
156 public void testFormatLong() {
157 final long now = System.currentTimeMillis();
158 final long start = now - TimeUnit.HOURS.toMillis(25);
159 final long end = now + TimeUnit.HOURS.toMillis(25);
160 for (final FixedFormat format : FixedFormat.values()) {
161 final String pattern = format.getPattern();
162 if (containsNanos(format) || format.getFixedTimeZoneFormat() != null) {
163 continue; // cannot compile precise timestamp formats with SimpleDateFormat
164 }
165 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
166 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
167 for (long time = start; time < end; time += 12345) {
168 final String actual = customTF.format(time);
169 final String expected = simpleDF.format(new Date(time));
170 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
171 }
172 }
173 }
174
175 @Test
176 public void testFormatLong_goingBackInTime() {
177 final long now = System.currentTimeMillis();
178 final long start = now - TimeUnit.HOURS.toMillis(25);
179 final long end = now + TimeUnit.HOURS.toMillis(25);
180 for (final FixedFormat format : FixedFormat.values()) {
181 final String pattern = format.getPattern();
182 if (containsNanos(format) || format.getFixedTimeZoneFormat() != null) {
183 continue; // cannot compile precise timestamp formats with SimpleDateFormat
184 }
185 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
186 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
187 for (long time = end; time > start; time -= 12345) {
188 final String actual = customTF.format(time);
189 final String expected = simpleDF.format(new Date(time));
190 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
191 }
192 }
193 }
194
195 @Test
196 public void testFormatLongCharArrayInt() {
197 final long now = System.currentTimeMillis();
198 final long start = now - TimeUnit.HOURS.toMillis(25);
199 final long end = now + TimeUnit.HOURS.toMillis(25);
200 final char[] buffer = new char[128];
201 for (final FixedFormat format : FixedFormat.values()) {
202 final String pattern = format.getPattern();
203 if (containsNanos(format) || format.getFixedTimeZoneFormat() != null) {
204 // cannot compile precise timestamp formats with SimpleDateFormat
205 // This format() API not include the TZ
206 continue;
207 }
208 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
209 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
210 for (long time = start; time < end; time += 12345) {
211 final int length = customTF.format(time, buffer, 23);
212 final String actual = new String(buffer, 23, length);
213 final String expected = simpleDF.format(new Date(time));
214 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
215 }
216 }
217 }
218
219 @Test
220 public void testFormatLongCharArrayInt_goingBackInTime() {
221 final long now = System.currentTimeMillis();
222 final long start = now - TimeUnit.HOURS.toMillis(25);
223 final long end = now + TimeUnit.HOURS.toMillis(25);
224 final char[] buffer = new char[128];
225 for (final FixedFormat format : FixedFormat.values()) {
226 final String pattern = format.getPattern();
227 if (pattern.endsWith("n") || pattern.matches(".+n+X*") || pattern.matches(".+n+Z*") || format.getFixedTimeZoneFormat() != null) {
228 continue; // cannot compile precise timestamp formats with SimpleDateFormat
229 }
230 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
231 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
232 for (long time = end; time > start; time -= 12345) {
233 final int length = customTF.format(time, buffer, 23);
234 final String actual = new String(buffer, 23, length);
235 final String expected = simpleDF.format(new Date(time));
236 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
237 }
238 }
115239 }
116240
117241 @Test
244368 calendar.add(Calendar.HOUR_OF_DAY, 1);
245369 }
246370 }
247
248 @Test
249 public void testFixedFormat_getDatePatternLengthReturnsDatePatternLength() {
250 assertEquals("yyyyMMdd".length(), FixedFormat.COMPACT.getDatePatternLength());
251 assertEquals("yyyy-MM-dd ".length(), DEFAULT.getDatePatternLength());
252 }
253
254 @Test
255 public void testFixedFormat_getDatePatternLengthZeroIfNoDateInPattern() {
256 assertEquals(0, FixedFormat.ABSOLUTE.getDatePatternLength());
257 assertEquals(0, FixedFormat.ABSOLUTE_PERIOD.getDatePatternLength());
258 }
259
260 @Test
261 public void testFixedFormat_getDatePatternNullIfNoDateInPattern() {
262 assertNull(FixedFormat.ABSOLUTE.getDatePattern());
263 assertNull(FixedFormat.ABSOLUTE_PERIOD.getDatePattern());
264 }
265
266 @Test
267 public void testFixedFormat_getDatePatternReturnsDatePatternIfExists() {
268 assertEquals("yyyyMMdd", FixedFormat.COMPACT.getDatePattern());
269 assertEquals("yyyy-MM-dd ", DEFAULT.getDatePattern());
270 }
271
272 @Test
273 public void testFixedFormat_getFastDateFormatNonNullIfDateInPattern() {
274 assertNotNull(FixedFormat.COMPACT.getFastDateFormat());
275 assertNotNull(DEFAULT.getFastDateFormat());
276 assertEquals("yyyyMMdd", FixedFormat.COMPACT.getFastDateFormat().getPattern());
277 assertEquals("yyyy-MM-dd ", DEFAULT.getFastDateFormat().getPattern());
278 }
279
280 @Test
281 public void testFixedFormat_getFastDateFormatNullIfNoDateInPattern() {
282 assertNull(FixedFormat.ABSOLUTE.getFastDateFormat());
283 assertNull(FixedFormat.ABSOLUTE_PERIOD.getFastDateFormat());
284 }
285
286 @Test
287 public void testFormatLong() {
288 final long now = System.currentTimeMillis();
289 final long start = now - TimeUnit.HOURS.toMillis(25);
290 final long end = now + TimeUnit.HOURS.toMillis(25);
291 for (final FixedFormat format : FixedFormat.values()) {
292 final String pattern = format.getPattern();
293 if (containsNanos(format) || format.getFixedTimeZoneFormat() != null) {
294 continue; // cannot compile precise timestamp formats with SimpleDateFormat
295 }
296 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
297 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
298 for (long time = start; time < end; time += 12345) {
299 final String actual = customTF.format(time);
300 final String expected = simpleDF.format(new Date(time));
301 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
302 }
303 }
304 }
305
306 @Test
307 public void testFormatLong_goingBackInTime() {
308 final long now = System.currentTimeMillis();
309 final long start = now - TimeUnit.HOURS.toMillis(25);
310 final long end = now + TimeUnit.HOURS.toMillis(25);
371
372 private boolean containsNanos(final FixedFormat fixedFormat) {
373 final String pattern = fixedFormat.getPattern();
374 return pattern.endsWith("n") || pattern.matches(".+n+X*") || pattern.matches(".+n+Z*");
375 }
376
377 /**
378 * This test case validates date pattern before and after DST
379 * Base Date : 12 Mar 2017
380 * Daylight Savings started on : 02:00 AM
381 */
382 @Test
383 public void testFormatLong_goingBackInTime_DST() {
384 final Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("EST"));
385 instance.set(2017, 2, 12, 2, 0);
386 final long now = instance.getTimeInMillis();
387 final long start = now - TimeUnit.HOURS.toMillis(1);
388 final long end = now + TimeUnit.HOURS.toMillis(1);
389
311390 for (final FixedFormat format : FixedFormat.values()) {
312391 final String pattern = format.getPattern();
313392 if (containsNanos(format) || format.getFixedTimeZoneFormat() != null) {
322401 }
323402 }
324403 }
325
326 /**
327 * This test case validates date pattern before and after DST
328 * Base Date : 12 Mar 2017
329 * Daylight Savings started on : 02:00 AM
330 */
331 @Test
332 public void testFormatLong_goingBackInTime_DST() {
333 final Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("EST"));
334 instance.set(2017, 2, 12, 2, 0);
335 final long now = instance.getTimeInMillis();
336 final long start = now - TimeUnit.HOURS.toMillis(1);
337 final long end = now + TimeUnit.HOURS.toMillis(1);
338
339 for (final FixedFormat format : FixedFormat.values()) {
340 final String pattern = format.getPattern();
341 if (containsNanos(format) || format.getFixedTimeZoneFormat() != null) {
342 continue; // cannot compile precise timestamp formats with SimpleDateFormat
343 }
344 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
345 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
346 for (long time = end; time > start; time -= 12345) {
347 final String actual = customTF.format(time);
348 final String expected = simpleDF.format(new Date(time));
349 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
350 }
351 }
352 }
353
354 @Test
355 public void testFormatLongCharArrayInt() {
356 final long now = System.currentTimeMillis();
357 final long start = now - TimeUnit.HOURS.toMillis(25);
358 final long end = now + TimeUnit.HOURS.toMillis(25);
359 final char[] buffer = new char[128];
360 for (final FixedFormat format : FixedFormat.values()) {
361 final String pattern = format.getPattern();
362 if (containsNanos(format) || format.getFixedTimeZoneFormat() != null) {
363 // cannot compile precise timestamp formats with SimpleDateFormat
364 // This format() API not include the TZ
365 continue;
366 }
367 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
368 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
369 for (long time = start; time < end; time += 12345) {
370 final int length = customTF.format(time, buffer, 23);
371 final String actual = new String(buffer, 23, length);
372 final String expected = simpleDF.format(new Date(time));
373 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
374 }
375 }
376 }
377
378 @Test
379 public void testFormatLongCharArrayInt_goingBackInTime() {
380 final long now = System.currentTimeMillis();
381 final long start = now - TimeUnit.HOURS.toMillis(25);
382 final long end = now + TimeUnit.HOURS.toMillis(25);
383 final char[] buffer = new char[128];
384 for (final FixedFormat format : FixedFormat.values()) {
385 final String pattern = format.getPattern();
386 if (pattern.endsWith("n") || pattern.matches(".+n+X*") || pattern.matches(".+n+Z*") || format.getFixedTimeZoneFormat() != null) {
387 continue; // cannot compile precise timestamp formats with SimpleDateFormat
388 }
389 final SimpleDateFormat simpleDF = new SimpleDateFormat(pattern, Locale.getDefault());
390 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
391 for (long time = end; time > start; time -= 12345) {
392 final int length = customTF.format(time, buffer, 23);
393 final String actual = new String(buffer, 23, length);
394 final String expected = simpleDF.format(new Date(time));
395 assertEquals(format + "(" + pattern + ")" + "/" + time, expected, actual);
396 }
397 }
398 }
399
400 @Test
401 public void testGetFormatReturnsConstructorFixedFormatPattern() {
402 final FixedDateFormat format = new FixedDateFormat(FixedDateFormat.FixedFormat.ABSOLUTE, TimeZone.getDefault());
403 assertSame(FixedDateFormat.FixedFormat.ABSOLUTE.getPattern(), format.getFormat());
404 }
405404 }
+0
-54
log4j-core/src/test/java/org/apache/logging/log4j/junit/AppenderResolver.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.core.Appender;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.junit.jupiter.api.extension.ExtensionContext;
22 import org.junit.jupiter.api.extension.ParameterContext;
23 import org.junit.jupiter.api.extension.ParameterResolutionException;
24 import org.junit.jupiter.api.extension.ParameterResolver;
25
26 import static org.apache.logging.log4j.junit.LoggerContextResolver.getParameterLoggerContext;
27
28 class AppenderResolver implements ParameterResolver {
29 @Override
30 public boolean supportsParameter(
31 ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
32 return Appender.class.isAssignableFrom(parameterContext.getParameter().getType()) && parameterContext
33 .isAnnotated(Named.class);
34 }
35
36 @Override
37 public Object resolveParameter(
38 ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
39 final LoggerContext loggerContext = getParameterLoggerContext(parameterContext, extensionContext);
40 if (loggerContext == null) {
41 throw new ParameterResolutionException("No LoggerContext defined");
42 }
43 final String name = parameterContext.findAnnotation(Named.class)
44 .map(Named::value)
45 .map(s -> s.isEmpty() ? parameterContext.getParameter().getName() : s)
46 .orElseThrow(() -> new ParameterResolutionException("No @Named present after checking earlier"));
47 final Appender appender = loggerContext.getConfiguration().getAppender(name);
48 if (appender == null) {
49 throw new ParameterResolutionException("No appender named " + name);
50 }
51 return appender;
52 }
53 }
6767
6868 private static final int MAX_TRIES = 10;
6969
70 public CleanFolders(final boolean before, final boolean after, final int maxTries, final File... files) {
71 super(before, after, maxTries, null, files);
72 }
73
74 public CleanFolders(final boolean before, final boolean after, final int maxTries, final Path... paths) {
75 super(before, after, maxTries, null, paths);
76 }
70 public CleanFolders(final boolean before, final boolean after, final int maxTries, final File... files) {
71 super(before, after, maxTries, null, files);
72 }
7773
7874 public CleanFolders(final boolean before, final boolean after, final int maxTries, final String... fileNames) {
7975 super(before, after, maxTries, null, fileNames);
+0
-39
log4j-core/src/test/java/org/apache/logging/log4j/junit/ConfigurationResolver.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.config.Configuration;
21 import org.junit.jupiter.api.extension.ExtensionContext;
22 import org.junit.jupiter.api.extension.ParameterContext;
23 import org.junit.jupiter.api.extension.ParameterResolutionException;
24 import org.junit.jupiter.api.extension.support.TypeBasedParameterResolver;
25
26 import static org.apache.logging.log4j.junit.LoggerContextResolver.getParameterLoggerContext;
27
28 class ConfigurationResolver extends TypeBasedParameterResolver<Configuration> {
29 @Override
30 public Configuration resolveParameter(
31 ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
32 final LoggerContext loggerContext = getParameterLoggerContext(parameterContext, extensionContext);
33 if (loggerContext == null) {
34 throw new ParameterResolutionException("No LoggerContext defined");
35 }
36 return loggerContext.getConfiguration();
37 }
38 }
+0
-157
log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextResolver.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.core.LoggerContextAccessor;
21 import org.apache.logging.log4j.core.config.Configurator;
22 import org.junit.jupiter.api.extension.AfterAllCallback;
23 import org.junit.jupiter.api.extension.AfterEachCallback;
24 import org.junit.jupiter.api.extension.BeforeAllCallback;
25 import org.junit.jupiter.api.extension.BeforeEachCallback;
26 import org.junit.jupiter.api.extension.ExtensionContext;
27 import org.junit.jupiter.api.extension.ParameterContext;
28 import org.junit.jupiter.api.extension.ParameterResolutionException;
29 import org.junit.jupiter.api.extension.support.TypeBasedParameterResolver;
30
31 import java.lang.reflect.Method;
32 import java.util.concurrent.TimeUnit;
33
34 class LoggerContextResolver extends TypeBasedParameterResolver<LoggerContext> implements BeforeAllCallback,
35 AfterAllCallback, BeforeEachCallback, AfterEachCallback {
36 @Override
37 public void beforeAll(ExtensionContext context) throws Exception {
38 final Class<?> testClass = context.getRequiredTestClass();
39 final LoggerContextSource testSource = testClass.getAnnotation(LoggerContextSource.class);
40 if (testSource != null) {
41 final LoggerContextConfig config = new LoggerContextConfig(testSource, context);
42 getTestClassStore(context).put(LoggerContext.class, config);
43 }
44 }
45
46 @Override
47 public void afterAll(ExtensionContext context) throws Exception {
48 final LoggerContextConfig config =
49 getTestClassStore(context).get(LoggerContext.class, LoggerContextConfig.class);
50 if (config != null) {
51 config.close();
52 }
53 }
54
55 @Override
56 public void beforeEach(ExtensionContext context) throws Exception {
57 final Class<?> testClass = context.getRequiredTestClass();
58 if (testClass.isAnnotationPresent(LoggerContextSource.class)) {
59 final LoggerContextConfig config = getTestClassStore(context).get(LoggerContext.class, LoggerContextConfig.class);
60 if (config == null) {
61 throw new IllegalStateException(
62 "Specified @LoggerContextSource but no LoggerContext found for test class " +
63 testClass.getCanonicalName());
64 }
65 if (config.reconfigurationPolicy == ReconfigurationPolicy.BEFORE_EACH) {
66 config.reconfigure();
67 }
68 }
69 final LoggerContextSource source = context.getRequiredTestMethod().getAnnotation(LoggerContextSource.class);
70 if (source != null) {
71 final LoggerContextConfig config = new LoggerContextConfig(source, context);
72 if (config.reconfigurationPolicy == ReconfigurationPolicy.BEFORE_EACH) {
73 config.reconfigure();
74 }
75 getTestInstanceStore(context).put(LoggerContext.class, config);
76 }
77 }
78
79 @Override
80 public void afterEach(ExtensionContext context) throws Exception {
81 // method-annotated variant
82 final LoggerContextConfig testInstanceConfig =
83 getTestInstanceStore(context).get(LoggerContext.class, LoggerContextConfig.class);
84 if (testInstanceConfig != null) {
85 testInstanceConfig.close();
86 }
87 // reloadable variant
88 final Class<?> testClass = context.getRequiredTestClass();
89 if (testClass.isAnnotationPresent(LoggerContextSource.class)) {
90 final LoggerContextConfig config = getTestClassStore(context).get(LoggerContext.class, LoggerContextConfig.class);
91 if (config == null) {
92 throw new IllegalStateException(
93 "Specified @LoggerContextSource but no LoggerContext found for test class " +
94 testClass.getCanonicalName());
95 }
96 if (config.reconfigurationPolicy == ReconfigurationPolicy.AFTER_EACH) {
97 config.reconfigure();
98 }
99 }
100 }
101
102 @Override
103 public LoggerContext resolveParameter(
104 ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
105 return getParameterLoggerContext(parameterContext, extensionContext);
106 }
107
108 private static ExtensionContext.Store getTestClassStore(final ExtensionContext context) {
109 return context.getStore(ExtensionContext.Namespace.create(LoggerContext.class, context.getRequiredTestClass()));
110 }
111
112 private static ExtensionContext.Store getTestInstanceStore(final ExtensionContext context) {
113 return context.getStore(ExtensionContext.Namespace.create(LoggerContext.class, context.getRequiredTestInstance()));
114 }
115
116 static LoggerContext getParameterLoggerContext(ParameterContext parameterContext, ExtensionContext extensionContext) {
117 if (parameterContext.getDeclaringExecutable() instanceof Method) {
118 final LoggerContextAccessor accessor =
119 getTestInstanceStore(extensionContext).get(LoggerContext.class, LoggerContextAccessor.class);
120 return accessor != null ? accessor.getLoggerContext() :
121 getTestClassStore(extensionContext).get(LoggerContext.class, LoggerContextAccessor.class).getLoggerContext();
122 }
123 return getTestClassStore(extensionContext).get(LoggerContext.class, LoggerContextAccessor.class).getLoggerContext();
124 }
125
126 private static class LoggerContextConfig implements AutoCloseable, LoggerContextAccessor {
127 private final LoggerContext context;
128 private final ReconfigurationPolicy reconfigurationPolicy;
129 private final long shutdownTimeout;
130 private final TimeUnit unit;
131
132 private LoggerContextConfig(final LoggerContextSource source, final ExtensionContext extensionContext) {
133 final String displayName = extensionContext.getDisplayName();
134 final ClassLoader classLoader = extensionContext.getRequiredTestClass().getClassLoader();
135 context = Configurator.initialize(displayName, classLoader, source.value());
136 reconfigurationPolicy = source.reconfigure();
137 shutdownTimeout = source.timeout();
138 unit = source.unit();
139 }
140
141 @Override
142 public LoggerContext getLoggerContext() {
143 return context;
144 }
145
146 public void reconfigure() {
147 context.reconfigure();
148 }
149
150 @Override
151 public void close() {
152 context.stop(shutdownTimeout, unit);
153 }
154 }
155
156 }
4141 * property {@code EBUG} is set (e.g., through the command line option {@code -DEBUG}), then the StatusLogger will be
4242 * set to the debug level. This allows for more debug messages as the StatusLogger will be in the error level until a
4343 * configuration file has been read and parsed into a tree of Nodes.
44 *
45 * @see LoggerContextSource
46 * @see Named
4744 */
4845 public class LoggerContextRule implements TestRule, LoggerContextAccessor {
4946
+0
-79
log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextSource.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.core.Appender;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.junit.jupiter.api.Tag;
23 import org.junit.jupiter.api.extension.ExtendWith;
24
25 import java.lang.annotation.Documented;
26 import java.lang.annotation.ElementType;
27 import java.lang.annotation.Inherited;
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.lang.annotation.Target;
31 import java.util.concurrent.TimeUnit;
32
33 /**
34 * Specifies a configuration file to use for unit tests. This configuration file will be loaded once and used for all tests
35 * executed in the annotated test class unless otherwise specified by {@link #reconfigure()}. When annotated on a test method,
36 * this will override the class-level configuration if provided for that method. By using this JUnit 5 extension, the following
37 * types can be injected into tests via constructor or method parameters:
38 *
39 * <ul>
40 * <li>{@link LoggerContext};</li>
41 * <li>{@link Configuration};</li>
42 * <li>any subclass of {@link Appender} paired with a {@link Named} annotation to select the appender by name.</li>
43 * </ul>
44 *
45 * Tests using this extension will automatically be tagged as {@code functional} to indicate they perform functional tests that
46 * rely on configuration files and production code.
47 *
48 * @since 2.14.0
49 */
50 @Retention(RetentionPolicy.RUNTIME)
51 @Target({ElementType.TYPE, ElementType.METHOD})
52 @Documented
53 @Inherited
54 @Tag("functional")
55 @ExtendWith(LoggerContextResolver.class)
56 @ExtendWith(ConfigurationResolver.class)
57 @ExtendWith(AppenderResolver.class)
58 public @interface LoggerContextSource {
59 /**
60 * Specifies the name of the configuration file to use for the annotated test.
61 */
62 String value();
63
64 /**
65 * Specifies when to {@linkplain LoggerContext#reconfigure() reconfigure} the logging system.
66 */
67 ReconfigurationPolicy reconfigure() default ReconfigurationPolicy.NEVER;
68
69 /**
70 * Specifies the shutdown timeout limit. Defaults to 0 to mean no limit.
71 */
72 long timeout() default 0L;
73
74 /**
75 * Specifies the time unit {@link #timeout()} is measured in.
76 */
77 TimeUnit unit() default TimeUnit.SECONDS;
78 }
+0
-41
log4j-core/src/test/java/org/apache/logging/log4j/junit/Named.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
17 package org.apache.logging.log4j.junit;
18
19 import java.lang.annotation.Documented;
20 import java.lang.annotation.ElementType;
21 import java.lang.annotation.Retention;
22 import java.lang.annotation.RetentionPolicy;
23 import java.lang.annotation.Target;
24
25 /**
26 * Specifies the name of an {@link org.apache.logging.log4j.core.Appender} to inject into JUnit 5 tests from the specified
27 * configuration.
28 *
29 * @see LoggerContextSource
30 * @since 2.14.0
31 */
32 @Retention(RetentionPolicy.RUNTIME)
33 @Target(ElementType.PARAMETER)
34 @Documented
35 public @interface Named {
36 /**
37 * Specifies the name of the configuration item to inject. If blank, uses the name of the annotated parameter.
38 */
39 String value() default "";
40 }
+0
-35
log4j-core/src/test/java/org/apache/logging/log4j/junit/ReconfigurationPolicy.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
17 package org.apache.logging.log4j.junit;
18
19 import org.apache.logging.log4j.core.LoggerContext;
20
21 /**
22 * Indicates when to {@linkplain LoggerContext#reconfigure() reconfigure} the logging system during unit tests.
23 *
24 * @see LoggerContextSource
25 * @since 2.14.0
26 */
27 public enum ReconfigurationPolicy {
28 /** Performs no reconfiguration of the logging system for the entire run of tests in a test class. This is the default. */
29 NEVER,
30 /** Performs a reconfiguration before executing each test. */
31 BEFORE_EACH,
32 /** Performs a reconfiguration after executing each test. */
33 AFTER_EACH
34 }
1616 package org.apache.logging.log4j.message;
1717
1818 import org.apache.logging.log4j.core.impl.MutableLogEvent;
19 import org.junit.jupiter.api.Test;
19 import org.junit.Test;
2020
2121 import static org.hamcrest.MatcherAssert.assertThat;
2222 import static org.hamcrest.core.IsSame.sameInstance;
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.test;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.fail;
20
21 public class JUnit5Bridge {
22
23 /** This branch is on Java 7 and uses JUnit 4, hence this hack. */
24 public static <T> void assertThrows(Class<T> expectedType, Runnable runnable) {
25 try {
26 runnable.run();
27 fail("Expected " + expectedType.getCanonicalName());
28 } catch (Throwable t) {
29 assertEquals(expectedType, t.getClass());
30 }
31
32 }
33
34 }
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.test;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 /**
22 *
23 */
24 public class SomethingThatUsesLogging {
25
26 private final Logger logger;
27
28 public SomethingThatUsesLogging() {
29 logger = LogManager.getLogger();
30 }
31
32 public void doSomething() {
33 logger.isEnabled(Level.DEBUG);
34 }
35 }
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.test.appender;
17
18 import java.util.concurrent.TimeUnit;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.LoggingException;
23 import org.apache.logging.log4j.core.Appender;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.appender.AbstractAppender;
26 import org.apache.logging.log4j.core.config.Property;
27 import org.apache.logging.log4j.core.config.plugins.Plugin;
28 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
29 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
31
32 /**
33 *
34 */
35 @Plugin(name="Deadlock", category ="Core", elementType=Appender.ELEMENT_TYPE, printObject=true)
36 public class DeadlockAppender extends AbstractAppender {
37
38 private WorkerThread thread = null;
39
40 private DeadlockAppender(final String name) {
41 super(name, null, null, false, Property.EMPTY_ARRAY);
42 thread = new WorkerThread();
43 }
44
45 @Override
46 public void start() {
47 super.start();
48
49 }
50
51 @Override
52 public boolean stop(final long timeout, final TimeUnit timeUnit) {
53 setStopping();
54 super.stop(timeout, timeUnit, false);
55 thread.start();
56 try {
57 thread.join();
58 } catch (final Exception ex) {
59 System.out.println("Thread interrupted");
60 }
61 setStopped();
62 return true;
63 }
64
65 @Override
66 public void append(final LogEvent event) {
67 throw new LoggingException("Always fail");
68 }
69
70 @PluginFactory
71 public static DeadlockAppender createAppender(
72 @PluginAttribute("name") @Required(message = "A name for the Appender must be specified") final String name) {
73 return new DeadlockAppender(name);
74 }
75
76 private class WorkerThread extends Thread {
77
78 @Override
79 public void run() {
80 final Logger logger = LogManager.getLogger("org.apache.logging.log4j.test.WorkerThread");
81 logger.debug("Worker is running");
82 }
83 }
84 }
4040 super(name, filter, layout, newline, raw);
4141 }
4242
43 private static class Destination implements ByteBufferDestination {
44 // JUnit 5 stack traces can start to get looooong
45 ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[8192]);
46
43 private class Destination implements ByteBufferDestination {
44 ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4096]);
4745 @Override
4846 public ByteBuffer getByteBuffer() {
4947 return byteBuffer;
1515 */
1616 package org.apache.logging.log4j.test.appender;
1717
18 import java.util.ArrayList;
19 import java.util.List;
20
1821 import org.apache.logging.log4j.LoggingException;
1922 import org.apache.logging.log4j.core.Appender;
2023 import org.apache.logging.log4j.core.LogEvent;
2427 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2528 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
2629 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
27 import org.apache.logging.log4j.core.util.Throwables;
28
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.function.Supplier;
3230
3331 /**
34 * An {@link Appender} that fails on the first use and works for the rest.
32 *
3533 */
3634 @Plugin(name="FailOnce", category ="Core", elementType=Appender.ELEMENT_TYPE, printObject=true)
3735 public class FailOnceAppender extends AbstractAppender {
3836
39 private final Supplier<Throwable> throwableSupplier;
37 boolean fail = true;
4038
41 private boolean failed = false;
39 private final List<LogEvent> events = new ArrayList<>();
4240
43 private List<LogEvent> events = new ArrayList<>();
44
45 private FailOnceAppender(final String name, final Supplier<Throwable> throwableSupplier) {
41 private FailOnceAppender(final String name) {
4642 super(name, null, null, false, Property.EMPTY_ARRAY);
47 this.throwableSupplier = throwableSupplier;
4843 }
4944
5045 @Override
51 public synchronized void append(final LogEvent event) {
52 if (!failed) {
53 failed = true;
54 Throwable throwable = throwableSupplier.get();
55 Throwables.rethrow(throwable);
46 public void append(final LogEvent event) {
47 if (fail) {
48 fail = false;
49 throw new LoggingException("Always fail");
5650 }
5751 events.add(event);
5852 }
5953
60 public synchronized boolean isFailed() {
61 return failed;
62 }
63
64 /**
65 * Returns the list of accumulated events and resets the internal buffer.
66 */
67 public synchronized List<LogEvent> drainEvents() {
68 final List<LogEvent> oldEvents = events;
69 this.events = new ArrayList<>();
70 return oldEvents;
54 public List<LogEvent> getEvents() {
55 final List<LogEvent> list = new ArrayList<>(events);
56 events.clear();
57 return list;
7158 }
7259
7360 @PluginFactory
7461 public static FailOnceAppender createAppender(
75 @PluginAttribute("name") @Required(message = "A name for the Appender must be specified") final String name,
76 @PluginAttribute("throwableClassName") final String throwableClassName) {
77 final Supplier<Throwable> throwableSupplier = createThrowableSupplier(name, throwableClassName);
78 return new FailOnceAppender(name, throwableSupplier);
79 }
80
81 private static Supplier<Throwable> createThrowableSupplier(
82 final String name,
83 final String throwableClassName) {
84
85 // Fallback to LoggingException if none is given.
86 final String message = String.format("failing on purpose for appender '%s'", name);
87 if (throwableClassName == null || ThrowableClassName.LOGGING_EXCEPTION.equals(throwableClassName)) {
88 return () -> new LoggingException(message);
89 }
90
91 // Check against the expected exception classes.
92 switch (throwableClassName) {
93 case ThrowableClassName.RUNTIME_EXCEPTION: return () -> new RuntimeException(message);
94 case ThrowableClassName.EXCEPTION: return () -> new Exception(message);
95 case ThrowableClassName.ERROR: return () -> new Error(message);
96 case ThrowableClassName.THROWABLE: return () -> new Throwable(message);
97 case ThrowableClassName.THREAD_DEATH: return () -> {
98 stopCurrentThread();
99 throw new IllegalStateException("should not have reached here");
100 };
101 default: throw new IllegalArgumentException("unknown throwable class name: " + throwableClassName);
102 }
103
104 }
105
106 @SuppressWarnings("deprecation")
107 private static void stopCurrentThread() {
108 Thread.currentThread().stop();
109 }
110
111 public enum ThrowableClassName {;
112
113 public static final String RUNTIME_EXCEPTION = "RuntimeException";
114
115 public static final String LOGGING_EXCEPTION = "LoggingException";
116
117 public static final String EXCEPTION = "Exception";
118
119 public static final String ERROR = "Error";
120
121 public static final String THROWABLE = "Throwable";
122
123 public static final String THREAD_DEATH = "ThreadDeath";
124
62 @PluginAttribute("name") @Required(message = "A name for the Appender must be specified") final String name) {
63 return new FailOnceAppender(name);
12564 }
12665
12766 }
8282 * listAppender.countDownLatch = new CountDownLatch(1);
8383 *
8484 * Logger logger = LogManager.getLogger();
85 * logger.info("log one event asynchronously");
85 * logger.info("log one event anynchronously");
8686 *
8787 * // wait for the appender to finish processing this event (wait max 1 second)
8888 * listAppender.countDownLatch.await(1, TimeUnit.SECONDS);
198198
199199 /** Returns an immutable snapshot of captured log events */
200200 public List<LogEvent> getEvents() {
201 return Collections.<LogEvent>unmodifiableList(new ArrayList<>(events));
201 return Collections.<LogEvent>unmodifiableList(new ArrayList<LogEvent>(events));
202202 }
203203
204204 /** Returns an immutable snapshot of captured messages */
205205 public List<String> getMessages() {
206 return Collections.<String>unmodifiableList(new ArrayList<>(messages));
206 return Collections.<String>unmodifiableList(new ArrayList<String>(messages));
207207 }
208208
209209 /**
220220
221221 /** Returns an immutable snapshot of captured data */
222222 public List<byte[]> getData() {
223 return Collections.<byte[]>unmodifiableList(new ArrayList<>(data));
223 return Collections.<byte[]>unmodifiableList(new ArrayList<byte[]>(data));
224224 }
225225
226226 public static ListAppender createAppender(final String name, final boolean newLine, final boolean raw,
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.test.appender;
17
18 import org.apache.logging.log4j.core.Appender;
19 import org.apache.logging.log4j.core.Core;
20 import org.apache.logging.log4j.core.Filter;
21 import org.apache.logging.log4j.core.Layout;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.appender.AbstractAppender;
24 import org.apache.logging.log4j.core.config.Property;
25 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
27 import org.apache.logging.log4j.core.config.plugins.PluginElement;
28 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
30 import org.apache.logging.log4j.test.SomethingThatUsesLogging;
31
32 /**
33 *
34 */
35 @Plugin(name = "UsesLoggingAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
36 public final class UsesLoggingAppender extends AbstractAppender {
37
38 private final SomethingThatUsesLogging thing;
39
40 private UsesLoggingAppender(final String name, final Filter filter, final Layout<?> layout, final boolean ignoreExceptions) {
41 super(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY);
42 thing = new SomethingThatUsesLogging();
43 }
44
45 @PluginFactory
46 public static UsesLoggingAppender createAppender(
47 @PluginAttribute("name") @Required(message = "A name for the Appender must be specified") final String name,
48 @PluginAttribute("ignoreExceptions") final boolean ignore,
49 @PluginElement("Layout") final Layout<?> layout,
50 @PluginElement("Filter") final Filter filter) {
51 return new UsesLoggingAppender(name, filter, layout, ignore);
52 }
53
54 @Override
55 public void append(final LogEvent event) {
56 try {
57 for (int i = 0; i < 50; i++) {
58 Thread.sleep(10);
59 thing.doSomething();
60 }
61 } catch (final InterruptedException e) {
62 e.printStackTrace();
63 }
64 // System.out.print("Log: " + getLayout().toSerializable(event));
65 }
66 }
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.test.layout;
17
18 import java.nio.charset.Charset;
19 import java.nio.charset.StandardCharsets;
20
21 import org.apache.logging.log4j.core.Core;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
25 import org.apache.logging.log4j.core.layout.AbstractStringLayout;
26 import org.apache.logging.log4j.util.Strings;
27
28 /**
29 *
30 */
31 @Plugin(name = "BasicLayout", category = Core.CATEGORY_NAME, elementType = "layout", printObject = true)
32 public class BasicLayout extends AbstractStringLayout {
33
34 private static final String HEADER = "Header" + Strings.LINE_SEPARATOR;
35
36 public BasicLayout(final Charset charset) {
37 super(charset);
38 }
39
40 @Override
41 public byte[] getHeader() {
42 return getBytes(HEADER);
43 }
44
45 @Override
46 public String toSerializable(final LogEvent event) {
47 return event.getMessage().getFormattedMessage() + Strings.LINE_SEPARATOR;
48 }
49
50 /**
51 */
52 @PluginFactory
53 public static BasicLayout createLayout() {
54 return new BasicLayout(StandardCharsets.UTF_8);
55 }
56 }
+0
-32
log4j-core/src/test/resources/AsyncAppenderExceptionHandlingTest.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2
3 Licensed to the Apache Software Foundation (ASF) under one or more
4 contributor license agreements. See the NOTICE file distributed with
5 this work for additional information regarding copyright ownership.
6 The ASF licenses this file to You under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with
8 the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17
18 -->
19 <Configuration status="OFF" name="AsyncAppenderExceptionHandlingTest">
20 <Appenders>
21 <FailOnce name="FailOnce" throwableClassName="${sys:throwableClassName}"/>
22 <Async name="Async">
23 <AppenderRef ref="FailOnce" />
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="info">
28 <AppenderRef ref="Async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
+0
-34
log4j-core/src/test/resources/GelfLayout2Test.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="OFF" name="GelfLayoutTest2">
19 <Appenders>
20 <List name="list">
21 <GelfLayout host="myhost">
22 <KeyValuePair key="foo" value="FOO"/>
23 <KeyValuePair key="runtime" value="$${java:runtime}"/>
24 </GelfLayout>
25 </List>
26 </Appenders>
27
28 <Loggers>
29 <Root level="info">
30 <AppenderRef ref="list"/>
31 </Root>
32 </Loggers>
33 </Configuration>
+0
-37
log4j-core/src/test/resources/GelfLayout3Test.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="GelfLayoutTest3">
19 <Appenders>
20 <List name="list">
21 <GelfLayout host="myhost" includeThreadContext="true" threadContextIncludes="requestId,loginId"
22 mapMessageIncludes="arg1,arg2,arg3" threadContextPrefix="mdc." mapPrefix="map." omitEmptyFields="true">
23 <MessagePattern>%d [%t] %-5p %X{requestId, loginId} %C{1.}.%M:%L - %m%n"</MessagePattern>
24 <KeyValuePair key="foo" value="FOO"/>
25 <KeyValuePair key="runtime" value="$${java:runtime}"/>
26 <KeyValuePair key="empty" value="${test:-}"/>
27 </GelfLayout>
28 </List>
29 </Appenders>
30
31 <Loggers>
32 <Root level="info">
33 <AppenderRef ref="list"/>
34 </Root>
35 </Loggers>
36 </Configuration>
+0
-37
log4j-core/src/test/resources/GelfLayoutPatternSelectorTest.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="GelfLayoutPatternSelectorTest">
19 <Appenders>
20 <List name="list">
21 <GelfLayout host="myhost" includeThreadContext="true" threadContextIncludes="requestId,loginId">
22 <MarkerPatternSelector defaultPattern="%d [%t] %-5p %X{requestId, loginId} %C{1.}.%M:%L - %m%n">
23 <PatternMatch key="FLOW" pattern="[%-5level] %X{requestId, loginId} ====== %C{1.}.%M:%L %msg ======%n"/>
24 </MarkerPatternSelector>
25 <KeyValuePair key="foo" value="FOO"/>
26 <KeyValuePair key="runtime" value="$${java:runtime}"/>
27 </GelfLayout>
28 </List>
29 </Appenders>
30
31 <Loggers>
32 <Root level="info">
33 <AppenderRef ref="list"/>
34 </Root>
35 </Loggers>
36 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="OFF" name="GelfLayoutTest2">
19 <Appenders>
20 <List name="list">
21 <GelfLayout host="myhost">
22 <KeyValuePair key="foo" value="FOO"/>
23 <KeyValuePair key="runtime" value="$${java:runtime}"/>
24 </GelfLayout>
25 </List>
26 </Appenders>
27
28 <Loggers>
29 <Root level="info">
30 <AppenderRef ref="list"/>
31 </Root>
32 </Loggers>
33 </Configuration>
+0
-4
log4j-core/src/test/resources/JndiRestrictedLookup.ldif less more
0 dn: dc=apache,dc=org
1 objectClass: domain
2 objectClass: top
3 dc: apache
1616 -->
1717 <Configuration name="KafkaAppenderTest" status="OFF">
1818 <Appenders>
19 <Kafka name="KafkaAppenderWithLayout" topic="kafka-topic">
19 <Kafka name="KafkaAppenderWithLayout" topic="kafka-topic">
2020 <PatternLayout pattern="[%m]"/>
2121 <Property name="bootstrap.servers">localhost:9092</Property>
2222 <Property name="timeout.ms">1000</Property>
4141 <Property name="timeout.ms">1000</Property>
4242 <Property name="bootstrap.servers">localhost:9092</Property>
4343 </Kafka>
44 <Kafka name="KafkaAppenderWithRetryCount" topic="kafka-topic" retryCount="3" >
45 <PatternLayout pattern="%m"/>
46 <Property name="timeout.ms">1000</Property>
47 <Property name="bootstrap.servers">fakeLoclhost:9092</Property>
48 </Kafka>
4944 </Appenders>
5045 <Loggers>
5146 <Root level="info">
5348 <AppenderRef ref="KafkaAppenderWithSerializedLayout"/>
5449 <AppenderRef ref="AsyncKafkaAppender"/>
5550 <AppenderRef ref="KafkaAppenderWithKey"/>
56 <AppenderRef ref="KafkaAppenderWithRetryCount"/>
5751 </Root>
5852 </Loggers>
59 </Configuration>
53 </Configuration>
+0
-31
log4j-core/src/test/resources/KafkaManagerProducerThreadLeakTest.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <Configuration name="KafkaManagerProducerThreadLeakTest" status="OFF">
18 <Appenders>
19 <Kafka name="KafkaAppender" topic="kafka-topic">
20 <PatternLayout pattern="[%m]"/>
21 <Property name="bootstrap.servers">localhost:9092</Property>
22 <Property name="timeout.ms">1000</Property>
23 </Kafka>
24 </Appenders>
25 <Loggers>
26 <Root level="info">
27 <AppenderRef ref="KafkaAppender"/>
28 </Root>
29 </Loggers>
30 </Configuration>
44 fileName="target/MemoryMappedFileAppenderLocationTest.log"
55 regionLength="32000" immediateFlush="true" append="false">
66 <PatternLayout>
7 <Pattern>%location: %m%n</Pattern>
7 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %location %ex%n</Pattern>
88 </PatternLayout>
99 </MemoryMappedFile>
1010 </Appenders>
1414 <AppenderRef ref="MemoryMappedFile"/>
1515 </Root>
1616 </Loggers>
17 </Configuration>
17 </Configuration>
44 fileName="target/MemoryMappedFileAppenderRemapTest.log"
55 regionLength="256" immediateFlush="true" append="false">
66 <PatternLayout>
7 <Pattern>%m%n</Pattern>
7 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
88 </PatternLayout>
99 </MemoryMappedFile>
1010 </Appenders>
1414 <AppenderRef ref="MemoryMappedFile"/>
1515 </Root>
1616 </Loggers>
17 </Configuration>
17 </Configuration>
44 fileName="target/MemoryMappedFileAppenderTest.log"
55 immediateFlush="false" append="false">
66 <PatternLayout>
7 <Pattern>%m%n</Pattern>
7 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
88 </PatternLayout>
99 </MemoryMappedFile>
1010 </Appenders>
1414 <AppenderRef ref="MemoryMappedFile"/>
1515 </Root>
1616 </Loggers>
17 </Configuration>
17 </Configuration>
+0
-32
log4j-core/src/test/resources/ReliabilityStrategyTest.xml less more
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <Configuration name="ReliabilityStrategyTest" status="OFF">
18 <Appenders>
19 <List name="list">
20 <PatternLayout pattern="%m"/>
21 </List>
22 <Async name="async">
23 <AppenderRef ref="list"/>
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="DEBUG">
28 <AppenderRef ref="async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
+0
-3
log4j-core/src/test/resources/__files/onStartup.log less more
0 This is test message number 1
1 This is test message number 2
2 This is test message number 3
1717 <KeyValuePair key="id" value="Login"/>
1818 <KeyValuePair key="id" value="Logout"/>
1919 </StructuredDataFilter>
20 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
20 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
2121 </Filters>
2222 <Appenders>
2323 <Console name="Console" target="SYSTEM_OUT">
2424 <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %X %m%ex%n" />
2525 </Console>
2626 <File name="File" fileName="target/gcfreefile.log" bufferedIO="false">
27 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
27 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
2828 <PatternLayout>
2929 <Pattern>%d{DEFAULT}{UTC} %r %sn %enc{'/} %notEmpty{[%marker]} %markerSimpleName %MAP %maxLen{%marker}{10} %equals{%markerSimpleName}{test}{substitute} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
3030 </PatternLayout>
3131 </File>
3232 <RollingFile name="RollingFile" fileName="target/gcfreeRollingFile.log"
3333 filePattern="target/gcfree-%d{MM-dd-yy-HH-mm-ss}.log.gz">
34 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
34 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
3535 <PatternLayout>
3636 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss,SSS}{UTC} %r %sn %markerSimpleName %MAP %maxLen{%marker}{10} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
3737 </PatternLayout>
4040 </Policies>
4141 </RollingFile>
4242 <RandomAccessFile name="RandomAccessFile" fileName="target/gcfreeRAF.log" immediateFlush="false" append="false">
43 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
43 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
4444 <PatternLayout>
4545 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSS}{UTC} %r %sn %markerSimpleName %MAP %maxLen{%marker}{10} %p %c{1.} [%t] %X{aKey} %m %ex%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %ex%n}</Pattern>
4646 </PatternLayout>
1717 <KeyValuePair key="id" value="Login"/>
1818 <KeyValuePair key="id" value="Logout"/>
1919 </StructuredDataFilter>
20 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
20 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
2121 </Filters>
2222 <Appenders>
2323 <Console name="Console" target="SYSTEM_OUT">
2424 <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %X %m%ex%n" />
2525 </Console>
2626 <File name="File" fileName="target/gcfreefileMixed.log" bufferedIO="false">
27 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
27 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
2828 <PatternLayout>
2929 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss,SSS}{UTC} %r %enc{'/} %notEmpty{[%marker]} %sn %markerSimpleName %MAP %maxLen{%marker}{10} %equals{%markerSimpleName}{test}{substitute} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
3030 </PatternLayout>
3131 </File>
3232 <RollingFile name="RollingFile" fileName="target/gcfreeRollingFileMixed.log"
3333 filePattern="target/gcfree-%d{MM-dd-yy-HH-mm-ss}.log.gz">
34 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
34 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
3535 <PatternLayout>
3636 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSS}{UTC} %r %sn %markerSimpleName %MAP %maxLen{%marker}{10} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
3737 </PatternLayout>
4040 </Policies>
4141 </RollingFile>
4242 <RandomAccessFile name="RandomAccessFile" fileName="target/gcfreeRAFMixed.log" immediateFlush="false" append="false">
43 <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>-->
43 <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
4444 <PatternLayout>
4545 <Pattern>%d{DEFAULT}{UTC} %r %sn %markerSimpleName %MAP %maxLen{%marker}{10} %p %c{1.} [%t] %X{aKey} %m %ex%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %ex%n}</Pattern>
4646 </PatternLayout>
1515 limitations under the License.
1616
1717 -->
18 <Configuration status="INFO" name="LoggerConfigTest">
18 <Configuration status="ERROR" name="LoggerConfigTest">
1919 <Appenders>
2020 <Console name="STDOUT">
2121 <PatternLayout pattern="%m%n"/>
2222 </Console>
23 <File name="File" fileName="target/test.log" bufferedIO="false">
23 <File name="File" fileName="${filename}" bufferedIO="false">
2424 <PatternLayout>
2525 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
2626 </PatternLayout>
+0
-29
log4j-core/src/test/resources/log4j-contextData.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17 <Configuration status="WARN" name="Context Data Test">
18 <Appenders>
19 <List name="List">
20 <PatternLayout pattern="[%-5level] ThreadContext%X %c{1.} %msg%n" />
21 </List>
22 </Appenders>
23 <Loggers>
24 <Root level="debug">
25 <AppenderRef ref="List" />
26 </Root>
27 </Loggers>
28 </Configuration>
4343 <KeyValuePair key="test" value="123"/>
4444 </ThreadContextMapFilter>
4545 <AppenderRef ref="STDOUT"/>
46 </Logger>
46 </Logger>>
4747
4848 <Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
4949 <AppenderRef ref="File"/>
50 </Logger>
50 </Logger>>
5151
5252 <Root level="error">
5353 <AppenderRef ref="STDOUT"/>
+0
-29
log4j-core/src/test/resources/log4j-list-lookups.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17 <Configuration status="WARN">
18 <Appenders>
19 <List name="List">
20 <PatternLayout pattern="[%-5level] %c{1.} %msg{ansi}{lookups}%n" />
21 </List>
22 </Appenders>
23 <Loggers>
24 <Root level="debug">
25 <AppenderRef ref="List" />
26 </Root>
27 </Loggers>
28 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17 <Configuration status="WARN">
18 <Appenders>
19 <List name="List">
20 <PatternLayout pattern="[%-5level] %c{1.} %msg{ansi}{nolookups}%n" />
21 </List>
22 </Appenders>
23 <Loggers>
24 <Root level="debug">
25 <AppenderRef ref="List" />
26 </Root>
27 </Loggers>
28 </Configuration>
2020 <List name="List">
2121 <PatternLayout>
2222 <replace regex="\." replacement="/"/>
23 <Pattern>%logger %msg{lookups}%n</Pattern>
23 <Pattern>%logger %msg%n</Pattern>
2424 </PatternLayout>
2525 </List>
2626 <List name="List2">
2727 <PatternLayout>
28 <Pattern>%replace{%logger %C{1.} %msg{lookups}%n}{\.}{/}</Pattern>
28 <Pattern>%replace{%logger %C{1.} %msg%n}{\.}{/}</Pattern>
2929 </PatternLayout>
3030 </List>
3131 </Appenders>
00 {
1 "configuration": { "status": "warn",
1 "configuration": { "status": "debug",
22 "appenders": {
33 "Console": {
44 "name": "Console",
+0
-38
log4j-core/src/test/resources/log4j-rollOnStartup.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="XMLConfigTest" monitorInterval="1">
19 <Appenders>
20 <RollingFile name="RollingFile" fileName="target/onStartup/onStartup.log"
21 filePattern="target/onStartup/onStartup-%d{MM-dd-yyyy}-%i.log">
22 <PatternLayout>
23 <Pattern>%m%n</Pattern>
24 </PatternLayout>
25 <Policies>
26 <OnStartupTriggeringPolicy minSize="10"/>
27 </Policies>
28 </RollingFile>
29 </Appenders>
30
31 <Loggers>
32 <Root level="trace">
33 <AppenderRef ref="RollingFile"/>
34 </Root>
35 </Loggers>
36
37 </Configuration>
+0
-37
log4j-core/src/test/resources/log4j-rollOnStartupDirect.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="XMLConfigTest" monitorInterval="1">
19 <Appenders>
20 <RollingFile name="RollingFile" filePattern="target/onStartup/onStartup-%d{MM-dd-yyyy}-%i.log">
21 <PatternLayout>
22 <Pattern>%m%n</Pattern>
23 </PatternLayout>
24 <Policies>
25 <OnStartupTriggeringPolicy minSize="10"/>
26 </Policies>
27 </RollingFile>
28 </Appenders>
29
30 <Loggers>
31 <Root level="trace">
32 <AppenderRef ref="RollingFile"/>
33 </Root>
34 </Loggers>
35
36 </Configuration>
+0
-44
log4j-core/src/test/resources/log4j-rolling-count.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="error" name="XmlProperties">
19 <Properties>
20 <Property name="baseFilename">target/rolling_count/rolling_test.log</Property>
21 <Property name="pattern">%d{HH:mm:ss.SSS} [%t] %-5level %logger{1.} - %msg%n</Property>
22 </Properties>
23
24 <Appenders>
25 <Console name="Console" target="SYSTEM_OUT">
26 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${baseFilename}" filePattern="${baseFilename}.%02i" immediateFlush="true" append="true">
29 <PatternLayout pattern="${pattern}"/>
30 <Policies>
31 <SizeBasedTriggeringPolicy size="1 KB"/>
32 </Policies>
33 <DefaultRolloverStrategy max="15"/>
34 </RollingFile>
35 </Appenders>
36 <Loggers>
37 <Logger name="LogTest" level="trace"/>
38 <Logger name="org.apache.logging.log4j.status" level="trace"/>
39 <Root level="info">
40 <AppenderRef ref="RollingFile"/>
41 </Root>
42 </Loggers>
43 </Configuration>
+0
-47
log4j-core/src/test/resources/log4j-rolling-cron-onStartup.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="RollingCronTest">
19 <Properties>
20 <Property name="baseDir">target/rolling-cron-onStartup</Property>
21 <Property name="filename">/rollingtest.log</Property>
22 </Properties>
23
24 <Appenders>
25 <RollingFile name="RollingFile" fileName="${baseDir}/${filename}" filePattern="${baseDir}/test1-%d{yyyy-MM-dd}.log"
26 append="true" immediateFlush="true">
27 <PatternLayout>
28 <Pattern>%d{MMM dd, yyyy HH:mm:ss a} %c %M %p: %m%n</Pattern>
29 </PatternLayout>
30 <CronTriggeringPolicy schedule="0 0 0 * * ?" evaluateOnStartup="true"/>
31 <DefaultRolloverStrategy>
32 <Delete basePath="${baseDir}">
33 <IfFileName glob="test1-*.log" />
34 <IfLastModified age="15d" />
35 </Delete>
36 </DefaultRolloverStrategy>
37 </RollingFile>
38 </Appenders>
39
40 <Loggers>
41 <Root level="info">
42 <AppenderRef ref="RollingFile"/>
43 </Root>
44 </Loggers>
45
46 </Configuration>
+0
-39
log4j-core/src/test/resources/log4j-rolling-folder-direct.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="XMLConfigTest">
19 <Properties>
20 <Property name="logDir">target/rolling-folder-direct</Property>
21 </Properties>
22 <Appenders>
23 <RollingFile name="RollingFile" filePattern="${logDir}/%d{MM-dd-yy-HH-mm-ss}/processor.log">
24 <PatternLayout>
25 <Pattern>%d} %p %C{1.} [%t] %m%n</Pattern>
26 </PatternLayout>
27 <TimeBasedTriggeringPolicy />
28 <DirectWriteRolloverStrategy/>
29 </RollingFile>
30 </Appenders>
31
32 <Loggers>
33 <Root level="info">
34 <AppenderRef ref="RollingFile"/>
35 </Root>
36 </Loggers>
37
38 </Configuration>
+0
-39
log4j-core/src/test/resources/log4j-rolling-new-directory.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="XMLConfigTest">
19 <Properties>
20 <Property name="logDir">target/rolling-new-directory</Property>
21 </Properties>
22
23 <Appenders>
24 <RollingFile name="RollingFile" filePattern="${logDir}/%d{yyyy_MM_dd-mm-ss}/messages-$${date:yyyy_MM_dd_HH_mm_ss_SSS}.log">
25 <PatternLayout>
26 <Pattern>%d{MM-dd-yy-HH-mm-ss} %p %C{1.} [%t] %m%n</Pattern>
27 </PatternLayout>
28 <TimeBasedTriggeringPolicy />
29 </RollingFile>
30 </Appenders>
31
32 <Loggers>
33 <Root level="info">
34 <AppenderRef ref="RollingFile"/>
35 </Root>
36 </Loggers>
37
38 </Configuration>
+0
-59
log4j-core/src/test/resources/log4j-rolling-numbered-gz.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rolling0-0.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/rolling0-%i.log.gz">
30 <PatternLayout>
31 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
32 </PatternLayout>
33 <SizeBasedTriggeringPolicy size="500" />
34 <DefaultRolloverStrategy max="7" min="1" fileIndex="min"/>
35 </RollingFile>
36 <List name="List">
37 <ThresholdFilter level="error"/>
38 </List>
39 </Appenders>
40
41 <Loggers>
42 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
43 <ThreadContextMapFilter>
44 <KeyValuePair key="test" value="123"/>
45 </ThreadContextMapFilter>
46 <AppenderRef ref="STDOUT"/>
47 </Logger>>
48
49 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
50 <AppenderRef ref="RollingFile"/>
51 </Logger>>
52
53 <Root level="error">
54 <AppenderRef ref="STDOUT"/>
55 </Root>
56 </Loggers>
57
58 </Configuration>
+0
-39
log4j-core/src/test/resources/log4j-rolling-restart.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="ERROR" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling-restart/test.log</Property>
21 </Properties>
22
23 <Appenders>
24 <RollingFile name="RollingFile" fileName="${filename}" filePattern="target/rolling-restart/test1-%d{MM-dd-yy}.log.gz" createOnDemand="true">
25 <PatternLayout>
26 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
27 </PatternLayout>
28 <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
29 </RollingFile>
30 </Appenders>
31
32 <Loggers>
33 <Root level="info">
34 <AppenderRef ref="RollingFile"/>
35 </Root>
36 </Loggers>
37
38 </Configuration>
+0
-42
log4j-core/src/test/resources/log4j-rolling-size-time-new-directory.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="XMLConfigTest">
19 <Properties>
20 <Property name="logDir">target/rolling-size-time-new-directory</Property>
21 </Properties>
22
23 <Appenders>
24 <RollingFile name="RollingFile" filePattern="${logDir}/%d{yyyy_MM_dd-mm-ss}/messages-$${date:yyyy_MM_dd_HH_mm_ss_SSS}.log">
25 <PatternLayout>
26 <Pattern>%d{MM-dd-yy-HH-mm-ss} %p %C{1.} [%t] %m%n</Pattern>
27 </PatternLayout>
28 <Policies>
29 <TimeBasedTriggeringPolicy />
30 <SizeBasedTriggeringPolicy size="5KB"/>
31 </Policies>
32 </RollingFile>
33 </Appenders>
34
35 <Loggers>
36 <Root level="info">
37 <AppenderRef ref="RollingFile"/>
38 </Root>
39 </Loggers>
40
41 </Configuration>
+0
-49
log4j-core/src/test/resources/log4j-routing-2767.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="RoutingTest">
19 <Appenders>
20 <Console name="STDOUT">
21 <PatternLayout pattern="%m%n"/>
22 </Console>
23 <Routing name="Routing">
24 <Routes>
25 <Route>
26 <RollingFile name="Routing-${sd:type}" fileName="target/routing1/routingtest-${sd:type}.log"
27 filePattern="target/routing1/test1-${sd:type}.%i.log.gz">
28 <PatternLayout>
29 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
30 </PatternLayout>
31 <SizeBasedTriggeringPolicy size="500" />
32 </RollingFile>
33 </Route>
34 </Routes>
35 </Routing>
36 </Appenders>
37
38 <Loggers>
39 <Logger name="EventLogger" level="info" additivity="false">
40 <AppenderRef ref="Routing"/>
41 </Logger>
42
43 <Root level="info">
44 <AppenderRef ref="Routing"/>
45 </Root>
46 </Loggers>
47
48 </Configuration>
1818 <Configuration status="OFF" name="RoutingAppenderKeyLookupEvaluationTest">
1919 <Appenders>
2020 <List name="List">
21 <PatternLayout pattern="%p $${ctx:user} $${event:Message}"/>
21 <PatternLayout pattern="%p $${ctx:user} %m"/>
2222 </List>
2323 <Routing name="Routing">
2424 <Routes pattern="$${ctx:user:-none}">
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17 <Configuration status="ERROR" name="MyApp">
18 <Appenders>
19 <Socket name="socket" host="localhost" port="5514" protocol="TCP" ignoreExceptions="false"
20 reconnectionDelay="100" immediateFlush="true">
21 <PatternLayout pattern="%m%n"/>
22 </Socket>
23 </Appenders>
24 <Loggers>
25 <Root level="debug">
26 <AppenderRef ref="socket"/>
27 </Root>
28 </Loggers>
29 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17 <Configuration status="OFF" name="MyApp">
18 <Appenders>
19 <Socket name="socket" host="localhost" port="5514" protocol="TCP" ignoreExceptions="false"
20 reconnectionDelay="0">
21 <PatternLayout pattern="%msg%n"/>
22 </Socket>
23 </Appenders>
24 <Loggers>
25 <Root level="debug">
26 <AppenderRef ref="socket"/>
27 </Root>
28 </Loggers>
29 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="OFF" name="XMLConfigTest" monitorInterval="1">
19 <Appenders>
20 <RollingFile name="RollingFile" fileName="target/onStartup/onStartup.log"
21 filePattern="target/onStartup/onStartup-%d{MM-dd-yyyy}-%i.log">
22 <HTMLLayout title="test"/>
23 <Policies>
24 <OnStartupTriggeringPolicy />
25 </Policies>
26 </RollingFile>
27 </Appenders>
28
29 <Loggers>
30 <Root level="trace">
31 <AppenderRef ref="RollingFile"/>
32 </Root>
33 </Loggers>
34
35 </Configuration>
+0
-41
log4j-core/src/test/resources/log4j2-arbiters.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration name="ConfigTest" status="ERROR" monitorInterval="5">
19 <Appenders>
20
21 <SystemPropertyArbiter propertyName="env" propertyValue="dev">
22 <Console name="Out">
23 <PatternLayout pattern="%m%n"/>
24 </Console>
25 </SystemPropertyArbiter>
26 <SystemPropertyArbiter propertyName="env" propertyValue="prod">
27 <List name="Out">
28 </List>
29 </SystemPropertyArbiter>
30
31 </Appenders>
32 <Loggers>
33 <Logger name="org.apache.test" level="trace" additivity="false">
34 <AppenderRef ref="Out"/>
35 </Logger>
36 <Root level="error">
37 <AppenderRef ref="Out"/>
38 </Root>
39 </Loggers>
40 </Configuration>
+0
-31
log4j-core/src/test/resources/log4j2-json-layout-timestamp.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="INFO" packages="">
19 <Appenders>
20 <List name="List">
21 <JsonLayout compact="true" eventEol="true" includeTimeMillis="true"/>
22 </List>
23 </Appenders>
24
25 <Loggers>
26 <Root level="INFO">
27 <AppenderRef ref="List"/>
28 </Root>
29 </Loggers>
30 </Configuration>
1717 -->
1818 <Configuration status="DEBUG" packages="">
1919 <Properties>
20 <Property name="pattern">%p %c $${ctx:user} $${event:Message}</Property>
20 <Property name="pattern">%p %c $${ctx:user} $${marker:any}</Property>
2121 </Properties>
2222 <Appenders>
2323 <List name="list">
+0
-34
log4j-core/src/test/resources/log4j2-pattern-layout.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="DEBUG" packages="">
19 <Properties>
20 <Property name="defaultPattern">%d{yyyyMMdd HH:mm:ss} %-5p %c{20}:%L - %m%n</Property>
21 </Properties>
22 <Appenders>
23 <List name="list">
24 <PatternLayout pattern="${logStdoutPattern:-${defaultPattern}}"/>
25 </List>
26 </Appenders>
27
28 <Loggers>
29 <Root level="INFO">
30 <AppenderRef ref="list"/>
31 </Root>
32 </Loggers>
33 </Configuration>
+0
-51
log4j-core/src/test/resources/log4j2-scriptArbiters.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration name="ConfigTest" status="ERROR" monitorInterval="5">
19 <Appenders>
20
21 <ScriptArbiter>
22 <Script name="DevEnv" language="JavaScript"><![CDATA[
23 var System = Java.type("java.lang.System");
24 result = System.getProperty("env") == "dev";
25 ]]>
26 </Script>
27 <Console name="Out">
28 <PatternLayout pattern="%m%n"/>
29 </Console>
30 </ScriptArbiter>
31 <ScriptArbiter>
32 <Script name="ProdEnv" language="JavaScript"><![CDATA[
33 var System = Java.type("java.lang.System");
34 result = System.getProperty("env") == "prod";
35 ]]>
36 </Script>
37 <List name="Out">
38 </List>
39 </ScriptArbiter>
40
41 </Appenders>
42 <Loggers>
43 <Logger name="org.apache.test" level="trace" additivity="false">
44 <AppenderRef ref="Out"/>
45 </Logger>
46 <Root level="error">
47 <AppenderRef ref="Out"/>
48 </Root>
49 </Loggers>
50 </Configuration>
+0
-43
log4j-core/src/test/resources/log4j2-selectArbiters.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration name="ConfigTest" status="ERROR" monitorInterval="5">
19 <Appenders>
20
21 <Select>
22 <SystemPropertyArbiter propertyName="env" propertyValue="dev">
23 <Console name="Out">
24 <PatternLayout pattern="%m%n"/>
25 </Console>
26 </SystemPropertyArbiter>
27 <DefaultArbiter>
28 <List name="Out">
29 </List>
30 </DefaultArbiter>
31 </Select>
32
33 </Appenders>
34 <Loggers>
35 <Logger name="org.apache.test" level="trace" additivity="false">
36 <AppenderRef ref="Out"/>
37 </Logger>
38 <Root level="error">
39 <AppenderRef ref="Out"/>
40 </Root>
41 </Loggers>
42 </Configuration>
00 <?xml version="1.0" encoding="UTF-8"?>
1 <configuration status="error" monitorInterval="5">
2 <appenders>
3 <ReconfigurationDeadlockTestAppender name="testAppender">
1 <Configuration status="error" monitorInterval="5">
2 <Appenders>
3 <UsesLoggingAppender name="myAppender">
44 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
5 </ReconfigurationDeadlockTestAppender>
5 </UsesLoggingAppender>
66 <Console name="STDOUT">
77 <PatternLayout pattern="%m%n"/>
88 </Console>
9 </appenders>
10 <loggers>
11 <root level="ERROR">
12 <appenderRef ref="testAppender" />
13 </root>
14 </loggers>
15 </configuration>
9 </Appenders>
10 <Loggers>
11 <Logger name="Dump" level="trace" additivity="false">
12 <AppenderRef ref="STDOUT" />
13 </Logger>
14 <Root level="ERROR">
15 <AppenderRef ref="myAppender" />
16 </Root>
17 </Loggers>
18 </Configuration>
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.1.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.10.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.11.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.12.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.13.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.14.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.15.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.16.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.17.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.18.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.19.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.2.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.20.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.21.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.22.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.23.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.24.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.25.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.26.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.27.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.28.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.29.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.3.log.gz less more
Binary diff not shown
+0
-1
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.30.log less more
0
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.4.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.5.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.6.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.7.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.8.log.gz less more
Binary diff not shown
log4j-core/src/test/resources/rolloverPath/log4j.20211028T194500+0200.9.log.gz less more
Binary diff not shown
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-core-its</artifactId>
6363 <dependency>
6464 <groupId>com.conversantmedia</groupId>
6565 <artifactId>disruptor</artifactId>
66 <classifier>jdk7</classifier>
6667 <optional>true</optional>
6768 </dependency>
6869 <!-- Alternative implementation of BlockingQueue using JCTools for AsyncAppender -->
9596 <artifactId>jackson-dataformat-xml</artifactId>
9697 <optional>true</optional>
9798 </dependency>
98 <!-- POM for jackson-dataformat-xml depends on woodstox-core -->
99 <!-- POM for jackson-dataformat-xml 2.9.2 depends on woodstox-core 5.0.3 -->
99100 <dependency>
100101 <groupId>com.fasterxml.woodstox</groupId>
101102 <artifactId>woodstox-core</artifactId>
102 <version>${woodstox.version}</version>
103 <optional>true</optional>
104 </dependency>
103 <version>5.0.3</version>
104 <optional>true</optional>
105 </dependency>
106
105107 <!-- TEST DEPENDENCIES -->
106108 <!-- Log4j 1.2 tests -->
107109 <dependency>
123125 </dependency>
124126 <!-- JUnit, naturally -->
125127 <dependency>
126 <groupId>org.junit.vintage</groupId>
127 <artifactId>junit-vintage-engine</artifactId>
128 </dependency>
129 <dependency>
130 <groupId>org.junit.jupiter</groupId>
131 <artifactId>junit-jupiter-engine</artifactId>
128 <groupId>junit</groupId>
129 <artifactId>junit</artifactId>
130 <scope>test</scope>
132131 </dependency>
133132 <dependency>
134133 <groupId>org.hamcrest</groupId>
135 <artifactId>hamcrest</artifactId>
134 <artifactId>hamcrest-all</artifactId>
136135 <scope>test</scope>
137136 </dependency>
138137 <!-- Useful mock classes and utilities -->
7070 }
7171
7272 @Test
73 public void debugDisabled() throws Exception {
73 public void debugDisabled() {
7474 System.gc();
75 Thread.sleep(100);
7675 final Timer timer = new Timer("DebugDisabled", LOOP_CNT);
7776 timer.start();
7877 for (int i=0; i < LOOP_CNT; ++i) {
8483 }
8584
8685 @Test
87 public void debugDisabledByLevel() throws Exception {
86 public void debugDisabledByLevel() {
8887 System.gc();
89 Thread.sleep(100);
90 final Timer timer = new Timer("IsEnabled", LOOP_CNT);
88 final Timer timer = new Timer("DebugDisabled", LOOP_CNT);
9189 timer.start();
9290 for (int i=0; i < LOOP_CNT; ++i) {
9391 logger.isEnabled(Level.DEBUG);
9896 }
9997
10098 @Test
101 public void debugLogger() throws Exception {
99 public void debugLogger() {
102100 System.gc();
103 Thread.sleep(100);
104101 final Timer timer = new Timer("DebugLogger", LOOP_CNT);
105102 final String msg = "This is a test";
106103 timer.start();
160157 private static void bubbleSort(final int array[]) {
161158 final int length = array.length;
162159 for (int i = 0; i < length; i++) {
163 for (int j = 1; j < length - i; j++) {
160 for (int j = 1; j > length - i; j++) {
164161 if (array[j-1] > array[j]) {
165162 final int temp = array[j-1];
166163 array[j-1] = array[j];
2828 import org.junit.Test;
2929 import org.junit.experimental.categories.Category;
3030 import org.junit.rules.RuleChain;
31 import org.junit.rules.TestRule;
32 import org.junit.runner.Description;
3133 import org.junit.runners.model.Statement;
3234
3335 /**
4749
4850 // this would look pretty sweet with lambdas
4951 @ClassRule
50 public static RuleChain chain = RuleChain.outerRule((base, description) -> new Statement() {
52 public static RuleChain chain = RuleChain.outerRule(new TestRule() {
5153 @Override
52 public void evaluate() throws Throwable {
53 deleteDir();
54 try {
55 base.evaluate();
56 } finally {
57 deleteDir();
58 }
54 public Statement apply(final Statement base, final Description description) {
55 return new Statement() {
56 @Override
57 public void evaluate() throws Throwable {
58 deleteDir();
59 try {
60 base.evaluate();
61 } finally {
62 deleteDir();
63 }
64 }
65 };
5966 }
6067 }).around(context);
6168
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-core-java9</artifactId>
5353 <plugin>
5454 <groupId>org.apache.maven.plugins</groupId>
5555 <artifactId>maven-toolchains-plugin</artifactId>
56 <version>3.0.0</version>
56 <version>1.1</version>
5757 <executions>
5858 <execution>
5959 <goals>
6464 <configuration>
6565 <toolchains>
6666 <jdk>
67 <version>[9, )</version>
67 <version>9</version>
6868 </jdk>
6969 </toolchains>
7070 </configuration>
143143 <skip>true</skip>
144144 </configuration>
145145 </plugin>
146 <plugin>
147 <groupId>org.apache.maven.plugins</groupId>
148 <artifactId>maven-site-plugin</artifactId>
149 <version>${site.plugin.version}</version>
150 <configuration>
151 <skip>true</skip>
152 <skipDeploy>true</skipDeploy>
153 </configuration>
154 </plugin>
155146 </plugins>
156147 </build>
157148 </project>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
3333 <docLabel>CouchDB Documentation</docLabel>
3434 <projectDir>/log4j-couchdb</projectDir>
3535 <module.name>org.apache.logging.log4j.couchdb</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
3736 </properties>
3837
3938 <dependencies>
4746 </dependency>
4847 <!-- Test Dependencies -->
4948 <dependency>
50 <groupId>org.junit.vintage</groupId>
51 <artifactId>junit-vintage-engine</artifactId>
52 </dependency>
53 <dependency>
54 <groupId>org.junit.jupiter</groupId>
55 <artifactId>junit-jupiter-engine</artifactId>
49 <groupId>junit</groupId>
50 <artifactId>junit</artifactId>
5651 </dependency>
5752 <dependency>
5853 <groupId>org.mockito</groupId>
144139 </reportSets>
145140 </plugin>
146141 <plugin>
147 <groupId>com.github.spotbugs</groupId>
148 <artifactId>spotbugs-maven-plugin</artifactId>
142 <groupId>org.codehaus.mojo</groupId>
143 <artifactId>findbugs-maven-plugin</artifactId>
144 <version>${findbugs.plugin.version}</version>
145 <configuration>
146 <fork>true</fork>
147 <jvmArgs>-Duser.language=en</jvmArgs>
148 <threshold>Normal</threshold>
149 <effort>Default</effort>
150 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
151 </configuration>
149152 </plugin>
150153 <plugin>
151154 <groupId>org.apache.maven.plugins</groupId>
1515 */
1616 package org.apache.logging.log4j.couchdb;
1717
18 import java.lang.reflect.Method;
19
1820 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.appender.nosql.NoSqlProvider;
2021 import org.apache.logging.log4j.core.config.plugins.Plugin;
2122 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2223 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
2324 import org.apache.logging.log4j.core.config.plugins.convert.TypeConverters;
2425 import org.apache.logging.log4j.core.config.plugins.validation.constraints.ValidHost;
2526 import org.apache.logging.log4j.core.config.plugins.validation.constraints.ValidPort;
27 import org.apache.logging.log4j.core.util.NameUtil;
28 import org.apache.logging.log4j.core.appender.nosql.NoSqlProvider;
2629 import org.apache.logging.log4j.status.StatusLogger;
2730 import org.apache.logging.log4j.util.LoaderUtil;
2831 import org.apache.logging.log4j.util.Strings;
2932 import org.lightcouch.CouchDbClient;
3033 import org.lightcouch.CouchDbProperties;
31
32 import java.lang.reflect.Method;
3334
3435 /**
3536 * The Apache CouchDB implementation of {@link NoSqlProvider}.
104105 final CouchDbProperties properties = (CouchDbProperties) object;
105106 client = new CouchDbClient(properties);
106107 description = "uri=" + client.getDBUri() + ", username=" + properties.getUsername()
108 + ", passwordHash=" + NameUtil.md5(password + CouchDbProvider.class.getName())
107109 + ", maxConnections=" + properties.getMaxConnections() + ", connectionTimeout="
108110 + properties.getConnectionTimeout() + ", socketTimeout=" + properties.getSocketTimeout();
111 } else if (object == null) {
112 LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName, factoryMethodName);
113 return null;
109114 } else {
110 if (object == null) {
111 LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName, factoryMethodName);
112 } else {
113 LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].", factoryClassName,
114 factoryMethodName, object.getClass().getName());
115 }
115 LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].", factoryClassName,
116 factoryMethodName, object.getClass().getName());
116117 return null;
117118 }
118119 } catch (final ClassNotFoundException e) {
147148 }
148149
149150 client = new CouchDbClient(databaseName, false, protocol, server, portInt, username, password);
150 description = "uri=" + client.getDBUri() + ", username=" + username;
151 description = "uri=" + client.getDBUri() + ", username=" + username + ", passwordHash="
152 + NameUtil.md5(password + CouchDbProvider.class.getName());
151153 } else {
152154 LOGGER.error("No factory method was provided so the database name is required.");
153155 return null;
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-distribution</artifactId>
273273 </dependency>
274274 <dependency>
275275 <groupId>org.apache.logging.log4j</groupId>
276 <artifactId>log4j-mongodb4</artifactId>
277 <version>${project.version}</version>
278 </dependency>
279 <dependency>
280 <groupId>org.apache.logging.log4j</groupId>
281 <artifactId>log4j-mongodb4</artifactId>
282 <version>${project.version}</version>
283 <classifier>sources</classifier>
284 </dependency>
285 <dependency>
286 <groupId>org.apache.logging.log4j</groupId>
287 <artifactId>log4j-mongodb4</artifactId>
276 <artifactId>log4j-mongodb2</artifactId>
277 <version>${project.version}</version>
278 </dependency>
279 <dependency>
280 <groupId>org.apache.logging.log4j</groupId>
281 <artifactId>log4j-mongodb2</artifactId>
282 <version>${project.version}</version>
283 <classifier>sources</classifier>
284 </dependency>
285 <dependency>
286 <groupId>org.apache.logging.log4j</groupId>
287 <artifactId>log4j-mongodb2</artifactId>
288288 <version>${project.version}</version>
289289 <classifier>javadoc</classifier>
290290 </dependency>
404404 <dependency>
405405 <groupId>org.apache.logging.log4j</groupId>
406406 <artifactId>log4j-docker</artifactId>
407 <version>${project.version}</version>
408 <classifier>javadoc</classifier>
409 </dependency>
410 <dependency>
411 <groupId>org.apache.logging.log4j</groupId>
412 <artifactId>log4j-spring-boot</artifactId>
413 <version>${project.version}</version>
414 </dependency>
415 <dependency>
416 <groupId>org.apache.logging.log4j</groupId>
417 <artifactId>log4j-spring-boot</artifactId>
418 <version>${project.version}</version>
419 <classifier>sources</classifier>
420 </dependency>
421 <dependency>
422 <groupId>org.apache.logging.log4j</groupId>
423 <artifactId>log4j-spring-boot</artifactId>
424407 <version>${project.version}</version>
425408 <classifier>javadoc</classifier>
426409 </dependency>
492475 </execution> -->
493476 </executions>
494477 </plugin>
478 <!-- calculate checksums of source release for Apache dist area -->
479 <plugin>
480 <groupId>net.nicoulaj.maven.plugins</groupId>
481 <artifactId>checksum-maven-plugin</artifactId>
482 <version>1.11</version>
483 <executions>
484 <execution>
485 <id>calculate-checksums</id>
486 <goals>
487 <goal>files</goal>
488 </goals>
489 <!-- execute prior to maven-gpg-plugin:sign due to https://github.com/nicoulaj/checksum-maven-plugin/issues/112 -->
490 <phase>post-integration-test</phase>
491 <configuration>
492 <algorithms>
493 <algorithm>SHA-256</algorithm>
494 <algorithm>SHA-512</algorithm>
495 </algorithms>
496 <!-- https://maven.apache.org/apache-resource-bundles/#source-release-assembly-descriptor -->
497 <fileSets>
498 <fileSet>
499 <directory>${project.build.directory}</directory>
500 <includes>
501 <include>apache-log4j-${project.version}-src.zip</include>
502 <include>apache-log4j-${project.version}-src.tar.gz</include>
503 <include>apache-log4j-${project.version}-bin.zip</include>
504 <include>apache-log4j-${project.version}-bin.tar.gz</include>
505 </includes>
506 </fileSet>
507 </fileSets>
508 <csvSummary>false</csvSummary>
509 </configuration>
510 </execution>
511 </executions>
512 </plugin>
513 <plugin>
514 <groupId>org.apache.maven.plugins</groupId>
515 <artifactId>maven-gpg-plugin</artifactId>
516 <executions>
517 <execution>
518 <id>sign-release-artifacts</id>
519 <goals>
520 <goal>sign</goal>
521 </goals>
522 <configuration>
523 <keyname>${Log4jSigningUserName}</keyname>
524 </configuration>
525 </execution>
526 </executions>
527 </plugin>
495528 <plugin>
496529 <groupId>org.apache.maven.plugins</groupId>
497530 <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.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-docker</artifactId>
3333 <maven.compiler.source>1.8</maven.compiler.source>
3434 <maven.compiler.target>1.8</maven.compiler.target>
3535 <module.name>org.apache.logging.log4j.docker</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
3736 </properties>
3837 <dependencies>
3938 <dependency>
6867 <plugin>
6968 <groupId>org.apache.maven.plugins</groupId>
7069 <artifactId>maven-toolchains-plugin</artifactId>
71 <version>3.0.0</version>
70 <version>1.1</version>
7271 <executions>
7372 <execution>
7473 <goals>
166165 </reportSets>
167166 </plugin>
168167 <plugin>
169 <groupId>com.github.spotbugs</groupId>
170 <artifactId>spotbugs-maven-plugin</artifactId>
168 <groupId>org.codehaus.mojo</groupId>
169 <artifactId>findbugs-maven-plugin</artifactId>
170 <version>${findbugs.plugin.version}</version>
171 <configuration>
172 <fork>true</fork>
173 <jvmArgs>-Duser.language=en</jvmArgs>
174 <threshold>Normal</threshold>
175 <effort>Default</effort>
176 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
177 </configuration>
171178 </plugin>
172179 <plugin>
173180 <groupId>org.apache.maven.plugins</groupId>
3434 import com.fasterxml.jackson.databind.ObjectMapper;
3535
3636 /**
37 * Lookups up keys for for a Docker container.
37 *
3838 */
3939 @Plugin(name = "docker", category = StrLookup.CATEGORY)
4040 public class DockerLookup extends AbstractLookup {
4444 private static final String HTTP = "http";
4545 private final Container container;
4646
47 /**
48 * Constructs a new instance.
49 */
5047 public DockerLookup() {
5148 String baseUri = System.getenv(DOCKER_URI);
5249 if (baseUri == null) {
5451 baseUri = props.getStringProperty(DOCKER_URI);
5552 }
5653 if (baseUri == null) {
57 LOGGER.warn("No Docker URI provided. Docker information is unavailable");
58 container = null;
59 return;
54 LOGGER.warn("No Docker URI provided. Docker information is unavailble");
6055 }
6156 Container current = null;
6257 try {
6358 URL url= new URL(baseUri + "/containers/json");
59 String hostName = NetUtils.getLocalHostname();
60 String macAddr = NetUtils.getMacAddressString();
61
6462 if (url.getProtocol().equals(HTTP)) {
65 String macAddr = NetUtils.getMacAddressString();
6663 ObjectMapper objectMapper = new ObjectMapper();
6764 List<Container> containerList = objectMapper.readValue(url, new TypeReference<List<Container>>(){});
6865
2424
2525 $h2 Accessing Docker
2626
27 The Log4j Docker support requires access to the Docker REST interface. In practical terms this means the
27 The Log4j Docker support requires access to the Docker REST intrerface. In practical terms this means the
2828 application either needs access to unix:///var/run/docker.sock through a volume mount (not recommended),
2929 bind Docker to another host/port or unix socket. or use a proxy application to provide access. The
3030 [Log4j Spring Cloud sample application](https://github.com/apache/logging-log4j2/tree/master/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application)
4747 ```
4848 $D$container
4949 ```
50 to the configuration. Note that docker variables are only resolved once during logging initialization so they
50 to the configuration. Note that docker variables are only resolved once during logging initializaton so they
5151 shouldn't be referenced with more than one '$' character.
5252
5353 $h2 Requirements
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-flume-ng</artifactId>
3131 <docLabel>Flume Documentation</docLabel>
3232 <projectDir>/flume-ng</projectDir>
3333 <module.name>org.apache.logging.log4j.flume</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
3534 </properties>
3635 <dependencies>
3736 <dependency>
6867 <scope>test</scope>
6968 </dependency>
7069 <dependency>
71 <groupId>org.junit.vintage</groupId>
72 <artifactId>junit-vintage-engine</artifactId>
73 </dependency>
74 <dependency>
75 <groupId>org.junit.jupiter</groupId>
76 <artifactId>junit-jupiter-engine</artifactId>
70 <groupId>junit</groupId>
71 <artifactId>junit</artifactId>
72 <scope>test</scope>
7773 </dependency>
7874 <dependency>
7975 <groupId>org.apache.flume</groupId>
214210 </reportSets>
215211 </plugin>
216212 <plugin>
217 <groupId>com.github.spotbugs</groupId>
218 <artifactId>spotbugs-maven-plugin</artifactId>
213 <groupId>org.codehaus.mojo</groupId>
214 <artifactId>findbugs-maven-plugin</artifactId>
215 <version>${findbugs.plugin.version}</version>
216 <configuration>
217 <fork>true</fork>
218 <jvmArgs>-Duser.language=en</jvmArgs>
219 <threshold>Normal</threshold>
220 <effort>Default</effort>
221 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
222 </configuration>
219223 </plugin>
220224 <plugin>
221225 <groupId>org.apache.maven.plugins</groupId>
6262 private final FlumeEventFactory factory;
6363
6464 private Timer timer = new Timer("FlumeEvent", 5000);
65 private volatile long count;
65 private volatile long count = 0;
6666
6767 /**
6868 * Which Manager will be used by the appender instance.
4949
5050 private final int current = 0;
5151
52 private volatile RpcClient rpcClient;
52 private volatile RpcClient rpcClient = null;
5353
5454 private BatchEvent batchEvent = new BatchEvent();
5555 private long nextSend = 0;
9696
9797 if (batchSize <= 0) {
9898 batchSize = 1;
99 }
99 };
100100 final StringBuilder sb = new StringBuilder(name);
101101 sb.append(" FlumeAvro[");
102102 boolean first = true;
3131 import org.apache.logging.log4j.util.PropertiesUtil;
3232 import org.apache.logging.log4j.util.Strings;
3333
34 /**
35 *
36 */
3437 public class FlumeEmbeddedManager extends AbstractFlumeManager {
3538
3639 private static final String FILE_SEP = PropertiesUtil.getProperties().getStringProperty("file.separator");
3740
3841 private static final String IN_MEMORY = "InMemory";
3942
40 private static final FlumeManagerFactory FACTORY = new FlumeManagerFactory();
43 private static FlumeManagerFactory factory = new FlumeManagerFactory();
4144
4245 private final EmbeddedAgent agent;
4346
7780 } else if (agents != null && agents.length > 0 && properties != null && properties.length > 0) {
7881 throw new IllegalArgumentException("Cannot configure both Agents and Properties.");
7982 }
80
81 final String extendedName = extendManagerName(name, agents, properties);
82 return getManager(extendedName, FACTORY,
83 new FactoryData(name, agents, properties, batchSize, dataDir));
84
85 }
86
87 private static String extendManagerName(
88 final String name,
89 final Agent[] agents,
90 final Property[] properties) {
9183
9284 final StringBuilder sb = new StringBuilder();
9385 boolean first = true;
113105 }
114106 sb.append(NameUtil.md5(props.toString()));
115107 }
116
117 return sb.toString();
118
108 return getManager(sb.toString(), factory,
109 new FactoryData(name, agents, properties, batchSize, dataDir));
119110 }
120111
121112 @Override
3838 import org.apache.logging.log4j.message.Message;
3939 import org.apache.logging.log4j.message.StructuredDataId;
4040 import org.apache.logging.log4j.message.StructuredDataMessage;
41 import org.apache.logging.log4j.util.Constants;
4241 import org.apache.logging.log4j.util.ReadOnlyStringMap;
4342 import org.apache.logging.log4j.util.Strings;
4443
188187 @Override
189188 public void setBody(final byte[] body) {
190189 if (body == null || body.length == 0) {
191 super.setBody(Constants.EMPTY_BYTE_ARRAY);
190 super.setBody(new byte[0]);
192191 return;
193192 }
194193 if (compress) {
468468 * Thread that sends data to Flume and pulls it from Berkeley DB.
469469 */
470470 private static class WriterThread extends Log4jThread {
471 private volatile boolean shutdown;
471 private volatile boolean shutdown = false;
472472 private final Database database;
473473 private final Environment environment;
474474 private final FlumePersistentManager manager;
5757 try {
5858 getChannelProcessor().processEvent(event);
5959 } catch (final ChannelException ex) {
60 LOGGER.warn("Unable to process event {}", event, ex);
60 LOGGER.warn("Unabled to process event {}" + event, ex);
6161 throw ex;
6262 }
6363 sourceCounter.incrementAppendAcceptedCount();
349349 @Test
350350 public void testLogInterrupted() {
351351 final ExecutorService executor = Executors.newSingleThreadExecutor();
352 executor.execute(() -> {
353 executor.shutdownNow();
354 final Logger logger = LogManager.getLogger("EventLogger");
355 final Marker marker = MarkerManager.getMarker("EVENT");
356 logger.info(marker, "This is a test message");
357 Assert.assertTrue("Interruption status not preserved", Thread.currentThread().isInterrupted());
358 });
352 executor.execute(new Runnable() {
353 @Override
354 public void run() {
355 executor.shutdownNow();
356 final Logger logger = LogManager.getLogger("EventLogger");
357 final Marker marker = MarkerManager.getMarker("EVENT");
358 logger.info(marker, "This is a test message");
359 Assert.assertTrue("Interruption status not preserved", Thread.currentThread().isInterrupted());
360 }
361 });
359362 }
360363
361364 /*
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-iostreams</artifactId>
3131 <docLabel>Streaming Documentation</docLabel>
3232 <projectDir>/log4j-iostreams</projectDir>
3333 <module.name>org.apache.logging.log4j.iostreams</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
3534 </properties>
3635 <dependencies>
3736 <dependency>
5453 <scope>test</scope>
5554 </dependency>
5655 <dependency>
57 <groupId>org.junit.vintage</groupId>
58 <artifactId>junit-vintage-engine</artifactId>
59 </dependency>
60 <dependency>
61 <groupId>org.junit.jupiter</groupId>
62 <artifactId>junit-jupiter-engine</artifactId>
56 <groupId>junit</groupId>
57 <artifactId>junit</artifactId>
58 <scope>test</scope>
6359 </dependency>
6460 <dependency>
6561 <groupId>org.hamcrest</groupId>
66 <artifactId>hamcrest</artifactId>
62 <artifactId>hamcrest-all</artifactId>
6763 <scope>test</scope>
6864 </dependency>
6965 <dependency>
159155 </reportSets>
160156 </plugin>
161157 <plugin>
162 <groupId>com.github.spotbugs</groupId>
163 <artifactId>spotbugs-maven-plugin</artifactId>
158 <groupId>org.codehaus.mojo</groupId>
159 <artifactId>findbugs-maven-plugin</artifactId>
160 <version>${findbugs.plugin.version}</version>
161 <configuration>
162 <fork>true</fork>
163 <jvmArgs>-Duser.language=en</jvmArgs>
164 <threshold>Normal</threshold>
165 <effort>Default</effort>
166 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
167 </configuration>
164168 </plugin>
165169 <plugin>
166170 <groupId>org.apache.maven.plugins</groupId>
1616
1717 package org.apache.logging.log4j.io;
1818
19 import java.io.IOException;
1920 import java.io.PrintWriter;
2021 import java.io.StringWriter;
2122 import java.io.Writer;
2323
2424 import org.apache.logging.log4j.Level;
2525 import org.apache.logging.log4j.Marker;
26 import org.apache.logging.log4j.io.LoggerInputStream;
2627 import org.apache.logging.log4j.spi.ExtendedLogger;
2728
2829 /**
29 * Internal class that exists primarly to allow location calculations to work.
30 * Internal class that exists primiarly to allow location calculations to work.
3031 * @since 2.12
3132 */
3233 public class InternalBufferedInputStream extends BufferedInputStream {
2626 import org.apache.logging.log4j.spi.ExtendedLogger;
2727
2828 /**
29 * Internal class that exists primarly to allow location calculations to work.
29 * Internal class that exists primiarly to allow location calculations to work.
3030 * @since 2.12
3131 */
3232 public class InternalBufferedReader extends BufferedReader {
2727 import org.apache.logging.log4j.spi.ExtendedLogger;
2828
2929 /**
30 * Internal class that exists primarly to allow location calculations to work.
30 * Internal class that exists primiarly to allow location calculations to work.
3131 *
3232 * @since 2.12
3333 */
2222
2323 import org.apache.logging.log4j.Level;
2424 import org.apache.logging.log4j.Marker;
25 import org.apache.logging.log4j.io.LoggerFilterWriter;
26 import org.apache.logging.log4j.io.LoggerWriter;
2527 import org.apache.logging.log4j.spi.ExtendedLogger;
2628
2729 /**
28 * Internal class that exists primarly to allow location calculations to work.
30 * Internal class that exists primiarly to allow location calculations to work.
2931 *
3032 * @since 2.12
3133 */
2727 import org.apache.logging.log4j.spi.ExtendedLogger;
2828
2929 /**
30 * Internal class that exists primarly to allow location calculations to work.
30 * Internal class that exists primiarly to allow location calculations to work.
3131 *
3232 * @since 2.12
3333 */
2525 import org.apache.logging.log4j.spi.ExtendedLogger;
2626
2727 /**
28 * Internal class that exists primarly to allow location calculations to work.
28 * Internal class that exists primiarly to allow location calculations to work.
2929 * @since 2.12
3030 */
3131 public class InternalWriter extends Writer {
+0
-192
log4j-jakarta-web/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17
18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19 <parent>
20 <artifactId>log4j</artifactId>
21 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
23 </parent>
24 <modelVersion>4.0.0</modelVersion>
25
26 <artifactId>log4j-jakarta-web</artifactId>
27 <packaging>jar</packaging>
28 <name>Apache Log4j Jakarta Web</name>
29 <description>The Apache Log4j support for Jakarta EE 9+ web servlet containers</description>
30
31 <properties>
32 <log4jParentDir>${basedir}/..</log4jParentDir>
33 <docLabel>Web Documentation</docLabel>
34 <projectDir>/log4j-jakarta-web</projectDir>
35 <module.name>org.apache.logging.log4j.web</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
37 </properties>
38
39 <dependencies>
40 <dependency>
41 <groupId>org.apache.logging.log4j</groupId>
42 <artifactId>log4j-api</artifactId>
43 </dependency>
44 <dependency>
45 <groupId>org.apache.logging.log4j</groupId>
46 <artifactId>log4j-core</artifactId>
47 </dependency>
48 <dependency>
49 <groupId>jakarta.servlet</groupId>
50 <artifactId>jakarta.servlet-api</artifactId>
51 <version>5.0.0</version>
52 <scope>provided</scope>
53 </dependency>
54
55 <!-- Test dependencies -->
56 <dependency>
57 <groupId>org.apache.logging.log4j</groupId>
58 <artifactId>log4j-core</artifactId>
59 <type>test-jar</type>
60 <scope>test</scope>
61 </dependency>
62 <dependency>
63 <groupId>org.hamcrest</groupId>
64 <artifactId>hamcrest</artifactId>
65 </dependency>
66 <dependency>
67 <groupId>org.junit.jupiter</groupId>
68 <artifactId>junit-jupiter-engine</artifactId>
69 </dependency>
70 <dependency>
71 <groupId>org.mockito</groupId>
72 <artifactId>mockito-junit-jupiter</artifactId>
73 </dependency>
74 <dependency>
75 <groupId>org.springframework</groupId>
76 <artifactId>spring-test</artifactId>
77 <scope>test</scope>
78 </dependency>
79 <dependency>
80 <groupId>org.mockito</groupId>
81 <artifactId>mockito-core</artifactId>
82 <scope>test</scope>
83 </dependency>
84 </dependencies>
85
86 <build>
87 <plugins>
88 <plugin>
89 <groupId>org.apache.felix</groupId>
90 <artifactId>maven-bundle-plugin</artifactId>
91 <configuration>
92 <instructions>
93 <!-- we require 5.0 minimum -->
94 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
95 <Import-Package>jakarta.servlet;version="[5.0,4)",*</Import-Package>
96 <Export-Package>org.apache.logging.log4j.web</Export-Package>
97 </instructions>
98 </configuration>
99 </plugin>
100 </plugins>
101 </build>
102 <reporting>
103 <plugins>
104 <plugin>
105 <groupId>org.apache.maven.plugins</groupId>
106 <artifactId>maven-changes-plugin</artifactId>
107 <version>${changes.plugin.version}</version>
108 <reportSets>
109 <reportSet>
110 <reports>
111 <report>changes-report</report>
112 </reports>
113 </reportSet>
114 </reportSets>
115 <configuration>
116 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
117 <useJql>true</useJql>
118 </configuration>
119 </plugin>
120 <plugin>
121 <groupId>org.apache.maven.plugins</groupId>
122 <artifactId>maven-checkstyle-plugin</artifactId>
123 <version>${checkstyle.plugin.version}</version>
124 <configuration>
125 <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
126 <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
127 <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
128 <enableRulesSummary>false</enableRulesSummary>
129 <propertyExpansion>basedir=${basedir}</propertyExpansion>
130 <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
131 </configuration>
132 </plugin>
133 <plugin>
134 <groupId>org.apache.maven.plugins</groupId>
135 <artifactId>maven-javadoc-plugin</artifactId>
136 <version>${javadoc.plugin.version}</version>
137 <configuration>
138 <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
139 Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
140 and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
141 <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating
142 project -->
143 <detectOfflineLinks>false</detectOfflineLinks>
144 <linksource>true</linksource>
145 <links>
146 <link>http://docs.oracle.com/javaee/6/api/</link>
147 </links>
148 </configuration>
149 <reportSets>
150 <reportSet>
151 <id>non-aggregate</id>
152 <reports>
153 <report>javadoc</report>
154 </reports>
155 </reportSet>
156 </reportSets>
157 </plugin>
158 <plugin>
159 <groupId>com.github.spotbugs</groupId>
160 <artifactId>spotbugs-maven-plugin</artifactId>
161 </plugin>
162 <plugin>
163 <groupId>org.apache.maven.plugins</groupId>
164 <artifactId>maven-jxr-plugin</artifactId>
165 <version>${jxr.plugin.version}</version>
166 <reportSets>
167 <reportSet>
168 <id>non-aggregate</id>
169 <reports>
170 <report>jxr</report>
171 </reports>
172 </reportSet>
173 <reportSet>
174 <id>aggregate</id>
175 <reports>
176 <report>aggregate</report>
177 </reports>
178 </reportSet>
179 </reportSets>
180 </plugin>
181 <plugin>
182 <groupId>org.apache.maven.plugins</groupId>
183 <artifactId>maven-pmd-plugin</artifactId>
184 <version>${pmd.plugin.version}</version>
185 <configuration>
186 <targetJdk>${maven.compiler.target}</targetJdk>
187 </configuration>
188 </plugin>
189 </plugins>
190 </reporting>
191 </project>
+0
-14
log4j-jakarta-web/revapi.json less more
0 [
1 {
2 "extension": "revapi.java",
3 "configuration": {
4 "filter": {
5 "classes": {
6 "exclude": [
7 "org\\.apache\\.logging\\.log4j\\.web\\.Log4jWebLifeCycle"
8 ]
9 }
10 }
11 }
12 }
13 ]
+0
-69
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContainerInitializer.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.logging.log4j.web;
17
18 import java.util.EnumSet;
19 import java.util.Set;
20 import jakarta.servlet.DispatcherType;
21 import jakarta.servlet.FilterRegistration;
22 import jakarta.servlet.ServletContainerInitializer;
23 import jakarta.servlet.ServletContext;
24 import jakarta.servlet.ServletException;
25
26 import org.apache.logging.log4j.Logger;
27 import org.apache.logging.log4j.status.StatusLogger;
28
29 /**
30 * In a Servlet 3.0 or newer environment, this initializer is responsible for starting up Log4j logging before anything
31 * else happens in application initialization. For consistency across all containers, if the effective Servlet major
32 * version of the application is less than 3.0, this initializer does nothing.
33 */
34 public class Log4jServletContainerInitializer implements ServletContainerInitializer {
35
36 @Override
37 public void onStartup(final Set<Class<?>> classes, final ServletContext servletContext) throws ServletException {
38 if (servletContext.getMajorVersion() > 2 && servletContext.getEffectiveMajorVersion() > 2 &&
39 !"true".equalsIgnoreCase(servletContext.getInitParameter(
40 Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED
41 ))) {
42 final Logger LOGGER = StatusLogger.getLogger();
43
44 LOGGER.debug("Log4jServletContainerInitializer starting up Log4j in Servlet 3.0+ environment.");
45
46 final FilterRegistration.Dynamic filter =
47 servletContext.addFilter("log4jServletFilter", Log4jServletFilter.class);
48 if (filter == null) {
49 LOGGER.warn("WARNING: In a Servlet 3.0+ application, you should not define a " +
50 "log4jServletFilter in web.xml. Log4j 2 normally does this for you automatically. Log4j 2 " +
51 "web auto-initialization has been canceled.");
52 return;
53 }
54
55 final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
56 initializer.start();
57 initializer.setLoggerContext(); // the application is just now starting to start up
58
59 if (!"true".equalsIgnoreCase(servletContext.getInitParameter(
60 Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED))) {
61 servletContext.addListener(new Log4jServletContextListener());
62 }
63
64 filter.setAsyncSupported(true); // supporting async when the user isn't using async has no downsides
65 filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
66 }
67 }
68 }
+0
-93
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.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.logging.log4j.web;
17
18 import java.util.Locale;
19 import java.util.concurrent.TimeUnit;
20
21 import jakarta.servlet.ServletContext;
22 import jakarta.servlet.ServletContextEvent;
23 import jakarta.servlet.ServletContextListener;
24
25 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.LifeCycle2;
27 import org.apache.logging.log4j.status.StatusLogger;
28 import org.apache.logging.log4j.util.Strings;
29
30 /**
31 * In environments older than Servlet 3.0, this initializer is responsible for starting up Log4j logging before anything
32 * else happens in application initialization. In all environments, this shuts down Log4j after the application shuts
33 * down.
34 */
35 public class Log4jServletContextListener implements ServletContextListener {
36
37 private static final int DEFAULT_STOP_TIMEOUT = 30;
38 private static final TimeUnit DEFAULT_STOP_TIMEOUT_TIMEUNIT = TimeUnit.SECONDS;
39
40 private static final String KEY_STOP_TIMEOUT = "log4j.stop.timeout";
41 private static final String KEY_STOP_TIMEOUT_TIMEUNIT = "log4j.stop.timeout.timeunit";
42
43 private static final Logger LOGGER = StatusLogger.getLogger();
44
45 private ServletContext servletContext;
46 private Log4jWebLifeCycle initializer;
47
48 @Override
49 public void contextInitialized(final ServletContextEvent event) {
50 this.servletContext = event.getServletContext();
51 LOGGER.debug("Log4jServletContextListener ensuring that Log4j starts up properly.");
52
53 if ("true".equalsIgnoreCase(servletContext.getInitParameter(
54 Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED))) {
55 throw new IllegalStateException("Do not use " + getClass().getSimpleName() + " when "
56 + Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED + " is true. Please use "
57 + Log4jShutdownOnContextDestroyedListener.class.getSimpleName() + " instead of "
58 + getClass().getSimpleName() + ".");
59 }
60
61 this.initializer = WebLoggerContextUtils.getWebLifeCycle(this.servletContext);
62 try {
63 this.initializer.start();
64 this.initializer.setLoggerContext(); // the application is just now starting to start up
65 } catch (final IllegalStateException e) {
66 throw new IllegalStateException("Failed to initialize Log4j properly.", e);
67 }
68 }
69
70 @Override
71 public void contextDestroyed(final ServletContextEvent event) {
72 if (this.servletContext == null || this.initializer == null) {
73 LOGGER.warn("Context destroyed before it was initialized.");
74 return;
75 }
76 LOGGER.debug("Log4jServletContextListener ensuring that Log4j shuts down properly.");
77
78 this.initializer.clearLoggerContext(); // the application is finished
79 // shutting down now
80 if (initializer instanceof LifeCycle2) {
81 final String stopTimeoutStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT);
82 final long stopTimeout = Strings.isEmpty(stopTimeoutStr) ? DEFAULT_STOP_TIMEOUT
83 : Long.parseLong(stopTimeoutStr);
84 final String timeoutTimeUnitStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT_TIMEUNIT);
85 final TimeUnit timeoutTimeUnit = Strings.isEmpty(timeoutTimeUnitStr) ? DEFAULT_STOP_TIMEOUT_TIMEUNIT
86 : TimeUnit.valueOf(timeoutTimeUnitStr.toUpperCase(Locale.ROOT));
87 ((LifeCycle2) this.initializer).stop(stopTimeout, timeoutTimeUnit);
88 } else {
89 this.initializer.stop();
90 }
91 }
92 }
+0
-87
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/Log4jServletFilter.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.logging.log4j.web;
17
18 import java.io.IOException;
19 import jakarta.servlet.Filter;
20 import jakarta.servlet.FilterChain;
21 import jakarta.servlet.FilterConfig;
22 import jakarta.servlet.ServletContext;
23 import jakarta.servlet.ServletException;
24 import jakarta.servlet.ServletRequest;
25 import jakarta.servlet.ServletResponse;
26
27 import org.apache.logging.log4j.Logger;
28 import org.apache.logging.log4j.status.StatusLogger;
29
30 /**
31 * This is responsible for the following:
32 * <ul>
33 * <li>Clearing the logger context when the application has finished starting up.</li>
34 * <li>Setting the logger context before processing a request and clearing it after processing a request.</li>
35 * <li>Setting the logger context when the application is starting to shut down.</li>
36 * </ul>
37 * This filter is a once-per-request filter. It is capable of filtering all the different types of requests
38 * (standard, asynchronous, error, etc.) but will not apply processing if the filter matches multiple times on the same
39 * logical request.
40 */
41 public class Log4jServletFilter implements Filter {
42
43 private static final Logger LOGGER = StatusLogger.getLogger();
44
45 static final String ALREADY_FILTERED_ATTRIBUTE = Log4jServletFilter.class.getName() + ".FILTERED";
46
47 private ServletContext servletContext;
48 private Log4jWebLifeCycle initializer;
49
50 @Override
51 public void init(final FilterConfig filterConfig) throws ServletException {
52 this.servletContext = filterConfig.getServletContext();
53 LOGGER.debug("Log4jServletFilter initialized.");
54
55 this.initializer = WebLoggerContextUtils.getWebLifeCycle(this.servletContext);
56 this.initializer.clearLoggerContext(); // the application is mostly finished starting up now
57 }
58
59 @Override
60 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
61 throws IOException, ServletException {
62 if (request.getAttribute(ALREADY_FILTERED_ATTRIBUTE) != null) {
63 chain.doFilter(request, response);
64 } else {
65 request.setAttribute(ALREADY_FILTERED_ATTRIBUTE, Boolean.TRUE);
66
67 try {
68 this.initializer.setLoggerContext();
69
70 chain.doFilter(request, response);
71 } finally {
72 this.initializer.clearLoggerContext();
73 }
74 }
75 }
76
77 @Override
78 public void destroy() {
79 if (this.servletContext == null || this.initializer == null) {
80 throw new IllegalStateException("Filter destroyed before it was initialized.");
81 }
82 LOGGER.debug("Log4jServletFilter destroyed.");
83
84 this.initializer.setLoggerContext(); // the application is just now starting to shut down
85 }
86 }
+0
-80
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListener.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.logging.log4j.web;
17
18 import java.util.Locale;
19 import java.util.concurrent.TimeUnit;
20
21 import jakarta.servlet.ServletContext;
22 import jakarta.servlet.ServletContextEvent;
23 import jakarta.servlet.ServletContextListener;
24
25 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.LifeCycle2;
27 import org.apache.logging.log4j.status.StatusLogger;
28 import org.apache.logging.log4j.util.Strings;
29
30 public class Log4jShutdownOnContextDestroyedListener implements ServletContextListener {
31
32 private static final int DEFAULT_STOP_TIMEOUT = 30;
33 private static final TimeUnit DEFAULT_STOP_TIMEOUT_TIMEUNIT = TimeUnit.SECONDS;
34
35 private static final String KEY_STOP_TIMEOUT = "log4j.stop.timeout";
36 private static final String KEY_STOP_TIMEOUT_TIMEUNIT = "log4j.stop.timeout.timeunit";
37
38 private static final Logger LOGGER = StatusLogger.getLogger();
39
40 private ServletContext servletContext;
41 private Log4jWebLifeCycle initializer;
42
43 @Override
44 public void contextInitialized(final ServletContextEvent event) {
45 LOGGER.debug(Log4jShutdownOnContextDestroyedListener.class.getSimpleName() +
46 " ensuring that Log4j started up properly.");
47 servletContext = event.getServletContext();
48 if (null == servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)) {
49 throw new IllegalStateException(
50 "Context did not contain required Log4jWebLifeCycle in the "
51 + Log4jWebSupport.SUPPORT_ATTRIBUTE + " attribute.");
52 }
53 this.initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
54 }
55
56 @Override
57 public void contextDestroyed(final ServletContextEvent event) {
58 if (this.servletContext == null || this.initializer == null) {
59 LOGGER.warn("Context destroyed before it was initialized.");
60 return;
61 }
62 LOGGER.debug(Log4jShutdownOnContextDestroyedListener.class.getSimpleName() +
63 " ensuring that Log4j shuts down properly.");
64
65 this.initializer.clearLoggerContext(); // the application is finished
66 // shutting down now
67 if (initializer instanceof LifeCycle2) {
68 final String stopTimeoutStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT);
69 final long stopTimeout = Strings.isEmpty(stopTimeoutStr) ? DEFAULT_STOP_TIMEOUT
70 : Long.parseLong(stopTimeoutStr);
71 final String timeoutTimeUnitStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT_TIMEUNIT);
72 final TimeUnit timeoutTimeUnit = Strings.isEmpty(timeoutTimeUnitStr) ? DEFAULT_STOP_TIMEOUT_TIMEUNIT
73 : TimeUnit.valueOf(timeoutTimeUnitStr.toUpperCase(Locale.ROOT));
74 ((LifeCycle2) this.initializer).stop(stopTimeout, timeoutTimeUnit);
75 } else {
76 this.initializer.stop();
77 }
78 }
79 }
+0
-311
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/Log4jWebInitializerImpl.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.logging.log4j.web;
17
18 import jakarta.servlet.ServletContext;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.core.AbstractLifeCycle;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.async.AsyncLoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24 import org.apache.logging.log4j.core.impl.ContextAnchor;
25 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
26 import org.apache.logging.log4j.core.lookup.ConfigurationStrSubstitutor;
27 import org.apache.logging.log4j.core.lookup.Interpolator;
28 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
29 import org.apache.logging.log4j.core.selector.ContextSelector;
30 import org.apache.logging.log4j.core.selector.NamedContextSelector;
31 import org.apache.logging.log4j.core.util.Loader;
32 import org.apache.logging.log4j.core.util.NetUtils;
33 import org.apache.logging.log4j.spi.LoggerContextFactory;
34 import org.apache.logging.log4j.util.LoaderUtil;
35 import org.apache.logging.log4j.util.Strings;
36
37 import java.net.URI;
38 import java.net.URL;
39 import java.text.SimpleDateFormat;
40 import java.util.*;
41 import java.util.concurrent.ConcurrentHashMap;
42 import java.util.concurrent.TimeUnit;
43
44 /**
45 * This class initializes and deinitializes Log4j no matter how the initialization occurs.
46 */
47 final class Log4jWebInitializerImpl extends AbstractLifeCycle implements Log4jWebLifeCycle {
48
49 private static final String WEB_INF = "/WEB-INF/";
50
51 static {
52 if (Loader.isClassAvailable("org.apache.logging.log4j.core.web.JNDIContextFilter")) {
53 throw new IllegalStateException("You are using Log4j 2 in a web application with the old, extinct "
54 + "log4j-web artifact. This is not supported and could cause serious runtime problems. Please"
55 + "remove the log4j-web JAR file from your application.");
56 }
57 }
58
59 private final Map<String, String> map = new ConcurrentHashMap<>();
60 private final StrSubstitutor substitutor = new ConfigurationStrSubstitutor(new Interpolator(map));
61 private final ServletContext servletContext;
62
63 private String name;
64 private NamedContextSelector namedContextSelector;
65 private LoggerContext loggerContext;
66
67 private Log4jWebInitializerImpl(final ServletContext servletContext) {
68 this.servletContext = servletContext;
69 this.map.put("hostName", NetUtils.getLocalHostname());
70 }
71
72 /**
73 * Initializes the Log4jWebLifeCycle attribute of a ServletContext. Those who wish to obtain this object should use
74 * the {@link org.apache.logging.log4j.web.WebLoggerContextUtils#getWebLifeCycle(jakarta.servlet.ServletContext)}
75 * method instead.
76 *
77 * @param servletContext
78 * the ServletContext to initialize
79 * @return a new Log4jWebLifeCycle
80 * @since 2.0.1
81 */
82 protected static Log4jWebInitializerImpl initialize(final ServletContext servletContext) {
83 final Log4jWebInitializerImpl initializer = new Log4jWebInitializerImpl(servletContext);
84 servletContext.setAttribute(SUPPORT_ATTRIBUTE, initializer);
85 return initializer;
86 }
87
88 @Override
89 public synchronized void start() {
90 if (this.isStopped() || this.isStopping()) {
91 throw new IllegalStateException("Cannot start this Log4jWebInitializerImpl after it was stopped.");
92 }
93
94 // only do this once
95 if (this.isInitialized()) {
96 super.setStarting();
97
98 this.name = this.substitutor.replace(this.servletContext.getInitParameter(LOG4J_CONTEXT_NAME));
99 final String location = this.substitutor.replace(this.servletContext
100 .getInitParameter(LOG4J_CONFIG_LOCATION));
101 final boolean isJndi = "true".equalsIgnoreCase(this.servletContext
102 .getInitParameter(IS_LOG4J_CONTEXT_SELECTOR_NAMED));
103
104 if (isJndi) {
105 this.initializeJndi(location);
106 } else {
107 this.initializeNonJndi(location);
108 }
109 if (this.loggerContext instanceof AsyncLoggerContext) {
110 ((AsyncLoggerContext) this.loggerContext).setUseThreadLocals(false);
111 }
112
113 this.servletContext.setAttribute(CONTEXT_ATTRIBUTE, this.loggerContext);
114 super.setStarted();
115 }
116 }
117
118 private void initializeJndi(final String location) {
119 final URI configLocation = getConfigURI(location);
120
121 if (this.name == null) {
122 throw new IllegalStateException("A log4jContextName context parameter is required");
123 }
124
125 LoggerContext context;
126 final LoggerContextFactory factory = LogManager.getFactory();
127 if (factory instanceof Log4jContextFactory) {
128 final ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
129 if (selector instanceof NamedContextSelector) {
130 this.namedContextSelector = (NamedContextSelector) selector;
131 context = this.namedContextSelector.locateContext(this.name,
132 WebLoggerContextUtils.createExternalEntry(this.servletContext), configLocation);
133 ContextAnchor.THREAD_CONTEXT.set(context);
134 if (context.isInitialized()) {
135 context.start();
136 }
137 ContextAnchor.THREAD_CONTEXT.remove();
138 } else {
139 LOGGER.warn("Potential problem: Selector is not an instance of NamedContextSelector.");
140 return;
141 }
142 } else {
143 LOGGER.warn("Potential problem: LoggerContextFactory is not an instance of Log4jContextFactory.");
144 return;
145 }
146 this.loggerContext = context;
147 LOGGER.debug("Created logger context for [{}] using [{}].", this.name, context.getClass().getClassLoader());
148 }
149
150 private void initializeNonJndi(final String location) {
151 if (this.name == null) {
152 this.name = this.servletContext.getServletContextName();
153 LOGGER.debug("Using the servlet context name \"{}\".", this.name);
154 }
155 if (this.name == null) {
156 this.name = this.servletContext.getContextPath();
157 LOGGER.debug("Using the servlet context context-path \"{}\".", this.name);
158 }
159 if (this.name == null && location == null) {
160 LOGGER.error("No Log4j context configuration provided. This is very unusual.");
161 this.name = new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(new Date());
162 }
163 if (location != null && location.contains(",")) {
164 final List<URI> uris = getConfigURIs(location);
165 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uris,
166 WebLoggerContextUtils.createExternalEntry(this.servletContext));
167 return;
168 }
169
170 final URI uri = getConfigURI(location);
171 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uri,
172 WebLoggerContextUtils.createExternalEntry(this.servletContext));
173 }
174
175 private List<URI> getConfigURIs(final String location) {
176 final String[] parts = location.split(",");
177 final List<URI> uris = new ArrayList<>(parts.length);
178 for (final String part : parts) {
179 final URI uri = getConfigURI(part);
180 if (uri != null) {
181 uris.add(uri);
182 }
183 }
184 return uris;
185 }
186
187 private URI getConfigURI(final String location) {
188 try {
189 String configLocation = location;
190 if (configLocation == null) {
191 final String[] paths = prefixSet(servletContext.getResourcePaths(WEB_INF), WEB_INF + "log4j2");
192 LOGGER.debug("getConfigURI found resource paths {} in servletContext at [{}]", Arrays.toString(paths), WEB_INF);
193 if (paths.length == 1) {
194 configLocation = paths[0];
195 } else if (paths.length > 1) {
196 final String prefix = WEB_INF + "log4j2-" + this.name + ".";
197 boolean found = false;
198 for (final String str : paths) {
199 if (str.startsWith(prefix)) {
200 configLocation = str;
201 found = true;
202 break;
203 }
204 }
205 if (!found) {
206 configLocation = paths[0];
207 }
208 }
209 }
210 if (configLocation != null) {
211 final URL url = servletContext.getResource(configLocation);
212 if (url != null) {
213 final URI uri = url.toURI();
214 LOGGER.debug("getConfigURI found resource [{}] in servletContext at [{}]", uri, configLocation);
215 return uri;
216 }
217 }
218 } catch (final Exception ex) {
219 // Just try passing the location.
220 }
221 if (location != null) {
222 try {
223 final URI correctedFilePathUri = NetUtils.toURI(location);
224 LOGGER.debug("getConfigURI found [{}] in servletContext at [{}]", correctedFilePathUri, location);
225 return correctedFilePathUri;
226 } catch (final Exception e) {
227 LOGGER.error("Unable to convert configuration location [{}] to a URI", location, e);
228 }
229 }
230 return null;
231 }
232
233 /**
234 * Collects strings starting with the given {@code prefix} from the given {@code set}.
235 *
236 * @param set a (nullable) set of strings
237 * @param prefix a prefix to look for in the string set
238 * @return an array of the matching strings from the given set
239 */
240 @SuppressWarnings("SameParameterValue")
241 private static String[] prefixSet(final Set<String> set, final String prefix) {
242 if (set == null) {
243 return Strings.EMPTY_ARRAY;
244 }
245 return set
246 .stream()
247 .filter(string -> string.startsWith(prefix))
248 .toArray(String[]::new);
249 }
250
251 @Override
252 public synchronized boolean stop(final long timeout, final TimeUnit timeUnit) {
253 if (!this.isStarted() && !this.isStopped()) {
254 throw new IllegalStateException("Cannot stop this Log4jWebInitializer because it has not started.");
255 }
256
257 // only do this once
258 if (this.isStarted()) {
259 this.setStopping();
260 if (this.loggerContext != null) {
261 LOGGER.debug("Removing LoggerContext for [{}].", this.name);
262 this.servletContext.removeAttribute(CONTEXT_ATTRIBUTE);
263 if (this.namedContextSelector != null) {
264 this.namedContextSelector.removeContext(this.name);
265 }
266 this.loggerContext.stop(timeout, timeUnit);
267 this.loggerContext.setExternalContext(null);
268 this.loggerContext = null;
269 }
270 this.setStopped();
271 }
272 return super.stop(timeout, timeUnit);
273 }
274
275 @Override
276 public void setLoggerContext() {
277 if (this.loggerContext != null) {
278 ContextAnchor.THREAD_CONTEXT.set(this.loggerContext);
279 }
280 }
281
282 @Override
283 public void clearLoggerContext() {
284 ContextAnchor.THREAD_CONTEXT.remove();
285 }
286
287 @Override
288 public void wrapExecution(final Runnable runnable) {
289 this.setLoggerContext();
290
291 try {
292 runnable.run();
293 } finally {
294 this.clearLoggerContext();
295 }
296 }
297
298 private ClassLoader getClassLoader() {
299 try {
300 // if container is Servlet 3.0, use its getClassLoader method
301 // this may look odd, but the call below will throw NoSuchMethodError if user is on Servlet 2.5
302 // we compile against 3.0 to support Log4jServletContainerInitializer, but we don't require 3.0
303 return this.servletContext.getClassLoader();
304 } catch (final Throwable ignore) {
305 // LOG4J2-248: use TCCL if possible
306 return LoaderUtil.getThreadContextClassLoader();
307 }
308 }
309
310 }
+0
-43
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/Log4jWebLifeCycle.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.logging.log4j.web;
17
18 import org.apache.logging.log4j.core.LifeCycle;
19
20 /**
21 * Specifies an interface for initializing and deinitializing Log4j in a Java EE web application. The default and only
22 * implementation is {@link Log4jWebInitializerImpl}. The initializer is based on an interface to improve testability.
23 * The methods here are contained in a package-private sub-interface because general application code should not have
24 * access to them.
25 */
26 interface Log4jWebLifeCycle extends Log4jWebSupport, LifeCycle {
27
28 /**
29 * Starts up Log4j in the web application. Calls {@link #setLoggerContext()} after initialization is complete.
30 *
31 * @throws IllegalStateException if a JNDI config location is specified but no name is specified.
32 */
33 @Override
34 void start();
35
36 /**
37 * Shuts down Log4j in the web application. Calls {@link #clearLoggerContext()} immediately before deinitialization
38 * begins.
39 */
40 @Override
41 void stop();
42 }
+0
-95
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/Log4jWebSupport.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.logging.log4j.web;
17
18 import org.apache.logging.log4j.spi.LoggerContext;
19
20 /**
21 * Specifies an interface for setting and clearing a thread-bound {@link LoggerContext} in a Java EE web application.
22 * Also defines constants for context parameter and attribute names. In most cases you will never need to use this
23 * directly because the Log4j filter handles this task automatically. However, in async operations you should wrap
24 * code that executes in separate threads with {@link #setLoggerContext} and {@link #clearLoggerContext}.
25 *
26 * <p>
27 * You can obtain the instance of this for your web application by retrieving the {@link jakarta.servlet.ServletContext}
28 * attribute named {@code org.apache.logging.log4j.core.web.Log4jWebSupport.INSTANCE}. If needed, you can also obtain
29 * the {@link LoggerContext} instance for your web application by retrieving the {@code ServletContext} attribute named
30 * {@code org.apache.logging.log4j.spi.LoggerContext.INSTANCE}.
31 * </p>
32 */
33 public interface Log4jWebSupport {
34 /**
35 * The {@link jakarta.servlet.ServletContext} parameter name for the name of the
36 * {@link org.apache.logging.log4j.core.LoggerContext}.
37 */
38 String LOG4J_CONTEXT_NAME = "log4jContextName";
39
40 /**
41 * The {@link jakarta.servlet.ServletContext} parameter name for the location of the configuration.
42 */
43 String LOG4J_CONFIG_LOCATION = "log4jConfiguration";
44
45 /**
46 * The {@link jakarta.servlet.ServletContext} parameter name for the JNDI flag.
47 */
48 String IS_LOG4J_CONTEXT_SELECTOR_NAMED = "isLog4jContextSelectorNamed";
49
50 /**
51 * The {@link jakarta.servlet.ServletContext} parameter name for the flag that disables Log4j's auto-initialization
52 * in Servlet 3.0+ web applications. Set a context parameter with this name to "true" to disable
53 * auto-initialization.
54 */
55 String IS_LOG4J_AUTO_INITIALIZATION_DISABLED = "isLog4jAutoInitializationDisabled";
56
57 /**
58 * The {@link jakarta.servlet.ServletContext} parameter name for the flag that disables Log4j's auto-shutdown
59 * in Servlet 3.0+ web applications. Set a context parameter with this name to "true" to disable
60 * auto-shutdown.
61 */
62 String IS_LOG4J_AUTO_SHUTDOWN_DISABLED = "isLog4jAutoShutdownDisabled";
63
64 /**
65 * The attribute key for the {@link jakarta.servlet.ServletContext} attribute that the singleton support instance
66 * is stored in.
67 */
68 String SUPPORT_ATTRIBUTE = Log4jWebSupport.class.getName() + ".INSTANCE";
69
70 /**
71 * The attribute key for the {@link jakarta.servlet.ServletContext} attribute that the {@link LoggerContext}
72 * is stored in.
73 */
74 String CONTEXT_ATTRIBUTE = LoggerContext.class.getName() + ".INSTANCE";
75
76 /**
77 * Sets the logger context so that code executing afterwards can easily and quickly access loggers via
78 * {@link org.apache.logging.log4j.LogManager#getLogger}.
79 */
80 void setLoggerContext();
81
82 /**
83 * Clears the logger context set up in {@link #setLoggerContext}.
84 */
85 void clearLoggerContext();
86
87 /**
88 * Sets the logger context by calling {@link #setLoggerContext}, executes the runnable argument, then clears the
89 * logger context by calling {@link #clearLoggerContext}.
90 *
91 * @param runnable The runnable to execute wrapped with a configured logger context
92 */
93 void wrapExecution(Runnable runnable);
94 }
+0
-45
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/ServletRequestThreadContext.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.logging.log4j.web;
17
18 import java.util.Objects;
19
20 import jakarta.servlet.ServletRequest;
21 import jakarta.servlet.http.HttpServletRequest;
22
23 import org.apache.logging.log4j.ThreadContext;
24
25 public class ServletRequestThreadContext {
26
27 public static void put(final String key, final ServletRequest servletRequest) {
28 put(key, "RemoteAddr", servletRequest.getRemoteAddr());
29 put(key, "RemoteHost", servletRequest.getRemoteHost());
30 put(key, "RemotePort", servletRequest.getRemotePort());
31 }
32
33 public static void put(final String key, final String field, final Object value) {
34 put(key + "." + field, Objects.toString(value));
35 }
36
37 public static void put(final String key, final String value) {
38 ThreadContext.put(key, value);
39 }
40
41 public static void put(final String key, final HttpServletRequest servletRequest) {
42 put(key, (ServletRequest) servletRequest);
43 }
44 }
+0
-143
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/WebLoggerContextUtils.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.logging.log4j.web;
17
18 import java.util.AbstractMap;
19 import java.util.Map;
20 import java.util.concurrent.locks.Lock;
21 import java.util.concurrent.locks.ReentrantLock;
22 import jakarta.servlet.ServletContext;
23
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.core.LoggerContext;
26 import org.apache.logging.log4j.core.impl.ContextAnchor;
27
28 /**
29 * Convenience methods for retrieving the {@link org.apache.logging.log4j.core.LoggerContext} associated with a
30 * particular ServletContext. These methods are most particularly useful for asynchronous servlets where the
31 * Thread Context ClassLoader (TCCL) is potentially different from the TCCL used by the
32 * Servlet container that bootstrapped Log4j.
33 *
34 * @since 2.0.1
35 */
36 public final class WebLoggerContextUtils {
37 private WebLoggerContextUtils() {
38 }
39
40 private static final Lock WEB_SUPPORT_LOOKUP = new ReentrantLock();
41 private static final String SERVLET_CONTEXT = "__SERVLET_CONTEXT__";
42
43 /**
44 * Finds the main {@link org.apache.logging.log4j.core.LoggerContext} configured for the given ServletContext.
45 *
46 * @param servletContext the ServletContext to locate a LoggerContext for
47 * @return the LoggerContext for the given ServletContext
48 * @since 2.0.1
49 */
50 public static LoggerContext getWebLoggerContext(final ServletContext servletContext) {
51 return (LoggerContext) servletContext.getAttribute(Log4jWebSupport.CONTEXT_ATTRIBUTE);
52 }
53
54 /**
55 * Finds the main {@link org.apache.logging.log4j.core.LoggerContext} configured for the given ServletContext.
56 *
57 * @param servletContext the ServletContext to locate a LoggerContext for
58 * @return the LoggerContext for the given ServletContext or {@code null} if none was set
59 * @throws java.lang.IllegalStateException if no LoggerContext could be found on the given ServletContext
60 * @since 2.0.1
61 */
62 public static LoggerContext getRequiredWebLoggerContext(final ServletContext servletContext) {
63 final LoggerContext loggerContext = getWebLoggerContext(servletContext);
64 if (loggerContext == null) {
65 throw new IllegalStateException(
66 "No LoggerContext found in ServletContext attribute " + Log4jWebSupport.CONTEXT_ATTRIBUTE);
67 }
68 return loggerContext;
69 }
70
71 /**
72 * Finds or initializes the {@link org.apache.logging.log4j.web.Log4jWebLifeCycle} singleton for the given
73 * ServletContext.
74 *
75 * @param servletContext the ServletContext to get the Log4jWebLifeCycle for
76 * @return the Log4jWebLifeCycle for the given ServletContext
77 * @since 2.0.1
78 */
79 public static Log4jWebLifeCycle getWebLifeCycle(final ServletContext servletContext) {
80 WEB_SUPPORT_LOOKUP.lock();
81 try {
82 Log4jWebLifeCycle webLifeCycle = (Log4jWebLifeCycle) servletContext.getAttribute(
83 Log4jWebSupport.SUPPORT_ATTRIBUTE);
84 if (webLifeCycle == null) {
85 webLifeCycle = Log4jWebInitializerImpl.initialize(servletContext);
86 }
87 return webLifeCycle;
88 } finally {
89 WEB_SUPPORT_LOOKUP.unlock();
90 }
91 }
92
93 /**
94 * Wraps a Runnable instance by setting its thread context {@link org.apache.logging.log4j.core.LoggerContext}
95 * before execution and clearing it after execution.
96 *
97 * @param servletContext the ServletContext to locate a LoggerContext for
98 * @param runnable the Runnable to wrap execution for
99 * @return a wrapped Runnable
100 * @since 2.0.1
101 */
102 public static Runnable wrapExecutionContext(final ServletContext servletContext, final Runnable runnable) {
103 return () -> {
104 final Log4jWebSupport webSupport = getWebLifeCycle(servletContext);
105 webSupport.setLoggerContext();
106 try {
107 runnable.run();
108 } finally {
109 webSupport.clearLoggerContext();
110 }
111 };
112 }
113
114 public static Map.Entry<String, Object> createExternalEntry(ServletContext servletContext) {
115 return new AbstractMap.SimpleEntry<>(SERVLET_CONTEXT, servletContext);
116 }
117
118 public static void setServletContext(LoggerContext lc, ServletContext servletContext) {
119 if (lc != null) {
120 lc.putObject(SERVLET_CONTEXT, servletContext);
121 }
122 }
123
124 /**
125 * Gets the current {@link ServletContext} if it has already been assigned to a LoggerContext's external context.
126 *
127 * @return the current ServletContext attached to a LoggerContext or {@code null} if none could be found
128 * @since 2.1
129 */
130 public static ServletContext getServletContext() {
131 org.apache.logging.log4j.spi.LoggerContext lc = ContextAnchor.THREAD_CONTEXT.get();
132 if (lc == null) {
133 lc = LogManager.getContext(false);
134 }
135
136 Object obj = lc != null ? lc.getObject(SERVLET_CONTEXT) : null;
137 if (obj instanceof ServletContext) {
138 return (ServletContext) obj;
139 }
140 return null;
141 }
142 }
+0
-115
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/WebLookup.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.logging.log4j.web;
17 // Please note that if you move this class, make sure to update the Interpolator class (if still applicable) or remove
18 // this comment if no longer relevant
19
20 import jakarta.servlet.ServletContext;
21
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.lookup.AbstractLookup;
25 import org.apache.logging.log4j.util.Strings;
26
27 @Plugin(name = "web", category = "Lookup")
28 public class WebLookup extends AbstractLookup {
29 private static final String ATTR_PREFIX = "attr.";
30 private static final String INIT_PARAM_PREFIX = "initParam.";
31
32 @Override
33 public String lookup(final LogEvent event, final String key) {
34 final ServletContext ctx = WebLoggerContextUtils.getServletContext();
35 if (ctx == null) {
36 return null;
37 }
38
39 if (key.startsWith(ATTR_PREFIX)) {
40 final String attrName = key.substring(ATTR_PREFIX.length());
41 final Object attrValue = ctx.getAttribute(attrName);
42 return attrValue == null ? null : attrValue.toString();
43 }
44
45 if (key.startsWith(INIT_PARAM_PREFIX)) {
46 final String paramName = key.substring(INIT_PARAM_PREFIX.length());
47 return ctx.getInitParameter(paramName);
48 }
49
50 if ("rootDir".equals(key)) {
51 final String root = ctx.getRealPath("/");
52 if (root == null) {
53 final String msg = "Failed to resolve web:rootDir -- " +
54 "servlet container unable to translate virtual path " +
55 " to real path (probably not deployed as exploded";
56 throw new IllegalStateException(msg);
57 }
58 return root;
59 }
60
61 if ("contextPathName".equals(key)) {
62 String path = ctx.getContextPath();
63 if (path.trim().contains("/")) {
64 String[] fields = path.split("/");
65 for (String field : fields) {
66 if (field.length() > 0) {
67 return field;
68 }
69 }
70 return null;
71 }
72 return ctx.getContextPath();
73 }
74
75 if ("contextPath".equals(key)) {
76 return ctx.getContextPath();
77 }
78
79 if ("servletContextName".equals(key)) {
80 return ctx.getServletContextName();
81 }
82
83 if ("serverInfo".equals(key)) {
84 return ctx.getServerInfo();
85 }
86
87 if ("effectiveMajorVersion".equals(key)) {
88 return String.valueOf(ctx.getEffectiveMajorVersion());
89 }
90
91 if ("effectiveMinorVersion".equals(key)) {
92 return String.valueOf(ctx.getEffectiveMinorVersion());
93 }
94
95 if ("majorVersion".equals(key)) {
96 return String.valueOf(ctx.getMajorVersion());
97 }
98
99 if ("minorVersion".equals(key)) {
100 return String.valueOf(ctx.getMinorVersion());
101 }
102
103 if (ctx.getAttribute(key) != null) {
104 return ctx.getAttribute(key).toString();
105 }
106
107 if (ctx.getInitParameter(key) != null) {
108 return ctx.getInitParameter(key);
109 }
110
111 ctx.log(getClass().getName() + " unable to resolve key " + Strings.quote(key));
112 return null;
113 }
114 }
+0
-130
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/appender/ServletAppender.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.logging.log4j.web.appender;
17
18 import java.io.Serializable;
19
20 import jakarta.servlet.ServletContext;
21
22 import org.apache.logging.log4j.core.Filter;
23 import org.apache.logging.log4j.core.Layout;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.appender.AbstractAppender;
26 import org.apache.logging.log4j.core.config.Property;
27 import org.apache.logging.log4j.core.config.plugins.Plugin;
28 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
29 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
30 import org.apache.logging.log4j.core.layout.AbstractStringLayout;
31 import org.apache.logging.log4j.core.layout.PatternLayout;
32 import org.apache.logging.log4j.web.WebLoggerContextUtils;
33
34 /**
35 * Logs using the ServletContext's log method
36 */
37 @Plugin(name = "Servlet", category = "Core", elementType = "appender", printObject = true)
38 public class ServletAppender extends AbstractAppender {
39
40 public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
41 implements org.apache.logging.log4j.core.util.Builder<ServletAppender> {
42
43 @PluginBuilderAttribute
44 private boolean logThrowables;
45
46 @Override
47 public ServletAppender build() {
48 final String name = getName();
49 if (name == null) {
50 LOGGER.error("No name provided for ServletAppender");
51 }
52 final ServletContext servletContext = WebLoggerContextUtils.getServletContext();
53 if (servletContext == null) {
54 LOGGER.error("No servlet context is available");
55 return null;
56 }
57 Layout<? extends Serializable> layout = getLayout();
58 if (layout == null) {
59 layout = PatternLayout.createDefaultLayout();
60 } else if (!(layout instanceof AbstractStringLayout)) {
61 LOGGER.error("Layout must be a StringLayout to log to ServletContext");
62 return null;
63 }
64 return new ServletAppender(name, layout, getFilter(), servletContext, isIgnoreExceptions(), logThrowables);
65 }
66
67 /**
68 * Logs with {@link ServletContext#log(String, Throwable)} if true and with {@link ServletContext#log(String)} if false.
69 *
70 * @return whether to log a Throwable with the servlet context.
71 */
72 public boolean isLogThrowables() {
73 return logThrowables;
74 }
75
76 /**
77 * Logs with {@link ServletContext#log(String, Throwable)} if true and with {@link ServletContext#log(String)} if false.
78 */
79 public void setLogThrowables(final boolean logThrowables) {
80 this.logThrowables = logThrowables;
81 }
82
83 }
84
85 @PluginBuilderFactory
86 public static <B extends Builder<B>> B newBuilder() {
87 return new Builder<B>().asBuilder();
88 }
89
90 private final ServletContext servletContext;
91 private final boolean logThrowables;
92
93 private ServletAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
94 final ServletContext servletContext, final boolean ignoreExceptions, final boolean logThrowables) {
95 super(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY);
96 this.servletContext = servletContext;
97 this.logThrowables = logThrowables;
98 }
99
100 @Override
101 public void append(final LogEvent event) {
102 final String serialized = ((AbstractStringLayout) getLayout()).toSerializable(event);
103 if (logThrowables) {
104 servletContext.log(serialized, event.getThrown());
105 } else {
106 servletContext.log(serialized);
107 }
108 }
109
110 /**
111 * Creates a Servlet Appender.
112 * @param layout The layout to use (required). Must extend {@link AbstractStringLayout}.
113 * @param filter The Filter or null.
114 * @param name The name of the Appender (required).
115 * @param ignoreExceptions If {@code true} (default) exceptions encountered when appending events are logged;
116 * otherwise they are propagated to the caller.
117 * @return The ServletAppender.
118 * @deprecated Use {@link #newBuilder()}.
119 */
120 @Deprecated
121 public static ServletAppender createAppender(final Layout<? extends Serializable> layout, final Filter filter,
122 final String name, final boolean ignoreExceptions) {
123 // @formatter:off
124 return newBuilder().setFilter(filter).setIgnoreExceptions(ignoreExceptions).setLayout(layout).setName(name)
125 .build();
126 // @formatter:on
127 }
128
129 }
+0
-24
log4j-jakarta-web/src/main/java/org/apache/logging/log4j/web/package-info.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
17 /**
18 * The classes in this package are responsible for properly initializing and deinitializing Log4j in a Java EE web
19 * application.
20 *
21 * @see <a href="http://logging.apache.org/log4j/2.x/manual/webapp.html">Using Log4j 2 in Web Applications</a>
22 */
23 package org.apache.logging.log4j.web;
+0
-22
log4j-jakarta-web/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer less more
0 org.apache.logging.log4j.web.Log4jServletContainerInitializer
1 #
2 # See https://issues.apache.org/jira/browse/LOG4J2-890
3 # See https://issues.jboss.org/browse/WFLY-4458
4 #
5
6 #
7 # Licensed to the Apache Software Foundation (ASF) under one or more
8 # contributor license agreements. See the NOTICE file distributed with
9 # this work for additional information regarding copyright ownership.
10 # The ASF licenses this file to You under the Apache license, Version 2.0
11 # (the "License"); you may not use this file except in compliance with
12 # the License. You may obtain a copy of the License at
13 #
14 # http://www.apache.org/licenses/LICENSE-2.0
15 #
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS,
18 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 # See the license for the specific language governing permissions and
20 # limitations under the license.
21 #
+0
-33
log4j-jakarta-web/src/main/resources/META-INF/web-fragment.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
18 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
20 http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
21 version="3.0" metadata-complete="true">
22 <!-- The Log4j web fragment must be loaded before all other fragments. The configuration below should make this
23 happen automatically. If you experience problems, try specifying an <absolute-ordering> in your web.xml
24 deployment descriptor. -->
25 <name>log4j</name>
26 <distributable />
27 <ordering>
28 <before>
29 <others />
30 </before>
31 </ordering>
32 </web-fragment>
+0
-30
log4j-jakarta-web/src/site/markdown/index.md less more
0 <!-- vim: set syn=markdown : -->
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <!-- TODO: turn this into a velocity template for all the version numbers -->
18
19 # Web Servlet Containers
20
21 The Web module provides support for automatically enabling Log4j in Servlet containers.
22
23 See the user manual page on [Web Applications and JSPs](../manual/webapp.html)
24 for details on using Log4j 2 in Web Applications.
25
26 ## Requirements
27
28 The Web module requires Servlet 5.0 at minimum and is dependent on the Log4j 2 API and implementation.
29 For more information, see [Runtime Dependencies](../runtime-dependencies.html).
+0
-52
log4j-jakarta-web/src/site/site.xml 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 -->
17 <project name="Log4j Web Support"
18 xmlns="http://maven.apache.org/DECORATION/1.4.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
21 <body>
22 <links>
23 <item name="Apache" href="http://www.apache.org/" />
24 <item name="Logging Services" href="http://logging.apache.org/"/>
25 <item name="Log4j" href="../index.html"/>
26 </links>
27
28 <!-- Component-specific reports -->
29 <menu ref="reports"/>
30
31 <!-- Overall Project Info -->
32 <menu name="Log4j Project Information" img="icon-info-sign">
33 <item name="Dependencies" href="../dependencies.html" />
34 <item name="Dependency Convergence" href="../dependency-convergence.html" />
35 <item name="Dependency Management" href="../dependency-management.html" />
36 <item name="Project Team" href="../team-list.html" />
37 <item name="Mailing Lists" href="../mail-lists.html" />
38 <item name="Issue Tracking" href="../issue-tracking.html" />
39 <item name="Project License" href="../license.html" />
40 <item name="Source Repository" href="../source-repository.html" />
41 <item name="Project Summary" href="../project-summary.html" />
42 </menu>
43
44 <menu name="Log4j Project Reports" img="icon-cog">
45 <item name="Changes Report" href="../changes-report.html" />
46 <item name="JIRA Report" href="../jira-report.html" />
47 <item name="Surefire Report" href="../surefire-report.html" />
48 <item name="RAT Report" href="../rat-report.html" />
49 </menu>
50 </body>
51 </project>
+0
-184
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContainerInitializerTest.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.logging.log4j.web;
17
18 import java.util.EnumSet;
19 import java.util.EventListener;
20 import jakarta.servlet.DispatcherType;
21 import jakarta.servlet.Filter;
22 import jakarta.servlet.FilterRegistration;
23 import jakarta.servlet.ServletContext;
24
25 import org.apache.logging.log4j.util.Strings;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.ExtendWith;
29 import org.mockito.ArgumentCaptor;
30 import org.mockito.Captor;
31 import org.mockito.Mock;
32 import org.mockito.junit.jupiter.MockitoExtension;
33
34 import static org.junit.jupiter.api.Assertions.*;
35 import static org.mockito.ArgumentMatchers.eq;
36 import static org.mockito.BDDMockito.any;
37 import static org.mockito.BDDMockito.given;
38 import static org.mockito.BDDMockito.never;
39 import static org.mockito.BDDMockito.then;
40 import static org.mockito.BDDMockito.willThrow;
41 import static org.mockito.Mockito.mock;
42
43 @ExtendWith(MockitoExtension.class)
44 public class Log4jServletContainerInitializerTest {
45 @Mock
46 private ServletContext servletContext;
47 @Mock
48 private Log4jWebLifeCycle initializer;
49 @Captor
50 private ArgumentCaptor<Class<? extends Filter>> filterCaptor;
51 @Captor
52 private ArgumentCaptor<EventListener> listenerCaptor;
53
54 private Log4jServletContainerInitializer containerInitializer;
55
56 @BeforeEach
57 public void setUp() {
58 this.containerInitializer = new Log4jServletContainerInitializer();
59 }
60
61 @Test
62 public void testOnStartupWithServletVersion2_x() throws Exception {
63 given(servletContext.getMajorVersion()).willReturn(2);
64
65 this.containerInitializer.onStartup(null, this.servletContext);
66 }
67
68 @Test
69 public void testOnStartupWithServletVersion3_xEffectiveVersion2_x() throws Exception {
70 given(servletContext.getMajorVersion()).willReturn(3);
71 given(servletContext.getEffectiveMajorVersion()).willReturn(2);
72
73 this.containerInitializer.onStartup(null, this.servletContext);
74 }
75
76 @Test
77 public void testOnStartupWithServletVersion3_xEffectiveVersion3_xDisabledTrue() throws Exception {
78 given(servletContext.getMajorVersion()).willReturn(3);
79 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
80 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
81 "true");
82
83 this.containerInitializer.onStartup(null, this.servletContext);
84 }
85
86 @Test
87 public void testOnStartupWithServletVersion3_xEffectiveVersion3_xShutdownDisabled() throws Exception {
88 final FilterRegistration.Dynamic registration = mock(FilterRegistration.Dynamic.class);
89 given(servletContext.getMajorVersion()).willReturn(3);
90 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
91 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
92 .willReturn("true");
93 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
94 null);
95 given(servletContext.addFilter(eq("log4jServletFilter"), filterCaptor.capture())).willReturn(registration);
96 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
97
98 this.containerInitializer.onStartup(null, this.servletContext);
99
100 then(initializer).should().start();
101 then(initializer).should().setLoggerContext();
102 then(registration).should().setAsyncSupported(eq(true));
103 then(registration).should().addMappingForUrlPatterns(eq(EnumSet.allOf(DispatcherType.class)), eq(false), eq("/*"));
104
105 // initParam IS_LOG4J_AUTO_SHUTDOWN_DISABLED is "true" so addListener shouldn't be called.
106 then(servletContext).should(never()).addListener(any(Log4jServletContextListener.class));
107 }
108
109 @Test
110 public void testOnStartupWithServletVersion3_xEffectiveVersion3_xDisabledTRUE() throws Exception {
111 given(servletContext.getMajorVersion()).willReturn(3);
112 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
113 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
114 "TRUE");
115
116 this.containerInitializer.onStartup(null, this.servletContext);
117 }
118
119 @Test
120 public void testOnStartupWithServletVersion3_xEffectiveVersion3_x() throws Exception {
121 final FilterRegistration.Dynamic registration = mock(FilterRegistration.Dynamic.class);
122 given(servletContext.getMajorVersion()).willReturn(3);
123 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
124 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
125 null);
126 given(servletContext.addFilter(eq("log4jServletFilter"), filterCaptor.capture())).willReturn(registration);
127 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
128
129 containerInitializer.onStartup(null, servletContext);
130
131 then(initializer).should().start();
132 then(initializer).should().setLoggerContext();
133 then(servletContext).should().addListener(listenerCaptor.capture());
134 then(registration).should().setAsyncSupported(eq(true));
135 then(registration).should().addMappingForUrlPatterns(eq(EnumSet.allOf(DispatcherType.class)), eq(false), eq("/*"));
136
137 assertNotNull(listenerCaptor.getValue(), "The listener should not be null.");
138 assertSame(Log4jServletContextListener.class,
139 listenerCaptor.getValue().getClass(),
140 "The listener is not correct.");
141
142 assertNotNull(filterCaptor.getValue(), "The filter should not be null.");
143 assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The filter is not correct.");
144 }
145
146 @Test
147 public void testOnStartupCanceledDueToPreExistingFilter() throws Exception {
148 given(servletContext.getMajorVersion()).willReturn(3);
149 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
150 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
151 "false");
152 given(servletContext.addFilter(eq("log4jServletFilter"), filterCaptor.capture())).willReturn(null);
153
154 this.containerInitializer.onStartup(null, this.servletContext);
155
156 assertNotNull(filterCaptor.getValue(), "The filter should not be null.");
157 assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The filter is not correct.");
158 }
159
160 @Test
161 public void testOnStartupFailedDueToInitializerFailure() throws Exception {
162 final FilterRegistration.Dynamic registration = mock(FilterRegistration.Dynamic.class);
163 final IllegalStateException exception = new IllegalStateException(Strings.EMPTY);
164 given(servletContext.getMajorVersion()).willReturn(3);
165 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
166 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
167 "balderdash");
168 given(servletContext.addFilter(eq("log4jServletFilter"), filterCaptor.capture())).willReturn(registration);
169 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
170 willThrow(exception).given(initializer).start();
171
172 try {
173 this.containerInitializer.onStartup(null, this.servletContext);
174 fail("Expected the exception thrown by the initializer; got no exception.");
175 } catch (final IllegalStateException e) {
176 assertSame(exception, e, "The exception is not correct.");
177 }
178
179 then(initializer).should().start();
180 assertNotNull(filterCaptor.getValue(), "The filter should not be null.");
181 assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The filter is not correct.");
182 }
183 }
+0
-109
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.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.logging.log4j.web;
17
18 import jakarta.servlet.ServletContext;
19 import jakarta.servlet.ServletContextEvent;
20
21 import org.apache.logging.log4j.util.Strings;
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.api.extension.ExtendWith;
25 import org.mockito.Mock;
26 import org.mockito.junit.jupiter.MockitoExtension;
27
28 import static org.junit.jupiter.api.Assertions.*;
29 import static org.mockito.BDDMockito.eq;
30 import static org.mockito.BDDMockito.given;
31 import static org.mockito.BDDMockito.then;
32 import static org.mockito.BDDMockito.willThrow;
33
34 @ExtendWith(MockitoExtension.class)
35 public class Log4jServletContextListenerTest {
36 /* event and servletContext are marked lenient because they aren't used in the
37 * testDestroyWithNoInit but are only accessed during initialization
38 */
39 @Mock(lenient = true)
40 private ServletContextEvent event;
41 @Mock(lenient = true)
42 private ServletContext servletContext;
43 @Mock
44 private Log4jWebLifeCycle initializer;
45
46 private Log4jServletContextListener listener;
47
48 @BeforeEach
49 public void setUp() {
50 this.listener = new Log4jServletContextListener();
51 given(event.getServletContext()).willReturn(servletContext);
52 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
53 }
54
55 @Test
56 public void testInitAndDestroy() throws Exception {
57 this.listener.contextInitialized(this.event);
58
59 then(initializer).should().start();
60 then(initializer).should().setLoggerContext();
61
62 this.listener.contextDestroyed(this.event);
63
64 then(initializer).should().clearLoggerContext();
65 then(initializer).should().stop();
66 }
67
68 @Test
69 public void testInitFailure() throws Exception {
70 willThrow(new IllegalStateException(Strings.EMPTY)).given(initializer).start();
71
72 try {
73 this.listener.contextInitialized(this.event);
74 fail("Expected a RuntimeException.");
75 } catch (final RuntimeException e) {
76 assertEquals("Failed to initialize Log4j properly.", e.getMessage(), "The message is not correct.");
77 }
78 }
79
80 @Test
81 public void initializingLog4jServletContextListenerShouldFaileWhenAutoShutdownIsTrue() throws Exception {
82 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
83 .willReturn("true");
84 ensureInitializingFailsWhenAuthShutdownIsEnabled();
85 }
86
87 @Test
88 public void initializingLog4jServletContextListenerShouldFaileWhenAutoShutdownIsTRUE() throws Exception {
89 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
90 .willReturn("TRUE");
91 ensureInitializingFailsWhenAuthShutdownIsEnabled();
92 }
93
94 private void ensureInitializingFailsWhenAuthShutdownIsEnabled() {
95 try {
96 this.listener.contextInitialized(this.event);
97 fail("Expected a RuntimeException.");
98 } catch (final RuntimeException e) {
99 String expectedMessage =
100 "Do not use " + Log4jServletContextListener.class.getSimpleName() + " when "
101 + Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED + " is true. Please use "
102 + Log4jShutdownOnContextDestroyedListener.class.getSimpleName() + " instead of "
103 + Log4jServletContextListener.class.getSimpleName() + ".";
104
105 assertEquals(expectedMessage, e.getMessage(), "The message is not correct");
106 }
107 }
108 }
+0
-111
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/Log4jServletFilterTest.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.logging.log4j.web;
17
18 import jakarta.servlet.FilterChain;
19 import jakarta.servlet.FilterConfig;
20 import jakarta.servlet.ServletContext;
21 import jakarta.servlet.ServletRequest;
22 import jakarta.servlet.ServletResponse;
23
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.mockito.Mock;
28 import org.mockito.junit.jupiter.MockitoExtension;
29
30 import static org.junit.jupiter.api.Assertions.*;
31 import static org.mockito.ArgumentMatchers.eq;
32 import static org.mockito.ArgumentMatchers.same;
33 import static org.mockito.BDDMockito.given;
34 import static org.mockito.BDDMockito.then;
35 import static org.mockito.Mockito.reset;
36
37 @ExtendWith(MockitoExtension.class)
38 public class Log4jServletFilterTest {
39 @Mock(lenient = true) // because filterConfig is not used in testDestroy
40 private FilterConfig filterConfig;
41 @Mock(lenient = true) // because filterConfig is not used in testDestroy
42 private ServletContext servletContext;
43 @Mock
44 private Log4jWebLifeCycle initializer;
45 @Mock
46 private ServletRequest request;
47 @Mock
48 private ServletResponse response;
49 @Mock
50 private FilterChain chain;
51
52 private Log4jServletFilter filter;
53
54 @BeforeEach
55 public void setUp() {
56 given(filterConfig.getServletContext()).willReturn(servletContext);
57 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
58 this.filter = new Log4jServletFilter();
59 }
60
61 @Test
62 public void testInitAndDestroy() throws Exception {
63 this.filter.init(this.filterConfig);
64
65 then(initializer).should().clearLoggerContext();
66
67 this.filter.destroy();
68
69 then(initializer).should().setLoggerContext();
70 }
71
72 @Test
73 public void testDestroy() {
74 assertThrows(IllegalStateException.class, () -> {
75 this.filter.destroy();
76 });
77 }
78
79 @Test
80 public void testDoFilterFirstTime() throws Exception {
81 this.filter.init(this.filterConfig);
82
83 then(initializer).should().clearLoggerContext();
84 reset(initializer);
85
86 given(request.getAttribute(Log4jServletFilter.ALREADY_FILTERED_ATTRIBUTE)).willReturn(null);
87
88 this.filter.doFilter(request, response, chain);
89
90 then(request).should().setAttribute(eq(Log4jServletFilter.ALREADY_FILTERED_ATTRIBUTE), eq(true));
91 then(initializer).should().setLoggerContext();
92 then(chain).should().doFilter(same(request), same(response));
93 then(chain).shouldHaveNoMoreInteractions();
94 then(initializer).should().clearLoggerContext();
95 }
96
97 @Test
98 public void testDoFilterSecondTime() throws Exception {
99 this.filter.init(this.filterConfig);
100
101 then(initializer).should().clearLoggerContext();
102
103 given(request.getAttribute(Log4jServletFilter.ALREADY_FILTERED_ATTRIBUTE)).willReturn(true);
104
105 this.filter.doFilter(request, response, chain);
106
107 then(chain).should().doFilter(same(request), same(response));
108 then(chain).shouldHaveNoMoreInteractions();
109 }
110 }
+0
-83
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListenerTest.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.logging.log4j.web;
17
18 import static org.junit.jupiter.api.Assertions.*;
19 import static org.mockito.BDDMockito.given;
20 import static org.mockito.BDDMockito.then;
21 import static org.mockito.Mockito.never;
22
23 import jakarta.servlet.ServletContext;
24 import jakarta.servlet.ServletContextEvent;
25
26 import org.junit.jupiter.api.Test;
27 import org.junit.jupiter.api.extension.ExtendWith;
28 import org.mockito.Mock;
29 import org.mockito.junit.jupiter.MockitoExtension;
30
31 @ExtendWith(MockitoExtension.class)
32 public class Log4jShutdownOnContextDestroyedListenerTest {
33 @Mock(lenient = true)
34 private ServletContextEvent event;
35 @Mock(lenient = true)
36 private ServletContext servletContext;
37 @Mock
38 private Log4jWebLifeCycle initializer;
39
40 private Log4jShutdownOnContextDestroyedListener listener;
41
42 public void setUp(boolean mockInitializer) {
43 this.listener = new Log4jShutdownOnContextDestroyedListener();
44 given(event.getServletContext()).willReturn(servletContext);
45 if (mockInitializer) {
46 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE))
47 .willReturn(initializer);
48 }
49 }
50
51 @Test
52 public void testInitAndDestroy() throws Exception {
53 setUp(true);
54 this.listener.contextInitialized(this.event);
55
56 then(initializer).should(never()).start();
57 then(initializer).should(never()).setLoggerContext();
58
59 this.listener.contextDestroyed(this.event);
60
61 then(initializer).should().clearLoggerContext();
62 then(initializer).should().stop();
63 }
64
65 @Test
66 public void testDestroy() throws Exception {
67 setUp(true);
68 this.listener.contextDestroyed(this.event);
69
70 then(initializer).should(never()).clearLoggerContext();
71 then(initializer).should(never()).stop();
72 }
73
74 @Test
75 public void whenNoInitializerInContextTheContextInitializedShouldThrowAnException() {
76 setUp(false);
77
78 assertThrows(IllegalStateException.class, () -> {
79 this.listener.contextInitialized(this.event);
80 });
81 }
82 }
+0
-403
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/Log4jWebInitializerImplTest.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.logging.log4j.web;
17
18 import java.net.URI;
19 import java.net.URL;
20 import java.util.HashSet;
21 import jakarta.servlet.ServletContext;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.DefaultConfiguration;
24 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
25 import org.apache.logging.log4j.core.impl.ContextAnchor;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.ExtendWith;
29 import org.mockito.ArgumentCaptor;
30 import org.mockito.Captor;
31 import org.mockito.Mock;
32 import org.mockito.junit.jupiter.MockitoExtension;
33
34 import static java.util.Arrays.asList;
35 import static java.util.Collections.singletonList;
36 import static org.hamcrest.CoreMatchers.instanceOf;
37 import static org.hamcrest.CoreMatchers.is;
38 import static org.hamcrest.CoreMatchers.nullValue;
39 import static org.hamcrest.MatcherAssert.assertThat;
40 import static org.junit.jupiter.api.Assertions.*;
41 import static org.mockito.ArgumentMatchers.eq;
42 import static org.mockito.BDDMockito.given;
43 import static org.mockito.BDDMockito.then;
44
45 @ExtendWith(MockitoExtension.class)
46 public class Log4jWebInitializerImplTest {
47 /* Marking servletContext lenient because otherwise testCompositeLocationParameterWithEmptyUriListSetsDefaultConfiguration fails
48 * when null is passed in as the initial param because Mockito deciced null isn't a String rather than the absence of a string.
49 */
50 @Mock(lenient = true)
51 private ServletContext servletContext;
52 @Captor
53 private ArgumentCaptor<Log4jWebLifeCycle> initializerCaptor;
54 @Captor
55 private ArgumentCaptor<LoggerContext> loggerContextCaptor;
56
57 private Log4jWebInitializerImpl initializerImpl;
58
59 @BeforeEach
60 public void setUp() {
61 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(null);
62
63 final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(this.servletContext);
64
65 then(servletContext).should().setAttribute(eq(Log4jWebSupport.SUPPORT_ATTRIBUTE), initializerCaptor.capture());
66 assertNotNull(initializer, "The initializer should not be null.");
67 assertSame(initializer, initializerCaptor.getValue(), "The capture is not correct.");
68 assertTrue(initializer instanceof Log4jWebInitializerImpl, "The initializer is not correct.");
69
70 this.initializerImpl = (Log4jWebInitializerImpl) initializer;
71 }
72
73 @Test
74 public void testDeinitializeBeforeInitialize() {
75 assertThrows(IllegalStateException.class, () -> {
76 this.initializerImpl.stop();
77 });
78 }
79
80 @Test
81 public void testSetLoggerContextBeforeInitialize() {
82 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
83
84 this.initializerImpl.setLoggerContext();
85
86 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
87 }
88
89 @Test
90 public void testClearLoggerContextBeforeInitialize() {
91 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
92
93 this.initializerImpl.clearLoggerContext();
94
95 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
96 }
97
98 @Test
99 public void testInitializeWithNoParametersThenSetLoggerContextThenDeinitialize() {
100 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
101 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
102 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
103 given(servletContext.getServletContextName()).willReturn("helloWorld01");
104 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
105
106 this.initializerImpl.start();
107
108 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
109 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
110 final org.apache.logging.log4j.spi.LoggerContext loggerContext = loggerContextCaptor.getValue();
111
112 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
113
114 this.initializerImpl.setLoggerContext();
115
116 final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
117 assertNotNull(context, "The context should not be null.");
118 assertSame(loggerContext, context, "The context is not correct.");
119
120 this.initializerImpl.clearLoggerContext();
121
122 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
123
124 this.initializerImpl.stop();
125
126 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
127
128 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
129
130 this.initializerImpl.setLoggerContext();
131
132 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
133 }
134
135 @Test
136 public void testInitializeWithClassLoaderNoParametersThenSetLoggerContextThenDeinitialize() {
137 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
138 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
139 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("false");
140 given(servletContext.getServletContextName()).willReturn("helloWorld02");
141 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
142 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
143 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
144
145 this.initializerImpl.start();
146
147 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
148 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
149 final org.apache.logging.log4j.spi.LoggerContext loggerContext = loggerContextCaptor.getValue();
150
151 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
152
153 this.initializerImpl.setLoggerContext();
154
155 final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
156 assertNotNull(context, "The context should not be null.");
157 assertSame(loggerContext, context, "The context is not correct.");
158
159 this.initializerImpl.clearLoggerContext();
160
161 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
162
163 this.initializerImpl.stop();
164
165 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
166
167 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
168
169 this.initializerImpl.setLoggerContext();
170
171 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
172 }
173
174 @Test
175 public void testInitializeIsIdempotent() {
176 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
177 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
178 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("nothing");
179 given(servletContext.getServletContextName()).willReturn("helloWorld03");
180 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
181 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
182 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
183
184 this.initializerImpl.start();
185
186 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
187 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
188
189 this.initializerImpl.start();
190 this.initializerImpl.start();
191 this.initializerImpl.start();
192 this.initializerImpl.stop();
193
194 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
195 }
196
197 @Test
198 public void testInitializeFailsAfterDeinitialize() {
199 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
200 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
201 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
202 given(servletContext.getServletContextName()).willReturn("helloWorld04");
203 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
204 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
205 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
206
207 this.initializerImpl.start();
208
209 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
210 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
211
212 this.initializerImpl.stop();
213
214 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
215
216 assertThrows(IllegalStateException.class, () -> {
217 this.initializerImpl.start();
218 });
219 }
220
221 @Test
222 public void testDeinitializeIsIdempotent() {
223 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
224 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
225 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
226 given(servletContext.getServletContextName()).willReturn("helloWorld05");
227 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
228 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
229 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
230
231 this.initializerImpl.start();
232
233 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
234 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
235
236 this.initializerImpl.stop();
237 this.initializerImpl.stop();
238 this.initializerImpl.stop();
239 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
240 }
241
242 @Test
243 public void testInitializeUsingJndiSelectorFails() {
244 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
245 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
246 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("true");
247 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
248 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
249
250 assertThrows(IllegalStateException.class, () -> {
251 this.initializerImpl.start();
252 });
253 }
254
255 @Test
256 public void testInitializeUsingJndiSelector() {
257 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn("helloWorld06");
258 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
259 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("true");
260 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
261 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
262
263 this.initializerImpl.start();
264
265 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
266 assertNull(loggerContextCaptor.getValue(), "The context attribute should be null.");
267
268 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
269
270 this.initializerImpl.setLoggerContext();
271
272 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null because no named selector.");
273
274 this.initializerImpl.clearLoggerContext();
275
276 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
277
278 this.initializerImpl.stop();
279
280 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
281
282 this.initializerImpl.setLoggerContext();
283
284 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
285 }
286
287 @Test
288 public void testWrapExecutionWithNoParameters() {
289 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
290 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
291 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
292 given(servletContext.getServletContextName()).willReturn("helloWorld07");
293 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
294 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
295
296 this.initializerImpl.start();
297
298 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
299 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
300 final org.apache.logging.log4j.spi.LoggerContext loggerContext = loggerContextCaptor.getValue();
301
302 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
303
304 final Runnable runnable = () -> {
305 final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
306 assertNotNull(context, "The context should not be null.");
307 assertSame(loggerContext, context, "The context is not correct.");
308 };
309
310 this.initializerImpl.wrapExecution(runnable);
311
312 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
313
314 this.initializerImpl.stop();
315
316 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
317
318 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
319
320 this.initializerImpl.setLoggerContext();
321
322 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
323 }
324
325 @Test
326 public void testMissingLocationParameterWithNoMatchingResourceSetsNoConfigLocation() {
327 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(new HashSet<String>());
328
329 this.initializerImpl.start();
330
331 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
332 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
333
334 assertThat(loggerContextCaptor.getValue().getConfigLocation(), is(nullValue()));
335
336 this.initializerImpl.stop();
337 }
338
339 @Test
340 public void testMissingLocationParameterWithOneMatchingResourceUsesResourceConfigLocation() throws Exception {
341 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(new HashSet<>(singletonList("/WEB-INF/log4j2.xml")));
342 given(servletContext.getResource("/WEB-INF/log4j2.xml")).willReturn(new URL("file:/a/b/c/WEB-INF/log4j2.xml"));
343
344 this.initializerImpl.start();
345
346 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
347 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
348
349 assertThat(loggerContextCaptor.getValue().getConfigLocation(), is(URI.create("file:/a/b/c/WEB-INF/log4j2.xml")));
350
351 this.initializerImpl.stop();
352 }
353
354 @Test
355 public void testMissingLocationParameterWithManyMatchingResourcesUsesFirstMatchingResourceConfigLocation() throws Exception {
356 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn("mycontext");
357 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(
358 new HashSet<>(asList("/WEB-INF/a.xml", "/WEB-INF/log4j2-mycontext.xml", "/WEB-INF/log4j2.xml")));
359 given(servletContext.getResource("/WEB-INF/log4j2-mycontext.xml")).willReturn(
360 new URL("file:/a/b/c/WEB-INF/log4j2-mycontext.xml"));
361
362 this.initializerImpl.start();
363
364 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
365 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
366
367 assertThat(loggerContextCaptor.getValue().getConfigLocation(),
368 is(URI.create("file:/a/b/c/WEB-INF/log4j2-mycontext.xml")));
369
370 this.initializerImpl.stop();
371 }
372
373 @Test
374 public void testCompositeLocationParameterWithEmptyUriListSetsDefaultConfiguration() {
375 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(",,,");
376
377 this.initializerImpl.start();
378
379 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
380 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
381
382 assertThat(loggerContextCaptor.getValue().getConfiguration(), is(instanceOf(DefaultConfiguration.class)));
383
384 this.initializerImpl.stop();
385 }
386
387 @Test
388 public void testCompositeLocationParameterSetsCompositeConfiguration() {
389 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn("mycontext");
390 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(
391 "log4j2-combined.xml,log4j2-override.xml");
392
393 this.initializerImpl.start();
394
395 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
396 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
397
398 assertThat(loggerContextCaptor.getValue().getConfiguration(), is(instanceOf(CompositeConfiguration.class)));
399
400 this.initializerImpl.stop();
401 }
402 }
+0
-42
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/PropertyTest.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.logging.log4j.web;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
20 import org.apache.logging.log4j.util.Constants;
21 import org.junit.jupiter.api.Test;
22
23 import static org.junit.jupiter.api.Assertions.*;
24
25 /**
26 *
27 */
28 public class PropertyTest {
29
30 @Test
31 public void testShutdownHookDisabled() {
32 assertFalse(
33 ((Log4jContextFactory) LogManager.getFactory()).isShutdownHookEnabled(),
34 "Shutdown hook should be disabled by default in web applications");
35 }
36
37 @Test
38 public void testIsWebApp() {
39 assertTrue(Constants.IS_WEB_APP, "When servlet classes are available IS_WEB_APP should default to true");
40 }
41 }
+0
-58
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/ServletAppenderTest.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.logging.log4j.web;
17
18 /**
19 *
20 */
21 public class ServletAppenderTest {
22
23 // TODO: re-enable when https://github.com/spring-projects/spring-framework/issues/25354 is fixed
24
25 // private static final String CONFIG = "WEB-INF/classes/log4j-servlet.xml";
26 //
27 // @Test
28 // public void testAppender() throws Exception {
29 // ContextAnchor.THREAD_CONTEXT.remove();
30 // final ServletContext servletContext = new MockServletContext();
31 // servletContext.setAttribute("TestAttr", "AttrValue");
32 // servletContext.setInitParameter("TestParam", "ParamValue");
33 // servletContext.setAttribute("Name1", "Ben");
34 // servletContext.setInitParameter("Name2", "Jerry");
35 // servletContext.setInitParameter(Log4jWebSupport.LOG4J_CONFIG_LOCATION, CONFIG);
36 // final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
37 // try {
38 // initializer.start();
39 // initializer.setLoggerContext();
40 // final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
41 // assertNotNull(ctx, "No LoggerContext");
42 // assertNotNull(WebLoggerContextUtils.getServletContext(), "No ServletContext");
43 // final Configuration configuration = ctx.getConfiguration();
44 // assertNotNull(configuration, "No configuration");
45 // final Appender appender = configuration.getAppender("Servlet");
46 // assertNotNull(appender, "No ServletAppender");
47 // final Logger logger = LogManager.getLogger("Test");
48 // logger.info("This is a test");
49 // logger.error("This is a test 2", new IllegalStateException().fillInStackTrace());
50 // } catch (final IllegalStateException e) {
51 // fail("Failed to initialize Log4j properly." + e.getMessage());
52 // } finally {
53 // initializer.stop();
54 // ContextAnchor.THREAD_CONTEXT.remove();
55 // }
56 // }
57 }
+0
-54
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/TestAsyncServlet.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.logging.log4j.web;
17
18 import java.io.IOException;
19 import jakarta.servlet.AsyncContext;
20 import jakarta.servlet.ServletException;
21 import jakarta.servlet.http.HttpServlet;
22 import jakarta.servlet.http.HttpServletRequest;
23 import jakarta.servlet.http.HttpServletResponse;
24
25 import org.apache.logging.log4j.LogManager;
26 import org.apache.logging.log4j.Logger;
27
28 // TODO: write an integration test that deploys this Servlet 3.0 class to Tomcat and Jetty
29 public class TestAsyncServlet extends HttpServlet {
30
31 private static final long serialVersionUID = 1L;
32
33 @Override
34 protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
35 final AsyncContext asyncContext = req.startAsync();
36 asyncContext.start(WebLoggerContextUtils.wrapExecutionContext(this.getServletContext(), () -> {
37 final Logger logger = LogManager.getLogger(TestAsyncServlet.class);
38 logger.info("Hello, servlet!");
39 }));
40 }
41
42 @Override
43 protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
44 final AsyncContext asyncContext = req.startAsync();
45 asyncContext.start(() -> {
46 final Log4jWebSupport webSupport =
47 WebLoggerContextUtils.getWebLifeCycle(TestAsyncServlet.this.getServletContext());
48 webSupport.setLoggerContext();
49 // do stuff
50 webSupport.clearLoggerContext();
51 });
52 }
53 }
+0
-98
log4j-jakarta-web/src/test/java/org/apache/logging/log4j/web/WebLookupTest.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.logging.log4j.web;
17
18 public class WebLookupTest {
19
20 // TODO: re-enable when https://github.com/spring-projects/spring-framework/issues/25354 is fixed
21
22 // @Test
23 // public void testLookup() throws Exception {
24 // ContextAnchor.THREAD_CONTEXT.remove();
25 // final ServletContext servletContext = new MockServletContext();
26 // ((MockServletContext) servletContext).setContextPath("/WebApp");
27 // servletContext.setAttribute("TestAttr", "AttrValue");
28 // servletContext.setInitParameter("TestParam", "ParamValue");
29 // servletContext.setAttribute("Name1", "Ben");
30 // servletContext.setInitParameter("Name2", "Jerry");
31 // final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
32 // try {
33 // initializer.start();
34 // initializer.setLoggerContext();
35 // final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
36 // assertNotNull(ctx, "No LoggerContext");
37 // assertNotNull(WebLoggerContextUtils.getServletContext(), "No ServletContext");
38 // final Configuration config = ctx.getConfiguration();
39 // assertNotNull(config, "No Configuration");
40 // final StrSubstitutor substitutor = config.getStrSubstitutor();
41 // assertNotNull(substitutor, "No Interpolator");
42 // String value = substitutor.replace("${web:initParam.TestParam}");
43 // assertNotNull(value, "No value for TestParam");
44 // assertEquals("ParamValue", value, "Incorrect value for TestParam: " + value);
45 // value = substitutor.replace("${web:attr.TestAttr}");
46 // assertNotNull(value, "No value for TestAttr");
47 // assertEquals("AttrValue", value, "Incorrect value for TestAttr: " + value);
48 // value = substitutor.replace("${web:Name1}");
49 // assertNotNull(value, "No value for Name1");
50 // assertEquals("Ben", value, "Incorrect value for Name1: " + value);
51 // value = substitutor.replace("${web:Name2}");
52 // assertNotNull(value, "No value for Name2");
53 // assertEquals("Jerry", value, "Incorrect value for Name2: " + value);
54 // value = substitutor.replace("${web:contextPathName}");
55 // assertNotNull(value, "No value for context name");
56 // assertEquals("WebApp", value, "Incorrect value for context name");
57 // } catch (final IllegalStateException e) {
58 // fail("Failed to initialize Log4j properly." + e.getMessage());
59 // }
60 // initializer.stop();
61 // ContextAnchor.THREAD_CONTEXT.remove();
62 // }
63 //
64 // @Test
65 // public void testLookup2() throws Exception {
66 // ContextAnchor.THREAD_CONTEXT.remove();
67 // final ServletContext servletContext = new MockServletContext();
68 // ((MockServletContext) servletContext).setContextPath("/");
69 // servletContext.setAttribute("TestAttr", "AttrValue");
70 // servletContext.setInitParameter("myapp.logdir", "target");
71 // servletContext.setAttribute("Name1", "Ben");
72 // servletContext.setInitParameter("Name2", "Jerry");
73 // servletContext.setInitParameter("log4jConfiguration", "WEB-INF/classes/log4j-webvar.xml");
74 // final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
75 // initializer.start();
76 // initializer.setLoggerContext();
77 // final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
78 // assertNotNull(ctx, "No LoggerContext");
79 // assertNotNull(WebLoggerContextUtils.getServletContext(), "No ServletContext");
80 // final Configuration config = ctx.getConfiguration();
81 // assertNotNull(config, "No Configuration");
82 // final Map<String, Appender> appenders = config.getAppenders();
83 // for (final Map.Entry<String, Appender> entry : appenders.entrySet()) {
84 // if (entry.getKey().equals("file")) {
85 // final FileAppender fa = (FileAppender) entry.getValue();
86 // assertEquals("target/myapp.log", fa.getFileName());
87 // }
88 // }
89 // final StrSubstitutor substitutor = config.getStrSubstitutor();
90 // String value = substitutor.replace("${web:contextPathName:-default}");
91 // assertEquals("default", value, "Incorrect value for context name");
92 // assertNotNull(value, "No value for context name");
93 // initializer.stop();
94 // ContextAnchor.THREAD_CONTEXT.remove();
95 // }
96
97 }
+0
-33
log4j-jakarta-web/src/test/resources/WEB-INF/classes/log4j-servlet.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN" name="ServletTest">
19
20 <Appenders>
21 <Servlet name="Servlet" logThrowables="true">
22 <PatternLayout pattern="%m%n%ex{none}"/>
23 </Servlet>
24 </Appenders>
25
26 <Loggers>
27 <Root level="debug">
28 <AppenderRef ref="Servlet"/>
29 </Root>
30 </Loggers>
31
32 </Configuration>
+0
-29
log4j-jakarta-web/src/test/resources/WEB-INF/classes/log4j-webvar.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17 <Configuration status="OFF">
18 <Appenders>
19 <File name="file" fileName="${web:initParam.myapp.logdir}/myapp.log" append="true">
20 <PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
21 </File>
22 </Appenders>
23 <Loggers>
24 <Root level="warn">
25 <AppenderRef ref="file"/>
26 </Root>
27 </Loggers>
28 </Configuration>
+0
-31
log4j-jakarta-web/src/test/resources/log4j2-combined.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="OFF">
19 <Appenders>
20 <Console name="Console" target="SYSTEM_OUT">
21 <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable" />
22 </Console>
23 </Appenders>
24 <Loggers>
25 <Logger name="org.foo" level="DEBUG" />
26 <Root level="TRACE">
27 <AppenderRef ref="Console" />
28 </Root>
29 </Loggers>
30 </Configuration>
+0
-23
log4j-jakarta-web/src/test/resources/log4j2-override.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration>
19 <Loggers>
20 <Logger name="org.foo" level="ERROR" />
21 </Loggers>
22 </Configuration>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-jcl</artifactId>
3131 <docLabel>JCL Bridge Documentation</docLabel>
3232 <projectDir>/jcl-bridge</projectDir>
3333 <module.name>org.apache.logging.log4j.jcl</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
3534 </properties>
3635 <dependencies>
3736 <dependency>
38 <groupId>org.junit.vintage</groupId>
39 <artifactId>junit-vintage-engine</artifactId>
40 </dependency>
41 <dependency>
42 <groupId>org.junit.jupiter</groupId>
43 <artifactId>junit-jupiter-engine</artifactId>
37 <groupId>junit</groupId>
38 <artifactId>junit</artifactId>
39 <scope>test</scope>
4440 </dependency>
4541 <dependency>
4642 <groupId>org.hamcrest</groupId>
47 <artifactId>hamcrest</artifactId>
43 <artifactId>hamcrest-all</artifactId>
4844 <scope>test</scope>
4945 </dependency>
5046 <dependency>
149145 </reportSets>
150146 </plugin>
151147 <plugin>
152 <groupId>com.github.spotbugs</groupId>
153 <artifactId>spotbugs-maven-plugin</artifactId>
148 <groupId>org.codehaus.mojo</groupId>
149 <artifactId>findbugs-maven-plugin</artifactId>
150 <version>${findbugs.plugin.version}</version>
151 <configuration>
152 <fork>true</fork>
153 <jvmArgs>-Duser.language=en</jvmArgs>
154 <threshold>Normal</threshold>
155 <effort>Default</effort>
156 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
157 </configuration>
154158 </plugin>
155159 <plugin>
156160 <groupId>org.apache.maven.plugins</groupId>
1717
1818 import org.apache.commons.logging.Log;
1919 import org.apache.commons.logging.LogFactory;
20 import org.apache.logging.log4j.LogManager;
2120 import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
2221 import org.apache.logging.log4j.spi.LoggerContext;
2322 import org.apache.logging.log4j.util.StackLocatorUtil;
3635
3736 @Override
3837 protected LoggerContext getContext() {
39 return getContext(LogManager.getFactory().isClassLoaderDependent()
40 ? StackLocatorUtil.getCallerClass(LogFactory.class)
41 : null);
38 return getContext(StackLocatorUtil.getCallerClass(LogFactory.class));
4239 }
4340
4441 }
1010 <parent>
1111 <groupId>org.apache.logging.log4j</groupId>
1212 <artifactId>log4j</artifactId>
13 <version>2.17.0</version>
13 <version>2.12.3</version>
1414 </parent>
1515 <modelVersion>4.0.0</modelVersion>
1616
2424 <docLabel>Log4j JDBC DBCP 2 Documentation</docLabel>
2525 <projectDir>/log4j-jdbc-dbcp2</projectDir>
2626 <module.name>org.apache.logging.log4j.jdbc.dbcp2</module.name>
27 <maven.doap.skip>true</maven.doap.skip>
2827 </properties>
2928
3029 <dependencies>
3534 <dependency>
3635 <groupId>org.apache.commons</groupId>
3736 <artifactId>commons-dbcp2</artifactId>
37 <version>2.4.0</version>
3838 </dependency>
3939 <!-- Test Dependencies -->
4040 <dependency>
41 <groupId>org.junit.vintage</groupId>
42 <artifactId>junit-vintage-engine</artifactId>
43 </dependency>
44 <dependency>
45 <groupId>org.junit.jupiter</groupId>
46 <artifactId>junit-jupiter-engine</artifactId>
41 <groupId>junit</groupId>
42 <artifactId>junit</artifactId>
4743 </dependency>
4844 <dependency>
4945 <groupId>org.apache.logging.log4j</groupId>
129125 </reportSets>
130126 </plugin>
131127 <plugin>
132 <groupId>com.github.spotbugs</groupId>
133 <artifactId>spotbugs-maven-plugin</artifactId>
128 <groupId>org.codehaus.mojo</groupId>
129 <artifactId>findbugs-maven-plugin</artifactId>
130 <version>${findbugs.plugin.version}</version>
131 <configuration>
132 <fork>true</fork>
133 <jvmArgs>-Duser.language=en</jvmArgs>
134 <threshold>Normal</threshold>
135 <effort>Default</effort>
136 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
137 </configuration>
134138 </plugin>
135139 <plugin>
136140 <groupId>org.apache.maven.plugins</groupId>
227227 final boolean fastFailValidation, final long maxConnLifetimeMillis, final int maxOpenPreparedStatements,
228228 final boolean poolStatements, final boolean rollbackOnReturn, final String validationQuery,
229229 final int validationQueryTimeoutSeconds) {
230 super();
230231 this.cacheState = cacheState;
231232 this.connectionInitSqls = connectionInitSqls;
232233 this.defaultAutoCommit = defaultAutoCommit;
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-jmx-gui</artifactId>
3434 <projectDir>/jmx-gui</projectDir>
3535 <jenkins.java.home>/home/jenkins/tools/java/latest1.7</jenkins.java.home>
3636 <module.name>org.apache.logging.log4j.jmx.gui</module.name>
37 <maven.doap.skip>true</maven.doap.skip>
3837 </properties>
3938 <dependencies>
4039 <dependency>
140139 </reportSets>
141140 </plugin>
142141 <plugin>
143 <groupId>com.github.spotbugs</groupId>
144 <artifactId>spotbugs-maven-plugin</artifactId>
142 <groupId>org.codehaus.mojo</groupId>
143 <artifactId>findbugs-maven-plugin</artifactId>
144 <version>${findbugs.plugin.version}</version>
145 <configuration>
146 <fork>true</fork>
147 <jvmArgs>-Duser.language=en</jvmArgs>
148 <threshold>Normal</threshold>
149 <effort>Default</effort>
150 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
151 </configuration>
145152 </plugin>
146153 <plugin>
147154 <groupId>org.apache.maven.plugins</groupId>
139139 final String mbean = String.format(pattern, Server.escape(contextName));
140140 final ObjectName search = new ObjectName(mbean);
141141 final Set<ObjectName> result = connection.queryNames(search, null);
142 if (result.isEmpty()) {
142 if (result.size() == 0) {
143143 return null;
144144 }
145145 if (result.size() > 1) {
178178
179179 @Override
180180 public void handleNotification(final Notification notif, final Object paramObject) {
181 SwingUtilities.invokeLater(() -> handleNotificationInAwtEventThread(notif, paramObject));
181 SwingUtilities.invokeLater(new Runnable() {
182 @Override
183 public void run() { // LOG4J2-538
184 handleNotificationInAwtEventThread(notif, paramObject);
185 }
186 });
182187 }
183188
184189 private void handleNotificationInAwtEventThread(final Notification notif, final Object paramObject) {
278283 final Client client = new Client(connector);
279284 final String title = "Log4j JMX Client - " + url;
280285
281 SwingUtilities.invokeLater(() -> {
282 installLookAndFeel();
283 try {
284 final ClientGui gui = new ClientGui(client);
285 final JFrame frame = new JFrame(title);
286 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
287 frame.getContentPane().add(gui, BorderLayout.CENTER);
288 frame.pack();
289 frame.setVisible(true);
290 } catch (final Exception ex) {
291 // if console is visible, print error so that
292 // the stack trace remains visible after error dialog is
293 // closed
294 ex.printStackTrace();
295
296 // show error in dialog: there may not be a console window
297 // visible
298 final StringWriter sr = new StringWriter();
299 ex.printStackTrace(new PrintWriter(sr));
300 JOptionPane.showMessageDialog(null, sr.toString(), "Error", JOptionPane.ERROR_MESSAGE);
286 SwingUtilities.invokeLater(new Runnable() {
287 @Override
288 public void run() {
289 installLookAndFeel();
290 try {
291 final ClientGui gui = new ClientGui(client);
292 final JFrame frame = new JFrame(title);
293 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
294 frame.getContentPane().add(gui, BorderLayout.CENTER);
295 frame.pack();
296 frame.setVisible(true);
297 } catch (final Exception ex) {
298 // if console is visible, print error so that
299 // the stack trace remains visible after error dialog is
300 // closed
301 ex.printStackTrace();
302
303 // show error in dialog: there may not be a console window
304 // visible
305 final StringWriter sr = new StringWriter();
306 ex.printStackTrace(new PrintWriter(sr));
307 JOptionPane.showMessageDialog(null, sr.toString(), "Error", JOptionPane.ERROR_MESSAGE);
308 }
301309 }
302310 });
303311 }
1010 <parent>
1111 <groupId>org.apache.logging.log4j</groupId>
1212 <artifactId>log4j</artifactId>
13 <version>2.17.0</version>
13 <version>2.12.3</version>
1414 </parent>
1515 <modelVersion>4.0.0</modelVersion>
1616
2424 <docLabel>Log4j JPA Documentation</docLabel>
2525 <projectDir>/log4j-jpa</projectDir>
2626 <module.name>org.apache.logging.log4j.jpa</module.name>
27 <maven.doap.skip>true</maven.doap.skip>
2827 </properties>
2928
3029 <dependencies>
4847 </dependency>
4948 <!-- Test Dependencies -->
5049 <dependency>
51 <groupId>org.junit.vintage</groupId>
52 <artifactId>junit-vintage-engine</artifactId>
53 </dependency>
54 <dependency>
55 <groupId>org.junit.jupiter</groupId>
56 <artifactId>junit-jupiter-engine</artifactId>
50 <groupId>junit</groupId>
51 <artifactId>junit</artifactId>
5752 </dependency>
5853 <dependency>
5954 <groupId>org.apache.logging.log4j</groupId>
149144 </reportSets>
150145 </plugin>
151146 <plugin>
152 <groupId>com.github.spotbugs</groupId>
153 <artifactId>spotbugs-maven-plugin</artifactId>
147 <groupId>org.codehaus.mojo</groupId>
148 <artifactId>findbugs-maven-plugin</artifactId>
149 <version>${findbugs.plugin.version}</version>
150 <configuration>
151 <fork>true</fork>
152 <jvmArgs>-Duser.language=en</jvmArgs>
153 <threshold>Normal</threshold>
154 <effort>Default</effort>
155 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
156 </configuration>
154157 </plugin>
155158 <plugin>
156159 <groupId>org.apache.maven.plugins</groupId>
1717
1818 import java.io.Serializable;
1919 import java.lang.reflect.Constructor;
20 import java.util.Objects;
2120
2221 import javax.persistence.EntityManager;
2322 import javax.persistence.EntityManagerFactory;
3837 private final String entityClassName;
3938 private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
4039 private final String persistenceUnitName;
40
4141 private EntityManagerFactory entityManagerFactory;
42
4243 private EntityManager entityManager;
4344 private EntityTransaction transaction;
4445
4546 private JpaDatabaseManager(final String name, final int bufferSize,
46 final Class<? extends AbstractLogEventWrapperEntity> entityClass,
47 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
48 final String persistenceUnitName) {
47 final Class<? extends AbstractLogEventWrapperEntity> entityClass,
48 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
49 final String persistenceUnitName) {
4950 super(name, bufferSize);
50 this.entityClassName = Objects.requireNonNull(entityClass, "entityClass").getName();
51 this.entityClassName = entityClass.getName();
5152 this.entityConstructor = entityConstructor;
5253 this.persistenceUnitName = persistenceUnitName;
5354 }
7778 this.transaction.begin();
7879 } catch (final Exception e) {
7980 throw new AppenderLoggingException(
80 "Cannot write logging event or flush buffer; manager cannot create EntityManager or transaction.", e);
81 "Cannot write logging event or flush buffer; manager cannot create EntityManager or transaction.", e
82 );
8183 }
8284 }
8385
8486 @Override
8587 protected void writeInternal(final LogEvent event, final Serializable serializable) {
8688 if (!this.isRunning() || this.entityManagerFactory == null || this.entityManager == null
87 || this.transaction == null) {
89 || this.transaction == null) {
8890 throw new AppenderLoggingException(
89 "Cannot write logging event; JPA manager not connected to the database.");
91 "Cannot write logging event; JPA manager not connected to the database.");
9092 }
9193
9294 AbstractLogEventWrapperEntity entity;
103105 this.transaction.rollback();
104106 this.transaction = null;
105107 }
106 throw new AppenderLoggingException(
107 "Failed to insert record for log event in JPA manager: " + e.getMessage(), e);
108 throw new AppenderLoggingException("Failed to insert record for log event in JPA manager: " +
109 e.getMessage(), e);
108110 }
109111 }
110112
141143 * @param name The name of the manager, which should include connection details, entity class name, etc.
142144 * @param bufferSize The size of the log event buffer.
143145 * @param entityClass The fully-qualified class name of the {@link AbstractLogEventWrapperEntity} concrete
144 * implementation.
146 * implementation.
145147 * @param entityConstructor The one-arg {@link LogEvent} constructor for the concrete entity class.
146148 * @param persistenceUnitName The name of the JPA persistence unit that should be used for persisting log events.
147149 * @return a new or existing JPA manager as applicable.
148150 */
149151 public static JpaDatabaseManager getJPADatabaseManager(final String name, final int bufferSize,
150 final Class<? extends AbstractLogEventWrapperEntity> entityClass,
151 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
152 final String persistenceUnitName) {
152 final Class<? extends AbstractLogEventWrapperEntity>
153 entityClass,
154 final Constructor<? extends AbstractLogEventWrapperEntity>
155 entityConstructor,
156 final String persistenceUnitName) {
153157
154 return AbstractDatabaseManager.getManager(name,
155 new FactoryData(bufferSize, entityClass, entityConstructor, persistenceUnitName), FACTORY);
158 return AbstractDatabaseManager.getManager(
159 name, new FactoryData(bufferSize, entityClass, entityConstructor, persistenceUnitName), FACTORY
160 );
156161 }
157162
158163 /**
164169 private final String persistenceUnitName;
165170
166171 protected FactoryData(final int bufferSize, final Class<? extends AbstractLogEventWrapperEntity> entityClass,
167 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
168 final String persistenceUnitName) {
172 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
173 final String persistenceUnitName) {
169174 super(bufferSize, null);
170175
171176 this.entityClass = entityClass;
180185 private static final class JPADatabaseManagerFactory implements ManagerFactory<JpaDatabaseManager, FactoryData> {
181186 @Override
182187 public JpaDatabaseManager createManager(final String name, final FactoryData data) {
183 return new JpaDatabaseManager(name, data.getBufferSize(), data.entityClass, data.entityConstructor,
184 data.persistenceUnitName);
188 return new JpaDatabaseManager(
189 name, data.getBufferSize(), data.entityClass, data.entityConstructor, data.persistenceUnitName
190 );
185191 }
186192 }
187193 }
2525 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2626 import org.apache.logging.log4j.core.impl.ContextDataFactory;
2727 import org.apache.logging.log4j.util.StringMap;
28 import org.apache.logging.log4j.util.BiConsumer;
2829 import org.apache.logging.log4j.util.Strings;
2930
3031 import com.fasterxml.jackson.databind.JsonNode;
5354 try {
5455 final JsonNodeFactory factory = OBJECT_MAPPER.getNodeFactory();
5556 final ObjectNode root = factory.objectNode();
56 contextData.forEach((key, value) -> root.put(key, String.valueOf(value)));
57 contextData.forEach(new BiConsumer<String, Object>() {
58 @Override
59 public void accept(final String key, final Object value) {
60 // we will cheat here and write the toString of the Object... meh, but ok.
61 root.put(key, String.valueOf(value));
62 }
63 });
5764 return OBJECT_MAPPER.writeValueAsString(root);
5865 } catch (final Exception e) {
5966 throw new PersistenceException("Failed to convert contextData to JSON string.", e);
1717
1818 # Log4j Java Persistence API module
1919
20 As of Log4j 2.11.0, JPA support has moved from the existing module log4j-core to the new module log4j-jpa.
20 As of Log4j 2.11.0, JPA support has moved from the existing module logj-core to the new module log4j-jpa.
2121
2222 ## Requirements
2323
5151 private long id = 0L;
5252
5353 public TestBaseEntity() {
54 super();
5455 }
5556
5657 public TestBaseEntity(final LogEvent wrappedEvent) {
3737 private long id = 0L;
3838
3939 public TestBasicEntity() {
40 super();
4041 }
4142
4243 public TestBasicEntity(final LogEvent wrapped) {
+0
-280
log4j-jpl/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17
18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19 <parent>
20 <artifactId>log4j</artifactId>
21 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
23 <relativePath>../</relativePath>
24 </parent>
25 <modelVersion>4.0.0</modelVersion>
26
27 <properties>
28 <log4jParentDir>${basedir}/..</log4jParentDir>
29 <module.name>org.apache.logging.log4j.jpl</module.name>
30 <maven.doap.skip>true</maven.doap.skip>
31 </properties>
32
33 <artifactId>log4j-jpl</artifactId>
34 <name>Apache Log4j JDK Platform Logging Adapter</name>
35 <description>The Apache Log4j implementation of java.lang.System.LoggerFinder</description>
36
37 <dependencies>
38 <dependency>
39 <groupId>org.apache.logging.log4j</groupId>
40 <artifactId>log4j-api</artifactId>
41 </dependency>
42 <dependency>
43 <groupId>org.apache.logging.log4j</groupId>
44 <artifactId>log4j-core</artifactId>
45 <scope>test</scope>
46 </dependency>
47 <dependency>
48 <groupId>org.apache.logging.log4j</groupId>
49 <artifactId>log4j-core</artifactId>
50 <type>test-jar</type>
51 <scope>test</scope>
52 </dependency>
53 <dependency>
54 <groupId>org.hamcrest</groupId>
55 <artifactId>hamcrest</artifactId>
56 <scope>test</scope>
57 </dependency>
58 <dependency>
59 <groupId>org.junit.vintage</groupId>
60 <artifactId>junit-vintage-engine</artifactId>
61 </dependency>
62 <dependency>
63 <groupId>org.junit.jupiter</groupId>
64 <artifactId>junit-jupiter-engine</artifactId>
65 </dependency>
66 </dependencies>
67
68 <build>
69 <plugins>
70 <!-- Include the standard NOTICE and LICENSE -->
71 <plugin>
72 <groupId>org.apache.maven.plugins</groupId>
73 <artifactId>maven-remote-resources-plugin</artifactId>
74 <executions>
75 <execution>
76 <goals>
77 <goal>process</goal>
78 </goals>
79 <configuration>
80 <skip>false</skip>
81 </configuration>
82 </execution>
83 </executions>
84 </plugin>
85 <plugin>
86 <groupId>org.apache.felix</groupId>
87 <artifactId>maven-bundle-plugin</artifactId>
88 <configuration>
89 <instructions>
90 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
91 <Export-Package>org.apache.logging.log4j.jpl</Export-Package>
92 </instructions>
93 </configuration>
94 </plugin>
95 <plugin>
96 <groupId>org.apache.maven.plugins</groupId>
97 <artifactId>maven-toolchains-plugin</artifactId>
98 <version>3.0.0</version>
99 <executions>
100 <execution>
101 <goals>
102 <goal>toolchain</goal>
103 </goals>
104 </execution>
105 </executions>
106 <configuration>
107 <toolchains>
108 <jdk>
109 <version>[11, )</version>
110 </jdk>
111 </toolchains>
112 </configuration>
113 </plugin>
114 <plugin>
115 <groupId>org.apache.maven.plugins</groupId>
116 <artifactId>maven-compiler-plugin</artifactId>
117 <executions>
118 <execution>
119 <id>default-compile</id>
120 <phase>compile</phase>
121 <goals>
122 <goal>compile</goal>
123 </goals>
124 </execution>
125 <execution>
126 <id>default-testCompile</id>
127 <phase>test-compile</phase>
128 <goals>
129 <goal>testCompile</goal>
130 </goals>
131 </execution>
132 </executions>
133 <configuration>
134 <source>11</source>
135 <target>11</target>
136 <release>11</release>
137 <proc>none</proc>
138 <!-- disable errorprone -->
139 <compilerId>javac</compilerId>
140 </configuration>
141 </plugin>
142 <plugin>
143 <groupId>org.apache.maven.plugins</groupId>
144 <artifactId>maven-surefire-plugin</artifactId>
145 <!-- Do not upgrade until https://issues.apache.org/jira/browse/SUREFIRE-720 is fixed -->
146 <version>2.13</version>
147 <configuration>
148 <excludes combine.self="override" />
149 </configuration>
150 <executions>
151 <execution>
152 <id>test</id>
153 <phase>test</phase>
154 <goals>
155 <goal>test</goal>
156 </goals>
157 </execution>
158 </executions>
159 </plugin>
160 </plugins>
161 </build>
162 <reporting>
163 <plugins>
164 <plugin>
165 <groupId>org.apache.maven.plugins</groupId>
166 <artifactId>maven-changes-plugin</artifactId>
167 <version>${changes.plugin.version}</version>
168 <reportSets>
169 <reportSet>
170 <reports>
171 <report>changes-report</report>
172 </reports>
173 </reportSet>
174 </reportSets>
175 <configuration>
176 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
177 <useJql>true</useJql>
178 </configuration>
179 </plugin>
180 <plugin>
181 <groupId>org.apache.maven.plugins</groupId>
182 <artifactId>maven-checkstyle-plugin</artifactId>
183 <version>${checkstyle.plugin.version}</version>
184 <configuration>
185 <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
186 <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
187 <enableRulesSummary>false</enableRulesSummary>
188 <propertyExpansion>basedir=${basedir}</propertyExpansion>
189 <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
190 <excludes>**/module-info.java</excludes>
191 </configuration>
192 </plugin>
193 <plugin>
194 <groupId>org.apache.maven.plugins</groupId>
195 <artifactId>maven-javadoc-plugin</artifactId>
196 <version>${javadoc.plugin.version}</version>
197 <configuration>
198 <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
199 Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
200 and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
201 <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating
202 project -->
203 <detectOfflineLinks>false</detectOfflineLinks>
204 <linksource>true</linksource>
205 <failOnError>false</failOnError>
206 </configuration>
207 <reportSets>
208 <reportSet>
209 <id>non-aggregate</id>
210 <reports>
211 <report>javadoc</report>
212 </reports>
213 </reportSet>
214 </reportSets>
215 </plugin>
216 <plugin>
217 <groupId>org.apache.maven.plugins</groupId>
218 <artifactId>maven-jxr-plugin</artifactId>
219 <version>${jxr.plugin.version}</version>
220 <reportSets>
221 <reportSet>
222 <id>non-aggregate</id>
223 <reports>
224 <report>jxr</report>
225 </reports>
226 </reportSet>
227 <reportSet>
228 <id>aggregate</id>
229 <reports>
230 <report>aggregate</report>
231 </reports>
232 </reportSet>
233 </reportSets>
234 </plugin>
235 </plugins>
236 </reporting>
237 <profiles>
238 <profile>
239 <id>java11-module</id>
240 <activation>
241 <jdk>[11,)</jdk>
242 </activation>
243 <build>
244 <plugins>
245 <plugin>
246 <groupId>org.apache.maven.plugins</groupId>
247 <artifactId>maven-surefire-plugin</artifactId>
248 <!-- Use Maven Surefire 2.21 which brings module support -->
249 <version>${surefire.plugin.version}</version>
250 <!-- Disable forked VM as 2.21 yields https://issues.apache.org/jira/browse/SUREFIRE-720 -->
251 <configuration combine.self="override" />
252 <executions>
253 <execution>
254 <id>test</id>
255 <phase>test</phase>
256 <goals>
257 <goal>test</goal>
258 </goals>
259 </execution>
260 </executions>
261 </plugin>
262 </plugins>
263 </build>
264 <reporting>
265 <plugins>
266 <plugin>
267 <!-- pmd is not compatible with toolchain and needs same JDK than one use to compile -->
268 <groupId>org.apache.maven.plugins</groupId>
269 <artifactId>maven-pmd-plugin</artifactId>
270 <version>${pmd.plugin.version}</version>
271 <configuration>
272 <targetJdk>${maven.compiler.target}</targetJdk>
273 </configuration>
274 </plugin>
275 </plugins>
276 </reporting>
277 </profile>
278 </profiles>
279 </project>
+0
-136
log4j-jpl/src/main/java/org/apache/logging/log4j/jpl/Log4jSystemLogger.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
17 package org.apache.logging.log4j.jpl;
18
19 import java.lang.System.Logger;
20 import java.util.MissingResourceException;
21 import java.util.Objects;
22 import java.util.ResourceBundle;
23 import java.util.function.Supplier;
24
25 import org.apache.logging.log4j.spi.ExtendedLogger;
26
27 /**
28 * JPL {@link Logger logger} implementation that uses Log4j.
29 * Implement all default {@link Logger} methods to ensure proper class resolution
30 *
31 * @since 2.14
32 */
33 public class Log4jSystemLogger implements Logger {
34
35 private final ExtendedLogger logger;
36
37 private static final String FQCN = Log4jSystemLogger.class.getName();
38
39 public Log4jSystemLogger(final ExtendedLogger logger) {
40 this.logger = logger;
41 }
42
43 @Override
44 public String getName() {
45 return logger.getName();
46 }
47
48 @Override
49 public boolean isLoggable(final Level level) {
50 return logger.isEnabled(getLevel(level));
51 }
52
53 @Override
54 public void log(Level level, String msg) {
55 log(level, (ResourceBundle) null, msg, (Object[]) null);
56 }
57
58 @Override
59 public void log(Level level, Supplier<String> msgSupplier) {
60 Objects.requireNonNull(msgSupplier);
61 if (isLoggable(Objects.requireNonNull(level))) {
62 log(level, (ResourceBundle) null, msgSupplier.get(), (Object[]) null);
63 }
64 }
65
66 @Override
67 public void log(Level level, Object obj) {
68 Objects.requireNonNull(obj);
69 if (isLoggable(Objects.requireNonNull(level))) {
70 log(level, (ResourceBundle) null, obj.toString(), (Object[]) null);
71 }
72 }
73
74 @Override
75 public void log(Level level, String msg, Throwable thrown) {
76 log(level, null, msg, thrown);
77 }
78
79 @Override
80 public void log(Level level, Supplier<String> msgSupplier, Throwable thrown) {
81 Objects.requireNonNull(msgSupplier);
82 if (isLoggable(Objects.requireNonNull(level))) {
83 log(level, null, msgSupplier.get(), thrown);
84 }
85 }
86
87 @Override
88 public void log(Level level, String format, Object... params) {
89 log(level, null, format, params);
90 }
91
92 @Override
93 public void log(final Level level, final ResourceBundle bundle, final String msg, final Throwable thrown) {
94 logger.logIfEnabled(FQCN, getLevel(level), null, getResource(bundle, msg), thrown);
95 }
96
97 @Override
98 public void log(final Level level, final ResourceBundle bundle, final String format, final Object... params) {
99 logger.logIfEnabled(FQCN, getLevel(level), null, getResource(bundle, format), params);
100 }
101
102 private static org.apache.logging.log4j.Level getLevel(final Level level) {
103 switch (level) {
104 case OFF:
105 return org.apache.logging.log4j.Level.OFF;
106 case ERROR:
107 return org.apache.logging.log4j.Level.ERROR;
108 case WARNING:
109 return org.apache.logging.log4j.Level.WARN;
110 case INFO:
111 return org.apache.logging.log4j.Level.INFO;
112 case DEBUG:
113 return org.apache.logging.log4j.Level.DEBUG;
114 case TRACE:
115 return org.apache.logging.log4j.Level.TRACE;
116 case ALL:
117 return org.apache.logging.log4j.Level.ALL;
118 }
119 return org.apache.logging.log4j.Level.ERROR;
120 }
121
122 private static String getResource(ResourceBundle bundle, String msg) {
123 if (bundle == null || msg == null) {
124 return msg;
125 }
126 try {
127 return bundle.getString(msg);
128 } catch (MissingResourceException e) {
129 // ignore
130 return msg;
131 } catch (ClassCastException ex) {
132 return bundle.getObject(msg).toString();
133 }
134 }
135 }
+0
-46
log4j-jpl/src/main/java/org/apache/logging/log4j/jpl/Log4jSystemLoggerAdapter.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
17 package org.apache.logging.log4j.jpl;
18
19 import java.lang.System.Logger;
20 import java.lang.System.LoggerFinder;
21
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
24 import org.apache.logging.log4j.spi.LoggerContext;
25 import org.apache.logging.log4j.util.StackLocatorUtil;
26
27 /**
28 * {@link Logger} registry implementation using just log4j-api.
29 *
30 * @since 2.14
31 */
32 public class Log4jSystemLoggerAdapter extends AbstractLoggerAdapter<Logger> {
33
34 @Override
35 protected Logger newLogger(String name, LoggerContext context) {
36 return new Log4jSystemLogger(context.getLogger(name));
37 }
38
39 @Override
40 protected LoggerContext getContext() {
41 return getContext(LogManager.getFactory().isClassLoaderDependent()
42 ? StackLocatorUtil.getCallerClass(LoggerFinder.class)
43 : null);
44 }
45 }
+0
-33
log4j-jpl/src/main/java/org/apache/logging/log4j/jpl/Log4jSystemLoggerFinder.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
17 package org.apache.logging.log4j.jpl;
18
19 import java.lang.System.Logger;
20
21 /**
22 * @since 2.14
23 */
24 public class Log4jSystemLoggerFinder extends System.LoggerFinder {
25
26 private final Log4jSystemLoggerAdapter loggerAdapter = new Log4jSystemLoggerAdapter();
27
28 @Override
29 public Logger getLogger(String name, Module module) {
30 return loggerAdapter.getLogger(name);
31 }
32 }
+0
-1
log4j-jpl/src/main/resources/META-INF/services/java.lang.System$LoggerFinder less more
0 org.apache.logging.log4j.jpl.Log4jSystemLoggerFinder
+0
-30
log4j-jpl/src/site/markdown/index.md less more
0 <!-- vim: set syn=markdown : -->
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17
18 # Log4j 2 JDK Platform Logging Adapter
19
20 The Log4j 2 JDK Logging Adapter allow to route all System.Logger events to Log4j 2 APIs.
21
22 ## Requirements
23
24 The JDK Platform Logging Adapter is dependent on the Log4j API as well as Java 11.
25
26 ## Usage
27
28 Simply include the Log4j 2 JDK Platform Logging Adapter jar along with the Log4j2 jars to cause all System.Logger
29 logging to be handled by Log4j 2.
+0
-52
log4j-jpl/src/site/site.xml 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 -->
17 <project name="Log4j JDK Platform Logging Adapter"
18 xmlns="http://maven.apache.org/DECORATION/1.4.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
21 <body>
22 <links>
23 <item name="Apache" href="http://www.apache.org/" />
24 <item name="Logging Services" href="http://logging.apache.org/"/>
25 <item name="Log4j" href="../index.html"/>
26 </links>
27
28 <!-- Component-specific reports -->
29 <menu ref="reports"/>
30
31 <!-- Overall Project Info -->
32 <menu name="Log4j Project Information" img="icon-info-sign">
33 <item name="Dependencies" href="../dependencies.html" />
34 <item name="Dependency Convergence" href="../dependency-convergence.html" />
35 <item name="Dependency Management" href="../dependency-management.html" />
36 <item name="Project Team" href="../team-list.html" />
37 <item name="Mailing Lists" href="../mail-lists.html" />
38 <item name="Issue Tracking" href="../issue-tracking.html" />
39 <item name="Project License" href="../license.html" />
40 <item name="Source Repository" href="../source-repository.html" />
41 <item name="Project Summary" href="../project-summary.html" />
42 </menu>
43
44 <menu name="Log4j Project Reports" img="icon-cog">
45 <item name="Changes Report" href="../changes-report.html" />
46 <item name="JIRA Report" href="../jira-report.html" />
47 <item name="Surefire Report" href="../surefire-report.html" />
48 <item name="RAT Report" href="../rat-report.html" />
49 </menu>
50 </body>
51 </project>
+0
-122
log4j-jpl/src/test/java/org/apache/logging/log4j/jpl/Log4jSystemLoggerTest.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
17 package org.apache.logging.log4j.jpl;
18
19 import static org.hamcrest.Matchers.equalTo;
20 import static org.hamcrest.Matchers.hasSize;
21 import static org.hamcrest.Matchers.instanceOf;
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertThat;
25
26 import java.lang.System.Logger;
27 import java.util.List;
28
29 import org.apache.logging.log4j.Level;
30 import org.apache.logging.log4j.core.LogEvent;
31 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
32 import org.apache.logging.log4j.test.appender.ListAppender;
33 import org.junit.After;
34 import org.junit.Before;
35 import org.junit.Test;
36
37 public class Log4jSystemLoggerTest {
38
39 public static final String LOGGER_NAME = "Test";
40 protected Logger logger;
41 protected ListAppender eventAppender;
42 protected ListAppender stringAppender;
43
44 @Before
45 public void setUp() throws Exception {
46 logger = System.getLogger(LOGGER_NAME);
47 assertThat(logger, instanceOf(Log4jSystemLogger.class));
48 eventAppender = ListAppender.getListAppender("TestAppender");
49 stringAppender = ListAppender.getListAppender("StringAppender");
50 assertNotNull(eventAppender);
51 assertNotNull(stringAppender);
52 }
53
54 @After
55 public void tearDown() throws Exception {
56 if (eventAppender != null) {
57 eventAppender.clear();
58 }
59 if (stringAppender != null) {
60 stringAppender.clear();
61 }
62 }
63
64 @Test
65 public void testGetName() throws Exception {
66 assertThat(logger.getName(), equalTo(LOGGER_NAME));
67 }
68
69 @Test
70 public void testIsLoggable() throws Exception {
71 assertThat(logger.isLoggable(Logger.Level.ERROR), equalTo(true));
72 }
73
74 @Test
75 public void testLog() throws Exception {
76 logger.log(Logger.Level.INFO, "Informative message here.");
77 final List<LogEvent> events = eventAppender.getEvents();
78 assertThat(events, hasSize(1));
79 final LogEvent event = events.get(0);
80 assertThat(event, instanceOf(Log4jLogEvent.class));
81 assertEquals(Level.INFO, event.getLevel());
82 assertEquals(LOGGER_NAME, event.getLoggerName());
83 assertEquals("Informative message here.", event.getMessage().getFormattedMessage());
84 assertEquals(Log4jSystemLogger.class.getName(), event.getLoggerFqcn());
85 }
86
87 @Test
88 public void testLogWithCallingClass() throws Exception {
89 final Logger log = System.getLogger("Test.CallerClass");
90 log.log(Logger.Level.INFO, "Calling from LoggerTest");
91 final List<String> messages = stringAppender.getMessages();
92 assertThat(messages, hasSize(1));
93 final String message = messages.get(0);
94 assertEquals(Log4jSystemLoggerTest.class.getName(), message);
95 }
96
97 @Test
98 public void testCurlyBraces() {
99 testMessage("{message}");
100 }
101
102 @Test
103 public void testPercent() {
104 testMessage("message%s");
105 }
106
107 @Test
108 public void testPercentAndCurlyBraces() {
109 testMessage("message{%s}");
110 }
111
112 private void testMessage(final String string) {
113 logger.log(Logger.Level.INFO, "Test info " + string);
114 final List<LogEvent> events = eventAppender.getEvents();
115 assertThat(events, hasSize(1));
116 for (final LogEvent event : events) {
117 final String message = event.getMessage().getFormattedMessage();
118 assertThat(message, equalTo("Test info " + string));
119 }
120 }
121 }
+0
-39
log4j-jpl/src/test/resources/log4j2-test.xml 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
17 <Configuration name="LoggerTest" status="OFF">
18 <Appenders>
19 <List name="TestAppender"/>
20 <List name="StringAppender">
21 <PatternLayout pattern="%class"/>
22 </List>
23 <Console name="Console" target="SYSTEM_ERR">
24 <PatternLayout pattern="%highlight{%p - %m%n}"/>
25 </Console>
26 </Appenders>
27 <Loggers>
28 <Logger name="Test" level="DEBUG" additivity="false">
29 <AppenderRef ref="TestAppender"/>
30 </Logger>
31 <Logger name="Test.CallerClass" level="DEBUG" additivity="false">
32 <AppenderRef ref="StringAppender"/>
33 </Logger>
34 <Root level="ERROR">
35 <AppenderRef ref="Console"/>
36 </Root>
37 </Loggers>
38 </Configuration>
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <modelVersion>4.0.0</modelVersion>
2727 <properties>
2828 <log4jParentDir>${basedir}/..</log4jParentDir>
2929 <module.name>org.apache.logging.log4j.jul</module.name>
30 <maven.doap.skip>true</maven.doap.skip>
3130 </properties>
3231
3332 <artifactId>log4j-jul</artifactId>
5251 </dependency>
5352 <dependency>
5453 <groupId>org.hamcrest</groupId>
55 <artifactId>hamcrest</artifactId>
56 <scope>test</scope>
57 </dependency>
58 <dependency>
59 <groupId>org.assertj</groupId>
60 <artifactId>assertj-core</artifactId>
54 <artifactId>hamcrest-all</artifactId>
6155 <scope>test</scope>
6256 </dependency>
6357 <dependency>
6458 <groupId>junit</groupId>
6559 <artifactId>junit</artifactId>
66 </dependency>
67 <!-- Required for AsyncLogger testing -->
68 <dependency>
69 <groupId>com.lmax</groupId>
70 <artifactId>disruptor</artifactId>
7160 <scope>test</scope>
7261 </dependency>
7362 </dependencies>
9988 </instructions>
10089 </configuration>
10190 </plugin>
102 <plugin>
103 <groupId>org.apache.maven.plugins</groupId>
104 <artifactId>maven-surefire-plugin</artifactId>
105 <version>${surefire.plugin.version}</version>
106 <configuration>
107 <systemPropertyVariables>
108 <java.awt.headless>true</java.awt.headless>
109 </systemPropertyVariables>
110 <argLine>-Xms256m -Xmx1024m</argLine>
111 <forkCount>1</forkCount>
112 <reuseForks>false</reuseForks>
113 </configuration>
114 <executions>
115 <execution>
116 <id>default-test</id>
117 <phase>test</phase>
118 <goals>
119 <goal>test</goal>
120 </goals>
121 <configuration>
122 <excludes>
123 <exclude>${log4j.skip.test1}</exclude>
124 <exclude>${log4j.skip.test2}</exclude>
125 <exclude>Log4jBridgeHandlerTest.java</exclude>
126 </excludes>
127 </configuration>
128 </execution>
129 <execution>
130 <!-- this test needs some special configuration, thus its own run -->
131 <id>bridgeHandler-test</id>
132 <phase>test</phase>
133 <goals>
134 <goal>test</goal>
135 </goals>
136 <configuration>
137 <includes>
138 <include>Log4jBridgeHandlerTest.java</include>
139 </includes>
140 <systemPropertyVariables>
141 <java.util.logging.config.file>src/test/resources/logging-test.properties</java.util.logging.config.file>
142 <log4j2.configurationFile>log4j2-julBridge-test.xml</log4j2.configurationFile>
143 </systemPropertyVariables>
144 </configuration>
145 </execution>
146 </executions>
147 </plugin>
91 <plugin>
92 <groupId>org.apache.maven.plugins</groupId>
93 <artifactId>maven-surefire-plugin</artifactId>
94 <version>${surefire.plugin.version}</version>
95 <configuration>
96 <systemPropertyVariables>
97 <java.awt.headless>true</java.awt.headless>
98 </systemPropertyVariables>
99 <argLine>-Xms256m -Xmx1024m</argLine>
100 <forkCount>1</forkCount>
101 <reuseForks>false</reuseForks>
102 <excludes>
103 <exclude>${log4j.skip.test1}</exclude>
104 <exclude>${log4j.skip.test2}</exclude>
105 </excludes>
106 </configuration>
107 </plugin>
148108 </plugins>
149109 </build>
150110 <reporting>
201161 </reportSets>
202162 </plugin>
203163 <plugin>
204 <groupId>com.github.spotbugs</groupId>
205 <artifactId>spotbugs-maven-plugin</artifactId>
164 <groupId>org.codehaus.mojo</groupId>
165 <artifactId>findbugs-maven-plugin</artifactId>
166 <version>${findbugs.plugin.version}</version>
167 <configuration>
168 <fork>true</fork>
169 <jvmArgs>-Duser.language=en</jvmArgs>
170 <threshold>Normal</threshold>
171 <effort>Default</effort>
172 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
173 </configuration>
206174 </plugin>
207175 <plugin>
208176 <groupId>org.apache.maven.plugins</groupId>
1717
1818 import java.util.logging.Logger;
1919
20 import org.apache.logging.log4j.LogManager;
2120 import org.apache.logging.log4j.spi.LoggerContext;
2221 import org.apache.logging.log4j.util.StackLocatorUtil;
2322
3130
3231 @Override
3332 protected LoggerContext getContext() {
34 return getContext(LogManager.getFactory().isClassLoaderDependent()
35 ? StackLocatorUtil.getCallerClass(java.util.logging.LogManager.class)
36 : null);
33 return getContext(StackLocatorUtil.getCallerClass(java.util.logging.LogManager.class));
3734 }
3835
3936 }
5050 super(logger.getName(), null);
5151 final Level javaLevel = LevelTranslator.toJavaLevel(logger.getLevel());
5252 // "java.util.logging.LoggingPermission" "control"
53 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
54 ApiLogger.super.setLevel(javaLevel);
55 return null;
53 AccessController.doPrivileged(new PrivilegedAction<Object>() {
54 @Override
55 public Object run() {
56 ApiLogger.super.setLevel(javaLevel);
57 return null;
58 }
5659 });
5760 this.logger = new WrappedLogger(logger);
5861 }
115118
116119 @Override
117120 public void log(final Level level, final String msg) {
118 if (getFilter() == null) {
119 logger.log(LevelTranslator.toLevel(level), msg);
120 } else {
121 super.log(level, msg);
122 }
121 logger.log(LevelTranslator.toLevel(level), msg);
123122 }
124123
125124 @Override
126125 public void log(final Level level, final String msg, final Object param1) {
127 if (getFilter() == null) {
128 logger.log(LevelTranslator.toLevel(level), msg, param1);
129 } else {
130 super.log(level, msg, param1);
131 }
126 logger.log(LevelTranslator.toLevel(level), msg, param1);
132127 }
133128
134129 @Override
135130 public void log(final Level level, final String msg, final Object[] params) {
136 if (getFilter() == null) {
137 logger.log(LevelTranslator.toLevel(level), msg, params);
138 } else {
139 super.log(level, msg, params);
140 }
131 logger.log(LevelTranslator.toLevel(level), msg, params);
141132 }
142133
143134 @Override
144135 public void log(final Level level, final String msg, final Throwable thrown) {
145 if (getFilter() == null) {
146 logger.log(LevelTranslator.toLevel(level), msg, thrown);
147 } else {
148 super.log(level, msg, thrown);
149 }
136 logger.log(LevelTranslator.toLevel(level), msg, thrown);
150137 }
151138
152139 @Override
228215
229216 @Override
230217 public void severe(final String msg) {
231 if (getFilter() == null) {
232 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.ERROR, null, msg);
233 } else {
234 super.severe(msg);
235 }
218 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.ERROR, null, msg);
236219 }
237220
238221 @Override
239222 public void warning(final String msg) {
240 if (getFilter() == null) {
241 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.WARN, null, msg);
242 } else {
243 super.warning(msg);
244 }
223 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.WARN, null, msg);
245224 }
246225
247226 @Override
248227 public void info(final String msg) {
249 if (getFilter() == null) {
250 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.INFO, null, msg);
251 } else {
252 super.info(msg);
253 }
228 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.INFO, null, msg);
254229 }
255230
256231 @Override
257232 public void config(final String msg) {
258 if (getFilter() == null) {
259 logger.logIfEnabled(FQCN, LevelTranslator.CONFIG, null, msg);
260 } else {
261 super.config(msg);
262 }
233 logger.logIfEnabled(FQCN, LevelTranslator.CONFIG, null, msg);
263234 }
264235
265236 @Override
266237 public void fine(final String msg) {
267 if (getFilter() == null) {
268 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.DEBUG, null, msg);
269 } else {
270 super.fine(msg);
271 }
238 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.DEBUG, null, msg);
272239 }
273240
274241 @Override
275242 public void finer(final String msg) {
276 if (getFilter() == null) {
277 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.TRACE, null, msg);
278 } else {
279 super.finer(msg);
280 }
243 logger.logIfEnabled(FQCN, org.apache.logging.log4j.Level.TRACE, null, msg);
281244 }
282245
283246 @Override
284247 public void finest(final String msg) {
285 if (getFilter() == null) {
286 logger.logIfEnabled(FQCN, LevelTranslator.FINEST, null, msg);
287 } else {
288 super.finest(msg);
289 }
248 logger.logIfEnabled(FQCN, LevelTranslator.FINEST, null, msg);
290249 }
291250 }
+0
-319
log4j-jul/src/main/java/org/apache/logging/log4j/jul/Log4jBridgeHandler.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.logging.log4j.jul;
17
18 //note: NO import of Logger, Level, LogManager to prevent conflicts JUL/log4j
19 import java.beans.PropertyChangeEvent;
20 import java.beans.PropertyChangeListener;
21 import java.util.Enumeration;
22 import java.util.HashSet;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.logging.LogRecord;
26
27 import org.apache.logging.log4j.core.LoggerContext;
28 import org.apache.logging.log4j.core.config.Configuration;
29 import org.apache.logging.log4j.core.config.LoggerConfig;
30 import org.apache.logging.log4j.spi.ExtendedLogger;
31 import org.apache.logging.log4j.status.StatusLogger;
32
33
34 /**
35 * Bridge from JUL to log4j2.<br>
36 * This is an alternative to log4j.jul.LogManager (running as complete JUL replacement),
37 * especially useful for webapps running on a container for which the LogManager cannot or
38 * should not be used.<br><br>
39 *
40 * Installation/usage:<ul>
41 * <li> Declaratively inside JUL's <code>logging.properties</code>:<br>
42 * <code>handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler</code><br>
43 * (and typically also:   <code>org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true</code> )<br>
44 * Note: in a webapp running on Tomcat, you may create a <code>WEB-INF/classes/logging.properties</code>
45 * file to configure JUL for this webapp only: configured handlers and log levels affect your webapp only!
46 * This file is then the <i>complete</i> JUL configuration, so JUL's defaults (e.g. log level INFO) apply
47 * for stuff not explicitly defined therein.
48 * <li> Programmatically by calling <code>install()</code> method,
49 * e.g. inside ServletContextListener static-class-init. or contextInitialized()
50 * </ul>
51 * Configuration (in JUL's <code>logging.properties</code>):<ul>
52 * <li> Log4jBridgeHandler.<code>suffixToAppend</code><br>
53 * String, suffix to append to JUL logger names, to easily recognize bridged log messages.
54 * A dot "." is automatically prepended, so configuration for the basis logger is used<br>
55 * Example: <code>Log4jBridgeHandler.suffixToAppend = _JUL</code><br>
56 * Useful, for example, if you use JSF because it logs exceptions and throws them afterwards;
57 * you can easily recognize the duplicates with this (or concentrate on the non-JUL-logs).
58 * <li> Log4jBridgeHandler.<code>propagateLevels</code>   boolean, "true" to automatically propagate log4j log levels to JUL.
59 * <li> Log4jBridgeHandler.<code>sysoutDebug</code>   boolean, perform some (developer) debug output to sysout
60 * </ul>
61 *
62 * Log levels are translated with {@link LevelTranslator}, see also
63 * <a href="https://logging.apache.org/log4j/2.x/log4j-jul/index.html#Default_Level_Conversions">log4j doc</a>.<br><br>
64 *
65 * Restrictions:<ul>
66 * <li> Manually given source/location info in JUL (e.g. entering(), exiting(), throwing(), logp(), logrb() )
67 * will NOT be considered, i.e. gets lost in log4j logging.
68 * <li> Log levels of JUL have to be adjusted according to log4j log levels:
69 * Either by using "propagateLevels" (preferred), or manually by specifying them explicitly,
70 * i.e. logging.properties and log4j2.xml have some redundancies.
71 * <li> Only JUL log events that are allowed according to the JUL log level get to this handler and thus to log4j.
72 * This is only relevant and important if you NOT use "propagateLevels".
73 * If you set <code>.level = SEVERE</code> only error logs will be seen by this handler and thus log4j
74 * - even if the corresponding log4j log level is ALL.<br>
75 * On the other side, you should NOT set <code>.level = FINER or FINEST</code> if the log4j level is higher.
76 * In this case a lot of JUL log events would be generated, sent via this bridge to log4j and thrown away by the latter.<br>
77 * Note: JUL's default log level (i.e. none specified in logger.properties) is INFO.
78 * </ul>
79 *
80 * (Credits: idea and concept originate from org.slf4j.bridge.SLF4JBridgeHandler;
81 * level propagation idea originates from logback/LevelChangePropagator;
82 * but no source code has been copied)
83 */
84 public class Log4jBridgeHandler extends java.util.logging.Handler implements PropertyChangeListener {
85 private static final org.apache.logging.log4j.Logger SLOGGER = StatusLogger.getLogger();
86
87 // the caller of the logging is java.util.logging.Logger (for location info)
88 private static final String FQCN = java.util.logging.Logger.class.getName();
89 private static final String UNKNOWN_LOGGER_NAME = "unknown.jul.logger";
90 private static final java.util.logging.Formatter julFormatter = new java.util.logging.SimpleFormatter();
91
92 private boolean doDebugOutput = false;
93 private String julSuffixToAppend = null;
94 //not needed: private boolean installAsLevelPropagator = false;
95
96
97 /**
98 * Adds a new Log4jBridgeHandler instance to JUL's root logger.
99 * This is a programmatic alternative to specify
100 * <code>handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler</code>
101 * and its configuration in logging.properties.<br>
102 * @param removeHandlersForRootLogger true to remove all other installed handlers on JUL root level
103 */
104 public static void install(boolean removeHandlersForRootLogger, String suffixToAppend, boolean propagateLevels) {
105 java.util.logging.Logger rootLogger = getJulRootLogger();
106 if (removeHandlersForRootLogger) {
107 for (java.util.logging.Handler hdl : rootLogger.getHandlers()) {
108 rootLogger.removeHandler(hdl);
109 }
110 }
111 rootLogger.addHandler(new Log4jBridgeHandler(false, suffixToAppend, propagateLevels));
112 // note: filter-level of Handler defaults to ALL, so nothing to do here
113 }
114
115 private static java.util.logging.Logger getJulRootLogger() {
116 return java.util.logging.LogManager.getLogManager().getLogger("");
117 }
118
119
120 /** Initialize this handler by reading out JUL configuration. */
121 public Log4jBridgeHandler() {
122 final java.util.logging.LogManager julLogMgr = java.util.logging.LogManager.getLogManager();
123 final String className = this.getClass().getName();
124 init(Boolean.parseBoolean(julLogMgr.getProperty(className + ".sysoutDebug")),
125 julLogMgr.getProperty(className + ".appendSuffix"),
126 Boolean.parseBoolean(julLogMgr.getProperty(className + ".propagateLevels")) );
127
128 }
129
130 /** Initialize this handler with given configuration. */
131 public Log4jBridgeHandler(boolean debugOutput, String suffixToAppend, boolean propagateLevels) {
132 init(debugOutput, suffixToAppend, propagateLevels);
133 }
134
135
136 /** Perform init. of this handler with given configuration (typical use is for constructor). */
137 protected void init(boolean debugOutput, String suffixToAppend, boolean propagateLevels) {
138 this.doDebugOutput = debugOutput;
139 if (debugOutput) {
140 new Exception("DIAGNOSTIC ONLY (sysout): Log4jBridgeHandler instance created (" + this + ")")
141 .printStackTrace(System.out); // is no error thus no syserr
142 }
143
144 if (suffixToAppend != null) {
145 suffixToAppend = suffixToAppend.trim(); // remove spaces
146 if (suffixToAppend.isEmpty()) {
147 suffixToAppend = null;
148 } else if (suffixToAppend.charAt(0) != '.') { // always make it a sub-logger
149 suffixToAppend = '.' + suffixToAppend;
150 }
151 }
152 this.julSuffixToAppend = suffixToAppend;
153
154 //not needed: this.installAsLevelPropagator = propagateLevels;
155 if (propagateLevels) {
156 @SuppressWarnings("resource") // no need to close the AutoCloseable ctx here
157 LoggerContext context = LoggerContext.getContext(false);
158 context.addPropertyChangeListener(this);
159 propagateLogLevels(context.getConfiguration());
160 // note: java.util.logging.LogManager.addPropertyChangeListener() could also
161 // be set here, but a call of JUL.readConfiguration() will be done on purpose
162 }
163
164 SLOGGER.debug("Log4jBridgeHandler init. with: suffix='{}', lvlProp={}, instance={}",
165 suffixToAppend, propagateLevels, this);
166 }
167
168
169 @Override
170 public void close() {
171 // cleanup and remove listener and JUL logger references
172 julLoggerRefs = null;
173 LoggerContext.getContext(false).removePropertyChangeListener(this);
174 if (doDebugOutput) {
175 System.out.println("sysout: Log4jBridgeHandler close(): " + this);
176 }
177 }
178
179
180 @Override
181 public void publish(LogRecord record) {
182 if (record == null) { // silently ignore null records
183 return;
184 }
185
186 org.apache.logging.log4j.Logger log4jLogger = getLog4jLogger(record);
187 String msg = julFormatter.formatMessage(record); // use JUL's implementation to get real msg
188 /* log4j allows nulls:
189 if (msg == null) {
190 // JUL allows nulls, but other log system may not
191 msg = "<null log msg>";
192 } */
193 org.apache.logging.log4j.Level log4jLevel = LevelTranslator.toLevel(record.getLevel());
194 Throwable thrown = record.getThrown();
195 if (log4jLogger instanceof ExtendedLogger) {
196 // relevant for location information
197 try {
198 ((ExtendedLogger) log4jLogger).logIfEnabled(FQCN, log4jLevel, null, msg, thrown);
199 } catch (NoClassDefFoundError e) {
200 // sometimes there are problems with log4j.ExtendedStackTraceElement, so try a workaround
201 log4jLogger.warn("Log4jBridgeHandler: ignored exception when calling 'ExtendedLogger': {}", e.toString());
202 log4jLogger.log(log4jLevel, msg, thrown);
203 }
204 } else {
205 log4jLogger.log(log4jLevel, msg, thrown);
206 }
207 }
208
209
210 @Override
211 public void flush() {
212 // nothing to do
213 }
214
215
216 /**
217 * Return the log4j-Logger instance that will be used for logging.
218 * Handles null name case and appends configured suffix.
219 */
220 private org.apache.logging.log4j.Logger getLog4jLogger(LogRecord record) {
221 String name = record.getLoggerName();
222 if (name == null) {
223 name = UNKNOWN_LOGGER_NAME;
224 } else if (julSuffixToAppend != null) {
225 name += julSuffixToAppend;
226 }
227 return org.apache.logging.log4j.LogManager.getLogger(name);
228 }
229
230
231 ///// log level propagation code
232
233
234 @Override
235 // impl. for PropertyChangeListener
236 public void propertyChange(PropertyChangeEvent evt) {
237 SLOGGER.debug("Log4jBridgeHandler.propertyChange(): {}", evt);
238 if (LoggerContext.PROPERTY_CONFIG.equals(evt.getPropertyName()) && evt.getNewValue() instanceof Configuration) {
239 propagateLogLevels((Configuration) evt.getNewValue());
240 }
241 }
242
243
244 /** Save "hard" references to configured JUL loggers. (is lazy init.) */
245 private Set<java.util.logging.Logger> julLoggerRefs;
246 /** Perform developer tests? (Should be unused/outcommented for real code) */
247 //private static final boolean DEVTEST = false;
248
249
250 private void propagateLogLevels(Configuration config) {
251 SLOGGER.debug("Log4jBridgeHandler.propagateLogLevels(): {}", config);
252 // clear or init. saved JUL logger references
253 // JUL loggers have to be explicitly referenced because JUL internally uses
254 // weak references so not instantiated loggers may be garbage collected
255 // and their level config gets lost then.
256 if (julLoggerRefs == null) {
257 julLoggerRefs = new HashSet<>();
258 } else {
259 julLoggerRefs.clear();
260 }
261
262 //if (DEVTEST) debugPrintJulLoggers("Start of propagation");
263 // walk through all log4j configured loggers and set JUL level accordingly
264 final Map<String, LoggerConfig> log4jLoggers = config.getLoggers();
265 //java.util.List<String> outTxt = new java.util.ArrayList<>(); // DEVTEST / DEV-DEBUG ONLY
266 for (LoggerConfig lcfg : log4jLoggers.values()) {
267 java.util.logging.Logger julLog = java.util.logging.Logger.getLogger(lcfg.getName()); // this also fits for root = ""
268 java.util.logging.Level julLevel = LevelTranslator.toJavaLevel(lcfg.getLevel()); // lcfg.getLevel() never returns null
269 julLog.setLevel(julLevel);
270 julLoggerRefs.add(julLog); // save an explicit reference to prevent GC
271 //if (DEVTEST) outTxt.add("propagating '" + lcfg.getName() + "' / " + lcfg.getLevel() + " -> " + julLevel);
272 } // for
273 //if (DEVTEST) java.util.Collections.sort(outTxt, String.CASE_INSENSITIVE_ORDER);
274 //if (DEVTEST) for (String s : outTxt) System.out.println("+ " + s);
275 //if (DEVTEST) debugPrintJulLoggers("After propagation");
276
277 // cleanup JUL: reset all log levels not explicitly given by log4j
278 // This has to happen after propagation because JUL creates and inits. the loggers lazily
279 // so a nested logger might be created during the propagation-for-loop above and gets
280 // its JUL-configured level not until then.
281 final java.util.logging.LogManager julMgr = java.util.logging.LogManager.getLogManager();
282 for (Enumeration<String> en = julMgr.getLoggerNames(); en.hasMoreElements(); ) {
283 java.util.logging.Logger julLog = julMgr.getLogger(en.nextElement());
284 if (julLog != null && julLog.getLevel() != null && !"".equals(julLog.getName())
285 && !log4jLoggers.containsKey(julLog.getName()) ) {
286 julLog.setLevel(null);
287 }
288 } // for
289 //if (DEVTEST) debugPrintJulLoggers("After JUL cleanup");
290 }
291
292
293 /* DEV-DEBUG ONLY (comment out for release) *xx/
294 private void debugPrintJulLoggers(String infoStr) {
295 if (!DEVTEST) return;
296 java.util.logging.LogManager julMgr = java.util.logging.LogManager.getLogManager();
297 System.out.println("sysout: " + infoStr + " - for " + julMgr);
298 java.util.List<String> txt = new java.util.ArrayList<>();
299 int n = 1;
300 for (Enumeration<String> en = julMgr.getLoggerNames(); en.hasMoreElements(); ) {
301 String ln = en.nextElement();
302 java.util.logging.Logger lg = julMgr.getLogger(ln);
303 if (lg == null) {
304 txt.add("(!null-Logger '" + ln + "') #" + n);
305 } else if (lg.getLevel() == null) {
306 txt.add("(null-Level Logger '" + ln + "') #" + n);
307 } else {
308 txt.add("Logger '" + ln + "', lvl = " + lg.getLevel() + " #" + n);
309 }
310 n++;
311 } // for
312 java.util.Collections.sort(txt, String.CASE_INSENSITIVE_ORDER);
313 for (String s : txt) {
314 System.out.println(" - " + s);
315 }
316 } /**/
317
318 }
1717
1818 import java.util.Collections;
1919 import java.util.Enumeration;
20 import java.util.HashSet;
21 import java.util.Set;
2220 import java.util.logging.Logger;
2321
2422 import org.apache.logging.log4j.LoggingException;
4240
4341 private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
4442 private final AbstractLoggerAdapter loggerAdapter;
45 // Contains the set of logger names that are actively being requested using getLogger.
46 private final ThreadLocal<Set<String>> recursive = ThreadLocal.withInitial(HashSet::new);
4743
4844 public LogManager() {
45 super();
4946 AbstractLoggerAdapter adapter = null;
5047 final String overrideAdaptorClassName =
5148 PropertiesUtil.getProperties().getStringProperty(Constants.LOGGER_ADAPTOR_PROPERTY);
8885 @Override
8986 public Logger getLogger(final String name) {
9087 LOGGER.trace("Call to LogManager.getLogger({})", name);
91 Set<String> activeRequests = recursive.get();
92 if (activeRequests.add(name)) {
93 try {
94 return loggerAdapter.getLogger(name);
95 } finally {
96 activeRequests.remove(name);
97 }
98 }
99 LOGGER.warn("Recursive call to getLogger for {} ignored.", name);
100 return new NoOpLogger(name);
88 return loggerAdapter.getLogger(name);
10189 }
10290
10391 @Override
+0
-209
log4j-jul/src/main/java/org/apache/logging/log4j/jul/NoOpLogger.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.logging.log4j.jul;
17
18 import java.util.ResourceBundle;
19 import java.util.function.Supplier;
20 import java.util.logging.Level;
21 import java.util.logging.LogRecord;
22 import java.util.logging.Logger;
23
24 /**
25 * Dummy version of a java.util.Logger.
26 */
27 public class NoOpLogger extends Logger {
28
29 protected NoOpLogger(String name) {
30 super(name, null);
31 }
32
33 @Override
34 public void log(LogRecord record) {
35 }
36
37 @Override
38 public void log(Level level, String msg) {
39 }
40
41 @Override
42 public void log(Level level, Supplier<String> msgSupplier) {
43 }
44
45 @Override
46 public void log(Level level, String msg, Object param1) {
47 }
48
49 @Override
50 public void log(Level level, String msg, Object[] params) {
51 }
52
53 @Override
54 public void log(Level level, String msg, Throwable thrown) {
55 }
56
57 @Override
58 public void log(Level level, Throwable thrown, Supplier<String> msgSupplier) {
59 }
60
61 @Override
62 public void logp(Level level, String sourceClass, String sourceMethod, String msg) {
63 }
64
65 @Override
66 public void logp(Level level, String sourceClass, String sourceMethod, Supplier<String> msgSupplier) {
67 }
68
69 @Override
70 public void logp(Level level, String sourceClass, String sourceMethod, String msg, Object param1) {
71 }
72
73 @Override
74 public void logp(Level level, String sourceClass, String sourceMethod, String msg, Object[] params) {
75 }
76
77 @Override
78 public void logp(Level level, String sourceClass, String sourceMethod, String msg, Throwable thrown) {
79 }
80
81 @Override
82 public void logp(Level level, String sourceClass, String sourceMethod, Throwable thrown,
83 Supplier<String> msgSupplier) {
84 }
85
86 @Override
87 public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName, String msg) {
88 }
89
90 @Override
91 public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName, String msg,
92 Object param1) {
93 }
94
95 @Override
96 public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName, String msg,
97 Object[] params) {
98 }
99
100 @Override
101 public void logrb(Level level, String sourceClass, String sourceMethod, ResourceBundle bundle, String msg,
102 Object... params) {
103 }
104
105 @Override
106 public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName, String msg,
107 Throwable thrown) {
108 }
109
110 @Override
111 public void logrb(Level level, String sourceClass, String sourceMethod, ResourceBundle bundle, String msg,
112 Throwable thrown) {
113 }
114
115 @Override
116 public void entering(String sourceClass, String sourceMethod) {
117 }
118
119 @Override
120 public void entering(String sourceClass, String sourceMethod, Object param1) {
121 }
122
123 @Override
124 public void entering(String sourceClass, String sourceMethod, Object[] params) {
125 }
126
127 @Override
128 public void exiting(String sourceClass, String sourceMethod) {
129 }
130
131 @Override
132 public void exiting(String sourceClass, String sourceMethod, Object result) {
133 }
134
135 @Override
136 public void throwing(String sourceClass, String sourceMethod, Throwable thrown) {
137 }
138
139 @Override
140 public void severe(String msg) {
141 }
142
143 @Override
144 public void warning(String msg) {
145 }
146
147 @Override
148 public void info(String msg) {
149 }
150
151 @Override
152 public void config(String msg) {
153 }
154
155 @Override
156 public void fine(String msg) {
157 }
158
159 @Override
160 public void finer(String msg) {
161 }
162
163 @Override
164 public void finest(String msg) {
165 }
166
167 @Override
168 public void severe(Supplier<String> msgSupplier) {
169 }
170
171 @Override
172 public void warning(Supplier<String> msgSupplier) {
173 }
174
175 @Override
176 public void info(Supplier<String> msgSupplier) {
177 }
178
179 @Override
180 public void config(Supplier<String> msgSupplier) {
181 }
182
183 @Override
184 public void fine(Supplier<String> msgSupplier) {
185 }
186
187 @Override
188 public void finer(Supplier<String> msgSupplier) {
189 }
190
191 @Override
192 public void finest(Supplier<String> msgSupplier) {
193 }
194
195 @Override
196 public void setLevel(Level newLevel) throws SecurityException {
197 }
198
199 @Override
200 public Level getLevel() {
201 return Level.OFF;
202 }
203
204 @Override
205 public boolean isLoggable(Level level) {
206 return false;
207 }
208 }
1414 See the License for the specific language governing permissions and
1515 limitations under the License.
1616 -->
17
18 There are two possibilities:
19 - Logging Adapter as complete replacement (preferred, but requires JVM start option)
20 - Bridge Handler, transfering JDK output to log4j, e.g. useful for webapps
2117
2218 # Log4j JDK Logging Adapter
2319
7773 [`FINER`](http://docs.oracle.com/javase/6/docs/api/java/util/logging/Level.html#FINER) | `TRACE`
7874 [`FINEST`](http://docs.oracle.com/javase/6/docs/api/java/util/logging/Level.html#FINEST) | [`FINEST`](apidocs/org/apache/logging/log4j/jul/LevelTranslator.html#FINEST)
7975 [`ALL`](http://docs.oracle.com/javase/6/docs/api/java/util/logging/Level.html#ALL) | `ALL`
80
81
82 # Log4j JDK Logging Bridge Handler
83
84 The LogManager is not always useable because you have to set a JVM wide effective system
85 property - e.g. in web servers this is not possible if you are not the administrator.
86
87 The [`Log4jBridgeHandler`](apidocs/org/apache/logging/log4j/jul/Log4jBridgeHandler.html) is an
88 alternative that can be declaratively used via `logging.properties`.
89
90 It is less performant than the LogManager but still okay to use: the LogManager replaces the JDK
91 implementation, so your logging code (using JDK syntax) effectively directly uses log4j.
92 When using the BridgeHandler the original JDK implementation along with its configuration
93 (e.g. log levels) is still fully working but the log events are "written" via this handler to log4j
94 as if you would have called log4j.Logger.debug() etc.; it is like a FileHandler but instead of
95 writing to a file, it "writes" to log4j Loggers - thus there is some overhead compared to using
96 LogManager.
97
98 ## Usage
99
100 The JUL configuration file `logging.properties` needs the line
101
102 `handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler`
103
104 and JUL logs go to log4j2. Additionally, you typically want to use to following:
105
106 `org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true`
107
108 In a webapp on Tomcat (and maybe other servers, too), you may simply create a
109 `WEB-INF/classes/logging.properties` file with above content.
110 The bridge and the log levels defined in this file are only valid for your webapp and
111 do *not* have any impact on the other webapps on the same Tomcat instance.
112
113 Alternatively you may call `Log4jBridgeHandler.install()` inside your webapp's initialization code,
114 e.g. inside `ServletContextListener` or a `ServletFilter` static-class-init. or `contextInitialized()`.
115
116 **Important:** Log levels of JDK should match the ones of log4j. You may do this manually or use the
117 automatic level propagation via `Log4jBridgeHandler.propagateLevels = true`.
118
119 Please, read the [JavaDoc](apidocs/org/apache/logging/log4j/jul/Log4jBridgeHandler.html) for detailed
120 configuration and limitation information!
2525 import org.apache.logging.log4j.test.appender.ListAppender;
2626 import org.junit.Test;
2727
28 import static org.assertj.core.api.Assertions.assertThat;
28 import static org.hamcrest.Matchers.equalTo;
29 import static org.hamcrest.Matchers.hasSize;
30 import static org.hamcrest.Matchers.instanceOf;
31 import static org.junit.Assert.*;
2932
3033 /**
3134 *
3942
4043 @Test
4144 public void testGetName() throws Exception {
42 assertThat(logger.getName()).isEqualTo(LOGGER_NAME);
45 assertThat(logger.getName(), equalTo(LOGGER_NAME));
4346 }
4447
4548 @Test
4952 root.config("Test info message");
5053 root.fine("Test info message");
5154 final List<LogEvent> events = eventAppender.getEvents();
52 assertThat(events).hasSize(3);
55 assertThat(events, hasSize(3));
5356 for (final LogEvent event : events) {
5457 final String message = event.getMessage().getFormattedMessage();
55 assertThat(message).isEqualTo("Test info message");
58 assertThat(message, equalTo("Test info message"));
5659 }
5760 }
5861
5962 @Test
6063 public void testGlobalLoggerName() throws Exception {
6164 final Logger root = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
62 assertThat(root.getName()).isEqualTo(Logger.GLOBAL_LOGGER_NAME);
65 assertThat(root.getName(), equalTo(Logger.GLOBAL_LOGGER_NAME));
6366 }
6467
6568 @Test
6669 public void testIsLoggable() throws Exception {
67 assertThat(logger.isLoggable(java.util.logging.Level.SEVERE)).isTrue();
70 assertThat(logger.isLoggable(java.util.logging.Level.SEVERE), equalTo(true));
6871 }
6972
7073 @Test
7174 public void testLog() throws Exception {
7275 logger.info("Informative message here.");
7376 final List<LogEvent> events = eventAppender.getEvents();
74 assertThat(events).hasSize(1);
77 assertThat(events, hasSize(1));
7578 final LogEvent event = events.get(0);
76 assertThat(event).isInstanceOf(Log4jLogEvent.class);
77 assertThat(event.getLevel()).isEqualTo(Level.INFO);
78 assertThat(event.getLoggerName()).isEqualTo(LOGGER_NAME);
79 assertThat(event.getMessage().getFormattedMessage()).isEqualTo("Informative message here.");
80 assertThat(event.getLoggerFqcn()).isEqualTo(ApiLogger.class.getName());
81 }
82
83 @Test
84 public void testLogFilter() throws Exception {
85 logger.setFilter(record -> false);
86 logger.severe("Informative message here.");
87 logger.warning("Informative message here.");
88 logger.info("Informative message here.");
89 logger.config("Informative message here.");
90 logger.fine("Informative message here.");
91 logger.finer("Informative message here.");
92 logger.finest("Informative message here.");
93 final List<LogEvent> events = eventAppender.getEvents();
94 assertThat(events).isEmpty();
95 }
96
97 @Test
98 public void testAlteringLogFilter() throws Exception {
99 logger.setFilter(record -> { record.setMessage("This is not the message you are looking for."); return true; });
100 logger.info("Informative message here.");
101 final List<LogEvent> events = eventAppender.getEvents();
102 assertThat(events).hasSize(1);
103 final LogEvent event = events.get(0);
104 assertThat(event).isInstanceOf(Log4jLogEvent.class);
105 assertThat(event.getLevel()).isEqualTo(Level.INFO);
106 assertThat(event.getLoggerName()).isEqualTo(LOGGER_NAME);
107 assertThat(event.getMessage().getFormattedMessage()).isEqualTo("This is not the message you are looking for.");
108 assertThat(event.getLoggerFqcn()).isEqualTo(ApiLogger.class.getName());
79 assertThat(event, instanceOf(Log4jLogEvent.class));
80 assertEquals(Level.INFO, event.getLevel());
81 assertEquals(LOGGER_NAME, event.getLoggerName());
82 assertEquals("Informative message here.", event.getMessage().getFormattedMessage());
83 assertEquals(ApiLogger.class.getName(), event.getLoggerFqcn());
10984 }
11085
11186 @Test
11388 final Logger flowLogger = Logger.getLogger("TestFlow");
11489 flowLogger.logp(java.util.logging.Level.FINER, "sourceClass", "sourceMethod", "ENTER {0}", "params");
11590 final List<LogEvent> events = flowAppender.getEvents();
116 assertThat(events.get(0).getMessage().getFormattedMessage()).isEqualTo("ENTER params");
91 assertEquals("ENTER params", events.get(0).getMessage().getFormattedMessage());
11792 }
11893
11994 @Test
12095 public void testLogUsingCustomLevel() throws Exception {
12196 logger.config("Config level");
12297 final List<LogEvent> events = eventAppender.getEvents();
123 assertThat(events).hasSize(1);
98 assertThat(events, hasSize(1));
12499 final LogEvent event = events.get(0);
125 assertThat(event.getLevel()).isEqualTo(LevelTranslator.CONFIG);
100 assertThat(event.getLevel(), equalTo(LevelTranslator.CONFIG));
126101 }
127102
128103 @Test
130105 final Logger log = Logger.getLogger("Test.CallerClass");
131106 log.config("Calling from LoggerTest");
132107 final List<String> messages = stringAppender.getMessages();
133 assertThat(messages).hasSize(1);
108 assertThat(messages, hasSize(1));
134109 final String message = messages.get(0);
135 assertThat(message).isEqualTo(AbstractLoggerTest.class.getName());
110 assertEquals(AbstractLoggerTest.class.getName(), message);
136111 }
137112
138113 @Test
156131 root.config("Test info " + string);
157132 root.fine("Test info " + string);
158133 final List<LogEvent> events = eventAppender.getEvents();
159 assertThat(events).hasSize(3);
134 assertThat(events, hasSize(3));
160135 for (final LogEvent event : events) {
161136 final String message = event.getMessage().getFormattedMessage();
162 assertThat(message).isEqualTo("Test info " + string);
137 assertThat(message, equalTo("Test info " + string));
163138 }
164139 }
165140
171146 flowLogger.entering("com.example.TestSourceClass3", "testSourceMethod3(String)",
172147 new Object[] { "TestParam0", "TestParam1" });
173148 final List<LogEvent> events = flowAppender.getEvents();
174 assertThat(events).hasSize(3);
175 assertThat(events.get(0).getMessage().getFormattedMessage()).isEqualTo("Enter");
176 assertThat(events.get(1).getMessage().getFormattedMessage()).isEqualTo("Enter params(TestParam)");
177 assertThat(events.get(2).getMessage().getFormattedMessage()).isEqualTo("Enter params(TestParam0, TestParam1)");
149 assertThat(events, hasSize(3));
150 assertEquals("Enter", events.get(0).getMessage().getFormattedMessage());
151 assertEquals("Enter params(TestParam)", events.get(1).getMessage().getFormattedMessage());
152 assertEquals("Enter params(TestParam0, TestParam1)", events.get(2).getMessage().getFormattedMessage());
178153 }
179154
180155 @Test
198173 }
199174
200175 private void testLambdaMessages(final String string) {
201 final Logger root = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
202 root.info(() -> "Test info " + string);
203 root.config(() -> "Test info " + string);
204 root.fine(() -> "Test info " + string);
205 final List<LogEvent> events = eventAppender.getEvents();
206 assertThat(events).hasSize(3);
207 for (final LogEvent event : events) {
208 final String message = event.getMessage().getFormattedMessage();
209 assertThat(message).isEqualTo("Test info " + string);
210 }
176 // TODO FOR JAVA 8
177 // final Logger root = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
178 // root.info(() -> "Test info " + string);
179 // root.config(() -> "Test info " + string);
180 // root.fine(() -> "Test info " + string);
181 // final List<LogEvent> events = eventAppender.getEvents();
182 // assertThat(events, hasSize(3));
183 // for (final LogEvent event : events) {
184 // final String message = event.getMessage().getFormattedMessage();
185 // assertThat(message, equalTo("Test info " + string));
186 // }
211187 }
212188
213189 }
4747 @Before
4848 public void setUp() throws Exception {
4949 logger = Logger.getLogger(LOGGER_NAME);
50 logger.setFilter(null);
5150 assertThat(logger.getLevel(), equalTo(java.util.logging.Level.FINE));
5251 eventAppender = ListAppender.getListAppender("TestAppender");
5352 flowAppender = ListAppender.getListAppender("FlowAppender");
+0
-57
log4j-jul/src/test/java/org/apache/logging/log4j/jul/AsyncLoggerThreadsTest.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.logging.log4j.jul;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.categories.AsyncLoggers;
20 import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
21 import org.apache.logging.log4j.core.util.Constants;
22 import org.junit.AfterClass;
23 import org.junit.BeforeClass;
24 import org.junit.Test;
25 import org.junit.experimental.categories.Category;
26
27 import java.util.List;
28 import java.util.stream.Collectors;
29
30 import static org.junit.Assert.assertEquals;
31
32 @Category(AsyncLoggers.class)
33 public class AsyncLoggerThreadsTest {
34
35 @BeforeClass
36 public static void beforeClass() {
37 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
38 AsyncLoggerContextSelector.class.getName());
39 System.setProperty("java.util.logging.manager", org.apache.logging.log4j.jul.LogManager.class.getName());
40 }
41
42 @AfterClass
43 public static void afterClass() {
44 System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
45 System.clearProperty("java.util.logging.manager");
46 }
47
48 @Test
49 public void testAsyncLoggerThreads() {
50 LogManager.getLogger("com.foo.Bar").info("log");
51 List<Thread> asyncLoggerThreads = Thread.getAllStackTraces().keySet().stream()
52 .filter(thread -> thread.getName().matches("Log4j2-TF.*AsyncLogger.*"))
53 .collect(Collectors.toList());
54 assertEquals(asyncLoggerThreads.toString(), 1, asyncLoggerThreads.size());
55 }
56 }
4747 @Before
4848 public void setUp() throws Exception {
4949 logger = Logger.getLogger(LOGGER_NAME);
50 logger.setFilter(null);
5150 assertThat(logger.getLevel(), equalTo(Level.FINE));
5251 eventAppender = ListAppender.getListAppender("TestAppender");
5352 flowAppender = ListAppender.getListAppender("FlowAppender");
+0
-459
log4j-jul/src/test/java/org/apache/logging/log4j/jul/Log4jBridgeHandlerTest.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.logging.log4j.jul;
17
18 //note: NO import of Logger, Level, LogManager to prevent conflicts JUL/log4j
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.io.ByteArrayOutputStream;
25 import java.io.PrintStream;
26 import java.util.Arrays;
27 import java.util.Enumeration;
28 import java.util.Map.Entry;
29
30 import org.apache.logging.log4j.core.LoggerContext;
31 import org.apache.logging.log4j.core.config.Configuration;
32 import org.apache.logging.log4j.core.config.ConfigurationListener;
33 import org.apache.logging.log4j.core.config.Configurator;
34 import org.apache.logging.log4j.core.config.LoggerConfig;
35 import org.apache.logging.log4j.core.config.Reconfigurable;
36 import org.junit.AfterClass;
37 import org.junit.Before;
38 import org.junit.BeforeClass;
39 import org.junit.FixMethodOrder;
40 import org.junit.Test;
41
42
43 /**
44 * Test the Log4jBridgeHandler.
45 * Requires some configurations in the log-config-files, for format/layout
46 * see also jul() and log4j():
47 * - JUL-config ("logging-test.properties", must be set on JVM-start via "-D..."):
48 * + handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler, java.util.logging.ConsoleHandler
49 * + org.apache.logging.log4j.jul.Log4jBridgeHandler.appendSuffix = _JUL
50 * + java.util.logging.ConsoleHandler.level = ALL
51 * + java.util.logging.SimpleFormatter.format = JUL: %1$tT.%1$tL %4$s [%3$s: %2$s] - %5$s%6$s%n
52 * + .level = FINER
53 * - log4j2-config ("log4j2-test.xml"):
54 * + <Root level="TRACE">
55 * + <Appenders> <Console> with target="SYSTEM_ERR", follow="true",
56 * <PatternLayout> "log4j2: %d{HH:mm:ss.SSS} %5level - [%thread][%logger: %class/%method/%line] - %message%n"
57 *
58 * This test needs to capture syserr because it uses java.util.logging.ConsoleHandler.
59 * Also, it performs some outputs to console (sysout and syserr); see also field OUTPUT_CAPTURED.
60 *
61 * The code also contains evaluation/test code for development time. It is not used for the unit tests
62 * but kept here for reference and info. See field DEVTEST.
63 */
64 @FixMethodOrder(org.junit.runners.MethodSorters.NAME_ASCENDING) // is nicer for manually checking console output
65 public class Log4jBridgeHandlerTest {
66 /** Perform developer tests? */
67 private static final boolean DEVTEST = false;
68
69 /** Do output the captured logger-output to stdout? */
70 private static final boolean OUTPUT_CAPTURED = !DEVTEST && Boolean.parseBoolean(
71 System.getProperty("log4j.Log4jBridgeHandlerTest.outputCaptured"));
72
73 /** This classes' simple name = relevant part of logger name. */
74 private static final String CSNAME = Log4jBridgeHandlerTest.class.getSimpleName();
75 // loggers used in many tests
76 private static final java.util.logging.Logger julLog = java.util.logging.Logger.getLogger(Log4jBridgeHandlerTest.class.getName());
77 private static final org.apache.logging.log4j.Logger log4jLog = org.apache.logging.log4j.LogManager.getLogger();
78
79 // capture sysout/syserr
80 //@Rule public final SystemErrRule systemOutRule = new SystemErrRule().enableLog();
81 private static final ByteArrayOutputStream sysoutBytes = new ByteArrayOutputStream(1024);
82 private static PrintStream prevSysErrStream;
83
84
85 @BeforeClass
86 public static void beforeClass() {
87 // debug output to easily recognize misconfig.:
88 //System.out.println("sys-props:\n" + System.getProperties());
89 System.out.println("sysout: logging-cfg-file: " + System.getProperty("java.util.logging.config.file"));
90 if (DEVTEST) devTestBeforeClass(); // call before stderr capturing
91
92 // JUL does not like setting stderr inbetween, so set it once and reset collecting stream
93 // for each method; (thus com.github.stefanbirkner:system-rules:SystemErrRule cannot be used)
94 System.err.println("vvv--- BEGIN capturing output to stderr ---vvv"
95 + " (do output of captured text to orig. stderr: " + OUTPUT_CAPTURED + ")");
96 prevSysErrStream = System.err;
97 System.setErr(new PrintStream(sysoutBytes, true));
98 }
99
100 @AfterClass
101 public static void afterClass() {
102 // reset sysout/err to original value
103 System.setErr(prevSysErrStream);
104 System.err.println("^^^--- END capturing output of stderr ---^^^");
105 }
106
107
108 @Before
109 public void beforeTest() {
110 // reset sysout collector
111 sysoutBytes.reset();
112 }
113
114
115
116 /** Assert that captured sysout matches given regexp (any text may follow afterwards). */
117 private void assertSysoutMatches(String regex) {
118 //String logOutput = systemOutRule.getLogWithNormalizedLineSeparator();
119 String logOutput = sysoutBytes.toString();
120 if (OUTPUT_CAPTURED) prevSysErrStream.print(logOutput);
121 logOutput = logOutput.replace("\r\n", "\n");
122 regex = regex + "(.|\\n)*"; // allow any text with NL afterwards
123 assertTrue("Unmatching output:\n" + logOutput + "\n-- vs: --\n" + regex + "\n----", logOutput.matches(regex));
124 }
125
126 /** Get regex for a JUL console output. Must match JUL-Console-Formatter! */
127 private String jul(java.util.logging.Level lvl, String locationPartRE,
128 String msgPartRE, String exceptionClassAndMsgRE) {
129 return "JUL:.*" + lvl.getLocalizedName() + ".*" + CSNAME
130 + ".*" + locationPartRE + ".*" + msgPartRE + ".*\n" // use real \n at end here for better error output
131 + (exceptionClassAndMsgRE == null ? ""
132 : ".*" + exceptionClassAndMsgRE + ".*\\n(\tat .*\\n)*\\n?");
133 }
134
135 /** Get regex for a log4j console output. Must match log4j2-Console-Layout! */
136 private String log4j(org.apache.logging.log4j.Level lvl, boolean julBridged,
137 String methodPartRE, String msgPartRE, String exceptionClassAndMsgRE) {
138 return "log4j2:.*" + lvl.name() + ".*" + CSNAME + (julBridged ? "\\._JUL" : "")
139 + ".*" + CSNAME + "/\\w*" + methodPartRE + "\\w*/.*"
140 + msgPartRE + ".*\n" // use real \n at end here for better error output
141 + (exceptionClassAndMsgRE == null ? ""
142 : ".*" + exceptionClassAndMsgRE + ".*\\n(\tat .*\\n)*\\n?");
143 }
144
145
146
147 @Test
148 public void test1SimpleLoggings1Jul() {
149 julLog.info("Test-'Info'-Log with JUL");
150 julLog.fine("Test-'Fine'-Log with JUL");
151 julLog.finest("Test-'Finest'-Log with JUL"); // should not be logged because JUL-level is FINER
152 julLog.warning("Test-'Warn'-Log with JUL"); // thus add another log afterwards to allow checking
153 String methodRE = "SimpleLoggings1Jul";
154 assertSysoutMatches(
155 log4j(org.apache.logging.log4j.Level.INFO, true, methodRE, "'Info'-Log with JUL", null)
156 + jul(java.util.logging.Level.INFO, methodRE, "'Info'-Log with JUL", null)
157 + log4j(org.apache.logging.log4j.Level.DEBUG, true, methodRE, "'Fine'-Log with JUL", null)
158 + jul(java.util.logging.Level.FINE, methodRE, "'Fine'-Log with JUL", null)
159 // no finest/trace
160 + log4j(org.apache.logging.log4j.Level.WARN, true, methodRE, "'Warn'-Log with JUL", null)
161 + jul(java.util.logging.Level.WARNING, methodRE, "'Warn'-Log with JUL", null)
162 );
163 }
164
165 @Test
166 public void test1SimpleLoggings2Log4jDirect() {
167 log4jLog.info("Test-'Info'-Log with log4j2");
168 log4jLog.debug("Test-'Debug'-Log with log4j2");
169 log4jLog.trace("Test-'Trace'-Log with log4j2");
170 String methodRE = "SimpleLoggings2Log4jDirect";
171 assertSysoutMatches(
172 log4j(org.apache.logging.log4j.Level.INFO, false, methodRE, "'Info'-Log with log4j2", null)
173 + log4j(org.apache.logging.log4j.Level.DEBUG, false, methodRE, "'Debug'-Log with log4j2", null)
174 + log4j(org.apache.logging.log4j.Level.TRACE, false, methodRE, "'Trace'-Log with log4j2", null)
175 );
176 }
177
178
179 @Test
180 public void test2SubMethod() {
181 subMethodWithLogs(); // location info is sub method now
182 String methodRE = "subMethodWithLogs";
183 assertSysoutMatches(
184 log4j(org.apache.logging.log4j.Level.DEBUG, true, methodRE, "'Fine'-Log with JUL in subMethod", null)
185 + jul(java.util.logging.Level.FINE, methodRE, "'Fine'-Log with JUL in subMethod", null)
186 + log4j(org.apache.logging.log4j.Level.INFO, false, methodRE, "'Info'-Log with log4j2 in subMethod", null)
187 );
188 }
189 private void subMethodWithLogs() {
190 julLog.fine("Test-'Fine'-Log with JUL in subMethod");
191 log4jLog.info("Test-'Info'-Log with log4j2 in subMethod");
192 }
193
194
195 @Test
196 public void test3JulFlow1() {
197 // note: manually given source information get lost in log4j!
198 julLog.entering("enteringExampleClassParam", "enteringExampleMethodParam");
199 String methodRE = "JulFlow";
200 assertSysoutMatches(
201 log4j(org.apache.logging.log4j.Level.TRACE, true, methodRE, "ENTRY", null)
202 + jul(java.util.logging.Level.FINER, "enteringExampleClassParam enteringExampleMethodParam", "ENTRY", null)
203 );
204 }
205
206 @Test
207 public void test3JulFlow2() {
208 // note: manually given source information get lost in log4j!
209 julLog.entering("enteringExampleClassParam", "enteringExampleMethodParam_withParams",
210 new Object[] {"with some", "parameters", 42} );
211 String methodRE = "JulFlow";
212 assertSysoutMatches(
213 log4j(org.apache.logging.log4j.Level.TRACE, true, methodRE,
214 "ENTRY.*with some.*param.*42", null)
215 + jul(java.util.logging.Level.FINER, "enteringExampleClassParam enteringExampleMethodParam_withParams",
216 "ENTRY.*with some.*param.*42", null)
217 );
218 }
219
220 @Test
221 public void test3JulFlow3() {
222 // note: manually given source information get lost in log4j!
223 julLog.exiting("exitingExampleClassParam", "exitingExampleMethodParam",
224 Arrays.asList("array of Strings", "that are the exit", "result"));
225 String methodRE = "JulFlow";
226 assertSysoutMatches(
227 log4j(org.apache.logging.log4j.Level.TRACE, true, methodRE,
228 "RETURN.*array of Str.*that are.*result", null)
229 + jul(java.util.logging.Level.FINER, "exitingExampleClassParam exitingExampleMethodParam",
230 "RETURN.*array of Str.*that are.*result", null)
231 );
232 }
233
234 @Test
235 public void test3JulFlow4() {
236 // note: manually given source information get lost in log4j!
237 julLog.throwing("throwingExampleClassParam", "throwingExampleMethodParam",
238 new IllegalStateException("ONLY TEST for JUL-throwing()"));
239 String methodRE = "JulFlow";
240 assertSysoutMatches(
241 log4j(org.apache.logging.log4j.Level.TRACE, true, methodRE,
242 "THROW", "IllegalStateException.*ONLY TEST for JUL-throwing")
243 + jul(java.util.logging.Level.FINER, "throwingExampleClassParam throwingExampleMethodParam",
244 "THROW", "IllegalStateException.*ONLY TEST for JUL-throwing")
245 );
246 }
247
248
249
250 @Test
251 public void test4JulSpecials1() {
252 julLog.log(java.util.logging.Level.WARNING, "JUL-Test via log() as warning with exception",
253 new java.util.zip.DataFormatException("ONLY TEST for JUL.log()"));
254 String methodRE = "JulSpecials";
255 assertSysoutMatches(
256 log4j(org.apache.logging.log4j.Level.WARN, true, methodRE,
257 "JUL-Test via log\\(\\) as warning", "DataFormatException.*ONLY TEST for JUL")
258 + jul(java.util.logging.Level.WARNING, methodRE, "JUL-Test via log\\(\\) as warning",
259 "DataFormatException.*ONLY TEST for JUL")
260 );
261 }
262
263 @Test
264 public void test4JulSpecials2() {
265 // test with MessageFormat
266 julLog.log(java.util.logging.Level.INFO, "JUL-Test via log() with parameters (0={0}, 1={1}, 2={2,number,##000.0})",
267 new Object[] {"a", "b", 42} );
268 String methodRE = "JulSpecials";
269 assertSysoutMatches(
270 log4j(org.apache.logging.log4j.Level.INFO, true, methodRE,
271 "JUL-Test via log\\(\\) with parameters \\(0=a, 1=b, 2=042.0\\)", null)
272 + jul(java.util.logging.Level.INFO, methodRE,
273 "JUL-Test via log\\(\\) with parameters \\(0=a, 1=b, 2=042.0\\)", null)
274 );
275 }
276
277 // no test for logrb(ResourceBundle)-case as this is very specific and seldom used (in
278 // my opinion); and it does not add any real thing to test here
279
280
281 private void assertLogLevel(String loggerName, java.util.logging.Level julLevel) {
282 java.util.logging.Logger lg = java.util.logging.LogManager.getLogManager().getLogger(loggerName);
283 assertEquals("Logger '" + loggerName + "'", julLevel, (lg == null ? null : lg.getLevel()));
284 }
285
286 @Test
287 public void test5LevelPropFromConfigFile() {
288 // JUL levels are set from config files and the initial propagation
289 assertLogLevel("", java.util.logging.Level.FINE);
290 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate1", java.util.logging.Level.FINE);
291 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate1.nested1", java.util.logging.Level.FINER);
292 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate1.nested2.deeplyNested", java.util.logging.Level.WARNING);
293 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate2", java.util.logging.Level.ALL);
294 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate2.nested.deeplyNested", java.util.logging.Level.INFO);
295 // these are set in logging.properties but not in log4j2.xml:
296 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate2.nested", null);
297 assertLogLevel("javax.mail", null);
298 // these should not exist:
299 assertLogLevel("log4j.Log4jBridgeHandlerTest", null);
300 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate1.nested", null);
301 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate1.nested1.deeplyNested", null);
302 }
303
304
305 @Test
306 public void test5LevelPropSetLevel() {
307 String name = "log4j.test.new_logger_level_set";
308 Configurator.setLevel(name, org.apache.logging.log4j.Level.DEBUG);
309 assertLogLevel(name, java.util.logging.Level.FINE);
310 test5LevelPropFromConfigFile(); // the rest should be untouched!
311
312 name = "log4j.Log4jBridgeHandlerTest.propagate1.nested1";
313 Configurator.setLevel(name, org.apache.logging.log4j.Level.WARN);
314 assertLogLevel(name, java.util.logging.Level.WARNING);
315 // the others around should be untouched
316 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate1", java.util.logging.Level.FINE);
317 assertLogLevel("log4j.Log4jBridgeHandlerTest.propagate1.nested2.deeplyNested", java.util.logging.Level.WARNING);
318
319 // note: no need to check for the other set[Root]Level() methods, because they all call
320 // loggerContext.updateLoggers() which calls firePropertyChangeEvent()
321 }
322
323
324 @Test
325 public void test5LevelPropGC() {
326 // this test will fail if you comment out "julLoggerRefs.add(julLog);" in propagateLogLevels()
327 test5LevelPropFromConfigFile(); // at start, all should be fine
328 java.util.logging.Logger julLogRef = java.util.logging.Logger
329 .getLogger("log4j.Log4jBridgeHandlerTest.propagate1.nested1");
330 System.gc(); // a single call is sufficient
331 System.out.println("sysout: test5LevelPropGC() still has reference to JUL-logger: "
332 + julLogRef.getName() + " / " + julLogRef);
333 try {
334 test5LevelPropFromConfigFile(); // even after GC the not referenced loggers should still be there
335 } catch (Throwable t) {
336 debugPrintJulLoggers("After GC");
337 // => JUL root logger, above explicitly referenced logger and its parent ("...propagate1")
338 // and the global referenced julLog ("...jul.Log4jBridgeHandlerTest") are still there, the
339 // others are null-references now
340 throw t;
341 }
342 }
343
344
345 /** Print all available JUL loggers to stdout. */
346 private static void debugPrintJulLoggers(String infoStr) {
347 java.util.logging.LogManager julMgr = java.util.logging.LogManager.getLogManager();
348 System.out.println("sysout: " + infoStr + " - for " + julMgr);
349 java.util.List<String> txt = new java.util.ArrayList<>();
350 int n = 1;
351 for (Enumeration<String> en = julMgr.getLoggerNames(); en.hasMoreElements(); ) {
352 String ln = en.nextElement();
353 java.util.logging.Logger lg = julMgr.getLogger(ln);
354 if (lg == null) {
355 txt.add("(!null-Logger '" + ln + "') #" + n);
356 } else if (lg.getLevel() == null) {
357 txt.add("(null-Level Logger '" + ln + "') #" + n);
358 } else {
359 txt.add("Logger '" + ln + "', lvl = " + lg.getLevel() + " #" + n);
360 }
361 n++;
362 } // for
363 java.util.Collections.sort(txt, String.CASE_INSENSITIVE_ORDER);
364 for (String s : txt) {
365 System.out.println(" - " + s);
366 }
367 }
368
369
370
371
372 ////////////////
373 //////////////// INTERNAL DEVELOPER TESTS follow
374 //////////////// (these are NOT neccessary for unit test but source is kept here for reference and info)
375
376
377 static {
378 if (DEVTEST) {
379 System.out.println("sysout: static init. BEGIN");
380
381 // get log4j context impl. (requires log4j-core!)
382 // note: "LogManager.getContext();" does not work, it returns another instance!?!
383 LoggerContext context = LoggerContext.getContext(false); // this matches Configurator.setLevel() impl.
384 Configuration cfg = context.getConfiguration();
385 // print real loggers (=> is empty when using LogManager.getContext()!?! only contains already instantiated loggers)
386 System.out.println("LogCtx " + context + " '" + context.getName() + "', loc = "
387 + context.getConfigLocation() + ", cfg = " + cfg + " = " + System.identityHashCode(cfg));
388 for (org.apache.logging.log4j.Logger lg : context.getLoggers()) {
389 System.out.println("- Logger '" + lg.getName() + "', lvl = " + lg.getLevel());
390 }
391 // print logger configurations (=> all loggers with level are present here)
392 System.out.println("Loggers in Cfg:");
393 for (Entry<String, LoggerConfig> entry : cfg.getLoggers().entrySet()) {
394 LoggerConfig lcfg = entry.getValue();
395 System.out.println("- '" + entry.getKey() + "' = '" + lcfg.getName() + "' / "
396 + lcfg.getLevel() + "; " + lcfg);
397 }
398
399 // print JUL loggers (=> is completely init. here, even if first JUL log and BridgeHandler-creation happens later)
400 debugPrintJulLoggers("in static-class-init");
401 /* java.util.logging.LogManager julMgr = java.util.logging.LogManager.getLogManager();
402 System.out.println("\nJUL-Loggers for " + julMgr);
403 for (Enumeration<String> en = julMgr.getLoggerNames(); en.hasMoreElements(); ) {
404 String ln = en.nextElement();
405 java.util.logging.Logger lg = julMgr.getLogger(ln);
406 if (lg.getLevel() == null) {
407 System.out.println("- (null-Level Logger '" + ln + "')");
408 } else {
409 System.out.println("- Logger '" + ln + "', lvl = " + lg.getLevel());
410 }
411 } */
412
413 // changing of log4j config. is to be done via log4j.core.config.Configurator,
414 // e.g. setLevel(loggerName, newLevel)
415 // Note: the (internal) log4j.core.Logger has a setLevel() but this should not be used.
416 CfgListener listener = new CfgListener();
417 cfg.addListener(listener); // => onChange() is never called: not on start, not on setLevel
418 context.addPropertyChangeListener(listener);
419
420 System.out.println("sysout: static init. END");
421 } // if
422 }
423
424
425 private static void devTestBeforeClass() {
426 log4jLog.info("Dummy-Start-Log in beforeClass()"); // force init. of log4j (needed?? does not harm)
427 @SuppressWarnings("resource")
428 LoggerContext context = LoggerContext.getContext(false); // this matches Configurator.setLevel() impl. (instead of "LogManager.getContext();")
429 System.out.println("beforeClass(): LogCtx " + context + " '" + context.getName() + "', loc = " + context.getConfigLocation()
430 + ", cfg = " + context.getConfiguration());
431 for (org.apache.logging.log4j.Logger lg : context.getLoggers()) {
432 System.out.println("- Logger '" + lg.getName() + "', lvl = " + lg.getLevel());
433 }
434
435 // force level change
436 System.out.println("sysout: now calling log4j-setLevel()");
437 Configurator.setLevel("log4jTest.Dummy_set_in_devTestBeforeClass", org.apache.logging.log4j.Level.DEBUG);
438 }
439
440
441 private static class CfgListener implements ConfigurationListener, PropertyChangeListener {
442 public CfgListener() {
443 System.out.println("sysout: CfgListener created: " + this);
444 }
445
446 @Override
447 public void onChange(Reconfigurable reconfigurable) { // from ConfigurationListener
448 System.out.println("sysout: CfgListener.CfgLi-onChange(): " + reconfigurable
449 + " = " + System.identityHashCode(reconfigurable));
450 }
451
452 @Override
453 public void propertyChange(PropertyChangeEvent evt) { // from PropertyChangeListener
454 System.out.println("sysout: CfgListener.PropChLi-propertyChange(): " + evt);
455 }
456 }
457
458 }
+0
-24
log4j-jul/src/test/resources/log4j2-julBridge-test.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!-- Log4jBridgeHandlerTest TEST execution config -->
2 <Configuration status="info">
3 <Appenders>
4 <Console name="STDOUT" target="SYSTEM_ERR" follow="true"> <!-- syserr + follow !! -->
5 <PatternLayout pattern="log4j2: %d{HH:mm:ss.SSS} %5level - [%thread][%logger: %class/%method/%line] - %message%n" />
6 </Console>
7 </Appenders>
8
9 <Loggers>
10 <Root level="DEBUG">
11 <AppenderRef ref="STDOUT" />
12 </Root>
13
14 <!-- needs to be set to a lower level: -->
15 <Logger name="org.apache.logging.log4j.jul.Log4jBridgeHandlerTest" level="TRACE" />
16 <!-- some test configs: -->
17 <Logger name="log4j.Log4jBridgeHandlerTest.propagate1" level="DEBUG" />
18 <Logger name="log4j.Log4jBridgeHandlerTest.propagate1.nested1" level="TRACE" />
19 <Logger name="log4j.Log4jBridgeHandlerTest.propagate1.nested2.deeplyNested" level="WARN" />
20 <Logger name="log4j.Log4jBridgeHandlerTest.propagate2" level="ALL" />
21 <Logger name="log4j.Log4jBridgeHandlerTest.propagate2.nested.deeplyNested" level="INFO" />
22 </Loggers>
23 </Configuration>
+0
-31
log4j-jul/src/test/resources/logging-test.properties less more
0 ### JUL configuration for Log4jBridgeHandler test
1 # JVM must be started with to use this file: -Djava.util.logging.config.file=path_to_this_file
2
3
4 # install bridge but also output JUL-logs to console (order of handler matters!):
5 handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler, java.util.logging.ConsoleHandler
6
7 #org.apache.logging.log4j.jul.Log4jBridgeHandler.sysoutDebug = true
8 # append given suffix to logger names (e.g. "_JUL"); a dot is prepended automatically
9 org.apache.logging.log4j.jul.Log4jBridgeHandler.appendSuffix = _JUL
10 org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true
11
12 # ConsoleHandler defaults to INFO filtering, but we need all here
13 java.util.logging.ConsoleHandler.level = ALL
14 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
15 java.util.logging.SimpleFormatter.format = JUL: %1$tT.%1$tL %4$s [%3$s: %2$s] - %5$s%6$s%n
16
17
18 # note: JUL levels are SEVERE, WARNING, INFO, FINE, FINER, FINEST, ALL
19
20 # set default JUL logging level (FINER is for entering, exiting etc.)
21 # out-comment to use default of "INFO" - will be set by level propagation to DEBUG=FINE again
22 #.level = FINE
23 org.apache.logging.log4j.jul.Log4jBridgeHandlerTest.level = FINER
24 # do not log mail-init. (is done on INFO-level) because this would init. JUL before setErr() happens
25 javax.mail.level = WARNING
26
27 # configure (initial) JUL levels differently to log4j-config (and use high levels here)
28 log4j.Log4jBridgeHandlerTest.propagate1.nested1.level = SEVERE
29 # this is a logger not directly available in log4j, but the level above and below is defined in log4j:
30 log4j.Log4jBridgeHandlerTest.propagate2.nested.level = WARNING
+0
-203
log4j-kubernetes/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
18 <modelVersion>4.0.0</modelVersion>
19 <parent>
20 <groupId>org.apache.logging.log4j</groupId>
21 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
23 <relativePath>../</relativePath>
24 </parent>
25 <artifactId>log4j-kubernetes</artifactId>
26 <packaging>jar</packaging>
27 <name>Apache Log4j Kubernetes Library</name>
28 <description>Apache Log4j Kubernetes Support</description>
29 <properties>
30 <log4jParentDir>${basedir}/..</log4jParentDir>
31 <docLabel>Log4j Kubernetes Library Documentation</docLabel>
32 <projectDir>/kubernetes</projectDir>
33 <maven.compiler.source>1.8</maven.compiler.source>
34 <maven.compiler.target>1.8</maven.compiler.target>
35 <module.name>org.apache.logging.log4j.kubernetes</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
37 </properties>
38 <dependencies>
39 <dependency>
40 <groupId>org.apache.logging.log4j</groupId>
41 <artifactId>log4j-api</artifactId>
42 </dependency>
43 <dependency>
44 <groupId>org.apache.logging.log4j</groupId>
45 <artifactId>log4j-core</artifactId>
46 </dependency>
47 <!-- Kubernetes Client -->
48 <dependency>
49 <groupId>io.fabric8</groupId>
50 <artifactId>kubernetes-client</artifactId>
51 </dependency>
52 <dependency>
53 <groupId>org.junit.vintage</groupId>
54 <artifactId>junit-vintage-engine</artifactId>
55 </dependency>
56 <dependency>
57 <groupId>org.junit.jupiter</groupId>
58 <artifactId>junit-jupiter-engine</artifactId>
59 </dependency>
60 </dependencies>
61 <build>
62 <plugins>
63 <plugin>
64 <groupId>org.apache.maven.plugins</groupId>
65 <artifactId>maven-toolchains-plugin</artifactId>
66 <version>3.0.0</version>
67 <executions>
68 <execution>
69 <goals>
70 <goal>toolchain</goal>
71 </goals>
72 </execution>
73 </executions>
74 <configuration>
75 <toolchains>
76 <jdk>
77 <version>[8, )</version>
78 </jdk>
79 </toolchains>
80 </configuration>
81 </plugin>
82 <!-- Include the standard NOTICE and LICENSE -->
83 <plugin>
84 <groupId>org.apache.maven.plugins</groupId>
85 <artifactId>maven-remote-resources-plugin</artifactId>
86 <executions>
87 <execution>
88 <goals>
89 <goal>process</goal>
90 </goals>
91 <configuration>
92 <skip>false</skip>
93 </configuration>
94 </execution>
95 </executions>
96 </plugin>
97 <plugin>
98 <groupId>org.apache.felix</groupId>
99 <artifactId>maven-bundle-plugin</artifactId>
100 </plugin>
101 <plugin>
102 <artifactId>maven-surefire-plugin</artifactId>
103 <configuration>
104 <forkCount>1</forkCount>
105 <reuseForks>false</reuseForks>
106 </configuration>
107 </plugin>
108 </plugins>
109 </build>
110 <reporting>
111 <plugins>
112 <plugin>
113 <groupId>org.apache.maven.plugins</groupId>
114 <artifactId>maven-changes-plugin</artifactId>
115 <version>${changes.plugin.version}</version>
116 <reportSets>
117 <reportSet>
118 <reports>
119 <report>changes-report</report>
120 </reports>
121 </reportSet>
122 </reportSets>
123 <configuration>
124 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
125 <useJql>true</useJql>
126 </configuration>
127 </plugin>
128 <plugin>
129 <groupId>org.apache.maven.plugins</groupId>
130 <artifactId>maven-checkstyle-plugin</artifactId>
131 <version>${checkstyle.plugin.version}</version>
132 <configuration>
133 <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
134 <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
135 <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
136 <enableRulesSummary>false</enableRulesSummary>
137 <propertyExpansion>basedir=${basedir}</propertyExpansion>
138 <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
139 </configuration>
140 </plugin>
141 <plugin>
142 <groupId>org.apache.maven.plugins</groupId>
143 <artifactId>maven-javadoc-plugin</artifactId>
144 <version>${javadoc.plugin.version}</version>
145 <configuration>
146 <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
147 Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
148 and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
149 <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating
150 project -->
151 <detectOfflineLinks>false</detectOfflineLinks>
152 <linksource>true</linksource>
153 </configuration>
154 <reportSets>
155 <reportSet>
156 <id>non-aggregate</id>
157 <reports>
158 <report>javadoc</report>
159 </reports>
160 </reportSet>
161 </reportSets>
162 </plugin>
163 <plugin>
164 <groupId>com.github.spotbugs</groupId>
165 <artifactId>spotbugs-maven-plugin</artifactId>
166 </plugin>
167 <plugin>
168 <groupId>org.apache.maven.plugins</groupId>
169 <artifactId>maven-jxr-plugin</artifactId>
170 <version>${jxr.plugin.version}</version>
171 <reportSets>
172 <reportSet>
173 <id>non-aggregate</id>
174 <reports>
175 <report>jxr</report>
176 </reports>
177 </reportSet>
178 <reportSet>
179 <id>aggregate</id>
180 <reports>
181 <report>aggregate</report>
182 </reports>
183 </reportSet>
184 </reportSets>
185 </plugin>
186 <plugin>
187 <groupId>org.apache.maven.plugins</groupId>
188 <artifactId>maven-pmd-plugin</artifactId>
189 <version>${pmd.plugin.version}</version>
190 <configuration>
191 <targetJdk>${maven.compiler.target}</targetJdk>
192 </configuration>
193 </plugin>
194 <plugin>
195 <groupId>net.sourceforge.maven-taglib</groupId>
196 <artifactId>maven-taglib-plugin</artifactId>
197 <version>2.4</version>
198 </plugin>
199 </plugins>
200 </reporting>
201 </project>
202
+0
-89
log4j-kubernetes/src/main/java/org/apache/logging/log4j/kubernetes/ContainerUtil.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.logging.log4j.kubernetes;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.nio.file.Files;
21 import java.nio.file.Path;
22 import java.util.Objects;
23
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.status.StatusLogger;
26
27 /**
28 * Locate the current docker container.
29 */
30 public class ContainerUtil {
31 private static final Logger LOGGER = StatusLogger.getLogger();
32 private static final int MAXLENGTH = 65;
33
34 /**
35 * Returns the container id when running in a Docker container.
36 *
37 * This inspects /proc/self/cgroup looking for a Kubernetes Control Group. Once it finds one it attempts
38 * to isolate just the docker container id. There doesn't appear to be a standard way to do this, but
39 * it seems to be the only way to determine what the current container is in a multi-container pod. It would have
40 * been much nicer if Kubernetes would just put the container id in a standard environment variable.
41 *
42 * @see <a href="http://stackoverflow.com/a/25729598/12916">Stackoverflow</a> for a discussion on retrieving the containerId.
43 * @see <a href="https://github.com/jenkinsci/docker-workflow-plugin/blob/master/src/main/java/org/jenkinsci/plugins/docker/workflow/client/ControlGroup.java>ControlGroup</a>
44 * for the original version of this. Not much is actually left but it provided good inspiration.
45 */
46 public static String getContainerId() {
47 try {
48 File file = new File("/proc/self/cgroup");
49 if (file.exists()) {
50 Path path = file.toPath();
51 String id = Files.lines(path).map(ContainerUtil::getContainerId).filter(Objects::nonNull)
52 .findFirst().orElse(null);
53 LOGGER.debug("Found container id {}", id);
54 return id;
55 }
56 LOGGER.warn("Unable to access container information");
57 } catch (IOException ioe) {
58 LOGGER.warn("Error obtaining container id: {}", ioe.getMessage());
59 }
60 return null;
61 }
62
63 private static String getContainerId(String line) {
64 // Every control group in Kubernetes will use
65 if (line.contains("/kubepods")) {
66 // Strip off everything up to the last slash.
67 int i = line.lastIndexOf('/');
68 if (i < 0) {
69 return null;
70 }
71 // If the remainder has a period then take everything up to it.
72 line = line.substring(i + 1);
73 i = line.lastIndexOf('.');
74 if (i > 0) {
75 line = line.substring(0, i);
76 }
77 // Everything ending with a '/' has already been stripped but the remainder might start with "docker-"
78 if (line.contains("docker-")) {
79 // 8:cpuset:/kubepods.slice/kubepods-pod9c26dfb6_b9c9_11e7_bfb9_02c6c1fc4861.slice/docker-3dd988081e7149463c043b5d9c57d7309e079c5e9290f91feba1cc45a04d6a5b.scope
80 i = line.lastIndexOf("docker-");
81 line = line.substring(i + 7);
82 }
83 return line.length() <= MAXLENGTH ? line : line.substring(0, MAXLENGTH);
84 }
85
86 return null;
87 }
88 }
+0
-75
log4j-kubernetes/src/main/java/org/apache/logging/log4j/kubernetes/KubernetesClientBuilder.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.logging.log4j.kubernetes;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.status.StatusLogger;
20
21 import io.fabric8.kubernetes.client.Config;
22 import io.fabric8.kubernetes.client.ConfigBuilder;
23 import io.fabric8.kubernetes.client.DefaultKubernetesClient;
24 import io.fabric8.kubernetes.client.KubernetesClient;
25
26 /**
27 * Builds a Kubernetes Client.
28 */
29 public class KubernetesClientBuilder {
30
31 private static final Logger LOGGER = StatusLogger.getLogger();
32
33 public KubernetesClient createClient() {
34 Config config = kubernetesClientConfig();
35 return config != null ? new DefaultKubernetesClient(config) : null;
36 }
37
38 private Config kubernetesClientConfig() {
39 Config base = null;
40 try {
41 base = Config.autoConfigure(null);
42 } catch (Exception ex) {
43 if (ex instanceof NullPointerException) {
44 return null;
45 }
46 }
47 KubernetesClientProperties props = new KubernetesClientProperties(base);
48 Config properties = new ConfigBuilder(base)
49 .withApiVersion(props.getApiVersion())
50 .withCaCertData(props.getCaCertData())
51 .withCaCertFile(props.getCaCertFile())
52 .withClientCertData(props.getClientCertData())
53 .withClientCertFile(props.getClientCertFile())
54 .withClientKeyAlgo(props.getClientKeyAlgo())
55 .withClientKeyData(props.getClientKeyData())
56 .withClientKeyFile(props.getClientKeyFile())
57 .withClientKeyPassphrase(props.getClientKeyPassphrase())
58 .withConnectionTimeout(props.getConnectionTimeout())
59 .withHttpProxy(props.getHttpProxy())
60 .withHttpsProxy(props.getHttpsProxy())
61 .withMasterUrl(props.getMasterUrl())
62 .withNamespace(props.getNamespace())
63 .withNoProxy(props.getNoProxy())
64 .withPassword(props.getPassword())
65 .withProxyPassword(props.getProxyPassword())
66 .withProxyUsername(props.getProxyUsername())
67 .withRequestTimeout(props.getRequestTimeout())
68 .withRollingTimeout(props.getRollingTimeout())
69 .withTrustCerts(props.isTrustCerts())
70 .withUsername(props.getUsername())
71 .build();
72 return properties;
73 }
74 }
+0
-191
log4j-kubernetes/src/main/java/org/apache/logging/log4j/kubernetes/KubernetesClientProperties.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.logging.log4j.kubernetes;
17
18 import java.time.Duration;
19
20 import org.apache.logging.log4j.util.PropertiesUtil;
21
22 import io.fabric8.kubernetes.client.Config;
23
24 /**
25 * Obtains properties used to configure the Kubernetes client.
26 */
27 public class KubernetesClientProperties {
28
29 private static final String[] PREFIXES = {"log4j2.kubernetes.client.", "spring.cloud.kubernetes.client."};
30 private static final String API_VERSION = "apiVersion";
31 private static final String CA_CERT_FILE = "caCertFile";
32 private static final String CA_CERT_DATA = "caCertData";
33 private static final String CLIENT_CERT_FILE = "clientCertFile";
34 private static final String CLIENT_CERT_DATA = "clientCertData";
35 private static final String CLIENT_KEY_FILE = "clientKeyFile";
36 private static final String CLIENT_KEY_DATA = "cientKeyData";
37 private static final String CLIENT_KEY_ALGO = "clientKeyAlgo";
38 private static final String CLIENT_KEY_PASSPHRASE = "clientKeyPassphrase";
39 private static final String CONNECTION_TIMEOUT = "connectionTimeout";
40 private static final String HTTP_PROXY = "httpProxy";
41 private static final String HTTPS_PROXY = "httpsProxy";
42 private static final String LOGGING_INTERVAL = "loggingInterval";
43 private static final String MASTER_URL = "masterUrl";
44 private static final String NAMESPACE = "namespace";
45 private static final String NO_PROXY = "noProxy";
46 private static final String PASSWORD = "password";
47 private static final String PROXY_USERNAME = "proxyUsername";
48 private static final String PROXY_PASSWORD = "proxyPassword";
49 private static final String REQUEST_TIMEOUT = "requestTimeout";
50 private static final String ROLLING_TIMEOUT = "rollingTimeout";
51 private static final String TRUST_CERTS = "trustCerts";
52 private static final String USERNAME = "username";
53 private static final String WATCH_RECONNECT_INTERVAL = "watchReconnectInterval";
54 private static final String WATCH_RECONNECT_LIMIT = "watchReconnectLimit";
55
56 private PropertiesUtil props = PropertiesUtil.getProperties();
57 private final Config base;
58
59 public KubernetesClientProperties(Config base) {
60 this.base = base;
61 }
62
63
64 public String getApiVersion() {
65 return props.getStringProperty(PREFIXES, API_VERSION, base::getApiVersion);
66 }
67 public String getCaCertFile() {
68 return props.getStringProperty(PREFIXES, CA_CERT_FILE, base::getCaCertFile);
69 }
70
71 public String getCaCertData() {
72 return props.getStringProperty(PREFIXES, CA_CERT_DATA, base::getCaCertData);
73 }
74
75 public String getClientCertFile() {
76 return props.getStringProperty(PREFIXES, CLIENT_CERT_FILE, base::getClientCertFile);
77 }
78
79 public String getClientCertData() {
80 return props.getStringProperty(PREFIXES, CLIENT_CERT_DATA, base::getClientCertData);
81 }
82
83 public String getClientKeyFile() {
84 return props.getStringProperty(PREFIXES, CLIENT_KEY_FILE, base::getClientKeyFile);
85 }
86
87 public String getClientKeyData() {
88 return props.getStringProperty(PREFIXES, CLIENT_KEY_DATA, base::getClientKeyData);
89 }
90
91 public String getClientKeyAlgo() {
92 return props.getStringProperty(PREFIXES, CLIENT_KEY_ALGO, base::getClientKeyAlgo);
93 }
94
95 public String getClientKeyPassphrase() {
96 return props.getStringProperty(PREFIXES, CLIENT_KEY_PASSPHRASE, base::getClientKeyPassphrase);
97 }
98
99 public int getConnectionTimeout() {
100 Duration timeout = props.getDurationProperty(PREFIXES, CONNECTION_TIMEOUT, null);
101 if (timeout != null) {
102 return (int) timeout.toMillis();
103 }
104 return base.getConnectionTimeout();
105 }
106
107 public String getHttpProxy() {
108 return props.getStringProperty(PREFIXES, HTTP_PROXY, base::getHttpProxy);
109 }
110
111 public String getHttpsProxy() {
112 return props.getStringProperty(PREFIXES, HTTPS_PROXY, base::getHttpsProxy);
113 }
114
115 public int getLoggingInterval() {
116 Duration interval = props.getDurationProperty(PREFIXES, LOGGING_INTERVAL, null);
117 if (interval != null) {
118 return (int) interval.toMillis();
119 }
120 return base.getLoggingInterval();
121 }
122
123 public String getMasterUrl() {
124 return props.getStringProperty(PREFIXES, MASTER_URL, base::getMasterUrl);
125 }
126
127 public String getNamespace() {
128 return props.getStringProperty(PREFIXES, NAMESPACE, base::getNamespace);
129 }
130
131 public String[] getNoProxy() {
132 String result = props.getStringProperty(PREFIXES, NO_PROXY, null);
133 if (result != null) {
134 return result.replace("\\s", "").split(",");
135 }
136 return base.getNoProxy();
137 }
138
139 public String getPassword() {
140 return props.getStringProperty(PREFIXES, PASSWORD, base::getPassword);
141 }
142
143 public String getProxyUsername() {
144 return props.getStringProperty(PREFIXES, PROXY_USERNAME, base::getProxyUsername);
145 }
146
147 public String getProxyPassword() {
148 return props.getStringProperty(PREFIXES, PROXY_PASSWORD, base::getProxyPassword);
149 }
150
151 public int getRequestTimeout() {
152 Duration interval = props.getDurationProperty(PREFIXES, REQUEST_TIMEOUT, null);
153 if (interval != null) {
154 return (int) interval.toMillis();
155 }
156 return base.getRequestTimeout();
157 }
158
159 public long getRollingTimeout() {
160 Duration interval = props.getDurationProperty(PREFIXES, ROLLING_TIMEOUT, null);
161 if (interval != null) {
162 return interval.toMillis();
163 }
164 return base.getRollingTimeout();
165 }
166
167 public Boolean isTrustCerts() {
168 return props.getBooleanProperty(PREFIXES, TRUST_CERTS, base::isTrustCerts);
169 }
170
171 public String getUsername() {
172 return props.getStringProperty(PREFIXES, USERNAME, base::getUsername);
173 }
174
175 public int getWatchReconnectInterval() {
176 Duration interval = props.getDurationProperty(PREFIXES, WATCH_RECONNECT_INTERVAL, null);
177 if (interval != null) {
178 return (int) interval.toMillis();
179 }
180 return base.getWatchReconnectInterval();
181 }
182
183 public int getWatchReconnectLimit() {
184 Duration interval = props.getDurationProperty(PREFIXES, WATCH_RECONNECT_LIMIT, null);
185 if (interval != null) {
186 return (int) interval.toMillis();
187 }
188 return base.getWatchReconnectLimit();
189 }
190 }
+0
-291
log4j-kubernetes/src/main/java/org/apache/logging/log4j/kubernetes/KubernetesLookup.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.logging.log4j.kubernetes;
17
18 import java.net.URL;
19 import java.nio.file.Paths;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.concurrent.locks.Lock;
23 import java.util.concurrent.locks.ReentrantLock;
24
25 import org.apache.logging.log4j.LogManager;
26 import org.apache.logging.log4j.Logger;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.config.plugins.Plugin;
29 import org.apache.logging.log4j.core.lookup.AbstractLookup;
30 import org.apache.logging.log4j.core.lookup.StrLookup;
31 import org.apache.logging.log4j.status.StatusLogger;
32 import org.apache.logging.log4j.util.LoaderUtil;
33 import org.apache.logging.log4j.util.Strings;
34
35 import io.fabric8.kubernetes.api.model.Container;
36 import io.fabric8.kubernetes.api.model.ContainerStatus;
37 import io.fabric8.kubernetes.api.model.Namespace;
38 import io.fabric8.kubernetes.api.model.Pod;
39 import io.fabric8.kubernetes.client.Config;
40 import io.fabric8.kubernetes.client.KubernetesClient;
41
42
43 /**
44 * Retrieve various Kubernetes attributes. Supported keys are:
45 * accountName, containerId, containerName, clusterName, host, hostIp, labels, labels.app,
46 * labels.podTemplateHash, masterUrl, namespaceId, namespaceName, podId, podIp, podName,
47 * imageId, imageName.
48 */
49 @Plugin(name = "k8s", category = StrLookup.CATEGORY)
50 public class KubernetesLookup extends AbstractLookup {
51
52 private static final Logger LOGGER = StatusLogger.getLogger();
53 private static final String HOSTNAME = "HOSTNAME";
54 private static final String SPRING_ENVIRONMENT_KEY = "SpringEnvironment";
55
56 private static volatile KubernetesInfo kubernetesInfo;
57 private static final Lock initLock = new ReentrantLock();
58 private static final boolean isSpringIncluded =
59 LoaderUtil.isClassAvailable("org.apache.logging.log4j.spring.cloud.config.client.SpringEnvironmentHolder")
60 || LoaderUtil.isClassAvailable("org.apache.logging.log4j.spring.boot.SpringEnvironmentHolder");
61 private Pod pod;
62 private Namespace namespace;
63 private URL masterUrl;
64
65 public KubernetesLookup() {
66 this.pod = null;
67 this.namespace = null;
68 this.masterUrl = null;
69 initialize();
70 }
71
72 KubernetesLookup(Pod pod, Namespace namespace, URL masterUrl) {
73 this.pod = pod;
74 this.namespace = namespace;
75 this.masterUrl = masterUrl;
76 initialize();
77 }
78 private boolean initialize() {
79 if (kubernetesInfo == null || (isSpringIncluded && !kubernetesInfo.isSpringActive)) {
80 initLock.lock();
81 try {
82 boolean isSpringActive = isSpringActive();
83 if (kubernetesInfo == null || (!kubernetesInfo.isSpringActive && isSpringActive)) {
84 KubernetesInfo info = new KubernetesInfo();
85 KubernetesClient client = null;
86 info.isSpringActive = isSpringActive;
87 if (pod == null) {
88 client = new KubernetesClientBuilder().createClient();
89 if (client != null) {
90 pod = getCurrentPod(System.getenv(HOSTNAME), client);
91 info.masterUrl = client.getMasterUrl();
92 if (pod != null) {
93 info.namespace = pod.getMetadata().getNamespace();
94 namespace = client.namespaces().withName(info.namespace).get();
95 }
96 } else {
97 LOGGER.warn("Kubernetes is not available for access");
98 }
99 } else {
100 info.masterUrl = masterUrl;
101 }
102 if (pod != null) {
103 if (namespace != null) {
104 info.namespaceId = namespace.getMetadata().getUid();
105 info.namespaceAnnotations = namespace.getMetadata().getAnnotations();
106 info.namespaceLabels = namespace.getMetadata().getLabels();
107 }
108 info.app = pod.getMetadata().getLabels().get("app");
109 info.hostName = pod.getSpec().getNodeName();
110 info.annotations = pod.getMetadata().getAnnotations();
111 final String app = info.app != null ? info.app : "";
112 info.podTemplateHash = pod.getMetadata().getLabels().get("pod-template-hash");
113 info.accountName = pod.getSpec().getServiceAccountName();
114 info.clusterName = pod.getMetadata().getClusterName();
115 info.hostIp = pod.getStatus().getHostIP();
116 info.labels = pod.getMetadata().getLabels();
117 info.podId = pod.getMetadata().getUid();
118 info.podIp = pod.getStatus().getPodIP();
119 info.podName = pod.getMetadata().getName();
120 ContainerStatus containerStatus = null;
121 List<ContainerStatus> statuses = pod.getStatus().getContainerStatuses();
122 if (statuses.size() == 1) {
123 containerStatus = statuses.get(0);
124 } else if (statuses.size() > 1) {
125 String containerId = ContainerUtil.getContainerId();
126 if (containerId != null) {
127 containerStatus = statuses.stream()
128 .filter(cs -> cs.getContainerID().contains(containerId))
129 .findFirst().orElse(null);
130 }
131 }
132 final String containerName;
133 if (containerStatus != null) {
134 info.containerId = containerStatus.getContainerID();
135 info.imageId = containerStatus.getImageID();
136 containerName = containerStatus.getName();
137 } else {
138 containerName = null;
139 }
140 Container container = null;
141 List<Container> containers = pod.getSpec().getContainers();
142 if (containers.size() == 1) {
143 container = containers.get(0);
144 } else if (containers.size() > 1 && containerName != null) {
145 container = containers.stream().filter(c -> c.getName().equals(containerName))
146 .findFirst().orElse(null);
147 }
148 if (container != null) {
149 info.containerName = container.getName();
150 info.imageName = container.getImage();
151 }
152
153 kubernetesInfo = info;
154 }
155 }
156 } finally {
157 initLock.unlock();
158 }
159 }
160 return kubernetesInfo != null;
161 }
162
163 @Override
164 public String lookup(LogEvent event, String key) {
165 if (kubernetesInfo == null) {
166 return null;
167 }
168 switch (key) {
169 case "accountName": {
170 return kubernetesInfo.accountName;
171 }
172 case "annotations": {
173 return kubernetesInfo.annotations.toString();
174 }
175 case "containerId": {
176 return kubernetesInfo.containerId;
177 }
178 case "containerName": {
179 return kubernetesInfo.containerName;
180 }
181 case "clusterName": {
182 return kubernetesInfo.clusterName;
183 }
184 case "host": {
185 return kubernetesInfo.hostName;
186 }
187 case "hostIp": {
188 return kubernetesInfo.hostIp;
189 }
190 case "labels": {
191 return kubernetesInfo.labels.toString();
192 }
193 case "labels.app": {
194 return kubernetesInfo.app;
195 }
196 case "labels.podTemplateHash": {
197 return kubernetesInfo.podTemplateHash;
198 }
199 case "masterUrl": {
200 return kubernetesInfo.masterUrl.toString();
201 }
202 case "namespaceAnnotations": {
203 return kubernetesInfo.namespaceAnnotations.toString();
204 }
205 case "namespaceId": {
206 return kubernetesInfo.namespaceId;
207 }
208 case "namespaceLabels": {
209 return kubernetesInfo.namespaceLabels.toString();
210 }
211 case "namespaceName": {
212 return kubernetesInfo.namespace;
213 }
214 case "podId": {
215 return kubernetesInfo.podId;
216 }
217 case "podIp": {
218 return kubernetesInfo.podIp;
219 }
220 case "podName": {
221 return kubernetesInfo.podName;
222 }
223 case "imageId": {
224 return kubernetesInfo.imageId;
225 }
226 case "imageName": {
227 return kubernetesInfo.imageName;
228 }
229 default:
230 return null;
231 }
232 }
233
234 /**
235 * For unit testing only.
236 */
237 void clearInfo() {
238 kubernetesInfo = null;
239 }
240
241 private String getHostname() {
242 return System.getenv(HOSTNAME);
243 }
244
245 private Pod getCurrentPod(String hostName, KubernetesClient kubernetesClient) {
246 try {
247 if (isServiceAccount() && Strings.isNotBlank(hostName)) {
248 return kubernetesClient.pods().withName(hostName).get();
249 }
250 } catch (Throwable t) {
251 LOGGER.debug("Unable to locate pod with name {}.", hostName);
252 }
253 return null;
254 }
255
256 private boolean isServiceAccount() {
257 return Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH).toFile().exists()
258 && Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile().exists();
259 }
260
261 private boolean isSpringActive() {
262 return isSpringIncluded && LogManager.getFactory() != null
263 && LogManager.getFactory().hasContext(KubernetesLookup.class.getName(), null, false)
264 && LogManager.getContext(false).getObject(SPRING_ENVIRONMENT_KEY) != null;
265 }
266
267 private static class KubernetesInfo {
268 boolean isSpringActive;
269 String accountName;
270 Map<String, String> annotations;
271 String app;
272 String clusterName;
273 String containerId;
274 String containerName;
275 String hostName;
276 String hostIp;
277 String imageId;
278 String imageName;
279 Map<String, String> labels;
280 URL masterUrl;
281 String namespace;
282 Map<String, String> namespaceAnnotations;
283 String namespaceId;
284 Map<String, String> namespaceLabels;
285 String podId;
286 String podIp;
287 String podName;
288 String podTemplateHash;
289 }
290 }
+0
-104
log4j-kubernetes/src/site/markdown/index.md.vm less more
0 <!-- vim: set syn=markdown : -->
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 #set($dollar = '$')
18 #set($h1='#')
19 #set($h2='##')
20
21 $h1 Log4j Kubernetes Support
22
23 Log4j supports Kubernetes by providing a Lookup to retrieve container information.
24
25 $h2 Accessing Kubernetes
26
27 The Log4j Kubernetes support requires access to the Docker REST interface. In many cases the REST service
28 can be accessed automatically. If needed the Kubernetes client can be configured any of the standard
29 Log4j configuration locations or via the Spring Boot configuration. Note, however, that since Spring Boot
30 causes logging to initialize 3 times and since the Spring environment is only available during the last
31 Log4j initialization Spring properties will only be available to Log4j in the last initialization.
32
33 $h2 Lookup Attributes
34
35 Log4j Kubernetes provides access to the following container attributes:
36
37 * accountName - The service account name.
38 * clusterName - The name of the cluster the application is running in.
39 * containerId - The full id assigned to the container.
40 * containerName - The name assigned to the container.
41 * host - The name of the host.
42 * hostIp - The host's ip address.
43 * imageId - The id assigned to the image.
44 * imageName - The name assigned to the image.
45 * labels - All labels formatted in a list.
46 * labels.app - The application name.
47 * labels.podTemplateHash - The pod's template hash value.
48 * masterUrl - The url needed to access the API server.
49 * namespaceId - The id of the namespace the various kubernetes components are located within.
50 * namespaceName - The namespace the various kubernetes components are located within.
51 * podId - The pod's id number.
52 * podIp - The pod's ip address.
53 * podName - The name of the pod.
54
55 #set( $D = '${' )
56 #set( $container = 'k8s:containerId}')
57 Attributes may be accessed by adding
58 ```
59 $D$container
60 ```
61 to the configuration. Note that kubernetes variables are only resolved once during logging initialization so they
62 shouldn't be referenced with more than one '$' character.
63
64 $h2 Configuration
65
66 Much of the configuration needed to access the Kubernetes API server is provided automatically by Kubernetes.
67 However, it is not uncommon to need to provide the url required to access the Kubernetes API server or the
68 namespace the application is assigned to. The properties below may either be configured using the Log4j
69 variable names and located by Log4j's normal property resolution mechansim or Log4j will resolve the
70 spring properties when the application is running in Spring Boot and the Spring Environment has been created.
71 Note that Spring Boot initializes logging 3 times and only the last will have a Spring Environment present.
72
73 | Log4j Property Name | Spring Property Name | Default | Description |
74 |------------------------ |----------------------:|----------:|------------:|
75 | log4j2.kubernetes.client.apiVersion | spring.cloud.kubernetes.client.apiVersion | v1 | Kubernetes API Version |
76 | log4j2.kubernetes.client.caCertData | spring.cloud.kubernetes.client.caCertData | | Kubernetes API CACertData |
77 | log4j2.kubernetes.client.caCertFile | spring.cloud.kubernetes.client.caCertFile | | Kubernetes API CACertFile |
78 | log4j2.kubernetes.client.clientCertData | spring.cloud.kubernetes.client.clientCertData | | Kubernetes API ClientCertData |
79 | log4j2.kubernetes.client.clientCertFile | spring.cloud.kubernetes.client.clientCertFile | | Kubernetes API ClientCertFile |
80 | log4j2.kubernetes.client.clientKeyAlgo | spring.cloud.kubernetes.client.clientKeyAlgo | RSA | Kubernetes API ClientKeyAlgo |
81 | log4j2.kubernetes.client.clientKeyData | spring.cloud.kubernetes.client.clientKeyData | | Kubernetes API ClientKeyData |
82 | log4j2.kubernetes.client.clientKeyFile | spring.cloud.kubernetes.client.clientKeyFile | | Kubernetes API ClientKeyFile |
83 | log4j2.kubernetes.client.clientKeyPassPhrase | spring.cloud.kubernetes.client.clientKeyPassphrase | changeit | Kubernetes API ClientKeyPassphrase |
84 | log4j2.kubernetes.client.connectionTimeout | spring.cloud.kubernetes.client.connectionTimeout | 10s | Connection timeout |
85 | log4j2.kubernetes.client.httpProxy | spring.cloud.kubernetes.client.http-proxy | | |
86 | log4j2.kubernetes.client.httpsProxy | spring.cloud.kubernetes.client.https-proxy | | |
87 | log4j2.kubernetes.client.loggingInberval | spring.cloud.kubernetes.client.loggingInterval | 20s | Logging interval |
88 | log4j2.kubernetes.client.masterUrl | spring.cloud.kubernetes.client.masterUrl | kubernetes.default.svc | Kubernetes API Master Node URL |
89 | log4j2.kubernetes.client.namespacce | spring.cloud.kubernetes.client.namespace | default | Kubernetes Namespace |
90 | log4j2.kubernetes.client.noProxy | spring.cloud.kubernetes.client.noProxy | | |
91 | log4j2.kubernetes.client.password | spring.cloud.kubernetes.client.password | | Kubernetes API Password |
92 | log4j2.kubernetes.client.proxyPassword | spring.cloud.kubernetes.client.proxyPassword | | |
93 | log4j2.kubernetes.client.proxyUsername | spring.cloud.kubernetes.client.proxyUsername | | |
94 | log4j2.kubernetes.client.requestTimeout | spring.cloud.kubernetes.client.requestTimeout | 10s | Request timeout |
95 | log4j2.kubernetes.client.rollingTimeout | spring.cloud.kubernetes.client.rollingTimeout | 900s | Rolling timeout |
96 | log4j2.kubernetes.client.trustCerts | spring.cloud.kubernetes.client.trustCerts | false | Kubernetes API Trust Certificates |
97 | log4j2.kubernetes.client.username | spring.cloud.kubernetes.client.username | | Kubernetes API Username |
98 | log4j2.kubernetes.client.watchReconnectInterval | spring.cloud.kubernetes.client.watchReconnectInterval | 1s | Reconnect Interval |
99 | log4j2.kubernetes.client.watchReconnectLimit | spring.cloud.kubernetes.client.watchReconnectLimit | -1 | Reconnect Interval limit retries |
100
101 $h2 Requirements
102 Log4j Kubernetes requires Log4j Core, Log4j API and a minimum of Java 8.
103 For more information, see [Runtime Dependencies](../runtime-dependencies.html).
+0
-52
log4j-kubernetes/src/site/site.xml 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 -->
17 <project name="Log4j Docker Support"
18 xmlns="http://maven.apache.org/DECORATION/1.4.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
21 <body>
22 <links>
23 <item name="Apache" href="http://www.apache.org/" />
24 <item name="Logging Services" href="http://logging.apache.org/"/>
25 <item name="Log4j" href="../index.html"/>
26 </links>
27
28 <!-- Component-specific reports -->
29 <menu ref="reports"/>
30
31 <!-- Overall Project Info -->
32 <menu name="Log4j Project Information" img="icon-info-sign">
33 <item name="Dependencies" href="../dependencies.html" />
34 <item name="Dependency Convergence" href="../dependency-convergence.html" />
35 <item name="Dependency Management" href="../dependency-management.html" />
36 <item name="Project Team" href="../team-list.html" />
37 <item name="Mailing Lists" href="../mail-lists.html" />
38 <item name="Issue Tracking" href="../issue-tracking.html" />
39 <item name="Project License" href="../license.html" />
40 <item name="Source Repository" href="../source-repository.html" />
41 <item name="Project Summary" href="../project-summary.html" />
42 </menu>
43
44 <menu name="Log4j Project Reports" img="icon-cog">
45 <item name="Changes Report" href="../changes-report.html" />
46 <item name="JIRA Report" href="../jira-report.html" />
47 <item name="Surefire Report" href="../surefire-report.html" />
48 <item name="RAT Report" href="../rat-report.html" />
49 </menu>
50 </body>
51 </project>
+0
-98
log4j-kubernetes/src/test/java/org/apache/logging/log4j/kubernetes/KubernetesLookupTest.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.logging.log4j.kubernetes;
17
18 import java.io.File;
19 import java.net.URL;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.UUID;
23
24 import org.junit.BeforeClass;
25 import org.junit.Test;
26
27 import com.fasterxml.jackson.databind.ObjectMapper;
28
29 import io.fabric8.kubernetes.api.model.Namespace;
30 import io.fabric8.kubernetes.api.model.ObjectMeta;
31 import io.fabric8.kubernetes.api.model.Pod;
32
33 import static org.junit.Assert.assertEquals;
34
35 /**
36 * Validate the Kubernetes Lookup.
37 */
38 public class KubernetesLookupTest {
39
40 private static final String localJson = "target/test-classes/localPod.json";
41 private static final String clusterJson = "target/test-classes/clusterPod.json";
42 private static final ObjectMapper objectMapper = new ObjectMapper();
43 public static URL masterUrl;
44
45 @BeforeClass
46 public static void beforeClass() throws Exception {
47 masterUrl = new URL("http://localhost:443/");
48 }
49
50 @Test
51 public void testLocal() throws Exception {
52 Pod pod = objectMapper.readValue(new File(localJson), Pod.class);
53 Namespace namespace = createNamespace();
54 KubernetesLookup lookup = new KubernetesLookup(pod, namespace, masterUrl);
55 try {
56 assertEquals("Incorrect container name", "sampleapp", lookup.lookup("containerName"));
57 assertEquals("Incorrect container id",
58 "docker://818b0098946c67e6ac56cb7c0934b7c2a9f50feb7244b422b2a7f566f7e5d0df",
59 lookup.lookup("containerId"));
60 assertEquals("Incorrect host name", "docker-desktop", lookup.lookup("host"));
61 assertEquals("Incorrect pod name", "sampleapp-584f99476d-mnrp4", lookup.lookup("podName"));
62 } finally {
63 lookup.clearInfo();
64 }
65 }
66
67 @Test
68 public void testCluster() throws Exception {
69 Pod pod = objectMapper.readValue(new File(clusterJson), Pod.class);
70 Namespace namespace = createNamespace();
71 KubernetesLookup lookup = new KubernetesLookup(pod, namespace, masterUrl);
72 try {
73 assertEquals("Incorrect container name", "platform-forms-service", lookup.lookup("containerName"));
74 assertEquals("Incorrect container id",
75 "docker://2b7c2a93dfb48334aa549e29fdd38039ddd256eec43ba64c145fa4b75a1542f0",
76 lookup.lookup("containerId"));
77 assertEquals("Incorrect host name", "k8s-tmpcrm-worker-s03-04", lookup.lookup("host"));
78 assertEquals("Incorrect pod name", "platform-forms-service-primary-5ddfc4f9b8-kfpzv", lookup.lookup("podName"));
79 } finally {
80 lookup.clearInfo();
81 }
82 }
83
84 private Namespace createNamespace() {
85 Namespace namespace = new Namespace();
86 ObjectMeta meta = new ObjectMeta();
87 Map<String, String> annotations = new HashMap<>();
88 annotations.put("test", "name");
89 meta.setAnnotations(annotations);
90 Map<String, String> labels = new HashMap<>();
91 labels.put("ns", "my-namespace");
92 meta.setLabels(labels);
93 meta.setUid(UUID.randomUUID().toString());
94 namespace.setMetadata(meta);
95 return namespace;
96 }
97 }
+0
-177
log4j-kubernetes/src/test/resources/clusterPod.json less more
0 {
1 "apiVersion": "v1",
2 "kind": "Pod",
3 "metadata": {
4 "annotations": {
5 "cni.projectcalico.org/podIP": "172.16.55.101/32",
6 "cni.projectcalico.org/podIPs": "172.16.55.101/32",
7 "flagger-id": "94d53b7b-cc06-41b3-bbac-a2d14a16d95d",
8 "prometheus.io/port": "9797",
9 "prometheus.io/scrape": "true"
10 },
11 "creationTimestamp": "2020-06-15T15:44:16Z",
12 "generateName": "platform-forms-service-primary-5ddfc4f9b8-",
13 "labels": {
14 "app": "platform-forms-service-primary",
15 "pod-template-hash": "5ddfc4f9b8"
16 },
17 "name": "platform-forms-service-primary-5ddfc4f9b8-kfpzv",
18 "namespace": "default",
19 "ownerReferences": [
20 {
21 "apiVersion": "apps/v1",
22 "kind": "ReplicaSet",
23 "blockOwnerDeletion": true,
24 "controller": true,
25 "name": "platform-forms-service-primary-5ddfc4f9b8",
26 "uid": "d2e89c56-7623-439e-a9ee-4a67e2f3a81a"
27 }],
28 "resourceVersion": "37382150",
29 "selfLink": "/api/v1/namespaces/default/pods/platform-forms-service-primary-5ddfc4f9b8-kfpzv",
30 "uid": "df8cbac1-129c-4cd3-b5bc-65d72d8ba5f0"
31 },
32 "spec": {
33 "containers": [
34 {
35 "env": [
36 {
37 "name": "APACHE_ENV",
38 "value": "tmpcrm"
39 },
40 {
41 "name": "SPRING_PROFILES_ACTIVE",
42 "value": "tmpcrm"
43 },
44 {
45 "name": "JAVA_OPTS",
46 "value": "-Dlogging.label=crm"
47 }],
48 "image": "docker.apache.xyz/platform-forms-service:0.15.0",
49 "imagePullPolicy": "Always",
50 "livenessProbe": {
51 "failureThreshold": 3,
52 "httpGet": {
53 "path": "/info",
54 "port": "http",
55 "scheme": "HTTP"
56 },
57 "periodSeconds": 10,
58 "successThreshold": 1,
59 "timeoutSeconds": 1
60 },
61 "name": "platform-forms-service",
62 "ports": [
63 {
64 "containerPort": 8080,
65 "name": "http",
66 "protocol": "TCP"
67 }],
68 "readinessProbe": {
69 "failureThreshold": 3,
70 "httpGet": {
71 "path": "/health",
72 "port": "http",
73 "scheme": "HTTP"
74 },
75 "periodSeconds": 10,
76 "successThreshold": 1,
77 "timeoutSeconds": 1
78 },
79 "resources": {
80 },
81 "securityContext": {
82 },
83 "terminationMessagePath": "/dev/termination-log",
84 "terminationMessagePolicy": "File",
85 "volumeMounts": [
86 {
87 "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
88 "name": "default-token-2nqlw",
89 "readOnly": true
90 }]
91 }],
92 "dnsPolicy": "ClusterFirst",
93 "enableServiceLinks": true,
94 "nodeName": "k8s-tmpcrm-worker-s03-04",
95 "priority": 0,
96 "restartPolicy": "Always",
97 "schedulerName": "default-scheduler",
98 "securityContext": {
99 },
100 "serviceAccount": "default",
101 "serviceAccountName": "default",
102 "terminationGracePeriodSeconds": 30,
103 "tolerations": [
104 {
105 "effect": "NoExecute",
106 "key": "node.kubernetes.io/not-ready",
107 "operator": "Exists",
108 "tolerationSeconds": 300
109 },
110 {
111 "effect": "NoExecute",
112 "key": "node.kubernetes.io/unreachable",
113 "operator": "Exists",
114 "tolerationSeconds": 300
115 }],
116 "volumes": [
117 {
118 "name": "default-token-2nqlw",
119 "secret": {
120 "defaultMode": 420,
121 "secretName": "default-token-2nqlw"
122 }
123 }]
124 },
125 "status": {
126 "conditions": [
127 {
128 "lastTransitionTime": "2020-06-15T15:44:16Z",
129 "status": "True",
130 "type": "Initialized"
131 },
132 {
133 "lastTransitionTime": "2020-06-15T15:44:46Z",
134 "status": "True",
135 "type": "Ready"
136 },
137 {
138 "lastTransitionTime": "2020-06-15T15:44:46Z",
139 "status": "True",
140 "type": "ContainersReady"
141 },
142 {
143 "lastTransitionTime": "2020-06-15T15:44:16Z",
144 "status": "True",
145 "type": "PodScheduled"
146 }],
147 "containerStatuses": [
148 {
149 "containerID": "docker://2b7c2a93dfb48334aa549e29fdd38039ddd256eec43ba64c145fa4b75a1542f0",
150 "image": "docker.apache.xyz/platform-forms-service:0.15.0",
151 "imageID":
152 "docker-pullable://docker.apache.xyz/platform-forms-service@sha256:45fd19ccd99e218a7685c4cee5bc5b16aeae1cdb8e8773f9c066d4cfb22ee195",
153 "lastState": {
154 },
155 "name": "platform-forms-service",
156 "ready": true,
157 "restartCount": 0,
158 "state": {
159 "running": {
160 "startedAt": "2020-06-15T15:44:21Z"
161 }
162 },
163 "started": true
164 }],
165 "hostIP": "10.103.220.170",
166 "phase": "Running",
167 "podIP": "172.16.55.101",
168 "qosClass": "BestEffort",
169 "startTime": "2020-06-15T15:44:16Z",
170 "podIPs": [
171 {
172 "ip": "172.16.55.101"
173 }]
174 }
175 }
176
+0
-141
log4j-kubernetes/src/test/resources/localPod.json less more
0 {
1 "apiVersion": "v1",
2 "kind": "Pod",
3 "metadata": {
4 "creationTimestamp": "2020-06-14T21:50:09Z",
5 "generateName": "sampleapp-584f99476d-",
6 "labels": {
7 "app": "sampleapp",
8 "pod-template-hash": "584f99476d"
9 },
10 "name": "sampleapp-584f99476d-mnrp4",
11 "namespace": "default",
12 "ownerReferences": [
13 {
14 "apiVersion": "apps/v1",
15 "kind": "ReplicaSet",
16 "blockOwnerDeletion": true,
17 "controller": true,
18 "name": "sampleapp-584f99476d",
19 "uid": "d68146d1-17c4-486e-aa8d-07d7d5d38b94"
20 }],
21 "resourceVersion": "1200430",
22 "selfLink": "/api/v1/namespaces/default/pods/sampleapp-584f99476d-mnrp4",
23 "uid": "9213879a-479c-42ce-856b-7e2666d21829"
24 },
25 "spec": {
26 "containers": [
27 {
28 "env": [
29 {
30 "name": "JAVA_OPTS",
31 "value": "-Delastic.search.host=host.docker.internal"
32 }],
33 "image": "localhost:5000/sampleapp:latest",
34 "imagePullPolicy": "Always",
35 "name": "sampleapp",
36 "ports": [
37 {
38 "containerPort": 8080,
39 "protocol": "TCP"
40 },
41 {
42 "containerPort": 5005,
43 "protocol": "TCP"
44 }],
45 "resources": {
46 },
47 "terminationMessagePath": "/dev/termination-log",
48 "terminationMessagePolicy": "File",
49 "volumeMounts": [
50 {
51 "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
52 "name": "default-token-jzq7d",
53 "readOnly": true
54 }]
55 }],
56 "dnsPolicy": "ClusterFirst",
57 "nodeName": "docker-desktop",
58 "priority": 0,
59 "restartPolicy": "Always",
60 "schedulerName": "default-scheduler",
61 "securityContext": {
62 },
63 "serviceAccount": "default",
64 "serviceAccountName": "default",
65 "terminationGracePeriodSeconds": 30,
66 "tolerations": [
67 {
68 "effect": "NoExecute",
69 "key": "node.kubernetes.io/not-ready",
70 "operator": "Exists",
71 "tolerationSeconds": 300
72 },
73 {
74 "effect": "NoExecute",
75 "key": "node.kubernetes.io/unreachable",
76 "operator": "Exists",
77 "tolerationSeconds": 300
78 }],
79 "volumes": [
80 {
81 "name": "default-token-jzq7d",
82 "secret": {
83 "defaultMode": 420,
84 "secretName": "default-token-jzq7d"
85 }
86 }],
87 "enableServiceLinks": true
88 },
89 "status": {
90 "conditions": [
91 {
92 "lastTransitionTime": "2020-06-14T21:50:09Z",
93 "status": "True",
94 "type": "Initialized"
95 },
96 {
97 "lastTransitionTime": "2020-06-14T21:50:10Z",
98 "status": "True",
99 "type": "Ready"
100 },
101 {
102 "lastTransitionTime": "2020-06-14T21:50:10Z",
103 "status": "True",
104 "type": "ContainersReady"
105 },
106 {
107 "lastTransitionTime": "2020-06-14T21:50:09Z",
108 "status": "True",
109 "type": "PodScheduled"
110 }],
111 "containerStatuses": [
112 {
113 "containerID": "docker://818b0098946c67e6ac56cb7c0934b7c2a9f50feb7244b422b2a7f566f7e5d0df",
114 "image": "sampleapp:latest",
115 "imageID":
116 "docker-pullable://localhost:5000/sampleapp@sha256:3cefb2db514db73c69854fee8abd072f27240519432d08aad177a57ee34b7d39",
117 "lastState": {
118 },
119 "name": "sampleapp",
120 "ready": true,
121 "restartCount": 0,
122 "state": {
123 "running": {
124 "startedAt": "2020-06-14T21:50:10Z"
125 }
126 },
127 "started": true
128 }],
129 "hostIP": "192.168.65.3",
130 "phase": "Running",
131 "podIP": "10.1.0.47",
132 "qosClass": "BestEffort",
133 "startTime": "2020-06-14T21:50:09Z",
134 "podIPs": [
135 {
136 "ip": "10.1.0.47"
137 }]
138 }
139 }
140
+0
-480
log4j-layout-template-json/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
18
19 <modelVersion>4.0.0</modelVersion>
20
21 <parent>
22 <groupId>org.apache.logging.log4j</groupId>
23 <artifactId>log4j</artifactId>
24 <version>2.17.0</version>
25 </parent>
26
27 <artifactId>log4j-layout-template-json</artifactId>
28 <name>Apache Log4j Layout for JSON template</name>
29 <description>
30 Apache Log4j Layout for JSON template.
31 </description>
32
33 <properties>
34 <log4jParentDir>${basedir}/..</log4jParentDir>
35 <docLabel>Log4j Layout for JSON Template Documentation</docLabel>
36 <projectDir>/log4j-layout-template-json</projectDir>
37 <module.name>org.apache.logging.log4j.layout.template.json</module.name>
38 <maven.doap.skip>true</maven.doap.skip>
39 </properties>
40
41 <dependencies>
42
43 <dependency>
44 <groupId>org.apache.logging.log4j</groupId>
45 <artifactId>log4j-core</artifactId>
46 </dependency>
47
48 <dependency>
49 <groupId>org.apache.logging.log4j</groupId>
50 <artifactId>log4j-core</artifactId>
51 <version>${project.version}</version>
52 <type>test-jar</type>
53 <scope>test</scope>
54 </dependency>
55
56 <dependency>
57 <groupId>org.apache.logging.log4j</groupId>
58 <artifactId>log4j-1.2-api</artifactId>
59 <scope>test</scope>
60 </dependency>
61
62 <dependency>
63 <groupId>org.jctools</groupId>
64 <artifactId>jctools-core</artifactId>
65 <optional>true</optional>
66 </dependency>
67
68 <dependency>
69 <groupId>org.junit.jupiter</groupId>
70 <artifactId>junit-jupiter-engine</artifactId>
71 <scope>test</scope>
72 </dependency>
73
74 <dependency>
75 <groupId>org.junit.jupiter</groupId>
76 <artifactId>junit-jupiter-params</artifactId>
77 <scope>test</scope>
78 </dependency>
79
80 <dependency>
81 <groupId>org.assertj</groupId>
82 <artifactId>assertj-core</artifactId>
83 <scope>test</scope>
84 </dependency>
85
86 <dependency>
87 <groupId>com.fasterxml.jackson.core</groupId>
88 <artifactId>jackson-databind</artifactId>
89 <scope>test</scope>
90 </dependency>
91
92 <dependency>
93 <groupId>co.elastic.logging</groupId>
94 <artifactId>log4j2-ecs-layout</artifactId>
95 <scope>test</scope>
96 </dependency>
97
98 <dependency>
99 <groupId>com.google.code.java-allocation-instrumenter</groupId>
100 <artifactId>java-allocation-instrumenter</artifactId>
101 <scope>test</scope>
102 </dependency>
103
104 <dependency>
105 <groupId>org.elasticsearch.client</groupId>
106 <artifactId>elasticsearch-rest-high-level-client</artifactId>
107 <scope>test</scope>
108 </dependency>
109
110 <dependency>
111 <groupId>org.awaitility</groupId>
112 <artifactId>awaitility</artifactId>
113 <scope>test</scope>
114 </dependency>
115
116 </dependencies>
117
118 <build>
119 <plugins>
120
121 <plugin>
122 <groupId>org.apache.felix</groupId>
123 <artifactId>maven-bundle-plugin</artifactId>
124 <configuration>
125 <instructions>
126 <Fragment-Host>org.apache.logging.log4j.layout.template.json</Fragment-Host>
127 <Export-Package>*</Export-Package>
128 </instructions>
129 </configuration>
130 </plugin>
131
132 <plugin>
133 <groupId>org.apache.maven.plugins</groupId>
134 <artifactId>maven-jar-plugin</artifactId>
135 <executions>
136 <execution>
137 <id>default-jar</id>
138 <goals>
139 <goal>jar</goal>
140 </goals>
141 <configuration combine.self="override">
142 <archive>
143 <manifestFile>${manifestfile}</manifestFile>
144 <manifestEntries>
145 <Specification-Title>${project.name}</Specification-Title>
146 <Specification-Version>${project.version}</Specification-Version>
147 <Specification-Vendor>${project.organization.name}</Specification-Vendor>
148 <Implementation-Title>${project.name}</Implementation-Title>
149 <Implementation-Version>${project.version}</Implementation-Version>
150 <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
151 <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
152 <X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
153 <X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
154 <Multi-Release>true</Multi-Release>
155 </manifestEntries>
156 </archive>
157 </configuration>
158 </execution>
159 <execution>
160 <id>default</id>
161 <goals>
162 <goal>test-jar</goal>
163 </goals>
164 <configuration>
165 <archive>
166 <manifestFile>${manifestfile}</manifestFile>
167 <manifestEntries>
168 <Specification-Title>${project.name}</Specification-Title>
169 <Specification-Version>${project.version}</Specification-Version>
170 <Specification-Vendor>${project.organization.name}</Specification-Vendor>
171 <Implementation-Title>${project.name}</Implementation-Title>
172 <Implementation-Version>${project.version}</Implementation-Version>
173 <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
174 <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
175 <X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
176 <X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
177 </manifestEntries>
178 </archive>
179 </configuration>
180 </execution>
181 </executions>
182 </plugin>
183
184 <plugin>
185 <groupId>org.apache.maven.plugins</groupId>
186 <artifactId>maven-surefire-plugin</artifactId>
187 <configuration>
188 <!-- Enforcing a non-UTF-8 encoding to check that the layout
189 indeed handles everything in UTF-8 without implicitly
190 relying on the system defaults. -->
191 <argLine>-Dfile.encoding=US-ASCII</argLine>
192 <systemPropertyVariables>
193 <!-- Enable JUnit 5 parallel execution. -->
194 <junit.jupiter.execution.parallel.enabled>true</junit.jupiter.execution.parallel.enabled>
195 <junit.jupiter.execution.parallel.mode.default>concurrent</junit.jupiter.execution.parallel.mode.default>
196 </systemPropertyVariables>
197 </configuration>
198 </plugin>
199
200 <!-- Disable ITs, which are Docker-dependent, by default. -->
201 <plugin>
202 <groupId>org.apache.maven.plugins</groupId>
203 <artifactId>maven-failsafe-plugin</artifactId>
204 <executions>
205 <execution>
206 <goals>
207 <goal>integration-test</goal>
208 <goal>verify</goal>
209 </goals>
210 </execution>
211 </executions>
212 <configuration>
213 <skip>true</skip>
214 </configuration>
215 </plugin>
216
217 </plugins>
218 </build>
219
220 <profiles>
221 <profile>
222 <id>docker</id>
223 <activation>
224 <activeByDefault>false</activeByDefault>
225 </activation>
226 <build>
227 <plugins>
228
229 <plugin>
230 <groupId>org.apache.maven.plugins</groupId>
231 <artifactId>maven-failsafe-plugin</artifactId>
232 <executions>
233 <execution>
234 <goals>
235 <goal>integration-test</goal>
236 <goal>verify</goal>
237 </goals>
238 </execution>
239 </executions>
240 <configuration>
241 <includes>
242 <include>**/*IT.java</include>
243 </includes>
244 </configuration>
245 </plugin>
246
247 <plugin>
248 <groupId>io.fabric8</groupId>
249 <artifactId>docker-maven-plugin</artifactId>
250 <executions>
251 <execution>
252 <id>start</id>
253 <phase>pre-integration-test</phase>
254 <goals>
255 <goal>start</goal>
256 </goals>
257 </execution>
258 <execution>
259 <id>stop</id>
260 <phase>post-integration-test</phase>
261 <goals>
262 <goal>stop</goal>
263 </goals>
264 </execution>
265 </executions>
266 <configuration>
267 <verbose>all</verbose>
268 <startParallel>true</startParallel>
269 <autoCreateCustomNetworks>true</autoCreateCustomNetworks>
270 <images>
271 <image>
272 <alias>elasticsearch</alias>
273 <name>elasticsearch:${elastic.version}</name>
274 <run>
275 <env>
276 <discovery.type>single-node</discovery.type>
277 </env>
278 <ports>
279 <port>9200:9200</port>
280 </ports>
281 <network>
282 <mode>custom</mode>
283 <name>log4j-layout-template-json-network</name>
284 <alias>elasticsearch</alias>
285 </network>
286 <log>
287 <prefix>[ES]</prefix>
288 <color>cyan</color>
289 </log>
290 <wait>
291 <log>recovered \[0\] indices into cluster_state</log>
292 <time>60000</time>
293 </wait>
294 </run>
295 </image>
296 <image>
297 <alias>logstash</alias>
298 <name>logstash:${elastic.version}</name>
299 <run>
300 <dependsOn>
301 <container>elasticsearch</container>
302 </dependsOn>
303 <network>
304 <mode>custom</mode>
305 <name>log4j-layout-template-json-network</name>
306 <alias>logstash</alias>
307 </network>
308 <ports>
309 <port>12222:12222</port>
310 <port>12345:12345</port>
311 </ports>
312 <log>
313 <prefix>[LS]</prefix>
314 <color>green</color>
315 </log>
316 <entrypoint>
317 <exec>
318 <arg>logstash</arg>
319 <arg>--pipeline.batch.size</arg>
320 <arg>1</arg>
321 <arg>-e</arg>
322 <arg>
323 <![CDATA[
324 input {
325 gelf {
326 host => "logstash"
327 use_tcp => true
328 use_udp => false
329 port => 12222
330 type => "gelf"
331 }
332 tcp {
333 port => 12345
334 codec => json
335 type => "tcp"
336 }
337 }
338
339 filter {
340 if [type] == "gelf" {
341 # These are GELF/Syslog logging levels as defined in RFC 3164.
342 # Map the integer level to its human readable format.
343 translate {
344 field => "[level]"
345 destination => "[levelName]"
346 dictionary => {
347 "0" => "EMERG"
348 "1" => "ALERT"
349 "2" => "CRITICAL"
350 "3" => "ERROR"
351 "4" => "WARN"
352 "5" => "NOTICE"
353 "6" => "INFO"
354 "7" => "DEBUG"
355 }
356 }
357 }
358 }
359
360 output {
361 # (Un)comment for debugging purposes
362 # stdout { codec => rubydebug }
363 elasticsearch {
364 hosts => ["http://elasticsearch:9200"]
365 index => "log4j"
366 }
367 }
368 ]]>
369 </arg>
370 </exec>
371 </entrypoint>
372 <wait>
373 <log>Successfully started Logstash API endpoint</log>
374 <time>60000</time>
375 </wait>
376 </run>
377 </image>
378 </images>
379 </configuration>
380 </plugin>
381 </plugins>
382 </build>
383 </profile>
384 </profiles>
385
386 <reporting>
387 <plugins>
388
389 <plugin>
390 <groupId>org.apache.maven.plugins</groupId>
391 <artifactId>maven-changes-plugin</artifactId>
392 <version>${changes.plugin.version}</version>
393 <reportSets>
394 <reportSet>
395 <reports>
396 <report>changes-report</report>
397 </reports>
398 </reportSet>
399 </reportSets>
400 <configuration>
401 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
402 <useJql>true</useJql>
403 </configuration>
404 </plugin>
405
406 <plugin>
407 <groupId>org.apache.maven.plugins</groupId>
408 <artifactId>maven-checkstyle-plugin</artifactId>
409 <version>${checkstyle.plugin.version}</version>
410 <configuration>
411 <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
412 <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
413 <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
414 <enableRulesSummary>false</enableRulesSummary>
415 <propertyExpansion>basedir=${basedir}</propertyExpansion>
416 <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
417 </configuration>
418 </plugin>
419
420 <plugin>
421 <groupId>org.apache.maven.plugins</groupId>
422 <artifactId>maven-javadoc-plugin</artifactId>
423 <version>${javadoc.plugin.version}</version>
424 <configuration>
425 <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
426 Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
427 and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
428 <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating project -->
429 <detectOfflineLinks>false</detectOfflineLinks>
430 <linksource>true</linksource>
431 </configuration>
432 <reportSets>
433 <reportSet>
434 <id>non-aggregate</id>
435 <reports>
436 <report>javadoc</report>
437 </reports>
438 </reportSet>
439 </reportSets>
440 </plugin>
441
442 <plugin>
443 <groupId>com.github.spotbugs</groupId>
444 <artifactId>spotbugs-maven-plugin</artifactId>
445 </plugin>
446
447 <plugin>
448 <groupId>org.apache.maven.plugins</groupId>
449 <artifactId>maven-jxr-plugin</artifactId>
450 <version>${jxr.plugin.version}</version>
451 <reportSets>
452 <reportSet>
453 <id>non-aggregate</id>
454 <reports>
455 <report>jxr</report>
456 </reports>
457 </reportSet>
458 <reportSet>
459 <id>aggregate</id>
460 <reports>
461 <report>aggregate</report>
462 </reports>
463 </reportSet>
464 </reportSets>
465 </plugin>
466
467 <plugin>
468 <groupId>org.apache.maven.plugins</groupId>
469 <artifactId>maven-pmd-plugin</artifactId>
470 <version>${pmd.plugin.version}</version>
471 <configuration>
472 <targetJdk>${maven.compiler.target}</targetJdk>
473 </configuration>
474 </plugin>
475
476 </plugins>
477 </reporting>
478
479 </project>
+0
-734
log4j-layout-template-json/revapi.json less more
0 [
1 {
2 "extension": "revapi.java",
3 "configuration": {
4 "filter": {
5 "classes": {
6 "exclude": [
7 "org\\.apache\\.logging\\.log4j\\.layout\\.template\\.json\\.resolver\\.TemplateResolverConfig",
8 "org\\.apache\\.logging\\.log4j\\.layout\\.template\\.json\\.resolver\\.TemplateResolverContext",
9 "org\\.apache\\.logging\\.log4j\\.layout\\.template\\.json\\.resolver\\.TemplateResolverFactory"
10 ]
11 }
12 }
13 }
14 },
15 {
16 "extension": "revapi.ignore",
17 "configuration": [
18 {
19 "code": "java.method.returnTypeChanged",
20 "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::getEventTemplateAdditionalFields()",
21 "new": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField[] org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::getEventTemplateAdditionalFields()",
22 "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
23 },
24 {
25 "code": "java.method.parameterTypeChanged",
26 "old": "parameter org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::setEventTemplateAdditionalFields(===org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields===)",
27 "new": "parameter org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::setEventTemplateAdditionalFields(===org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField[]===)",
28 "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
29 },
30 {
31 "code": "java.class.removed",
32 "old": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields",
33 "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
34 },
35 {
36 "code": "java.method.removed",
37 "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::getMdcKeyPattern()",
38 "justification": "Removed unused property getter."
39 },
40 {
41 "code": "java.method.removed",
42 "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::getNdcPattern()",
43 "justification": "Removed unused property getter."
44 },
45 {
46 "code": "java.method.removed",
47 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
48 "justification": "Replaced 'enum' singletons with 'final class'es."
49 },
50 {
51 "code": "java.method.removed",
52 "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
53 "justification": "Replaced 'enum' singletons with 'final class'es."
54 },
55 {
56 "code": "java.method.removed",
57 "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
58 "justification": "Replaced 'enum' singletons with 'final class'es."
59 },
60 {
61 "code": "java.method.removed",
62 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
63 "justification": "Replaced 'enum' singletons with 'final class'es."
64 },
65 {
66 "code": "java.class.noLongerImplementsInterface",
67 "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
68 "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
69 "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.Uris>",
70 "justification": "Replaced 'enum' singletons with 'final class'es."
71 },
72 {
73 "code": "java.class.noLongerImplementsInterface",
74 "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
75 "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
76 "interface": "java.io.Serializable",
77 "justification": "Replaced 'enum' singletons with 'final class'es."
78 },
79 {
80 "code": "java.method.removed",
81 "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
82 "justification": "Replaced 'enum' singletons with 'final class'es."
83 },
84 {
85 "code": "java.method.removed",
86 "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::valueOf(java.lang.String)",
87 "justification": "Replaced 'enum' singletons with 'final class'es."
88 },
89 {
90 "code": "java.method.removed",
91 "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults[] org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::values()",
92 "justification": "Replaced 'enum' singletons with 'final class'es."
93 },
94 {
95 "code": "java.class.noLongerInheritsFromClass",
96 "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
97 "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
98 "justification": "Replaced 'enum' singletons with 'final class'es."
99 },
100 {
101 "code": "java.class.kindChanged",
102 "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
103 "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
104 "justification": "Replaced 'enum' singletons with 'final class'es."
105 },
106 {
107 "code": "java.class.noLongerImplementsInterface",
108 "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
109 "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
110 "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults>",
111 "justification": "Replaced 'enum' singletons with 'final class'es."
112 },
113 {
114 "code": "java.class.noLongerImplementsInterface",
115 "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
116 "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
117 "interface": "java.io.Serializable",
118 "justification": "Replaced 'enum' singletons with 'final class'es."
119 },
120 {
121 "code": "java.method.removed",
122 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
123 "justification": "Replaced 'enum' singletons with 'final class'es."
124 },
125 {
126 "code": "java.method.removed",
127 "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
128 "justification": "Replaced 'enum' singletons with 'final class'es."
129 },
130 {
131 "code": "java.method.removed",
132 "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
133 "justification": "Replaced 'enum' singletons with 'final class'es."
134 },
135 {
136 "code": "java.method.removed",
137 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
138 "justification": "Replaced 'enum' singletons with 'final class'es."
139 },
140 {
141 "code": "java.method.removed",
142 "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
143 "justification": "Replaced 'enum' singletons with 'final class'es."
144 },
145 {
146 "code": "java.method.removed",
147 "old": "method org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers::valueOf(java.lang.String)",
148 "justification": "Replaced 'enum' singletons with 'final class'es."
149 },
150 {
151 "code": "java.method.removed",
152 "old": "method org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers[] org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers::values()",
153 "justification": "Replaced 'enum' singletons with 'final class'es."
154 },
155 {
156 "code": "java.class.noLongerInheritsFromClass",
157 "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
158 "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
159 "justification": "Replaced 'enum' singletons with 'final class'es."
160 },
161 {
162 "code": "java.class.kindChanged",
163 "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
164 "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
165 "justification": "Replaced 'enum' singletons with 'final class'es."
166 },
167 {
168 "code": "java.class.noLongerImplementsInterface",
169 "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
170 "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
171 "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers>",
172 "justification": "Replaced 'enum' singletons with 'final class'es."
173 },
174 {
175 "code": "java.class.noLongerImplementsInterface",
176 "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
177 "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
178 "interface": "java.io.Serializable",
179 "justification": "Replaced 'enum' singletons with 'final class'es."
180 },
181 {
182 "code": "java.method.removed",
183 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
184 "justification": "Replaced 'enum' singletons with 'final class'es."
185 },
186 {
187 "code": "java.method.removed",
188 "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
189 "justification": "Replaced 'enum' singletons with 'final class'es."
190 },
191 {
192 "code": "java.method.removed",
193 "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
194 "justification": "Replaced 'enum' singletons with 'final class'es."
195 },
196 {
197 "code": "java.method.removed",
198 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
199 "justification": "Replaced 'enum' singletons with 'final class'es."
200 },
201 {
202 "code": "java.method.removed",
203 "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
204 "justification": "Replaced 'enum' singletons with 'final class'es."
205 },
206 {
207 "code": "java.method.removed",
208 "old": "method org.apache.logging.log4j.layout.template.json.util.RecyclerFactories org.apache.logging.log4j.layout.template.json.util.RecyclerFactories::valueOf(java.lang.String)",
209 "justification": "Replaced 'enum' singletons with 'final class'es."
210 },
211 {
212 "code": "java.method.removed",
213 "old": "method org.apache.logging.log4j.layout.template.json.util.RecyclerFactories[] org.apache.logging.log4j.layout.template.json.util.RecyclerFactories::values()",
214 "justification": "Replaced 'enum' singletons with 'final class'es."
215 },
216 {
217 "code": "java.class.noLongerInheritsFromClass",
218 "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
219 "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
220 "justification": "Replaced 'enum' singletons with 'final class'es."
221 },
222 {
223 "code": "java.class.kindChanged",
224 "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
225 "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
226 "justification": "Replaced 'enum' singletons with 'final class'es."
227 },
228 {
229 "code": "java.class.noLongerImplementsInterface",
230 "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
231 "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
232 "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.RecyclerFactories>",
233 "justification": "Replaced 'enum' singletons with 'final class'es."
234 },
235 {
236 "code": "java.class.noLongerImplementsInterface",
237 "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
238 "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
239 "interface": "java.io.Serializable",
240 "justification": "Replaced 'enum' singletons with 'final class'es."
241 },
242 {
243 "code": "java.method.removed",
244 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
245 "justification": "Replaced 'enum' singletons with 'final class'es."
246 },
247 {
248 "code": "java.method.removed",
249 "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
250 "justification": "Replaced 'enum' singletons with 'final class'es."
251 },
252 {
253 "code": "java.method.removed",
254 "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
255 "justification": "Replaced 'enum' singletons with 'final class'es."
256 },
257 {
258 "code": "java.method.removed",
259 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
260 "justification": "Replaced 'enum' singletons with 'final class'es."
261 },
262 {
263 "code": "java.method.removed",
264 "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
265 "justification": "Replaced 'enum' singletons with 'final class'es."
266 },
267 {
268 "code": "java.method.removed",
269 "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values::valueOf(java.lang.String)",
270 "justification": "Replaced 'enum' singletons with 'final class'es."
271 },
272 {
273 "code": "java.method.removed",
274 "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values[] org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values::values()",
275 "justification": "Replaced 'enum' singletons with 'final class'es."
276 },
277 {
278 "code": "java.class.noLongerInheritsFromClass",
279 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
280 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
281 "justification": "Replaced 'enum' singletons with 'final class'es."
282 },
283 {
284 "code": "java.class.kindChanged",
285 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
286 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
287 "justification": "Replaced 'enum' singletons with 'final class'es."
288 },
289 {
290 "code": "java.class.noLongerImplementsInterface",
291 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
292 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
293 "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values>",
294 "justification": "Replaced 'enum' singletons with 'final class'es."
295 },
296 {
297 "code": "java.class.noLongerImplementsInterface",
298 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
299 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
300 "interface": "java.io.Serializable",
301 "justification": "Replaced 'enum' singletons with 'final class'es."
302 },
303 {
304 "code": "java.method.removed",
305 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
306 "justification": "Replaced 'enum' singletons with 'final class'es."
307 },
308 {
309 "code": "java.method.removed",
310 "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
311 "justification": "Replaced 'enum' singletons with 'final class'es."
312 },
313 {
314 "code": "java.method.removed",
315 "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
316 "justification": "Replaced 'enum' singletons with 'final class'es."
317 },
318 {
319 "code": "java.method.removed",
320 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
321 "justification": "Replaced 'enum' singletons with 'final class'es."
322 },
323 {
324 "code": "java.method.removed",
325 "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
326 "justification": "Replaced 'enum' singletons with 'final class'es."
327 },
328 {
329 "code": "java.method.removed",
330 "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser org.apache.logging.log4j.layout.template.json.util.StringParameterParser::valueOf(java.lang.String)",
331 "justification": "Replaced 'enum' singletons with 'final class'es."
332 },
333 {
334 "code": "java.method.removed",
335 "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser[] org.apache.logging.log4j.layout.template.json.util.StringParameterParser::values()",
336 "justification": "Replaced 'enum' singletons with 'final class'es."
337 },
338 {
339 "code": "java.class.noLongerInheritsFromClass",
340 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
341 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
342 "justification": "Replaced 'enum' singletons with 'final class'es."
343 },
344 {
345 "code": "java.class.kindChanged",
346 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
347 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
348 "justification": "Replaced 'enum' singletons with 'final class'es."
349 },
350 {
351 "code": "java.class.noLongerImplementsInterface",
352 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
353 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
354 "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.StringParameterParser>",
355 "justification": "Replaced 'enum' singletons with 'final class'es."
356 },
357 {
358 "code": "java.class.noLongerImplementsInterface",
359 "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
360 "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
361 "interface": "java.io.Serializable",
362 "justification": "Replaced 'enum' singletons with 'final class'es."
363 },
364 {
365 "code": "java.method.removed",
366 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.Uris",
367 "justification": "Replaced 'enum' singletons with 'final class'es."
368 },
369 {
370 "code": "java.method.removed",
371 "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.Uris",
372 "justification": "Replaced 'enum' singletons with 'final class'es."
373 },
374 {
375 "code": "java.method.removed",
376 "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.Uris",
377 "justification": "Replaced 'enum' singletons with 'final class'es."
378 },
379 {
380 "code": "java.method.removed",
381 "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.Uris",
382 "justification": "Replaced 'enum' singletons with 'final class'es."
383 },
384 {
385 "code": "java.method.removed",
386 "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.Uris",
387 "justification": "Replaced 'enum' singletons with 'final class'es."
388 },
389 {
390 "code": "java.method.removed",
391 "old": "method org.apache.logging.log4j.layout.template.json.util.Uris org.apache.logging.log4j.layout.template.json.util.Uris::valueOf(java.lang.String)",
392 "justification": "Replaced 'enum' singletons with 'final class'es."
393 },
394 {
395 "code": "java.method.removed",
396 "old": "method org.apache.logging.log4j.layout.template.json.util.Uris[] org.apache.logging.log4j.layout.template.json.util.Uris::values()",
397 "justification": "Replaced 'enum' singletons with 'final class'es."
398 },
399 {
400 "code": "java.class.noLongerInheritsFromClass",
401 "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
402 "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
403 "justification": "Replaced 'enum' singletons with 'final class'es."
404 },
405 {
406 "code": "java.class.kindChanged",
407 "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
408 "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
409 "justification": "Replaced 'enum' singletons with 'final class'es."
410 },
411 {
412 "code": "java.method.removed",
413 "old": "method char[] org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getBuffer()",
414 "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
415 },
416 {
417 "code": "java.method.removed",
418 "old": "method int org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getCapacity()",
419 "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
420 },
421 {
422 "code": "java.method.removed",
423 "old": "method int org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getPosition()",
424 "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
425 },
426 {
427 "code": "java.method.removed",
428 "old": "method boolean org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::isTruncated()",
429 "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
430 },
431 {
432 "code": "java.class.visibilityReduced",
433 "old": "class org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedWriter",
434 "new": "class org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedWriter",
435 "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
436 },
437 {
438 "code": "java.method.removed",
439 "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Builder::setType(org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type)",
440 "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
441 },
442 {
443 "code": "java.class.removed",
444 "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type",
445 "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
446 },
447 {
448 "code": "java.method.removed",
449 "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField::getType()",
450 "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
451 },
452 {
453 "code": "java.annotation.added",
454 "old": "method org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory::getInstance()",
455 "new": "method org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory::getInstance()",
456 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
457 "justification": "LOG4J2-3004 Add plugin support."
458 },
459 {
460 "code": "java.annotation.added",
461 "old": "class org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory",
462 "new": "class org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory",
463 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"EndOfBatchResolverFactory\", category = \"JsonTemplateResolverFactory\")",
464 "justification": "LOG4J2-3004 Add plugin support."
465 },
466 {
467 "code": "java.method.removed",
468 "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::getTruncatedStringSuffix()",
469 "justification": "LOG4J2-3004 Add plugin support."
470 },
471 {
472 "code": "java.method.removed",
473 "old": "method org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setStackTraceElementObjectResolver(org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver<java.lang.StackTraceElement>)",
474 "justification": "LOG4J2-3004 Add plugin support."
475 },
476 {
477 "code": "java.method.parameterTypeChanged",
478 "old": "parameter org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setSubstitutor(===org.apache.logging.log4j.core.lookup.StrSubstitutor===)",
479 "new": "parameter org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setSubstitutor(===org.apache.logging.log4j.layout.template.json.resolver.EventResolverStringSubstitutor===)",
480 "justification": "LOG4J2-3004 Add plugin support."
481 },
482 {
483 "code": "java.method.returnTypeTypeParametersChanged",
484 "old": "method java.util.Map<java.lang.String, org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory<org.apache.logging.log4j.core.LogEvent, org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext, ? extends org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver<org.apache.logging.log4j.core.LogEvent>>> org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getResolverFactoryByName()",
485 "new": "method java.util.Map<java.lang.String, org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory> org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getResolverFactoryByName()",
486 "justification": "LOG4J2-3004 Add plugin support."
487 },
488 {
489 "code": "java.method.returnTypeChanged",
490 "old": "method org.apache.logging.log4j.core.lookup.StrSubstitutor org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getSubstitutor()",
491 "new": "method org.apache.logging.log4j.layout.template.json.resolver.EventResolverStringSubstitutor org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getSubstitutor()",
492 "justification": "LOG4J2-3004 Add plugin support."
493 },
494 {
495 "code": "java.annotation.added",
496 "old": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory::getInstance()",
497 "new": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory::getInstance()",
498 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
499 "justification": "LOG4J2-3004 Add plugin support."
500 },
501 {
502 "code": "java.annotation.added",
503 "old": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory",
504 "new": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory",
505 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ExceptionResolverFactory\", category = \"JsonTemplateResolverFactory\")",
506 "justification": "LOG4J2-3004 Add plugin support."
507 },
508 {
509 "code": "java.annotation.added",
510 "old": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory::getInstance()",
511 "new": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory::getInstance()",
512 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
513 "justification": "LOG4J2-3004 Add plugin support."
514 },
515 {
516 "code": "java.annotation.added",
517 "old": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory",
518 "new": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory",
519 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ExceptionRootCauseResolverFactory\", category = \"JsonTemplateResolverFactory\")",
520 "justification": "LOG4J2-3004 Add plugin support."
521 },
522 {
523 "code": "java.annotation.added",
524 "old": "method org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory::getInstance()",
525 "new": "method org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory::getInstance()",
526 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
527 "justification": "LOG4J2-3004 Add plugin support."
528 },
529 {
530 "code": "java.annotation.added",
531 "old": "class org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory",
532 "new": "class org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory",
533 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"LevelResolverFactory\", category = \"JsonTemplateResolverFactory\")",
534 "justification": "LOG4J2-3004 Add plugin support."
535 },
536 {
537 "code": "java.annotation.added",
538 "old": "method org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory::getInstance()",
539 "new": "method org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory::getInstance()",
540 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
541 "justification": "LOG4J2-3004 Add plugin support."
542 },
543 {
544 "code": "java.annotation.added",
545 "old": "class org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory",
546 "new": "class org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory",
547 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"LoggerResolverFactory\", category = \"JsonTemplateResolverFactory\")",
548 "justification": "LOG4J2-3004 Add plugin support."
549 },
550 {
551 "code": "java.annotation.added",
552 "old": "method org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory::getInstance()",
553 "new": "method org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory::getInstance()",
554 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
555 "justification": "LOG4J2-3004 Add plugin support."
556 },
557 {
558 "code": "java.annotation.added",
559 "old": "class org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory",
560 "new": "class org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory",
561 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MainMapResolverFactory\", category = \"JsonTemplateResolverFactory\")",
562 "justification": "LOG4J2-3004 Add plugin support."
563 },
564 {
565 "code": "java.annotation.added",
566 "old": "method org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory::getInstance()",
567 "new": "method org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory::getInstance()",
568 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
569 "justification": "LOG4J2-3004 Add plugin support."
570 },
571 {
572 "code": "java.annotation.added",
573 "old": "class org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory",
574 "new": "class org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory",
575 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MapResolverFactory\", category = \"JsonTemplateResolverFactory\")",
576 "justification": "LOG4J2-3004 Add plugin support."
577 },
578 {
579 "code": "java.annotation.added",
580 "old": "method org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory::getInstance()",
581 "new": "method org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory::getInstance()",
582 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
583 "justification": "LOG4J2-3004 Add plugin support."
584 },
585 {
586 "code": "java.annotation.added",
587 "old": "class org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory",
588 "new": "class org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory",
589 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MarkerResolverFactory\", category = \"JsonTemplateResolverFactory\")",
590 "justification": "LOG4J2-3004 Add plugin support."
591 },
592 {
593 "code": "java.annotation.added",
594 "old": "method org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory::getInstance()",
595 "new": "method org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory::getInstance()",
596 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
597 "justification": "LOG4J2-3004 Add plugin support."
598 },
599 {
600 "code": "java.annotation.added",
601 "old": "class org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory",
602 "new": "class org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory",
603 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MessageParameterResolverFactory\", category = \"JsonTemplateResolverFactory\")",
604 "justification": "LOG4J2-3004 Add plugin support."
605 },
606 {
607 "code": "java.annotation.added",
608 "old": "method org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory::getInstance()",
609 "new": "method org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory::getInstance()",
610 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
611 "justification": "LOG4J2-3004 Add plugin support."
612 },
613 {
614 "code": "java.annotation.added",
615 "old": "class org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory",
616 "new": "class org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory",
617 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MessageResolverFactory\", category = \"JsonTemplateResolverFactory\")",
618 "justification": "LOG4J2-3004 Add plugin support."
619 },
620 {
621 "code": "java.annotation.added",
622 "old": "method org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory::getInstance()",
623 "new": "method org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory::getInstance()",
624 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
625 "justification": "LOG4J2-3004 Add plugin support."
626 },
627 {
628 "code": "java.annotation.added",
629 "old": "class org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory",
630 "new": "class org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory",
631 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"PatternResolverFactory\", category = \"JsonTemplateResolverFactory\")",
632 "justification": "LOG4J2-3004 Add plugin support."
633 },
634 {
635 "code": "java.annotation.added",
636 "old": "method org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory::getInstance()",
637 "new": "method org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory::getInstance()",
638 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
639 "justification": "LOG4J2-3004 Add plugin support."
640 },
641 {
642 "code": "java.annotation.added",
643 "old": "class org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory",
644 "new": "class org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory",
645 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"SourceResolverFactory\", category = \"JsonTemplateResolverFactory\")",
646 "justification": "LOG4J2-3004 Add plugin support."
647 },
648 {
649 "code": "java.class.removed",
650 "old": "class org.apache.logging.log4j.layout.template.json.resolver.StackTraceElementObjectResolverContext",
651 "justification": "LOG4J2-3004 Add plugin support."
652 },
653 {
654 "code": "java.annotation.added",
655 "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory::getInstance()",
656 "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory::getInstance()",
657 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
658 "justification": "LOG4J2-3004 Add plugin support."
659 },
660 {
661 "code": "java.annotation.added",
662 "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory",
663 "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory",
664 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextDataResolverFactory\", category = \"JsonTemplateResolverFactory\")",
665 "justification": "LOG4J2-3004 Add plugin support."
666 },
667 {
668 "code": "java.annotation.added",
669 "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory::getInstance()",
670 "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory::getInstance()",
671 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
672 "justification": "LOG4J2-3004 Add plugin support."
673 },
674 {
675 "code": "java.annotation.added",
676 "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
677 "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
678 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextDataResolverFactory\", category = \"JsonTemplateResolverFactory\")",
679 "justification": "LOG4J2-3004 Add plugin support."
680 },
681 {
682 "code": "java.annotation.added",
683 "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory::getInstance()",
684 "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory::getInstance()",
685 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
686 "justification": "LOG4J2-3004 Add plugin support."
687 },
688 {
689 "code": "java.annotation.added",
690 "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory",
691 "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory",
692 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadResolverFactory\", category = \"JsonTemplateResolverFactory\")",
693 "justification": "LOG4J2-3004 Add plugin support."
694 },
695 {
696 "code": "java.annotation.added",
697 "old": "method org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory::getInstance()",
698 "new": "method org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory::getInstance()",
699 "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
700 "justification": "LOG4J2-3004 Add plugin support."
701 },
702 {
703 "code": "java.annotation.added",
704 "old": "class org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory",
705 "new": "class org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory",
706 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"TimestampResolverFactory\", category = \"JsonTemplateResolverFactory\")",
707 "justification": "LOG4J2-3004 Add plugin support."
708 },
709 {
710 "code": "java.annotation.added",
711 "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
712 "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
713 "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextStackResolverFactory\", category = \"JsonTemplateResolverFactory\")",
714 "justification": "LOG4J2-3004 Add plugin support."
715 },
716 {
717 "code": "java.annotation.attributeValueChanged",
718 "old": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
719 "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
720 "annotationType": "org.apache.logging.log4j.core.config.plugins.Plugin",
721 "attribute": "name",
722 "oldValue": "\"RecyclerFactory\"",
723 "newValue": "\"RecyclerFactoryConverter\"",
724 "justification": "LOG4J2-3004 Add plugin support."
725 },
726 {
727 "code": "java.class.removed",
728 "old": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
729 "justification": "LOG4J2-3004 Add plugin support."
730 }
731 ]
732 }
733 ]
+0
-653
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.core.Layout;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.StringLayout;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
26 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
27 import org.apache.logging.log4j.core.config.plugins.PluginElement;
28 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
29 import org.apache.logging.log4j.core.layout.Encoder;
30 import org.apache.logging.log4j.core.layout.LockingStringBuilderEncoder;
31 import org.apache.logging.log4j.core.layout.StringBuilderEncoder;
32 import org.apache.logging.log4j.core.util.Constants;
33 import org.apache.logging.log4j.core.util.StringEncoder;
34 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext;
35 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactories;
36 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory;
37 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverInterceptor;
38 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverInterceptors;
39 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverStringSubstitutor;
40 import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver;
41 import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers;
42 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
43 import org.apache.logging.log4j.layout.template.json.util.Recycler;
44 import org.apache.logging.log4j.layout.template.json.util.RecyclerFactory;
45 import org.apache.logging.log4j.layout.template.json.util.Uris;
46 import org.apache.logging.log4j.util.Strings;
47
48 import java.nio.charset.Charset;
49 import java.util.Collections;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.Objects;
53 import java.util.function.Supplier;
54
55 @Plugin(name = "JsonTemplateLayout",
56 category = Node.CATEGORY,
57 elementType = Layout.ELEMENT_TYPE)
58 public class JsonTemplateLayout implements StringLayout {
59
60 private static final Map<String, String> CONTENT_FORMAT =
61 Collections.singletonMap("version", "1");
62
63 private final Charset charset;
64
65 private final String contentType;
66
67 private final TemplateResolver<LogEvent> eventResolver;
68
69 private final String eventDelimiter;
70
71 private final Recycler<Context> contextRecycler;
72
73 // The class and fields are visible for tests.
74 static final class Context implements AutoCloseable {
75
76 final JsonWriter jsonWriter;
77
78 final Encoder<StringBuilder> encoder;
79
80 private Context(
81 final JsonWriter jsonWriter,
82 final Encoder<StringBuilder> encoder) {
83 this.jsonWriter = jsonWriter;
84 this.encoder = encoder;
85 }
86
87 @Override
88 public void close() {
89 jsonWriter.close();
90 }
91
92 }
93
94 private JsonTemplateLayout(final Builder builder) {
95 this.charset = builder.charset;
96 this.contentType = "application/json; charset=" + charset;
97 final String eventDelimiterSuffix = builder.isNullEventDelimiterEnabled() ? "\0" : "";
98 this.eventDelimiter = builder.eventDelimiter + eventDelimiterSuffix;
99 final Configuration configuration = builder.configuration;
100 final JsonWriter jsonWriter = JsonWriter
101 .newBuilder()
102 .setMaxStringLength(builder.maxStringLength)
103 .setTruncatedStringSuffix(builder.truncatedStringSuffix)
104 .build();
105 this.eventResolver = createEventResolver(
106 builder,
107 configuration,
108 charset,
109 jsonWriter);
110 this.contextRecycler = createContextRecycler(builder, jsonWriter);
111 }
112
113 private TemplateResolver<LogEvent> createEventResolver(
114 final Builder builder,
115 final Configuration configuration,
116 final Charset charset,
117 final JsonWriter jsonWriter) {
118
119 // Inject resolver factory and interceptor plugins.
120 final List<String> pluginPackages = configuration.getPluginPackages();
121 final Map<String, EventResolverFactory> resolverFactoryByName =
122 EventResolverFactories.populateResolverFactoryByName(pluginPackages);
123 final List<EventResolverInterceptor> resolverInterceptors =
124 EventResolverInterceptors.populateInterceptors(pluginPackages);
125 final EventResolverStringSubstitutor substitutor =
126 new EventResolverStringSubstitutor(configuration.getStrSubstitutor());
127
128 // Read event and stack trace element templates.
129 final String eventTemplate = readEventTemplate(builder);
130 final String stackTraceElementTemplate = readStackTraceElementTemplate(builder);
131
132 // Determine the max. string byte count.
133 final float maxByteCountPerChar = builder.charset.newEncoder().maxBytesPerChar();
134 final int maxStringByteCount =
135 Math.toIntExact(Math.round(Math.ceil(
136 maxByteCountPerChar * builder.maxStringLength)));
137
138 // Replace null event template additional fields with an empty array.
139 final EventTemplateAdditionalField[] eventTemplateAdditionalFields =
140 builder.eventTemplateAdditionalFields != null
141 ? builder.eventTemplateAdditionalFields
142 : EventTemplateAdditionalField.EMPTY_ARRAY;
143
144 // Create the resolver context.
145 final EventResolverContext resolverContext = EventResolverContext
146 .newBuilder()
147 .setConfiguration(configuration)
148 .setResolverFactoryByName(resolverFactoryByName)
149 .setResolverInterceptors(resolverInterceptors)
150 .setSubstitutor(substitutor)
151 .setCharset(charset)
152 .setJsonWriter(jsonWriter)
153 .setRecyclerFactory(builder.recyclerFactory)
154 .setMaxStringByteCount(maxStringByteCount)
155 .setTruncatedStringSuffix(builder.truncatedStringSuffix)
156 .setLocationInfoEnabled(builder.locationInfoEnabled)
157 .setStackTraceEnabled(builder.stackTraceEnabled)
158 .setStackTraceElementTemplate(stackTraceElementTemplate)
159 .setEventTemplateRootObjectKey(builder.eventTemplateRootObjectKey)
160 .setEventTemplateAdditionalFields(eventTemplateAdditionalFields)
161 .build();
162
163 // Compile the resolver template.
164 return TemplateResolvers.ofTemplate(resolverContext, eventTemplate);
165
166 }
167
168 private static String readEventTemplate(final Builder builder) {
169 return readTemplate(
170 builder.eventTemplate,
171 builder.eventTemplateUri,
172 builder.charset);
173 }
174
175 private static String readStackTraceElementTemplate(final Builder builder) {
176 return readTemplate(
177 builder.stackTraceElementTemplate,
178 builder.stackTraceElementTemplateUri,
179 builder.charset);
180 }
181
182 private static String readTemplate(
183 final String template,
184 final String templateUri,
185 final Charset charset) {
186 return Strings.isBlank(template)
187 ? Uris.readUri(templateUri, charset)
188 : template;
189 }
190
191 private static Recycler<Context> createContextRecycler(
192 final Builder builder,
193 final JsonWriter jsonWriter) {
194 final Supplier<Context> supplier =
195 createContextSupplier(builder.charset, jsonWriter);
196 return builder
197 .recyclerFactory
198 .create(supplier, Context::close);
199 }
200
201 private static Supplier<Context> createContextSupplier(
202 final Charset charset,
203 final JsonWriter jsonWriter) {
204 return () -> {
205 final JsonWriter clonedJsonWriter = jsonWriter.clone();
206 final Encoder<StringBuilder> encoder = createStringBuilderEncoder(charset);
207 return new Context(clonedJsonWriter, encoder);
208 };
209 }
210
211 private static Encoder<StringBuilder> createStringBuilderEncoder(
212 final Charset charset) {
213 if (Constants.ENABLE_DIRECT_ENCODERS) {
214 return Constants.ENABLE_THREADLOCALS
215 ? new StringBuilderEncoder(charset)
216 : new LockingStringBuilderEncoder(charset);
217 }
218 return null;
219 }
220
221 @Override
222 public byte[] toByteArray(final LogEvent event) {
223 final String eventJson = toSerializable(event);
224 return StringEncoder.toBytes(eventJson, charset);
225 }
226
227 @Override
228 public String toSerializable(final LogEvent event) {
229 final Context context = acquireContext();
230 final JsonWriter jsonWriter = context.jsonWriter;
231 final StringBuilder stringBuilder = jsonWriter.getStringBuilder();
232 try {
233 eventResolver.resolve(event, jsonWriter);
234 stringBuilder.append(eventDelimiter);
235 return stringBuilder.toString();
236 } finally {
237 contextRecycler.release(context);
238 }
239 }
240
241 @Override
242 public void encode(final LogEvent event, final ByteBufferDestination destination) {
243
244 // Acquire a context.
245 final Context context = acquireContext();
246 final JsonWriter jsonWriter = context.jsonWriter;
247 final StringBuilder stringBuilder = jsonWriter.getStringBuilder();
248 final Encoder<StringBuilder> encoder = context.encoder;
249
250 try {
251
252 // Render the JSON.
253 eventResolver.resolve(event, jsonWriter);
254 stringBuilder.append(eventDelimiter);
255
256 // Write to the destination.
257 if (encoder == null) {
258 final String eventJson = stringBuilder.toString();
259 final byte[] eventJsonBytes = StringEncoder.toBytes(eventJson, charset);
260 destination.writeBytes(eventJsonBytes, 0, eventJsonBytes.length);
261 } else {
262 encoder.encode(stringBuilder, destination);
263 }
264
265 }
266
267 // Release the context.
268 finally {
269 contextRecycler.release(context);
270 }
271
272 }
273
274 // Visible for tests.
275 Context acquireContext() {
276 return contextRecycler.acquire();
277 }
278
279 @Override
280 public byte[] getFooter() {
281 return null;
282 }
283
284 @Override
285 public byte[] getHeader() {
286 return null;
287 }
288
289 @Override
290 public Charset getCharset() {
291 return charset;
292 }
293
294 @Override
295 public String getContentType() {
296 return contentType;
297 }
298
299 @Override
300 public Map<String, String> getContentFormat() {
301 return CONTENT_FORMAT;
302 }
303
304 @PluginBuilderFactory
305 @SuppressWarnings("WeakerAccess")
306 public static Builder newBuilder() {
307 return new Builder();
308 }
309
310 @SuppressWarnings({"unused", "WeakerAccess"})
311 public static final class Builder
312 implements org.apache.logging.log4j.core.util.Builder<JsonTemplateLayout> {
313
314 @PluginConfiguration
315 private Configuration configuration;
316
317 @PluginBuilderAttribute
318 private Charset charset = JsonTemplateLayoutDefaults.getCharset();
319
320 @PluginBuilderAttribute
321 private boolean locationInfoEnabled =
322 JsonTemplateLayoutDefaults.isLocationInfoEnabled();
323
324 @PluginBuilderAttribute
325 private boolean stackTraceEnabled =
326 JsonTemplateLayoutDefaults.isStackTraceEnabled();
327
328 @PluginBuilderAttribute
329 private String eventTemplate = JsonTemplateLayoutDefaults.getEventTemplate();
330
331 @PluginBuilderAttribute
332 private String eventTemplateUri =
333 JsonTemplateLayoutDefaults.getEventTemplateUri();
334
335 @PluginBuilderAttribute
336 private String eventTemplateRootObjectKey =
337 JsonTemplateLayoutDefaults.getEventTemplateRootObjectKey();
338
339 @PluginElement("EventTemplateAdditionalField")
340 private EventTemplateAdditionalField[] eventTemplateAdditionalFields;
341
342 @PluginBuilderAttribute
343 private String stackTraceElementTemplate =
344 JsonTemplateLayoutDefaults.getStackTraceElementTemplate();
345
346 @PluginBuilderAttribute
347 private String stackTraceElementTemplateUri =
348 JsonTemplateLayoutDefaults.getStackTraceElementTemplateUri();
349
350 @PluginBuilderAttribute
351 private String eventDelimiter = JsonTemplateLayoutDefaults.getEventDelimiter();
352
353 @PluginBuilderAttribute
354 private boolean nullEventDelimiterEnabled =
355 JsonTemplateLayoutDefaults.isNullEventDelimiterEnabled();
356
357 @PluginBuilderAttribute
358 private int maxStringLength = JsonTemplateLayoutDefaults.getMaxStringLength();
359
360 @PluginBuilderAttribute
361 private String truncatedStringSuffix =
362 JsonTemplateLayoutDefaults.getTruncatedStringSuffix();
363
364 @PluginBuilderAttribute
365 private RecyclerFactory recyclerFactory =
366 JsonTemplateLayoutDefaults.getRecyclerFactory();
367
368 private Builder() {
369 // Do nothing.
370 }
371
372 public Configuration getConfiguration() {
373 return configuration;
374 }
375
376 public Builder setConfiguration(final Configuration configuration) {
377 this.configuration = configuration;
378 return this;
379 }
380
381 public Charset getCharset() {
382 return charset;
383 }
384
385 public Builder setCharset(final Charset charset) {
386 this.charset = charset;
387 return this;
388 }
389
390 public boolean isLocationInfoEnabled() {
391 return locationInfoEnabled;
392 }
393
394 public Builder setLocationInfoEnabled(final boolean locationInfoEnabled) {
395 this.locationInfoEnabled = locationInfoEnabled;
396 return this;
397 }
398
399 public boolean isStackTraceEnabled() {
400 return stackTraceEnabled;
401 }
402
403 public Builder setStackTraceEnabled(final boolean stackTraceEnabled) {
404 this.stackTraceEnabled = stackTraceEnabled;
405 return this;
406 }
407
408 public String getEventTemplate() {
409 return eventTemplate;
410 }
411
412 public Builder setEventTemplate(final String eventTemplate) {
413 this.eventTemplate = eventTemplate;
414 return this;
415 }
416
417 public String getEventTemplateUri() {
418 return eventTemplateUri;
419 }
420
421 public Builder setEventTemplateUri(final String eventTemplateUri) {
422 this.eventTemplateUri = eventTemplateUri;
423 return this;
424 }
425
426 public String getEventTemplateRootObjectKey() {
427 return eventTemplateRootObjectKey;
428 }
429
430 public Builder setEventTemplateRootObjectKey(String eventTemplateRootObjectKey) {
431 this.eventTemplateRootObjectKey = eventTemplateRootObjectKey;
432 return this;
433 }
434
435 public EventTemplateAdditionalField[] getEventTemplateAdditionalFields() {
436 return eventTemplateAdditionalFields;
437 }
438
439 public Builder setEventTemplateAdditionalFields(
440 final EventTemplateAdditionalField[] eventTemplateAdditionalFields) {
441 this.eventTemplateAdditionalFields = eventTemplateAdditionalFields;
442 return this;
443 }
444
445 public String getStackTraceElementTemplate() {
446 return stackTraceElementTemplate;
447 }
448
449 public Builder setStackTraceElementTemplate(
450 final String stackTraceElementTemplate) {
451 this.stackTraceElementTemplate = stackTraceElementTemplate;
452 return this;
453 }
454
455 public String getStackTraceElementTemplateUri() {
456 return stackTraceElementTemplateUri;
457 }
458
459 public Builder setStackTraceElementTemplateUri(
460 final String stackTraceElementTemplateUri) {
461 this.stackTraceElementTemplateUri = stackTraceElementTemplateUri;
462 return this;
463 }
464
465 public String getEventDelimiter() {
466 return eventDelimiter;
467 }
468
469 public Builder setEventDelimiter(final String eventDelimiter) {
470 this.eventDelimiter = eventDelimiter;
471 return this;
472 }
473
474 public boolean isNullEventDelimiterEnabled() {
475 return nullEventDelimiterEnabled;
476 }
477
478 public Builder setNullEventDelimiterEnabled(
479 final boolean nullEventDelimiterEnabled) {
480 this.nullEventDelimiterEnabled = nullEventDelimiterEnabled;
481 return this;
482 }
483
484 public int getMaxStringLength() {
485 return maxStringLength;
486 }
487
488 public Builder setMaxStringLength(final int maxStringLength) {
489 this.maxStringLength = maxStringLength;
490 return this;
491 }
492
493 public String getTruncatedStringSuffix() {
494 return truncatedStringSuffix;
495 }
496
497 public Builder setTruncatedStringSuffix(final String truncatedStringSuffix) {
498 this.truncatedStringSuffix = truncatedStringSuffix;
499 return this;
500 }
501
502 public RecyclerFactory getRecyclerFactory() {
503 return recyclerFactory;
504 }
505
506 public Builder setRecyclerFactory(final RecyclerFactory recyclerFactory) {
507 this.recyclerFactory = recyclerFactory;
508 return this;
509 }
510
511 @Override
512 public JsonTemplateLayout build() {
513 validate();
514 return new JsonTemplateLayout(this);
515 }
516
517 private void validate() {
518 Objects.requireNonNull(configuration, "config");
519 if (Strings.isBlank(eventTemplate) && Strings.isBlank(eventTemplateUri)) {
520 throw new IllegalArgumentException(
521 "both eventTemplate and eventTemplateUri are blank");
522 }
523 if (stackTraceEnabled &&
524 Strings.isBlank(stackTraceElementTemplate)
525 && Strings.isBlank(stackTraceElementTemplateUri)) {
526 throw new IllegalArgumentException(
527 "both stackTraceElementTemplate and stackTraceElementTemplateUri are blank");
528 }
529 if (maxStringLength <= 0) {
530 throw new IllegalArgumentException(
531 "was expecting a non-zero positive maxStringLength: " +
532 maxStringLength);
533 }
534 Objects.requireNonNull(truncatedStringSuffix, "truncatedStringSuffix");
535 Objects.requireNonNull(recyclerFactory, "recyclerFactory");
536 }
537
538 }
539
540 @Plugin(name = "EventTemplateAdditionalField",
541 category = Node.CATEGORY,
542 printObject = true)
543 public static final class EventTemplateAdditionalField {
544
545 static final EventTemplateAdditionalField[] EMPTY_ARRAY = {};
546
547 public enum Format { STRING, JSON }
548
549 private final String key;
550
551 private final String value;
552
553 private final Format format;
554
555 private EventTemplateAdditionalField(final Builder builder) {
556 this.key = builder.key;
557 this.value = builder.value;
558 this.format = builder.format;
559 }
560
561 public String getKey() {
562 return key;
563 }
564
565 public String getValue() {
566 return value;
567 }
568
569 public Format getFormat() {
570 return format;
571 }
572
573 @Override
574 public boolean equals(Object object) {
575 if (this == object) {
576 return true;
577 }
578 if (object == null || getClass() != object.getClass()) {
579 return false;
580 }
581 EventTemplateAdditionalField that = (EventTemplateAdditionalField) object;
582 return key.equals(that.key) &&
583 value.equals(that.value) &&
584 format == that.format;
585 }
586
587 @Override
588 public int hashCode() {
589 return Objects.hash(key, value, format);
590 }
591
592 @Override
593 public String toString() {
594 final String formattedValue = Format.STRING.equals(format)
595 ? String.format("\"%s\"", value)
596 : value;
597 return String.format("%s=%s", key, formattedValue);
598 }
599
600 @PluginBuilderFactory
601 public static EventTemplateAdditionalField.Builder newBuilder() {
602 return new EventTemplateAdditionalField.Builder();
603 }
604
605 public static class Builder
606 implements org.apache.logging.log4j.core.util.Builder<EventTemplateAdditionalField> {
607
608 @PluginBuilderAttribute
609 private String key;
610
611 @PluginBuilderAttribute
612 private String value;
613
614 @PluginBuilderAttribute
615 private Format format = Format.STRING;
616
617 public Builder setKey(final String key) {
618 this.key = key;
619 return this;
620 }
621
622 public Builder setValue(final String value) {
623 this.value = value;
624 return this;
625 }
626
627 public Builder setFormat(final Format format) {
628 this.format = format;
629 return this;
630 }
631
632 @Override
633 public EventTemplateAdditionalField build() {
634 validate();
635 return new EventTemplateAdditionalField(this);
636 }
637
638 private void validate() {
639 if (Strings.isBlank(key)) {
640 throw new IllegalArgumentException("blank key");
641 }
642 if (Strings.isBlank(value)) {
643 throw new IllegalArgumentException("blank value");
644 }
645 Objects.requireNonNull(format, "format");
646 }
647
648 }
649
650 }
651
652 }
+0
-146
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutDefaults.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.layout.template.json.util.RecyclerFactories;
19 import org.apache.logging.log4j.layout.template.json.util.RecyclerFactory;
20 import org.apache.logging.log4j.util.PropertiesUtil;
21
22 import java.nio.charset.Charset;
23 import java.nio.charset.StandardCharsets;
24 import java.util.Locale;
25 import java.util.TimeZone;
26
27 public final class JsonTemplateLayoutDefaults {
28
29 private JsonTemplateLayoutDefaults() {}
30
31 private static final PropertiesUtil PROPERTIES = PropertiesUtil.getProperties();
32
33 public static Charset getCharset() {
34 final String charsetName =
35 PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.charset");
36 return charsetName != null
37 ? Charset.forName(charsetName)
38 : StandardCharsets.UTF_8;
39 }
40
41 public static boolean isLocationInfoEnabled() {
42 return PROPERTIES.getBooleanProperty(
43 "log4j.layout.jsonTemplate.locationInfoEnabled",
44 false);
45 }
46
47 public static boolean isStackTraceEnabled() {
48 return PROPERTIES.getBooleanProperty(
49 "log4j.layout.jsonTemplate.stackTraceEnabled",
50 true);
51 }
52
53 public static String getTimestampFormatPattern() {
54 return PROPERTIES.getStringProperty(
55 "log4j.layout.jsonTemplate.timestampFormatPattern",
56 "yyyy-MM-dd'T'HH:mm:ss.SSSZZZ");
57 }
58
59 public static TimeZone getTimeZone() {
60 final String timeZoneId =
61 PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.timeZone");
62 return timeZoneId != null
63 ? TimeZone.getTimeZone(timeZoneId)
64 : TimeZone.getDefault();
65 }
66
67 public static Locale getLocale() {
68 final String locale =
69 PROPERTIES.getStringProperty("log4j.layout.jsonTemplate.locale");
70 if (locale == null) {
71 return Locale.getDefault();
72 }
73 final String[] localeFields = locale.split("_", 3);
74 switch (localeFields.length) {
75 case 1: return new Locale(localeFields[0]);
76 case 2: return new Locale(localeFields[0], localeFields[1]);
77 case 3: return new Locale(localeFields[0], localeFields[1], localeFields[2]);
78 default: throw new IllegalArgumentException("invalid locale: " + locale);
79 }
80 }
81
82 public static String getEventTemplate() {
83 return PROPERTIES.getStringProperty(
84 "log4j.layout.jsonTemplate.eventTemplate");
85 }
86
87 public static String getEventTemplateUri() {
88 return PROPERTIES.getStringProperty(
89 "log4j.layout.jsonTemplate.eventTemplateUri",
90 "classpath:EcsLayout.json");
91 }
92
93 public static String getEventTemplateRootObjectKey() {
94 return PROPERTIES.getStringProperty(
95 "log4j.layout.jsonTemplate.eventTemplateRootObjectKey");
96 }
97
98 public static String getStackTraceElementTemplate() {
99 return PROPERTIES.getStringProperty(
100 "log4j.layout.jsonTemplate.stackTraceElementTemplate");
101 }
102
103 public static String getStackTraceElementTemplateUri() {
104 return PROPERTIES.getStringProperty(
105 "log4j.layout.jsonTemplate.stackTraceElementTemplateUri",
106 "classpath:StackTraceElementLayout.json");
107 }
108
109 public static String getEventDelimiter() {
110 return PROPERTIES.getStringProperty(
111 "log4j.layout.jsonTemplate.eventDelimiter",
112 System.lineSeparator());
113 }
114
115 public static boolean isNullEventDelimiterEnabled() {
116 return PROPERTIES.getBooleanProperty(
117 "log4j.layout.jsonTemplate.nullEventDelimiterEnabled",
118 false);
119 }
120
121 public static int getMaxStringLength() {
122 final int maxStringLength = PROPERTIES.getIntegerProperty(
123 "log4j.layout.jsonTemplate.maxStringLength",
124 16 * 1_024);
125 if (maxStringLength <= 0) {
126 throw new IllegalArgumentException(
127 "was expecting a non-zero positive maxStringLength: " +
128 maxStringLength);
129 }
130 return maxStringLength;
131 }
132
133 public static String getTruncatedStringSuffix() {
134 return PROPERTIES.getStringProperty(
135 "log4j.layout.jsonTemplate.truncatedStringSuffix",
136 "…");
137 }
138
139 public static RecyclerFactory getRecyclerFactory() {
140 final String recyclerFactorySpec = PROPERTIES.getStringProperty(
141 "log4j.layout.jsonTemplate.recyclerFactory");
142 return RecyclerFactories.ofSpec(recyclerFactorySpec);
143 }
144
145 }
+0
-324
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults;
20 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
21 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
22
23 import java.util.Locale;
24 import java.util.function.Function;
25
26 /**
27 * Converts the case of string values.
28 *
29 * <h3>Configuration</h3>
30 *
31 * <pre>
32 * config = case , input , [ locale ] , [ errorHandlingStrategy ]
33 * input = JSON
34 * case = "case" -> ( "upper" | "lower" )
35 * locale = "locale" -> (
36 * language |
37 * ( language , "_" , country ) |
38 * ( language , "_" , country , "_" , variant )
39 * )
40 * errorHandlingStrategy = "errorHandlingStrategy" -> (
41 * "fail" |
42 * "pass" |
43 * "replace"
44 * )
45 * replacement = "replacement" -> JSON
46 * </pre>
47 *
48 * {@code input} can be any available template value; e.g., a JSON literal,
49 * a lookup string, an object pointing to another resolver.
50 * <p>
51 * Unless provided, {@code locale} points to the one returned by
52 * {@link JsonTemplateLayoutDefaults#getLocale()}, which is configured by
53 * {@code log4j.layout.jsonTemplate.locale} system property and by default set
54 * to the default system locale.
55 * <p>
56 * {@code errorHandlingStrategy} determines the behavior when either the
57 * {@code input} doesn't resolve to a string value or case conversion throws an
58 * exception:
59 * <ul>
60 * <li>{@code fail} propagates the failure
61 * <li>{@code pass} causes the resolved value to be passed as is
62 * <li>{@code replace} suppresses the failure and replaces it with the
63 * {@code replacement}, which is set to {@code null} by default
64 * </ul>
65 * {@code errorHandlingStrategy} is set to {@code replace} by default.
66 * <p>
67 * Most of the time JSON logs are persisted to a storage solution
68 * (e.g., Elasticsearch) that keeps a statically-typed index on fields.
69 * Hence, if a field is always expected to be of type string, using non-string
70 * {@code replacement}s or {@code pass} in {@code errorHandlingStrategy} might
71 * result in type incompatibility issues at the storage level.
72 * <p>
73 * Unless the {@code input} value is {@code pass}ed intact or {@code replace}d,
74 * case conversion is not garbage-free.
75 *
76 * <h3>Examples</h3>
77 *
78 * Convert the resolved log level strings to upper-case:
79 *
80 * <pre>
81 * {
82 * "$resolver": "caseConverter",
83 * "case": "upper",
84 * "input": {
85 * "$resolver": "level",
86 * "field": "name"
87 * }
88 * }
89 * </pre>
90 *
91 * Convert the resolved {@code USER} environment variable to lower-case using
92 * {@code nl_NL} locale:
93 *
94 * <pre>
95 * {
96 * "$resolver": "caseConverter",
97 * "case": "lower",
98 * "locale": "nl_NL",
99 * "input": "${env:USER}"
100 * }
101 * </pre>
102 *
103 * Convert the resolved {@code sessionId} thread context data (MDC) to
104 * lower-case:
105 *
106 * <pre>
107 * {
108 * "$resolver": "caseConverter",
109 * "case": "lower",
110 * "input": {
111 * "$resolver": "mdc",
112 * "key": "sessionId"
113 * }
114 * }
115 * </pre>
116 *
117 * Above, if {@code sessionId} MDC resolves to a, say, number, case conversion
118 * will fail. Since {@code errorHandlingStrategy} is set to {@code replace} and
119 * {@code replacement} is set to {@code null} by default, the resolved value
120 * will be {@code null}. One can suppress this behavior and let the resolved
121 * {@code sessionId} number be left as is:
122 *
123 * <pre>
124 * {
125 * "$resolver": "caseConverter",
126 * "case": "lower",
127 * "input": {
128 * "$resolver": "mdc",
129 * "key": "sessionId"
130 * },
131 * "errorHandlingStrategy": "pass"
132 * }
133 * </pre>
134 *
135 * or replace it with a custom string:
136 *
137 * <pre>
138 * {
139 * "$resolver": "caseConverter",
140 * "case": "lower",
141 * "input": {
142 * "$resolver": "mdc",
143 * "key": "sessionId"
144 * },
145 * "errorHandlingStrategy": "replace"
146 * "replacement": "unknown"
147 * }
148 * </pre>
149 */
150 public final class CaseConverterResolver implements EventResolver {
151
152 private final TemplateResolver<LogEvent> inputResolver;
153
154 private final Function<String, String> converter;
155
156 private final ErrorHandlingStrategy errorHandlingStrategy;
157
158 private final TemplateResolver<LogEvent> replacementResolver;
159
160 private enum ErrorHandlingStrategy {
161
162 FAIL("fail"),
163
164 PASS("pass"),
165
166 REPLACE("replace");
167
168 private final String name;
169
170 ErrorHandlingStrategy(String name) {
171 this.name = name;
172 }
173
174 }
175
176 CaseConverterResolver(
177 final EventResolverContext context,
178 final TemplateResolverConfig config) {
179 this.inputResolver = createDelegate(context, config);
180 this.converter = createConverter(config);
181 this.errorHandlingStrategy = readErrorHandlingStrategy(config);
182 this.replacementResolver = createReplacement(context, config);
183 }
184
185 private static TemplateResolver<LogEvent> createDelegate(
186 final EventResolverContext context,
187 final TemplateResolverConfig config) {
188 Object delegateObject = config.getObject("input");
189 return TemplateResolvers.ofObject(context, delegateObject);
190 }
191
192 private static Function<String, String> createConverter(
193 final TemplateResolverConfig config) {
194 final Locale locale = config.getLocale("locale");
195 final String _case = config.getString("case");
196 if ("upper".equals(_case)) {
197 return input -> input.toUpperCase(locale);
198 } else if ("lower".equals(_case)) {
199 return input -> input.toLowerCase(locale);
200 } else {
201 throw new IllegalArgumentException("invalid case: " + config);
202 }
203 }
204
205 private static ErrorHandlingStrategy readErrorHandlingStrategy(
206 final TemplateResolverConfig config) {
207 final String strategyName = config.getString("errorHandlingStrategy");
208 if (strategyName == null) {
209 return ErrorHandlingStrategy.REPLACE;
210 }
211 for (ErrorHandlingStrategy strategy : ErrorHandlingStrategy.values()) {
212 if (strategy.name.equals(strategyName)) {
213 return strategy;
214 }
215 }
216 throw new IllegalArgumentException(
217 "illegal error handling strategy: " + config);
218 }
219
220 private static TemplateResolver<LogEvent> createReplacement(
221 final EventResolverContext context,
222 final TemplateResolverConfig config) {
223 Object replacementObject = config.getObject("replacement");
224 return TemplateResolvers.ofObject(context, replacementObject);
225 }
226
227 static String getName() {
228 return "caseConverter";
229 }
230
231 @Override
232 public boolean isFlattening() {
233 return inputResolver.isFlattening();
234 }
235
236 @Override
237 public boolean isResolvable() {
238 return inputResolver.isResolvable();
239 }
240
241 @Override
242 public boolean isResolvable(final LogEvent logEvent) {
243 return inputResolver.isResolvable(logEvent);
244 }
245
246 @Override
247 public void resolve(final LogEvent logEvent, final JsonWriter jsonWriter) {
248 final int startIndex = jsonWriter.getStringBuilder().length();
249 inputResolver.resolve(logEvent, jsonWriter);
250 convertCase(logEvent, jsonWriter, startIndex);
251 }
252
253 @Override
254 public void resolve(
255 final LogEvent logEvent,
256 final JsonWriter jsonWriter,
257 final boolean succeedingEntry) {
258 final int startIndex = jsonWriter.getStringBuilder().length();
259 inputResolver.resolve(logEvent, jsonWriter, succeedingEntry);
260 convertCase(logEvent, jsonWriter, startIndex);
261 }
262
263 private void convertCase(
264 final LogEvent logEvent,
265 final JsonWriter jsonWriter,
266 final int startIndex) {
267
268 // If the last emitted JSON token was a string, convert it.
269 final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
270 final int endIndex = jsonWriterStringBuilder.length();
271 final boolean stringTyped = (startIndex + 1) < endIndex
272 && jsonWriterStringBuilder.charAt(startIndex) == '"'
273 && jsonWriterStringBuilder.charAt(endIndex - 1) == '"';
274 if (stringTyped) {
275 final String json = jsonWriterStringBuilder.substring(startIndex, endIndex);
276 convertCase(logEvent, jsonWriter, startIndex, json);
277 }
278
279 // Otherwise, see what we can do.
280 else if (ErrorHandlingStrategy.FAIL.equals(errorHandlingStrategy)) {
281 final String json = jsonWriterStringBuilder.substring(startIndex, endIndex);
282 throw new RuntimeException(
283 "was expecting a string value, found: " + json);
284 } else if (ErrorHandlingStrategy.PASS.equals(errorHandlingStrategy)) {
285 // Do nothing.
286 } else if (ErrorHandlingStrategy.REPLACE.equals(errorHandlingStrategy)) {
287 jsonWriterStringBuilder.setLength(startIndex);
288 replacementResolver.resolve(logEvent, jsonWriter);
289 } else {
290 throw new AssertionError("should not have reached here");
291 }
292
293 }
294
295 private void convertCase(
296 final LogEvent logEvent,
297 final JsonWriter jsonWriter,
298 final int startIndex,
299 final String json) {
300 final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
301 final String string = (String) JsonReader.read(json);
302 final String convertedString;
303 try {
304 convertedString = converter.apply(string);
305 } catch (final Exception error) {
306 if (ErrorHandlingStrategy.FAIL.equals(errorHandlingStrategy)) {
307 throw new RuntimeException(
308 "case conversion failure for string: " + string,
309 error);
310 } else if (ErrorHandlingStrategy.PASS.equals(errorHandlingStrategy)) {
311 return;
312 } else if (ErrorHandlingStrategy.REPLACE.equals(errorHandlingStrategy)) {
313 jsonWriterStringBuilder.setLength(startIndex);
314 replacementResolver.resolve(logEvent, jsonWriter);
315 return;
316 }
317 throw new AssertionError("should not have reached here");
318 }
319 jsonWriterStringBuilder.setLength(startIndex);
320 jsonWriter.writeString(convertedString);
321 }
322
323 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link CaseConverterResolver} factory.
23 */
24 @Plugin(name = "CaseConverterResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class CaseConverterResolverFactory implements EventResolverFactory {
26
27 private static final CaseConverterResolverFactory INSTANCE =
28 new CaseConverterResolverFactory();
29
30 private CaseConverterResolverFactory() {}
31
32 @PluginFactory
33 public static CaseConverterResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return CaseConverterResolver.getName();
40 }
41
42 @Override
43 public CaseConverterResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return new CaseConverterResolver(context, config);
47 }
48
49 }
+0
-247
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CounterResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20 import org.apache.logging.log4j.layout.template.json.util.Recycler;
21
22 import java.math.BigInteger;
23 import java.util.concurrent.atomic.AtomicLong;
24 import java.util.concurrent.atomic.AtomicReference;
25 import java.util.concurrent.locks.LockSupport;
26 import java.util.function.Consumer;
27
28 /**
29 * Resolves a number from an internal counter.
30 *
31 * <h3>Configuration</h3>
32 *
33 * <pre>
34 * config = [ start ] , [ overflowing ] , [ stringified ]
35 * start = "start" -> number
36 * overflowing = "overflowing" -> boolean
37 * stringified = "stringified" -> boolean
38 * </pre>
39 *
40 * Unless provided, <tt>start</tt> and <tt>overflowing</tt> are respectively
41 * set to zero and <tt>true</tt> by default.
42 * <p>
43 * When <tt>overflowing</tt> is set to <tt>true</tt>, the internal counter
44 * is created using a <tt>long</tt>, which is subject to overflow while
45 * incrementing, though garbage-free. Otherwise, a {@link BigInteger} is used,
46 * which does not overflow, but incurs allocation costs.
47 * <p>
48 * When <tt>stringified</tt> is enabled, which is set to <tt>false</tt> by
49 * default, the resolved number will be converted to a string.
50 *
51 * <h3>Examples</h3>
52 *
53 * Resolves a sequence of numbers starting from 0. Once {@link Long#MAX_VALUE}
54 * is reached, counter overflows to {@link Long#MIN_VALUE}.
55 *
56 * <pre>
57 * {
58 * "$resolver": "counter"
59 * }
60 * </pre>
61 *
62 * Resolves a sequence of numbers starting from 1000. Once {@link Long#MAX_VALUE}
63 * is reached, counter overflows to {@link Long#MIN_VALUE}.
64 *
65 * <pre>
66 * {
67 * "$resolver": "counter",
68 * "start": 1000
69 * }
70 * </pre>
71 *
72 * Resolves a sequence of numbers starting from 0 and keeps on doing as long as
73 * JVM heap allows.
74 *
75 * <pre>
76 * {
77 * "$resolver": "counter",
78 * "overflowing": false
79 * }
80 * </pre>
81 */
82 public class CounterResolver implements EventResolver {
83
84 private final Consumer<JsonWriter> delegate;
85
86 public CounterResolver(
87 final EventResolverContext context,
88 final TemplateResolverConfig config) {
89 this.delegate = createDelegate(context, config);
90 }
91
92 private static Consumer<JsonWriter> createDelegate(
93 final EventResolverContext context,
94 final TemplateResolverConfig config) {
95 final BigInteger start = readStart(config);
96 final boolean overflowing = config.getBoolean("overflowing", true);
97 final boolean stringified = config.getBoolean("stringified", false);
98 if (stringified) {
99 final Recycler<StringBuilder> stringBuilderRecycler =
100 createStringBuilderRecycler(context);
101 return overflowing
102 ? createStringifiedLongResolver(start, stringBuilderRecycler)
103 : createStringifiedBigIntegerResolver(start, stringBuilderRecycler);
104 } else {
105 return overflowing
106 ? createLongResolver(start)
107 : createBigIntegerResolver(start);
108 }
109 }
110
111 private static BigInteger readStart(final TemplateResolverConfig config) {
112 final Object start = config.getObject("start", Object.class);
113 if (start == null) {
114 return BigInteger.ZERO;
115 } else if (start instanceof Short || start instanceof Integer || start instanceof Long) {
116 return BigInteger.valueOf(((Number) start).longValue());
117 } else if (start instanceof BigInteger) {
118 return (BigInteger) start;
119 } else {
120 final Class<?> clazz = start.getClass();
121 final String message = String.format(
122 "could not read start of type %s: %s", clazz, config);
123 throw new IllegalArgumentException(message);
124 }
125 }
126
127 private static Consumer<JsonWriter> createLongResolver(final BigInteger start) {
128 final long effectiveStart = start.longValue();
129 final AtomicLong counter = new AtomicLong(effectiveStart);
130 return (jsonWriter) -> {
131 final long number = counter.getAndIncrement();
132 jsonWriter.writeNumber(number);
133 };
134 }
135
136 private static Consumer<JsonWriter> createBigIntegerResolver(final BigInteger start) {
137 final AtomicBigInteger counter = new AtomicBigInteger(start);
138 return jsonWriter -> {
139 final BigInteger number = counter.getAndIncrement();
140 jsonWriter.writeNumber(number);
141 };
142 }
143
144 private static Recycler<StringBuilder> createStringBuilderRecycler(
145 final EventResolverContext context) {
146 return context
147 .getRecyclerFactory()
148 .create(
149 StringBuilder::new,
150 stringBuilder -> {
151 final int maxLength =
152 context.getJsonWriter().getMaxStringLength();
153 trimStringBuilder(stringBuilder, maxLength);
154 });
155 }
156
157 private static void trimStringBuilder(
158 final StringBuilder stringBuilder,
159 final int maxLength) {
160 if (stringBuilder.length() > maxLength) {
161 stringBuilder.setLength(maxLength);
162 stringBuilder.trimToSize();
163 }
164 stringBuilder.setLength(0);
165 }
166
167 private static Consumer<JsonWriter> createStringifiedLongResolver(
168 final BigInteger start,
169 final Recycler<StringBuilder> stringBuilderRecycler) {
170 final long effectiveStart = start.longValue();
171 final AtomicLong counter = new AtomicLong(effectiveStart);
172 return (jsonWriter) -> {
173 final long number = counter.getAndIncrement();
174 final StringBuilder stringBuilder = stringBuilderRecycler.acquire();
175 try {
176 stringBuilder.append(number);
177 jsonWriter.writeString(stringBuilder);
178 } finally {
179 stringBuilderRecycler.release(stringBuilder);
180 }
181 };
182 }
183
184 private static Consumer<JsonWriter> createStringifiedBigIntegerResolver(
185 final BigInteger start,
186 final Recycler<StringBuilder> stringBuilderRecycler) {
187 final AtomicBigInteger counter = new AtomicBigInteger(start);
188 return jsonWriter -> {
189 final BigInteger number = counter.getAndIncrement();
190 final StringBuilder stringBuilder = stringBuilderRecycler.acquire();
191 try {
192 stringBuilder.append(number);
193 jsonWriter.writeString(stringBuilder);
194 } finally {
195 stringBuilderRecycler.release(stringBuilder);
196 }
197 };
198 }
199
200 private static final class AtomicBigInteger {
201
202 private final AtomicReference<BigInteger> lastNumber;
203
204 private AtomicBigInteger(final BigInteger start) {
205 this.lastNumber = new AtomicReference<>(start);
206 }
207
208 private BigInteger getAndIncrement() {
209 BigInteger prevNumber;
210 BigInteger nextNumber;
211 do {
212 prevNumber = lastNumber.get();
213 nextNumber = prevNumber.add(BigInteger.ONE);
214 } while (!compareAndSetWithBackOff(prevNumber, nextNumber));
215 return prevNumber;
216 }
217
218 /**
219 * {@link AtomicReference#compareAndSet(Object, Object)} shortcut with a
220 * constant back off. This technique was originally described in
221 * <a href="https://arxiv.org/abs/1305.5800">Lightweight Contention
222 * Management for Efficient Compare-and-Swap Operations</a> and showed
223 * great results in benchmarks.
224 */
225 private boolean compareAndSetWithBackOff(
226 final BigInteger prevNumber,
227 final BigInteger nextNumber) {
228 if (lastNumber.compareAndSet(prevNumber, nextNumber)) {
229 return true;
230 }
231 LockSupport.parkNanos(1); // back-off
232 return false;
233 }
234
235 }
236
237 static String getName() {
238 return "counter";
239 }
240
241 @Override
242 public void resolve(final LogEvent ignored, final JsonWriter jsonWriter) {
243 delegate.accept(jsonWriter);
244 }
245
246 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CounterResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link CounterResolver} factory.
23 */
24 @Plugin(name = "CounterResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class CounterResolverFactory implements EventResolverFactory {
26
27 private static final CounterResolverFactory INSTANCE =
28 new CounterResolverFactory();
29
30 private CounterResolverFactory() {}
31
32 @PluginFactory
33 public static CounterResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return CounterResolver.getName();
40 }
41
42 @Override
43 public CounterResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return new CounterResolver(context, config);
47 }
48
49 }
+0
-47
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EndOfBatchResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20
21 /**
22 * {@code endOfBatch} indicator resolver.
23 */
24 public final class EndOfBatchResolver implements EventResolver {
25
26 private static final EndOfBatchResolver INSTANCE = new EndOfBatchResolver();
27
28 private EndOfBatchResolver() {}
29
30 static EndOfBatchResolver getInstance() {
31 return INSTANCE;
32 }
33
34 static String getName() {
35 return "endOfBatch";
36 }
37
38 @Override
39 public void resolve(
40 final LogEvent logEvent,
41 final JsonWriter jsonWriter) {
42 final boolean endOfBatch = logEvent.isEndOfBatch();
43 jsonWriter.writeBoolean(endOfBatch);
44 }
45
46 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EndOfBatchResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link EndOfBatchResolver} factory.
23 */
24 @Plugin(name = "EndOfBatchResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class EndOfBatchResolverFactory implements EventResolverFactory {
26
27 private static final EndOfBatchResolverFactory INSTANCE =
28 new EndOfBatchResolverFactory();
29
30 private EndOfBatchResolverFactory() {}
31
32 @PluginFactory
33 public static EndOfBatchResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return EndOfBatchResolver.getName();
40 }
41
42 @Override
43 public EndOfBatchResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return EndOfBatchResolver.getInstance();
47 }
48
49 }
+0
-98
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventAdditionalFieldInterceptor.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
21 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
22
23 import java.util.Map;
24
25 /**
26 * Interceptor to add {@link EventTemplateAdditionalField
27 * additional fields} after event template read.
28 */
29 @Plugin(name = "EventAdditionalFieldInterceptor", category = TemplateResolverInterceptor.CATEGORY)
30 public class EventAdditionalFieldInterceptor implements EventResolverInterceptor {
31
32 private static final EventAdditionalFieldInterceptor INSTANCE =
33 new EventAdditionalFieldInterceptor();
34
35 private EventAdditionalFieldInterceptor() {}
36
37 @PluginFactory
38 public static EventAdditionalFieldInterceptor getInstance() {
39 return INSTANCE;
40 }
41
42 @Override
43 public Object processTemplateBeforeResolverInjection(
44 final EventResolverContext context,
45 final Object node) {
46
47 // Short-circuit if there are no additional fields.
48 final EventTemplateAdditionalField[] additionalFields =
49 context.getEventTemplateAdditionalFields();
50 if (additionalFields.length == 0) {
51 return node;
52 }
53
54 // Check that the root is an object node.
55 final Map<String, Object> objectNode;
56 try {
57 @SuppressWarnings("unchecked") final Map<String, Object> map = (Map<String, Object>) node;
58 objectNode = map;
59 } catch (final ClassCastException error) {
60 final String message = String.format(
61 "was expecting an object to merge additional fields: %s",
62 node.getClass().getName());
63 throw new IllegalArgumentException(message);
64 }
65
66 // Merge additional fields.
67 for (final EventTemplateAdditionalField additionalField : additionalFields) {
68 final String additionalFieldKey = additionalField.getKey();
69 final Object additionalFieldValue;
70 final EventTemplateAdditionalField.Format additionalFieldFormat =
71 additionalField.getFormat();
72 if (EventTemplateAdditionalField.Format.STRING.equals(additionalFieldFormat)) {
73 additionalFieldValue = additionalField.getValue();
74 } else if (EventTemplateAdditionalField.Format.JSON.equals(additionalFieldFormat)) {
75 try {
76 additionalFieldValue = JsonReader.read(additionalField.getValue());
77 } catch (final Exception error) {
78 final String message = String.format(
79 "failed reading JSON provided by additional field: %s",
80 additionalFieldKey);
81 throw new IllegalArgumentException(message, error);
82 }
83 } else {
84 final String message = String.format(
85 "unknown format %s for additional field: %s",
86 additionalFieldKey, additionalFieldFormat);
87 throw new IllegalArgumentException(message);
88 }
89 objectNode.put(additionalFieldKey, additionalFieldValue);
90 }
91
92 // Return the modified node.
93 return node;
94
95 }
96
97 }
+0
-24
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19
20 /**
21 * {@link TemplateResolver} specialized for {@link LogEvent}s.
22 */
23 public interface EventResolver extends TemplateResolver<LogEvent> {}
+0
-292
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventResolverContext.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.Configuration;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
21 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
22 import org.apache.logging.log4j.layout.template.json.util.RecyclerFactory;
23 import org.apache.logging.log4j.util.Strings;
24
25 import java.nio.charset.Charset;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Objects;
29
30 /**
31 * {@link TemplateResolverContext} specialized for {@link LogEvent}s.
32 *
33 * @see EventResolver
34 * @see EventResolverFactory
35 */
36 public final class EventResolverContext implements TemplateResolverContext<LogEvent, EventResolverContext> {
37
38 private final Configuration configuration;
39
40 private final Map<String, EventResolverFactory> resolverFactoryByName;
41
42 private final List<EventResolverInterceptor> resolverInterceptors;
43
44 private final EventResolverStringSubstitutor substitutor;
45
46 private final Charset charset;
47
48 private final JsonWriter jsonWriter;
49
50 private final RecyclerFactory recyclerFactory;
51
52 private final int maxStringByteCount;
53
54 private final String truncatedStringSuffix;
55
56 private final boolean locationInfoEnabled;
57
58 private final boolean stackTraceEnabled;
59
60 private final String stackTraceElementTemplate;
61
62 private final String eventTemplateRootObjectKey;
63
64 private final EventTemplateAdditionalField[] eventTemplateAdditionalFields;
65
66 private EventResolverContext(final Builder builder) {
67 this.configuration = builder.configuration;
68 this.resolverFactoryByName = builder.resolverFactoryByName;
69 this.resolverInterceptors = builder.resolverInterceptors;
70 this.substitutor = builder.substitutor;
71 this.charset = builder.charset;
72 this.jsonWriter = builder.jsonWriter;
73 this.recyclerFactory = builder.recyclerFactory;
74 this.maxStringByteCount = builder.maxStringByteCount;
75 this.truncatedStringSuffix = builder.truncatedStringSuffix;
76 this.locationInfoEnabled = builder.locationInfoEnabled;
77 this.stackTraceEnabled = builder.stackTraceEnabled;
78 this.stackTraceElementTemplate = builder.stackTraceElementTemplate;
79 this.eventTemplateRootObjectKey = builder.eventTemplateRootObjectKey;
80 this.eventTemplateAdditionalFields = builder.eventTemplateAdditionalFields;
81 }
82
83 @Override
84 public final Class<EventResolverContext> getContextClass() {
85 return EventResolverContext.class;
86 }
87
88 public Configuration getConfiguration() {
89 return configuration;
90 }
91
92 @Override
93 public Map<String, EventResolverFactory> getResolverFactoryByName() {
94 return resolverFactoryByName;
95 }
96
97 @Override
98 public List<EventResolverInterceptor> getResolverInterceptors() {
99 return resolverInterceptors;
100 }
101
102 @Override
103 public EventResolverStringSubstitutor getSubstitutor() {
104 return substitutor;
105 }
106
107 public Charset getCharset() {
108 return charset;
109 }
110
111 @Override
112 public JsonWriter getJsonWriter() {
113 return jsonWriter;
114 }
115
116 public RecyclerFactory getRecyclerFactory() {
117 return recyclerFactory;
118 }
119
120 public int getMaxStringByteCount() {
121 return maxStringByteCount;
122 }
123
124 public String getTruncatedStringSuffix() {
125 return truncatedStringSuffix;
126 }
127
128 public boolean isLocationInfoEnabled() {
129 return locationInfoEnabled;
130 }
131
132 public boolean isStackTraceEnabled() {
133 return stackTraceEnabled;
134 }
135
136 public String getStackTraceElementTemplate() {
137 return stackTraceElementTemplate;
138 }
139
140 public String getEventTemplateRootObjectKey() {
141 return eventTemplateRootObjectKey;
142 }
143
144 public EventTemplateAdditionalField[] getEventTemplateAdditionalFields() {
145 return eventTemplateAdditionalFields;
146 }
147
148 public static Builder newBuilder() {
149 return new Builder();
150 }
151
152 public static class Builder {
153
154 private Configuration configuration;
155
156 private Map<String, EventResolverFactory> resolverFactoryByName;
157
158 private List<EventResolverInterceptor> resolverInterceptors;
159
160 private EventResolverStringSubstitutor substitutor;
161
162 private Charset charset;
163
164 private JsonWriter jsonWriter;
165
166 private RecyclerFactory recyclerFactory;
167
168 private int maxStringByteCount;
169
170 private String truncatedStringSuffix;
171
172 private boolean locationInfoEnabled;
173
174 private boolean stackTraceEnabled;
175
176 private String stackTraceElementTemplate;
177
178 private String eventTemplateRootObjectKey;
179
180 private EventTemplateAdditionalField[] eventTemplateAdditionalFields;
181
182 private Builder() {
183 // Do nothing.
184 }
185
186 public Builder setConfiguration(final Configuration configuration) {
187 this.configuration = configuration;
188 return this;
189 }
190
191 public Builder setResolverFactoryByName(
192 final Map<String, EventResolverFactory> resolverFactoryByName) {
193 this.resolverFactoryByName = resolverFactoryByName;
194 return this;
195 }
196
197 public Builder setResolverInterceptors(
198 final List<EventResolverInterceptor> resolverInterceptors) {
199 this.resolverInterceptors = resolverInterceptors;
200 return this;
201 }
202
203 public Builder setSubstitutor(final EventResolverStringSubstitutor substitutor) {
204 this.substitutor = substitutor;
205 return this;
206 }
207
208 public Builder setCharset(final Charset charset) {
209 this.charset = charset;
210 return this;
211 }
212
213 public Builder setJsonWriter(final JsonWriter jsonWriter) {
214 this.jsonWriter = jsonWriter;
215 return this;
216 }
217
218 public Builder setRecyclerFactory(final RecyclerFactory recyclerFactory) {
219 this.recyclerFactory = recyclerFactory;
220 return this;
221 }
222
223 public Builder setMaxStringByteCount(final int maxStringByteCount) {
224 this.maxStringByteCount = maxStringByteCount;
225 return this;
226 }
227
228 public Builder setTruncatedStringSuffix(final String truncatedStringSuffix) {
229 this.truncatedStringSuffix = truncatedStringSuffix;
230 return this;
231 }
232
233 public Builder setLocationInfoEnabled(final boolean locationInfoEnabled) {
234 this.locationInfoEnabled = locationInfoEnabled;
235 return this;
236 }
237
238 public Builder setStackTraceEnabled(final boolean stackTraceEnabled) {
239 this.stackTraceEnabled = stackTraceEnabled;
240 return this;
241 }
242
243 public Builder setStackTraceElementTemplate(final String stackTraceElementTemplate) {
244 this.stackTraceElementTemplate = stackTraceElementTemplate;
245 return this;
246 }
247
248 public Builder setEventTemplateRootObjectKey(String eventTemplateRootObjectKey) {
249 this.eventTemplateRootObjectKey = eventTemplateRootObjectKey;
250 return this;
251 }
252
253 public Builder setEventTemplateAdditionalFields(
254 final EventTemplateAdditionalField[] eventTemplateAdditionalFields) {
255 this.eventTemplateAdditionalFields = eventTemplateAdditionalFields;
256 return this;
257 }
258
259 public EventResolverContext build() {
260 validate();
261 return new EventResolverContext(this);
262 }
263
264 private void validate() {
265 Objects.requireNonNull(configuration, "configuration");
266 Objects.requireNonNull(resolverFactoryByName, "resolverFactoryByName");
267 if (resolverFactoryByName.isEmpty()) {
268 throw new IllegalArgumentException("empty resolverFactoryByName");
269 }
270 Objects.requireNonNull(resolverInterceptors, "resolverInterceptors");
271 Objects.requireNonNull(substitutor, "substitutor");
272 Objects.requireNonNull(charset, "charset");
273 Objects.requireNonNull(jsonWriter, "jsonWriter");
274 Objects.requireNonNull(recyclerFactory, "recyclerFactory");
275 if (maxStringByteCount <= 0) {
276 throw new IllegalArgumentException(
277 "was expecting maxStringByteCount > 0: " +
278 maxStringByteCount);
279 }
280 Objects.requireNonNull(truncatedStringSuffix, "truncatedStringSuffix");
281 if (stackTraceEnabled && Strings.isBlank(stackTraceElementTemplate)) {
282 throw new IllegalArgumentException(
283 "stackTraceElementTemplate cannot be blank when stackTraceEnabled is set to true");
284 }
285 Objects.requireNonNull(stackTraceElementTemplate, "stackTraceElementTemplate");
286 Objects.requireNonNull(eventTemplateAdditionalFields, "eventTemplateAdditionalFields");
287 }
288
289 }
290
291 }
+0
-39
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventResolverFactories.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19
20 import java.util.List;
21 import java.util.Map;
22
23 /**
24 * Utility class for {@link EventResolverFactory}.
25 */
26 public final class EventResolverFactories {
27
28 private EventResolverFactories() {}
29
30 public static Map<String, EventResolverFactory> populateResolverFactoryByName(
31 final List<String> pluginPackages) {
32 return TemplateResolverFactories.populateFactoryByName(
33 pluginPackages,
34 LogEvent.class,
35 EventResolverContext.class);
36 }
37
38 }
+0
-40
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19
20 /**
21 * {@link TemplateResolverFactory} specialized for {@link LogEvent}s.
22 *
23 * @see EventResolver
24 * @see EventResolverContext
25 */
26 public interface EventResolverFactory
27 extends TemplateResolverFactory<LogEvent, EventResolverContext> {
28
29 @Override
30 default Class<LogEvent> getValueClass() {
31 return LogEvent.class;
32 }
33
34 @Override
35 default Class<EventResolverContext> getContextClass() {
36 return EventResolverContext.class;
37 }
38
39 }
+0
-37
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventResolverInterceptor.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19
20 /**
21 * {@link TemplateResolverInterceptor} specialized for {@link LogEvent}s.
22 */
23 public interface EventResolverInterceptor
24 extends TemplateResolverInterceptor<LogEvent, EventResolverContext> {
25
26 @Override
27 default Class<LogEvent> getValueClass() {
28 return LogEvent.class;
29 }
30
31 @Override
32 default Class<EventResolverContext> getContextClass() {
33 return EventResolverContext.class;
34 }
35
36 }
+0
-38
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventResolverInterceptors.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19
20 import java.util.List;
21
22 /**
23 * Utility class for {@link EventResolverInterceptor}.
24 */
25 public final class EventResolverInterceptors {
26
27 private EventResolverInterceptors() {}
28
29 public static List<EventResolverInterceptor> populateInterceptors(
30 final List<String> pluginPackages) {
31 return TemplateResolverInterceptors.populateInterceptors(
32 pluginPackages,
33 LogEvent.class,
34 EventResolverContext.class);
35 }
36
37 }
+0
-51
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventResolverStringSubstitutor.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
20
21 import java.util.Objects;
22
23 /**
24 * {@link TemplateResolverStringSubstitutor} specialized for {@link LogEvent}s.
25 */
26 public final class EventResolverStringSubstitutor
27 implements TemplateResolverStringSubstitutor<LogEvent> {
28
29 private final StrSubstitutor substitutor;
30
31 public EventResolverStringSubstitutor(final StrSubstitutor substitutor) {
32 this.substitutor = Objects.requireNonNull(substitutor, "substitutor");
33 }
34
35 @Override
36 public StrSubstitutor getInternalSubstitutor() {
37 return substitutor;
38 }
39
40 @Override
41 public boolean isStable() {
42 return false;
43 }
44
45 @Override
46 public String replace(final LogEvent logEvent, final String source) {
47 return substitutor.replace(logEvent, source);
48 }
49
50 }
+0
-53
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/EventRootObjectKeyInterceptor.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
21
22 import java.util.Collections;
23
24 /**
25 * Interceptor to add a root object key to the event template.
26 *
27 * @see JsonTemplateLayout.Builder#getEventTemplateRootObjectKey()
28 */
29 @Plugin(name = "EventRootObjectKeyInterceptor", category = TemplateResolverInterceptor.CATEGORY)
30 public class EventRootObjectKeyInterceptor implements EventResolverInterceptor {
31
32 private static final EventRootObjectKeyInterceptor INSTANCE =
33 new EventRootObjectKeyInterceptor();
34
35 private EventRootObjectKeyInterceptor() {}
36
37 @PluginFactory
38 public static EventRootObjectKeyInterceptor getInstance() {
39 return INSTANCE;
40 }
41
42 @Override
43 public Object processTemplateBeforeResolverInjection(
44 final EventResolverContext context,
45 final Object node) {
46 String eventTemplateRootObjectKey = context.getEventTemplateRootObjectKey();
47 return eventTemplateRootObjectKey != null
48 ? Collections.singletonMap(eventTemplateRootObjectKey, node)
49 : node;
50 }
51
52 }
+0
-448
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ExceptionResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
21 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults;
22 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
23 import org.apache.logging.log4j.status.StatusLogger;
24
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.regex.Pattern;
29 import java.util.regex.PatternSyntaxException;
30
31 /**
32 * Exception resolver.
33 * <p>
34 * Note that this resolver is toggled by {@link
35 * JsonTemplateLayout.Builder#setStackTraceEnabled(boolean) stackTraceEnabled}
36 * layout configuration, which is by default populated from <tt>log4j.layout.jsonTemplate.stackTraceEnabled</tt>
37 * system property.
38 *
39 * <h3>Configuration</h3>
40 *
41 * <pre>
42 * config = field , [ stringified ] , [ stackTrace ]
43 * field = "field" -> ( "className" | "message" | "stackTrace" )
44 *
45 * stackTrace = "stackTrace" -> (
46 * [ stringified ]
47 * , [ elementTemplate ]
48 * )
49 *
50 * stringified = "stringified" -> ( boolean | truncation )
51 * truncation = "truncation" -> (
52 * [ suffix ]
53 * , [ pointMatcherStrings ]
54 * , [ pointMatcherRegexes ]
55 * )
56 * suffix = "suffix" -> string
57 * pointMatcherStrings = "pointMatcherStrings" -> string[]
58 * pointMatcherRegexes = "pointMatcherRegexes" -> string[]
59 *
60 * elementTemplate = "elementTemplate" -> object
61 * </pre>
62 *
63 * <tt>stringified</tt> is set to <tt>false</tt> by default.
64 * <tt>stringified</tt> at the root level is <b>deprecated</b> in favor of
65 * <tt>stackTrace.stringified</tt>, which has precedence if both are provided.
66 * <p>
67 * <tt>pointMatcherStrings</tt> and <tt>pointMatcherRegexes</tt> enable the
68 * truncation of stringified stack traces after the given matching point. If
69 * both parameters are provided, <tt>pointMatcherStrings</tt> will be checked
70 * first.
71 * <p>
72 * If a stringified stack trace truncation takes place, it will be indicated
73 * with <tt>suffix</tt>, which by default is set to the configured
74 * <tt>truncatedStringSuffix</tt> in the layout, unless explicitly provided.
75 * <p>
76 * <tt>elementTemplate</tt> is an object describing the template to be used
77 * while resolving the {@link StackTraceElement} array. If <tt>stringified</tt>
78 * is set to <tt>true</tt>, <tt>elementTemplate</tt> will be discarded. By
79 * default, <tt>elementTemplate</tt> is set to <tt>null</tt> and rather
80 * populated from the layout configuration. That is, the stack trace element
81 * template can also be provided using {@link JsonTemplateLayout.Builder#setStackTraceElementTemplate(String) stackTraceElementTemplate}
82 * and {@link JsonTemplateLayout.Builder#setStackTraceElementTemplateUri(String) setStackTraceElementTemplateUri}
83 * layout configuration parameters. The template to be employed is determined
84 * in the following order:
85 * <ol>
86 * <li><tt>elementTemplate</tt> provided in the resolver configuration
87 * <li><tt>stackTraceElementTemplate</tt> parameter from layout configuration
88 * (the default is populated from <tt>log4j.layout.jsonTemplate.stackTraceElementTemplate</tt>
89 * system property)
90 * <li><tt>stackTraceElementTemplateUri</tt> parameter from layout configuration
91 * (the default is populated from <tt>log4j.layout.jsonTemplate.stackTraceElementTemplateUri</tt>
92 * system property)
93 * </ol>
94 * <p>
95 * See {@link StackTraceElementResolver}
96 * for the list of available resolvers in a stack trace element template.
97 *
98 * <h3>Examples</h3>
99 *
100 * Resolve <tt>logEvent.getThrown().getClass().getCanonicalName()</tt>:
101 *
102 * <pre>
103 * {
104 * "$resolver": "exception",
105 * "field": "className"
106 * }
107 * </pre>
108 *
109 * Resolve the stack trace into a list of <tt>StackTraceElement</tt> objects:
110 *
111 * <pre>
112 * {
113 * "$resolver": "exception",
114 * "field": "stackTrace"
115 * }
116 * </pre>
117 *
118 * Resolve the stack trace into a string field:
119 *
120 * <pre>
121 * {
122 * "$resolver": "exception",
123 * "field": "stackTrace",
124 * "stackTrace": {
125 * "stringified": true
126 * }
127 * }
128 * </pre>
129 *
130 * Resolve the stack trace into a string field
131 * such that the content will be truncated after the given point matcher:
132 *
133 * <pre>
134 * {
135 * "$resolver": "exception",
136 * "field": "stackTrace",
137 * "stackTrace": {
138 * "stringified": {
139 * "truncation": {
140 * "suffix": ">",
141 * "pointMatcherStrings": ["at javax.servlet.http.HttpServlet.service"]
142 * }
143 * }
144 * }
145 * }
146 * </pre>
147 *
148 * Resolve the stack trace into an object described by the provided stack trace
149 * element template:
150 *
151 * <pre>
152 * {
153 * "$resolver": "exception",
154 * "field": "stackTrace",
155 * "stackTrace": {
156 * "elementTemplate": {
157 * "class": {
158 * "$resolver": "stackTraceElement",
159 * "field": "className"
160 * },
161 * "method": {
162 * "$resolver": "stackTraceElement",
163 * "field": "methodName"
164 * },
165 * "file": {
166 * "$resolver": "stackTraceElement",
167 * "field": "fileName"
168 * },
169 * "line": {
170 * "$resolver": "stackTraceElement",
171 * "field": "lineNumber"
172 * }
173 * }
174 * }
175 * }
176 * </pre>
177 *
178 * @see JsonTemplateLayout.Builder#getTruncatedStringSuffix()
179 * @see JsonTemplateLayoutDefaults#getTruncatedStringSuffix()
180 * @see JsonTemplateLayout.Builder#getStackTraceElementTemplate()
181 * @see JsonTemplateLayoutDefaults#getStackTraceElementTemplate()
182 * @see JsonTemplateLayout.Builder#getStackTraceElementTemplateUri()
183 * @see JsonTemplateLayoutDefaults#getStackTraceElementTemplateUri()
184 * @see ExceptionRootCauseResolver
185 * @see StackTraceElementResolver
186 */
187 public class ExceptionResolver implements EventResolver {
188
189 private static final Logger LOGGER = StatusLogger.getLogger();
190
191 private static final EventResolver NULL_RESOLVER =
192 (ignored, jsonGenerator) -> jsonGenerator.writeNull();
193
194 private final boolean stackTraceEnabled;
195
196 private final EventResolver internalResolver;
197
198 ExceptionResolver(
199 final EventResolverContext context,
200 final TemplateResolverConfig config) {
201 this.stackTraceEnabled = context.isStackTraceEnabled();
202 this.internalResolver = createInternalResolver(context, config);
203 }
204
205 EventResolver createInternalResolver(
206 final EventResolverContext context,
207 final TemplateResolverConfig config) {
208 final String fieldName = config.getString("field");
209 if ("className".equals(fieldName)) {
210 return createClassNameResolver();
211 } else if ("message".equals(fieldName)) {
212 return createMessageResolver();
213 } else if ("stackTrace".equals(fieldName)) {
214 return createStackTraceResolver(context, config);
215 }
216 throw new IllegalArgumentException("unknown field: " + config);
217 }
218
219 private EventResolver createClassNameResolver() {
220 return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
221 final Throwable exception = extractThrowable(logEvent);
222 if (exception == null) {
223 jsonWriter.writeNull();
224 } else {
225 String exceptionClassName = exception.getClass().getCanonicalName();
226 jsonWriter.writeString(exceptionClassName);
227 }
228 };
229 }
230
231 private EventResolver createMessageResolver() {
232 return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
233 final Throwable exception = extractThrowable(logEvent);
234 if (exception == null) {
235 jsonWriter.writeNull();
236 } else {
237 String exceptionMessage = exception.getMessage();
238 jsonWriter.writeString(exceptionMessage);
239 }
240 };
241 }
242
243 private EventResolver createStackTraceResolver(
244 final EventResolverContext context,
245 final TemplateResolverConfig config) {
246 if (!context.isStackTraceEnabled()) {
247 return NULL_RESOLVER;
248 }
249 final boolean stringified = isStackTraceStringified(config);
250 return stringified
251 ? createStackTraceStringResolver(context, config)
252 : createStackTraceObjectResolver(context, config);
253 }
254
255 private static boolean isStackTraceStringified(
256 final TemplateResolverConfig config) {
257 final Boolean stringifiedOld = config.getBoolean("stringified");
258 if (stringifiedOld != null) {
259 LOGGER.warn(
260 "\"stringified\" flag at the root level of an exception " +
261 "[root cause] resolver is deprecated in favor of " +
262 "\"stackTrace.stringified\"");
263 }
264 final Object stringifiedNew =
265 config.getObject(new String[]{"stackTrace", "stringified"});
266 if (stringifiedOld == null && stringifiedNew == null) {
267 return false;
268 } else if (stringifiedNew == null) {
269 return stringifiedOld;
270 } else {
271 return !(stringifiedNew instanceof Boolean) || (boolean) stringifiedNew;
272 }
273 }
274
275 private EventResolver createStackTraceStringResolver(
276 final EventResolverContext context,
277 final TemplateResolverConfig config) {
278
279 // Read the configuration.
280 final String truncationSuffix =
281 readTruncationSuffix(context, config);
282 final List<String> truncationPointMatcherStrings =
283 readTruncationPointMatcherStrings(config);
284 final List<String> truncationPointMatcherRegexes =
285 readTruncationPointMatcherRegexes(config);
286
287 // Create the resolver.
288 final StackTraceStringResolver resolver =
289 new StackTraceStringResolver(
290 context,
291 truncationSuffix,
292 truncationPointMatcherStrings,
293 truncationPointMatcherRegexes);
294
295 // Create the null-protected resolver.
296 return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
297 final Throwable exception = extractThrowable(logEvent);
298 if (exception == null) {
299 jsonWriter.writeNull();
300 } else {
301 resolver.resolve(exception, jsonWriter);
302 }
303 };
304
305 }
306
307 private static String readTruncationSuffix(
308 final EventResolverContext context,
309 final TemplateResolverConfig config) {
310 final String suffix = config.getString(
311 new String[]{"stackTrace", "stringified", "truncation", "suffix"});
312 return suffix != null
313 ? suffix
314 : context.getTruncatedStringSuffix();
315 }
316
317 private static List<String> readTruncationPointMatcherStrings(
318 final TemplateResolverConfig config) {
319 List<String> strings = config.getList(
320 new String[]{"stackTrace", "stringified", "truncation", "pointMatcherStrings"},
321 String.class);
322 if (strings == null) {
323 strings = Collections.emptyList();
324 }
325 return strings;
326 }
327
328 private static List<String> readTruncationPointMatcherRegexes(
329 final TemplateResolverConfig config) {
330
331 // Extract the regexes.
332 List<String> regexes = config.getList(
333 new String[]{"stackTrace", "stringified", "truncation", "pointMatcherRegexes"},
334 String.class);
335 if (regexes == null) {
336 regexes = Collections.emptyList();
337 }
338
339 // Check the regex syntax.
340 for (int i = 0; i < regexes.size(); i++) {
341 final String regex = regexes.get(i);
342 try {
343 Pattern.compile(regex);
344 } catch (final PatternSyntaxException error) {
345 final String message = String.format(
346 "invalid truncation point matcher regex at index %d: %s",
347 i, regex);
348 throw new IllegalArgumentException(message, error);
349 }
350 }
351
352 // Return the extracted regexes.
353 return regexes;
354
355 }
356
357 private static final Map<String, StackTraceElementResolverFactory> STACK_TRACE_ELEMENT_RESOLVER_FACTORY_BY_NAME;
358
359 static {
360 final StackTraceElementResolverFactory stackTraceElementResolverFactory =
361 StackTraceElementResolverFactory.getInstance();
362 STACK_TRACE_ELEMENT_RESOLVER_FACTORY_BY_NAME =
363 Collections.singletonMap(
364 stackTraceElementResolverFactory.getName(),
365 stackTraceElementResolverFactory);
366 }
367
368 private EventResolver createStackTraceObjectResolver(
369 final EventResolverContext context,
370 final TemplateResolverConfig config) {
371 final TemplateResolver<StackTraceElement> stackTraceElementResolver =
372 createStackTraceElementResolver(context, config);
373 final StackTraceObjectResolver stackTraceResolver =
374 new StackTraceObjectResolver(stackTraceElementResolver);
375 return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
376 final Throwable throwable = extractThrowable(logEvent);
377 if (throwable == null) {
378 jsonWriter.writeNull();
379 } else {
380 stackTraceResolver.resolve(throwable, jsonWriter);
381 }
382 };
383 }
384
385 private static TemplateResolver<StackTraceElement> createStackTraceElementResolver(
386 final EventResolverContext context,
387 final TemplateResolverConfig config) {
388 final StackTraceElementResolverStringSubstitutor substitutor =
389 new StackTraceElementResolverStringSubstitutor(
390 context.getSubstitutor().getInternalSubstitutor());
391 final StackTraceElementResolverContext stackTraceElementResolverContext =
392 StackTraceElementResolverContext
393 .newBuilder()
394 .setResolverFactoryByName(STACK_TRACE_ELEMENT_RESOLVER_FACTORY_BY_NAME)
395 .setSubstitutor(substitutor)
396 .setJsonWriter(context.getJsonWriter())
397 .build();
398 final String stackTraceElementTemplate =
399 findEffectiveStackTraceElementTemplate(context, config);
400 return TemplateResolvers.ofTemplate(
401 stackTraceElementResolverContext,
402 stackTraceElementTemplate);
403 }
404
405 private static String findEffectiveStackTraceElementTemplate(
406 final EventResolverContext context,
407 final TemplateResolverConfig config) {
408
409 // First, check the template configured in the resolver configuration.
410 final Object stackTraceElementTemplateObject =
411 config.getObject(new String[]{"stackTrace", "elementTemplate"});
412 if (stackTraceElementTemplateObject != null) {
413 final JsonWriter jsonWriter = context.getJsonWriter();
414 return jsonWriter.use(() -> jsonWriter.writeValue(stackTraceElementTemplateObject));
415 }
416
417 // Otherwise, use the template provided in the context.
418 return context.getStackTraceElementTemplate();
419
420 }
421
422 Throwable extractThrowable(final LogEvent logEvent) {
423 return logEvent.getThrown();
424 }
425
426 static String getName() {
427 return "exception";
428 }
429
430 @Override
431 public boolean isResolvable() {
432 return stackTraceEnabled;
433 }
434
435 @Override
436 public boolean isResolvable(final LogEvent logEvent) {
437 return stackTraceEnabled && logEvent.getThrown() != null;
438 }
439
440 @Override
441 public void resolve(
442 final LogEvent logEvent,
443 final JsonWriter jsonWriter) {
444 internalResolver.resolve(logEvent, jsonWriter);
445 }
446
447 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ExceptionResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link ExceptionResolver} factory.
23 */
24 @Plugin(name = "ExceptionResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class ExceptionResolverFactory implements EventResolverFactory {
26
27 private static final ExceptionResolverFactory INSTANCE =
28 new ExceptionResolverFactory();
29
30 private ExceptionResolverFactory() {}
31
32 @PluginFactory
33 public static ExceptionResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return ExceptionResolver.getName();
40 }
41
42 @Override
43 public ExceptionResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return new ExceptionResolver(context, config);
47 }
48
49 }
+0
-51
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ExceptionRootCauseResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.util.Throwables;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
21
22 /**
23 * Exception root cause resolver.
24 * <p>
25 * Note that this resolver is toggled by {@link
26 * JsonTemplateLayout.Builder#setStackTraceEnabled(boolean) stackTraceEnabled}
27 * layout configuration, which is by default populated from <tt>log4j.layout.jsonTemplate.stackTraceEnabled</tt>
28 * system property.
29 *
30 * @see ExceptionResolver
31 */
32 public final class ExceptionRootCauseResolver extends ExceptionResolver {
33
34 ExceptionRootCauseResolver(
35 final EventResolverContext context,
36 final TemplateResolverConfig config) {
37 super(context, config);
38 }
39
40 static String getName() {
41 return "exceptionRootCause";
42 }
43
44 @Override
45 Throwable extractThrowable(final LogEvent logEvent) {
46 final Throwable thrown = logEvent.getThrown();
47 return thrown != null ? Throwables.getRootCause(thrown) : null;
48 }
49
50 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ExceptionRootCauseResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link ExceptionRootCauseResolver} factory.
23 */
24 @Plugin(name = "ExceptionRootCauseResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class ExceptionRootCauseResolverFactory implements EventResolverFactory {
26
27 private static final ExceptionRootCauseResolverFactory INSTANCE =
28 new ExceptionRootCauseResolverFactory();
29
30 private ExceptionRootCauseResolverFactory() {}
31
32 @PluginFactory
33 public static ExceptionRootCauseResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return ExceptionRootCauseResolver.getName();
40 }
41
42 @Override
43 public ExceptionRootCauseResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return new ExceptionRootCauseResolver(context, config);
47 }
48
49 }
+0
-175
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/LevelResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.net.Severity;
21 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
22
23 import java.util.Arrays;
24 import java.util.Map;
25 import java.util.function.Function;
26 import java.util.stream.Collectors;
27
28 /**
29 * {@link Level} resolver.
30 *
31 * <h3>Configuration</h3>
32 *
33 * <pre>
34 * config = field , [ severity ]
35 * field = "field" -> ( "name" | "severity" )
36 * severity = severity-field
37 * severity-field = "field" -> ( "keyword" | "code" )
38 * </pre>
39 *
40 * <h3>Examples</h3>
41 *
42 * Resolve the level name:
43 *
44 * <pre>
45 * {
46 * "$resolver": "level",
47 * "field": "name"
48 * }
49 * </pre>
50 *
51 * Resolve the severity keyword:
52 *
53 * <pre>
54 * {
55 * "$resolver": "level",
56 * "field": "severity",
57 * "severity": {
58 * "field": "keyword"
59 * }
60 * }
61 *
62 * Resolve the severity code:
63 *
64 * <pre>
65 * {
66 * "$resolver": "level",
67 * "field": "severity",
68 * "severity": {
69 * "field": "code"
70 * }
71 * }
72 * </pre>
73 */
74 public final class LevelResolver implements EventResolver {
75
76 private static final String[] SEVERITY_CODE_RESOLUTION_BY_STANDARD_LEVEL_ORDINAL;
77
78 static {
79 final int levelCount = Level.values().length;
80 final String[] severityCodeResolutionByStandardLevelOrdinal =
81 new String[levelCount + 1];
82 for (final Level level : Level.values()) {
83 final int standardLevelOrdinal = level.getStandardLevel().ordinal();
84 final int severityCode = Severity.getSeverity(level).getCode();
85 severityCodeResolutionByStandardLevelOrdinal[standardLevelOrdinal] =
86 String.valueOf(severityCode);
87 }
88 SEVERITY_CODE_RESOLUTION_BY_STANDARD_LEVEL_ORDINAL =
89 severityCodeResolutionByStandardLevelOrdinal;
90 }
91
92 private static final EventResolver SEVERITY_CODE_RESOLVER =
93 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
94 final int standardLevelOrdinal =
95 logEvent.getLevel().getStandardLevel().ordinal();
96 final String severityCodeResolution =
97 SEVERITY_CODE_RESOLUTION_BY_STANDARD_LEVEL_ORDINAL[
98 standardLevelOrdinal];
99 jsonWriter.writeRawString(severityCodeResolution);
100 };
101
102 private final EventResolver internalResolver;
103
104 LevelResolver(
105 final EventResolverContext context,
106 final TemplateResolverConfig config) {
107 this.internalResolver = createResolver(context, config);
108 }
109
110 private static EventResolver createResolver(
111 final EventResolverContext context,
112 final TemplateResolverConfig config) {
113 final JsonWriter jsonWriter = context.getJsonWriter();
114 final String fieldName = config.getString("field");
115 if ("name".equals(fieldName)) {
116 return createNameResolver(jsonWriter);
117 } else if ("severity".equals(fieldName)) {
118 final String severityFieldName =
119 config.getString(new String[]{"severity", "field"});
120 if ("keyword".equals(severityFieldName)) {
121 return createSeverityKeywordResolver(jsonWriter);
122 } else if ("code".equals(severityFieldName)) {
123 return SEVERITY_CODE_RESOLVER;
124 }
125 throw new IllegalArgumentException(
126 "unknown severity field: " + config);
127 }
128 throw new IllegalArgumentException("unknown field: " + config);
129 }
130
131 private static EventResolver createNameResolver(
132 final JsonWriter contextJsonWriter) {
133 final Map<Level, String> resolutionByLevel = Arrays
134 .stream(Level.values())
135 .collect(Collectors.toMap(
136 Function.identity(),
137 (final Level level) -> contextJsonWriter.use(() -> {
138 final String name = level.name();
139 contextJsonWriter.writeString(name);
140 })));
141 return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
142 final String resolution = resolutionByLevel.get(logEvent.getLevel());
143 jsonWriter.writeRawString(resolution);
144 };
145 }
146
147 private static EventResolver createSeverityKeywordResolver(
148 final JsonWriter contextJsonWriter) {
149 final Map<Level, String> resolutionByLevel = Arrays
150 .stream(Level.values())
151 .collect(Collectors.toMap(
152 Function.identity(),
153 (final Level level) -> contextJsonWriter.use(() -> {
154 final String severityKeyword = Severity.getSeverity(level).name();
155 contextJsonWriter.writeString(severityKeyword);
156 })));
157 return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
158 final String resolution = resolutionByLevel.get(logEvent.getLevel());
159 jsonWriter.writeRawString(resolution);
160 };
161 }
162
163 static String getName() {
164 return "level";
165 }
166
167 @Override
168 public void resolve(
169 final LogEvent logEvent,
170 final JsonWriter jsonWriter) {
171 internalResolver.resolve(logEvent, jsonWriter);
172 }
173
174 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/LevelResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link LevelResolver} factory.
23 */
24 @Plugin(name = "LevelResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class LevelResolverFactory implements EventResolverFactory {
26
27 private static final LevelResolverFactory INSTANCE = new LevelResolverFactory();
28
29 private LevelResolverFactory() {}
30
31 @PluginFactory
32 public static LevelResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return LevelResolver.getName();
39 }
40
41 @Override
42 public LevelResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new LevelResolver(context, config);
46 }
47
48 }
+0
-93
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/LoggerResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20
21 /**
22 * Logger resolver.
23 *
24 * <h3>Configuration</h3>
25 *
26 * <pre>
27 * config = "field" -> ( "name" | "fqcn" )
28 * </pre>
29 *
30 * <h3>Examples</h3>
31 *
32 * Resolve the logger name:
33 *
34 * <pre>
35 * {
36 * "$resolver": "logger",
37 * "field": "name"
38 * }
39 * </pre>
40 *
41 * Resolve the logger's fully qualified class name:
42 *
43 * <pre>
44 * {
45 * "$resolver": "logger",
46 * "field": "fqcn"
47 * }
48 * </pre>
49 */
50 public final class LoggerResolver implements EventResolver {
51
52 private static final EventResolver NAME_RESOLVER =
53 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
54 final String loggerName = logEvent.getLoggerName();
55 jsonWriter.writeString(loggerName);
56 };
57
58 private static final EventResolver FQCN_RESOLVER =
59 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
60 final String loggerFqcn = logEvent.getLoggerFqcn();
61 jsonWriter.writeString(loggerFqcn);
62 };
63
64 private final EventResolver internalResolver;
65
66 LoggerResolver(final TemplateResolverConfig config) {
67 this.internalResolver = createInternalResolver(config);
68 }
69
70 private static EventResolver createInternalResolver(
71 final TemplateResolverConfig config) {
72 final String fieldName = config.getString("field");
73 if ("name".equals(fieldName)) {
74 return NAME_RESOLVER;
75 } else if ("fqcn".equals(fieldName)) {
76 return FQCN_RESOLVER;
77 }
78 throw new IllegalArgumentException("unknown field: " + config);
79 }
80
81 static String getName() {
82 return "logger";
83 }
84
85 @Override
86 public void resolve(
87 final LogEvent logEvent,
88 final JsonWriter jsonWriter) {
89 internalResolver.resolve(logEvent, jsonWriter);
90 }
91
92 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/LoggerResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link LoggerResolver} factory.
23 */
24 @Plugin(name = "LoggerResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class LoggerResolverFactory implements EventResolverFactory {
26
27 private static final LoggerResolverFactory INSTANCE = new LoggerResolverFactory();
28
29 private LoggerResolverFactory() {}
30
31 @PluginFactory
32 public static LoggerResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return LoggerResolver.getName();
39 }
40
41 @Override
42 public LoggerResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new LoggerResolver(config);
46 }
47
48 }
+0
-90
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MainMapResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.lookup.MainMapLookup;
20 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
21
22 /**
23 * An index-based resolver for the <tt>main()</tt> method arguments.
24 *
25 * <h3>Configuration</h3>
26 *
27 * <pre>
28 * config = index | key
29 * index = "index" -> number
30 * key = "key" -> string
31 * </pre>
32 *
33 * <h3>Examples</h3>
34 *
35 * Resolve the 1st <tt>main()</tt> method argument:
36 *
37 * <pre>
38 * {
39 * "$resolver": "main",
40 * "index": 0
41 * }
42 * </pre>
43 *
44 * Resolve the argument coming right after <tt>--userId</tt>:
45 *
46 * <pre>
47 * {
48 * "$resolver": "main",
49 * "key": "--userId"
50 * }
51 * </pre>
52 *
53 * @see MainMapResolver
54 */
55 public final class MainMapResolver implements EventResolver {
56
57 private static final MainMapLookup MAIN_MAP_LOOKUP = new MainMapLookup();
58
59 private final String key;
60
61 static String getName() {
62 return "main";
63 }
64
65 MainMapResolver(final TemplateResolverConfig config) {
66 final String key = config.getString("key");
67 final Integer index = config.getInteger("index");
68 if (key != null && index != null) {
69 throw new IllegalArgumentException(
70 "provided both key and index: " + config);
71 }
72 if (key == null && index == null) {
73 throw new IllegalArgumentException(
74 "either key or index must be provided: " + config);
75 }
76 this.key = index != null
77 ? String.valueOf(index)
78 : key;
79 }
80
81 @Override
82 public void resolve(
83 final LogEvent logEvent,
84 final JsonWriter jsonWriter) {
85 final String value = MAIN_MAP_LOOKUP.lookup(key);
86 jsonWriter.writeString(value);
87 }
88
89 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MainMapResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link MainMapResolver} factory.
23 */
24 @Plugin(name = "MainMapResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class MainMapResolverFactory implements EventResolverFactory {
26
27 private static final MainMapResolverFactory INSTANCE = new MainMapResolverFactory();
28
29 private MainMapResolverFactory() {}
30
31 @PluginFactory
32 public static MainMapResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return MainMapResolver.getName();
39 }
40
41 @Override
42 public MainMapResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new MainMapResolver(config);
46 }
47
48 }
+0
-51
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MapResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.message.MapMessage;
20 import org.apache.logging.log4j.message.Message;
21 import org.apache.logging.log4j.util.ReadOnlyStringMap;
22
23 /**
24 * {@link MapMessage} resolver.
25 *
26 * @see ReadOnlyStringMapResolver
27 */
28 public final class MapResolver extends ReadOnlyStringMapResolver {
29
30 MapResolver(
31 final EventResolverContext context,
32 final TemplateResolverConfig config) {
33 super(context, config, MapResolver::toMap);
34 }
35
36 private static ReadOnlyStringMap toMap(final LogEvent logEvent) {
37 final Message message = logEvent.getMessage();
38 if (!(message instanceof MapMessage)) {
39 return null;
40 }
41 @SuppressWarnings("unchecked")
42 final MapMessage<?, Object> mapMessage = (MapMessage<?, Object>) message;
43 return mapMessage.getIndexedReadOnlyStringMap();
44 }
45
46 static String getName() {
47 return "map";
48 }
49
50 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MapResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link MapResolver} factory.
23 */
24 @Plugin(name = "MapResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class MapResolverFactory implements EventResolverFactory {
26
27 private static final MapResolverFactory INSTANCE = new MapResolverFactory();
28
29 private MapResolverFactory() {}
30
31 @PluginFactory
32 public static MapResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return MapResolver.getName();
39 }
40
41 @Override
42 public MapResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new MapResolver(context, config);
46 }
47
48 }
+0
-86
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.Marker;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
21
22 /**
23 * A {@link Marker} resolver.
24 *
25 * <h3>Configuration</h3>
26 *
27 * <pre>
28 * config = "field" -> "name"
29 * </pre>
30 *
31 * <h3>Examples</h3>
32 *
33 * Resolve the marker name:
34 *
35 * <pre>
36 * {
37 * "$resolver": "marker",
38 * "field": "name"
39 * }
40 * </pre>
41 */
42 public final class MarkerResolver implements EventResolver {
43
44 private static final TemplateResolver<LogEvent> NAME_RESOLVER =
45 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
46 final Marker marker = logEvent.getMarker();
47 if (marker == null) {
48 jsonWriter.writeNull();
49 } else {
50 jsonWriter.writeString(marker.getName());
51 }
52 };
53
54 private final TemplateResolver<LogEvent> internalResolver;
55
56 MarkerResolver(final TemplateResolverConfig config) {
57 this.internalResolver = createInternalResolver(config);
58 }
59
60 private TemplateResolver<LogEvent> createInternalResolver(
61 final TemplateResolverConfig config) {
62 final String fieldName = config.getString("field");
63 if ("name".equals(fieldName)) {
64 return NAME_RESOLVER;
65 }
66 throw new IllegalArgumentException("unknown field: " + config);
67 }
68
69 static String getName() {
70 return "marker";
71 }
72
73 @Override
74 public boolean isResolvable(final LogEvent logEvent) {
75 return logEvent.getMarker() != null;
76 }
77
78 @Override
79 public void resolve(
80 final LogEvent logEvent,
81 final JsonWriter jsonWriter) {
82 internalResolver.resolve(logEvent, jsonWriter);
83 }
84
85 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link MarkerResolver} factory.
23 */
24 @Plugin(name = "MarkerResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class MarkerResolverFactory implements EventResolverFactory {
26
27 private static final MarkerResolverFactory INSTANCE = new MarkerResolverFactory();
28
29 private MarkerResolverFactory() {}
30
31 @PluginFactory
32 public static MarkerResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return MarkerResolver.getName();
39 }
40
41 @Override
42 public MarkerResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new MarkerResolver(config);
46 }
47
48 }
+0
-215
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageParameterResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20 import org.apache.logging.log4j.layout.template.json.util.Recycler;
21 import org.apache.logging.log4j.message.Message;
22 import org.apache.logging.log4j.message.ParameterConsumer;
23 import org.apache.logging.log4j.message.ParameterVisitable;
24
25 /**
26 * {@link Message} parameter (i.e., {@link Message#getParameters()}) resolver.
27 *
28 * <h3>Configuration</h3>
29 *
30 * <pre>
31 * config = [ stringified ] , [ index ]
32 * stringified = "stringified" -> boolean
33 * index = "index" -> number
34 * </pre>
35 *
36 * <h3>Examples</h3>
37 *
38 * Resolve the message parameters into an array:
39 *
40 * <pre>
41 * {
42 * "$resolver": "messageParameter"
43 * }
44 * </pre>
45 *
46 * Resolve the string representation of all message parameters into an array:
47 *
48 * <pre>
49 * {
50 * "$resolver": "messageParameter",
51 * "stringified": true
52 * }
53 * </pre>
54 *
55 * Resolve the first message parameter:
56 *
57 * <pre>
58 * {
59 * "$resolver": "messageParameter",
60 * "index": 0
61 * }
62 *
63 * Resolve the string representation of the first message parameter:
64 *
65 * <pre>
66 * {
67 * "$resolver": "messageParameter",
68 * "index": 0,
69 * "stringified": true
70 * }
71 * </pre>
72 */
73 public final class MessageParameterResolver implements EventResolver {
74
75 private final Recycler<ParameterConsumerState> parameterConsumerStateRecycler;
76
77 private final boolean stringified;
78
79 private final int index;
80
81 MessageParameterResolver(
82 final EventResolverContext context,
83 final TemplateResolverConfig config) {
84 this.parameterConsumerStateRecycler = context
85 .getRecyclerFactory()
86 .create(ParameterConsumerState::new);
87 this.stringified = config.getBoolean("stringified", false);
88 final Integer index = config.getInteger("index");
89 if (index != null && index < 0) {
90 throw new IllegalArgumentException("was expecting a positive index: " + config);
91 }
92 this.index = index == null ? -1 : index;
93 }
94
95 static String getName() {
96 return "messageParameter";
97 }
98
99 @Override
100 public void resolve(final LogEvent logEvent, final JsonWriter jsonWriter) {
101
102 // If possible, perform a garbage-free resolution.
103 final Message message = logEvent.getMessage();
104 if (message instanceof ParameterVisitable) {
105 final ParameterVisitable parameterVisitable = (ParameterVisitable) message;
106 resolve(parameterVisitable, jsonWriter);
107 return;
108 }
109
110 // Short-circuit if there are no parameters.
111 final Object[] parameters = message.getParameters();
112 if (parameters == null || parameters.length == 0 || index >= parameters.length) {
113 if (index < 0) {
114 jsonWriter.writeArrayStart();
115 jsonWriter.writeArrayEnd();
116 } else {
117 jsonWriter.writeNull();
118 }
119 return;
120 }
121
122 // Resolve all parameters.
123 if (index < 0) {
124 jsonWriter.writeArrayStart();
125 for (int i = 0; i < parameters.length; i++) {
126 if (i > 0) {
127 jsonWriter.writeSeparator();
128 }
129 final Object parameter = parameters[i];
130 if (stringified) {
131 final String stringifiedParameter = String.valueOf(parameter);
132 jsonWriter.writeString(stringifiedParameter);
133 } else {
134 jsonWriter.writeValue(parameter);
135 }
136 }
137 jsonWriter.writeArrayEnd();
138 }
139
140 // Resolve a single parameter.
141 else {
142 final Object parameter = parameters[index];
143 if (stringified) {
144 final String stringifiedParameter = String.valueOf(parameter);
145 jsonWriter.writeString(stringifiedParameter);
146 } else {
147 jsonWriter.writeValue(parameter);
148 }
149 }
150
151 }
152
153 /**
154 * Perform a garbage-free resolution via {@link ParameterVisitable} interface.
155 */
156 private void resolve(
157 final ParameterVisitable parameterVisitable,
158 final JsonWriter jsonWriter) {
159 final ParameterConsumerState parameterConsumerState =
160 parameterConsumerStateRecycler.acquire();
161 try {
162 final boolean arrayNeeded = index < 0;
163 if (arrayNeeded) {
164 jsonWriter.writeArrayStart();
165 }
166 final StringBuilder buf = jsonWriter.getStringBuilder();
167 final int startIndex = buf.length();
168 parameterConsumerState.resolver = this;
169 parameterConsumerState.jsonWriter = jsonWriter;
170 parameterVisitable.forEachParameter(
171 PARAMETER_CONSUMER, parameterConsumerState);
172 if (arrayNeeded) {
173 jsonWriter.writeArrayEnd();
174 } else if (startIndex == buf.length()) {
175 // Handle the case in which index was not present in the event.
176 jsonWriter.writeNull();
177 }
178 } finally {
179 parameterConsumerStateRecycler.release(parameterConsumerState);
180 }
181 }
182
183 private static final class ParameterConsumerState {
184
185 private MessageParameterResolver resolver;
186
187 private JsonWriter jsonWriter;
188
189 private ParameterConsumerState() {}
190
191 }
192
193 private static final ParameterConsumer<ParameterConsumerState> PARAMETER_CONSUMER =
194 (final Object parameter, final int index, final ParameterConsumerState state) -> {
195
196 // Write the separator, if needed.
197 final boolean arrayNeeded = state.resolver.index < 0;
198 if (arrayNeeded && index > 0) {
199 state.jsonWriter.writeSeparator();
200 }
201
202 // Write the value.
203 if (arrayNeeded || state.resolver.index == index) {
204 if (state.resolver.stringified) {
205 final String stringifiedParameter = String.valueOf(parameter);
206 state.jsonWriter.writeString(stringifiedParameter);
207 } else {
208 state.jsonWriter.writeValue(parameter);
209 }
210 }
211
212 };
213
214 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageParameterResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link MessageParameterResolver} factory.
23 */
24 @Plugin(name = "MessageParameterResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class MessageParameterResolverFactory implements EventResolverFactory {
26
27 private static final MessageParameterResolverFactory INSTANCE =
28 new MessageParameterResolverFactory();
29
30 private MessageParameterResolverFactory() {}
31
32 @PluginFactory
33 public static MessageParameterResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return MessageParameterResolver.getName();
40 }
41
42 @Override
43 public MessageParameterResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return new MessageParameterResolver(context, config);
47 }
48
49 }
+0
-223
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20 import org.apache.logging.log4j.message.MapMessage;
21 import org.apache.logging.log4j.message.Message;
22 import org.apache.logging.log4j.message.MultiformatMessage;
23 import org.apache.logging.log4j.message.ObjectMessage;
24 import org.apache.logging.log4j.message.SimpleMessage;
25 import org.apache.logging.log4j.util.StringBuilderFormattable;
26
27 /**
28 * {@link Message} resolver.
29 *
30 * <h3>Configuration</h3>
31 *
32 * <pre>
33 * config = [ stringified ] , [ fallbackKey ]
34 * stringified = "stringified" -> boolean
35 * fallbackKey = "fallbackKey" -> string
36 * </pre>
37 *
38 * <h3>Examples</h3>
39 *
40 * Resolve the message into a string:
41 *
42 * <pre>
43 * {
44 * "$resolver": "message",
45 * "stringified": true
46 * }
47 * </pre>
48 *
49 * Resolve the message such that if it is a {@link ObjectMessage} or {@link
50 * MultiformatMessage} with JSON support, its emitted JSON type (string, list,
51 * object, etc.) will be retained:
52 *
53 * <pre>
54 * {
55 * "$resolver": "message"
56 * }
57 * </pre>
58 *
59 * Given the above configuration, a {@link SimpleMessage} will generate a
60 * <tt>"sample log message"</tt>, whereas a {@link MapMessage} will generate a
61 * <tt>{"action": "login", "sessionId": "87asd97a"}</tt>. Certain indexed log
62 * storage systems (e.g., <a
63 * href="https://www.elastic.co/elasticsearch/">Elasticsearch</a>) will not
64 * allow both values to coexist due to type mismatch: one is a <tt>string</tt>
65 * while the other is an <tt>object</tt>. Here one can use a
66 * <tt>fallbackKey</tt> to work around the problem:
67 *
68 * <pre>
69 * {
70 * "$resolver": "message",
71 * "fallbackKey": "formattedMessage"
72 * }
73 * </pre>
74 *
75 * Using this configuration, a {@link SimpleMessage} will generate a
76 * <tt>{"formattedMessage": "sample log message"}</tt> and a {@link MapMessage}
77 * will generate a <tt>{"action": "login", "sessionId": "87asd97a"}</tt>. Note
78 * that both emitted JSONs are of type <tt>object</tt> and have no
79 * type-conflicting fields.
80 */
81 public final class MessageResolver implements EventResolver {
82
83 private static final String[] FORMATS = { "JSON" };
84
85 private final EventResolver internalResolver;
86
87 MessageResolver(final TemplateResolverConfig config) {
88 this.internalResolver = createInternalResolver(config);
89 }
90
91 static String getName() {
92 return "message";
93 }
94
95 private static EventResolver createInternalResolver(
96 final TemplateResolverConfig config) {
97 final boolean stringified = config.getBoolean("stringified", false);
98 final String fallbackKey = config.getString("fallbackKey");
99 if (stringified && fallbackKey != null) {
100 throw new IllegalArgumentException(
101 "fallbackKey is not allowed when stringified is enable: " + config);
102 }
103 return stringified
104 ? createStringResolver(fallbackKey)
105 : createObjectResolver(fallbackKey);
106 }
107
108 @Override
109 public void resolve(
110 final LogEvent logEvent,
111 final JsonWriter jsonWriter) {
112 internalResolver.resolve(logEvent, jsonWriter);
113 }
114
115 private static EventResolver createStringResolver(final String fallbackKey) {
116 return (final LogEvent logEvent, final JsonWriter jsonWriter) ->
117 resolveString(fallbackKey, logEvent, jsonWriter);
118 }
119
120 private static void resolveString(
121 final String fallbackKey,
122 final LogEvent logEvent,
123 final JsonWriter jsonWriter) {
124 final Message message = logEvent.getMessage();
125 resolveString(fallbackKey, message, jsonWriter);
126 }
127
128 private static void resolveString(
129 final String fallbackKey,
130 final Message message,
131 final JsonWriter jsonWriter) {
132 if (fallbackKey != null) {
133 jsonWriter.writeObjectStart();
134 jsonWriter.writeObjectKey(fallbackKey);
135 }
136 if (message instanceof StringBuilderFormattable) {
137 final StringBuilderFormattable formattable =
138 (StringBuilderFormattable) message;
139 jsonWriter.writeString(formattable);
140 } else {
141 final String formattedMessage = message.getFormattedMessage();
142 jsonWriter.writeString(formattedMessage);
143 }
144 if (fallbackKey != null) {
145 jsonWriter.writeObjectEnd();
146 }
147 }
148
149 private static EventResolver createObjectResolver(final String fallbackKey) {
150 return (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
151
152 // Skip custom serializers for SimpleMessage.
153 final Message message = logEvent.getMessage();
154 final boolean simple = message instanceof SimpleMessage;
155 if (!simple) {
156
157 // Try MultiformatMessage serializer.
158 if (writeMultiformatMessage(jsonWriter, message)) {
159 return;
160 }
161
162 // Try ObjectMessage serializer.
163 if (writeObjectMessage(jsonWriter, message)) {
164 return;
165 }
166
167 }
168
169 // Fallback to plain String serializer.
170 resolveString(fallbackKey, logEvent, jsonWriter);
171
172 };
173 }
174
175 private static boolean writeMultiformatMessage(
176 final JsonWriter jsonWriter,
177 final Message message) {
178
179 // Check type.
180 if (!(message instanceof MultiformatMessage)) {
181 return false;
182 }
183 final MultiformatMessage multiformatMessage = (MultiformatMessage) message;
184
185 // Check formatter's JSON support.
186 boolean jsonSupported = false;
187 final String[] formats = multiformatMessage.getFormats();
188 for (final String format : formats) {
189 if (FORMATS[0].equalsIgnoreCase(format)) {
190 jsonSupported = true;
191 break;
192 }
193 }
194 if (!jsonSupported) {
195 return false;
196 }
197
198 // Write the formatted JSON.
199 final String messageJson = multiformatMessage.getFormattedMessage(FORMATS);
200 jsonWriter.writeRawString(messageJson);
201 return true;
202
203 }
204
205 private static boolean writeObjectMessage(
206 final JsonWriter jsonWriter,
207 final Message message) {
208
209 // Check type.
210 if (!(message instanceof ObjectMessage)) {
211 return false;
212 }
213
214 // Serialize object.
215 final ObjectMessage objectMessage = (ObjectMessage) message;
216 final Object object = objectMessage.getParameter();
217 jsonWriter.writeValue(object);
218 return true;
219
220 }
221
222 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * @see MessageResolver
23 */
24 @Plugin(name = "MessageResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class MessageResolverFactory implements EventResolverFactory {
26
27 private static final MessageResolverFactory INSTANCE = new MessageResolverFactory();
28
29 private MessageResolverFactory() {}
30
31 @PluginFactory
32 public static MessageResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return MessageResolver.getName();
39 }
40
41 @Override
42 public MessageResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new MessageResolver(config);
46 }
47
48 }
+0
-88
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PatternResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.layout.PatternLayout;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
21 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
22 import org.apache.logging.log4j.util.BiConsumer;
23 import org.apache.logging.log4j.util.Strings;
24
25 import java.util.Optional;
26
27 /**
28 * Resolver delegating to {@link PatternLayout}.
29 *
30 * <h3>Configuration</h3>
31 *
32 * <pre>
33 * config = pattern , [ stackTraceEnabled ]
34 * pattern = "pattern" -> string
35 * stackTraceEnabled = "stackTraceEnabled" -> boolean
36 * </pre>
37 *
38 * The default value of <tt>stackTraceEnabled</tt> is inherited from the parent
39 * {@link JsonTemplateLayout}.
40 *
41 * <h3>Examples</h3>
42 *
43 * Resolve the string produced by <tt>%p %c{1.} [%t] %X{userId} %X %m%ex</tt>
44 * pattern:
45 *
46 * <pre>
47 * {
48 * "$resolver": "pattern",
49 * "pattern": "%p %c{1.} [%t] %X{userId} %X %m%ex"
50 * }
51 * </pre>
52 */
53 public final class PatternResolver implements EventResolver {
54
55 private final BiConsumer<StringBuilder, LogEvent> emitter;
56
57 PatternResolver(
58 final EventResolverContext context,
59 final TemplateResolverConfig config) {
60 final String pattern = config.getString("pattern");
61 if (Strings.isBlank(pattern)) {
62 throw new IllegalArgumentException("blank pattern: " + config);
63 }
64 final boolean stackTraceEnabled = Optional
65 .ofNullable(config.getBoolean("stackTraceEnabled"))
66 .orElse(context.isStackTraceEnabled());
67 final PatternLayout patternLayout = PatternLayout
68 .newBuilder()
69 .withConfiguration(context.getConfiguration())
70 .withCharset(context.getCharset())
71 .withPattern(pattern)
72 .withAlwaysWriteExceptions(stackTraceEnabled)
73 .build();
74 this.emitter = (final StringBuilder stringBuilder, final LogEvent logEvent) ->
75 patternLayout.serialize(logEvent, stringBuilder);
76 }
77
78 static String getName() {
79 return "pattern";
80 }
81
82 @Override
83 public void resolve(final LogEvent logEvent, final JsonWriter jsonWriter) {
84 jsonWriter.writeString(emitter, logEvent);
85 }
86
87 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PatternResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link PatternResolver} factory.
23 */
24 @Plugin(name = "PatternResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class PatternResolverFactory implements EventResolverFactory {
26
27 private static final PatternResolverFactory INSTANCE = new PatternResolverFactory();
28
29 private PatternResolverFactory() {}
30
31 @PluginFactory
32 public static PatternResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return PatternResolver.getName();
39 }
40
41 @Override
42 public PatternResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new PatternResolver(context, config);
46 }
47
48 }
+0
-435
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20 import org.apache.logging.log4j.layout.template.json.util.Recycler;
21 import org.apache.logging.log4j.layout.template.json.util.RecyclerFactory;
22 import org.apache.logging.log4j.util.ReadOnlyStringMap;
23 import org.apache.logging.log4j.util.TriConsumer;
24
25 import java.util.Map;
26 import java.util.function.Function;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29
30 /**
31 * {@link ReadOnlyStringMap} resolver.
32 *
33 * <h3>Configuration</h3>
34 *
35 * <pre>
36 * config = singleAccess | multiAccess
37 *
38 * singleAccess = key , [ stringified ]
39 * key = "key" -> string
40 * stringified = "stringified" -> boolean
41 *
42 * multiAccess = [ pattern ] , [ replacement ] , [ flatten ] , [ stringified ]
43 * pattern = "pattern" -> string
44 * replacement = "replacement" -> string
45 * flatten = "flatten" -> ( boolean | flattenConfig )
46 * flattenConfig = [ flattenPrefix ]
47 * flattenPrefix = "prefix" -> string
48 * </pre>
49 *
50 * Note that <tt>singleAccess</tt> resolves a single field, whilst
51 * <tt>multiAccess</tt> resolves a multitude of fields. If <tt>flatten</tt>
52 * is provided, <tt>multiAccess</tt> merges the fields with the parent,
53 * otherwise creates a new JSON object containing the values.
54 * <p>
55 * Enabling <tt>stringified</tt> flag converts each value to its string
56 * representation.
57 * <p>
58 * Regex provided in the <tt>pattern</tt> is used to match against the keys.
59 * If provided, <tt>replacement</tt> will be used to replace the matched keys.
60 * These two are effectively equivalent to
61 * <tt>Pattern.compile(pattern).matcher(key).matches()</tt> and
62 * <tt>Pattern.compile(pattern).matcher(key).replaceAll(replacement)</tt> calls.
63 *
64 * <h3>Garbage Footprint</h3>
65 *
66 * <tt>stringified</tt> allocates a new <tt>String</tt> for values that are not
67 * of type <tt>String</tt>.
68 * <p>
69 * <tt>pattern</tt> and <tt>replacement</tt> incur pattern matcher allocation
70 * costs.
71 * <p>
72 * Writing certain non-primitive values (e.g., <tt>BigDecimal</tt>,
73 * <tt>Set</tt>, etc.) to JSON generates garbage, though most (e.g.,
74 * <tt>int</tt>, <tt>long</tt>, <tt>String</tt>, <tt>List</tt>,
75 * <tt>boolean[]</tt>, etc.) don't.
76 *
77 * <h3>Examples</h3>
78 *
79 * <tt>"$resolver"</tt> is left out in the following examples, since it is to be
80 * defined by the actual resolver, e.g., {@link MapResolver},
81 * {@link ThreadContextDataResolver}.
82 * <p>
83 * Resolve the value of the field keyed with <tt>user:role</tt>:
84 *
85 * <pre>
86 * {
87 * "$resolver": "…",
88 * "key": "user:role"
89 * }
90 * </pre>
91 *
92 * Resolve the string representation of the <tt>user:rank</tt> field value:
93 *
94 * <pre>
95 * {
96 * "$resolver": "…",
97 * "key": "user:rank",
98 * "stringified": true
99 * }
100 * </pre>
101 *
102 * Resolve all fields into an object:
103 *
104 * <pre>
105 * {
106 * "$resolver": "…"
107 * }
108 * </pre>
109 *
110 * Resolve all fields into an object such that values are converted to
111 * string:
112 *
113 * <pre>
114 * {
115 * "$resolver": "…",
116 * "stringified": true
117 * }
118 * </pre>
119 *
120 * Resolve all fields whose keys match with the <tt>user:(role|rank)</tt> regex
121 * into an object:
122 *
123 * <pre>
124 * {
125 * "$resolver": "…",
126 * "pattern": "user:(role|rank)"
127 * }
128 * </pre>
129 *
130 * Resolve all fields whose keys match with the <tt>user:(role|rank)</tt> regex
131 * into an object after removing the <tt>user:</tt> prefix in the key:
132 *
133 * <pre>
134 * {
135 * "$resolver": "…",
136 * "pattern": "user:(role|rank)",
137 * "replacement": "$1"
138 * }
139 * </pre>
140 *
141 * Merge all fields whose keys are matching with the
142 * <tt>user:(role|rank)</tt> regex into the parent:
143 *
144 * <pre>
145 * {
146 * "$resolver": "…",
147 * "flatten": true,
148 * "pattern": "user:(role|rank)"
149 * }
150 * </pre>
151 *
152 * After converting the corresponding field values to string, merge all fields
153 * to parent such that keys are prefixed with <tt>_</tt>:
154 *
155 * <pre>
156 * {
157 * "$resolver": "…",
158 * "stringified": true,
159 * "flatten": {
160 * "prefix": "_"
161 * }
162 * }
163 * </pre>
164 *
165 * @see MapResolver
166 * @see ThreadContextDataResolver
167 */
168 class ReadOnlyStringMapResolver implements EventResolver {
169
170 private final EventResolver internalResolver;
171
172 ReadOnlyStringMapResolver(
173 final EventResolverContext context,
174 final TemplateResolverConfig config,
175 final Function<LogEvent, ReadOnlyStringMap> mapAccessor) {
176 this.internalResolver = createResolver(context, config, mapAccessor);
177 }
178
179 private static EventResolver createResolver(
180 final EventResolverContext context,
181 final TemplateResolverConfig config,
182 final Function<LogEvent, ReadOnlyStringMap> mapAccessor) {
183 final Object flattenObject = config.getObject("flatten");
184 final boolean flatten;
185 if (flattenObject == null) {
186 flatten = false;
187 } else if (flattenObject instanceof Boolean) {
188 flatten = (boolean) flattenObject;
189 } else if (flattenObject instanceof Map) {
190 flatten = true;
191 } else {
192 throw new IllegalArgumentException("invalid flatten option: " + config);
193 }
194 final String prefix = config.getString(new String[] {"flatten", "prefix"});
195 final String key = config.getString("key");
196 if (key != null && flatten) {
197 throw new IllegalArgumentException(
198 "key and flatten options cannot be combined: " + config);
199 }
200 final String pattern = config.getString("pattern");
201 if (pattern != null && key != null) {
202 throw new IllegalArgumentException(
203 "pattern and key options cannot be combined: " + config);
204 }
205 final String replacement = config.getString("replacement");
206 if (pattern == null && replacement != null) {
207 throw new IllegalArgumentException(
208 "replacement cannot be provided without a pattern: " + config);
209 }
210 final boolean stringified = config.getBoolean("stringified", false);
211 if (key != null) {
212 return createKeyResolver(key, stringified, mapAccessor);
213 } else {
214 final RecyclerFactory recyclerFactory = context.getRecyclerFactory();
215 return createResolver(
216 recyclerFactory,
217 flatten,
218 prefix,
219 pattern,
220 replacement,
221 stringified,
222 mapAccessor);
223 }
224 }
225
226 private static EventResolver createKeyResolver(
227 final String key,
228 final boolean stringified,
229 final Function<LogEvent, ReadOnlyStringMap> mapAccessor) {
230 return new EventResolver() {
231
232 @Override
233 public boolean isResolvable(final LogEvent logEvent) {
234 final ReadOnlyStringMap map = mapAccessor.apply(logEvent);
235 return map != null && map.containsKey(key);
236 }
237
238 @Override
239 public void resolve(final LogEvent logEvent, final JsonWriter jsonWriter) {
240 final ReadOnlyStringMap map = mapAccessor.apply(logEvent);
241 final Object value = map == null ? null : map.getValue(key);
242 if (stringified) {
243 final String valueString = String.valueOf(value);
244 jsonWriter.writeString(valueString);
245 } else {
246 jsonWriter.writeValue(value);
247 }
248 }
249
250 };
251 }
252
253 private static EventResolver createResolver(
254 final RecyclerFactory recyclerFactory,
255 final boolean flatten,
256 final String prefix,
257 final String pattern,
258 final String replacement,
259 final boolean stringified,
260 final Function<LogEvent, ReadOnlyStringMap> mapAccessor) {
261
262 // Compile the pattern.
263 final Pattern compiledPattern =
264 pattern == null
265 ? null
266 : Pattern.compile(pattern);
267
268 // Create the recycler for the loop context.
269 final Recycler<LoopContext> loopContextRecycler =
270 recyclerFactory.create(() -> {
271 final LoopContext loopContext = new LoopContext();
272 if (prefix != null) {
273 loopContext.prefix = prefix;
274 loopContext.prefixedKey = new StringBuilder(prefix);
275 }
276 loopContext.pattern = compiledPattern;
277 loopContext.replacement = replacement;
278 loopContext.stringified = stringified;
279 return loopContext;
280 });
281
282 // Create the resolver.
283 return createResolver(flatten, loopContextRecycler, mapAccessor);
284
285 }
286
287 private static EventResolver createResolver(
288 final boolean flatten,
289 final Recycler<LoopContext> loopContextRecycler,
290 final Function<LogEvent, ReadOnlyStringMap> mapAccessor) {
291 return new EventResolver() {
292
293 @Override
294 public boolean isFlattening() {
295 return flatten;
296 }
297
298 @Override
299 public boolean isResolvable(final LogEvent logEvent) {
300 final ReadOnlyStringMap map = mapAccessor.apply(logEvent);
301 return map != null && !map.isEmpty();
302 }
303
304 @Override
305 public void resolve(final LogEvent value, final JsonWriter jsonWriter) {
306 resolve(value, jsonWriter, false);
307 }
308
309 @Override
310 public void resolve(
311 final LogEvent logEvent,
312 final JsonWriter jsonWriter,
313 final boolean succeedingEntry) {
314
315 // Retrieve the map.
316 final ReadOnlyStringMap map = mapAccessor.apply(logEvent);
317 if (map == null || map.isEmpty()) {
318 if (!flatten) {
319 jsonWriter.writeNull();
320 }
321 return;
322 }
323
324 // Resolve the map.
325 if (!flatten) {
326 jsonWriter.writeObjectStart();
327 }
328 final LoopContext loopContext = loopContextRecycler.acquire();
329 loopContext.jsonWriter = jsonWriter;
330 loopContext.initJsonWriterStringBuilderLength = jsonWriter.getStringBuilder().length();
331 loopContext.succeedingEntry = flatten && succeedingEntry;
332 try {
333 map.forEach(LoopMethod.INSTANCE, loopContext);
334 } finally {
335 loopContextRecycler.release(loopContext);
336 }
337 if (!flatten) {
338 jsonWriter.writeObjectEnd();
339 }
340
341 }
342
343 };
344 }
345
346 private static final class LoopContext {
347
348 private String prefix;
349
350 private StringBuilder prefixedKey;
351
352 private Pattern pattern;
353
354 private String replacement;
355
356 private boolean stringified;
357
358 private JsonWriter jsonWriter;
359
360 private int initJsonWriterStringBuilderLength;
361
362 private boolean succeedingEntry;
363
364 }
365
366 private enum LoopMethod implements TriConsumer<String, Object, LoopContext> {
367
368 INSTANCE;
369
370 @Override
371 public void accept(
372 final String key,
373 final Object value,
374 final LoopContext loopContext) {
375 final Matcher matcher = loopContext.pattern != null
376 ? loopContext.pattern.matcher(key)
377 : null;
378 final boolean keyMatched = matcher == null || matcher.matches();
379 if (keyMatched) {
380 final String replacedKey =
381 matcher != null && loopContext.replacement != null
382 ? matcher.replaceAll(loopContext.replacement)
383 : key;
384 final boolean succeedingEntry =
385 loopContext.succeedingEntry ||
386 loopContext.initJsonWriterStringBuilderLength <
387 loopContext.jsonWriter.getStringBuilder().length();
388 if (succeedingEntry) {
389 loopContext.jsonWriter.writeSeparator();
390 }
391 if (loopContext.prefix == null) {
392 loopContext.jsonWriter.writeObjectKey(replacedKey);
393 } else {
394 loopContext.prefixedKey.setLength(loopContext.prefix.length());
395 loopContext.prefixedKey.append(replacedKey);
396 loopContext.jsonWriter.writeObjectKey(loopContext.prefixedKey);
397 }
398 if (loopContext.stringified && !(value instanceof String)) {
399 final String valueString = String.valueOf(value);
400 loopContext.jsonWriter.writeString(valueString);
401 } else {
402 loopContext.jsonWriter.writeValue(value);
403 }
404 }
405 }
406
407 }
408
409 @Override
410 public boolean isFlattening() {
411 return internalResolver.isFlattening();
412 }
413
414 @Override
415 public boolean isResolvable(final LogEvent logEvent) {
416 return internalResolver.isResolvable(logEvent);
417 }
418
419 @Override
420 public void resolve(
421 final LogEvent logEvent,
422 final JsonWriter jsonWriter) {
423 internalResolver.resolve(logEvent, jsonWriter);
424 }
425
426 @Override
427 public void resolve(
428 final LogEvent logEvent,
429 final JsonWriter jsonWriter,
430 final boolean succeedingEntry) {
431 internalResolver.resolve(logEvent, jsonWriter, succeedingEntry);
432 }
433
434 }
+0
-153
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SourceResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
20 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
21
22 /**
23 * Resolver for the {@link StackTraceElement} returned by {@link LogEvent#getSource()}.
24 * <p>
25 * Note that this resolver is toggled by {@link
26 * JsonTemplateLayout.Builder#setLocationInfoEnabled(boolean) locationInfoEnabled}
27 * layout configuration, which is by default populated from {@code log4j.layout.jsonTemplate.locationInfoEnabled}
28 * system property.
29 *
30 * <h3>Configuration</h3>
31 *
32 * <pre>
33 * config = "field" -> (
34 * "className" |
35 * "fileName" |
36 * "methodName" |
37 * "lineNumber" )
38 * </pre>
39 *
40 * <h3>Examples</h3>
41 *
42 * Resolve the line number:
43 *
44 * <pre>
45 * {
46 * "$resolver": "source",
47 * "field": "lineNumber"
48 * }
49 * </pre>
50 */
51 public final class SourceResolver implements EventResolver {
52
53 private static final EventResolver NULL_RESOLVER =
54 (final LogEvent value, final JsonWriter jsonWriter) ->
55 jsonWriter.writeNull();
56
57 private static final EventResolver CLASS_NAME_RESOLVER =
58 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
59 final StackTraceElement logEventSource = logEvent.getSource();
60 if (logEventSource == null) {
61 jsonWriter.writeNull();
62 } else {
63 final String sourceClassName = logEventSource.getClassName();
64 jsonWriter.writeString(sourceClassName);
65 }
66 };
67
68 private static final EventResolver FILE_NAME_RESOLVER =
69 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
70 final StackTraceElement logEventSource = logEvent.getSource();
71 if (logEventSource == null) {
72 jsonWriter.writeNull();
73 } else {
74 final String sourceFileName = logEventSource.getFileName();
75 jsonWriter.writeString(sourceFileName);
76 }
77 };
78
79 private static final EventResolver LINE_NUMBER_RESOLVER =
80 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
81 final StackTraceElement logEventSource = logEvent.getSource();
82 if (logEventSource == null) {
83 jsonWriter.writeNull();
84 } else {
85 final int sourceLineNumber = logEventSource.getLineNumber();
86 jsonWriter.writeNumber(sourceLineNumber);
87 }
88 };
89
90 private static final EventResolver METHOD_NAME_RESOLVER =
91 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
92 final StackTraceElement logEventSource = logEvent.getSource();
93 if (logEventSource == null) {
94 jsonWriter.writeNull();
95 } else {
96 final String sourceMethodName = logEventSource.getMethodName();
97 jsonWriter.writeString(sourceMethodName);
98 }
99 };
100
101 private final boolean locationInfoEnabled;
102
103 private final EventResolver internalResolver;
104
105 SourceResolver(
106 final EventResolverContext context,
107 final TemplateResolverConfig config) {
108 this.locationInfoEnabled = context.isLocationInfoEnabled();
109 this.internalResolver = createInternalResolver(context, config);
110 }
111
112 private static EventResolver createInternalResolver(
113 final EventResolverContext context,
114 final TemplateResolverConfig config) {
115 if (!context.isLocationInfoEnabled()) {
116 return NULL_RESOLVER;
117 }
118 final String fieldName = config.getString("field");
119 if ("className".equals(fieldName)) {
120 return CLASS_NAME_RESOLVER;
121 } else if ("fileName".equals(fieldName)) {
122 return FILE_NAME_RESOLVER;
123 } else if ("lineNumber".equals(fieldName)) {
124 return LINE_NUMBER_RESOLVER;
125 } else if ("methodName".equals(fieldName)) {
126 return METHOD_NAME_RESOLVER;
127 }
128 throw new IllegalArgumentException("unknown field: " + config);
129 }
130
131 static String getName() {
132 return "source";
133 }
134
135 @Override
136 public boolean isResolvable() {
137 return locationInfoEnabled;
138 }
139
140 @Override
141 public boolean isResolvable(final LogEvent logEvent) {
142 return locationInfoEnabled && logEvent.getSource() != null;
143 }
144
145 @Override
146 public void resolve(
147 final LogEvent logEvent,
148 final JsonWriter jsonWriter) {
149 internalResolver.resolve(logEvent, jsonWriter);
150 }
151
152 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SourceResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link SourceResolver} factory.
23 */
24 @Plugin(name = "SourceResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class SourceResolverFactory implements EventResolverFactory {
26
27 private static final SourceResolverFactory INSTANCE = new SourceResolverFactory();
28
29 private SourceResolverFactory() {}
30
31 @PluginFactory
32 public static SourceResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return SourceResolver.getName();
39 }
40
41 @Override
42 public SourceResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new SourceResolver(context, config);
46 }
47
48 }
+0
-95
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceElementResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
19
20 /**
21 * {@link StackTraceElement} resolver.
22 *
23 * <h3>Configuration</h3>
24 *
25 * <pre>
26 * config = "field" -> (
27 * "className" |
28 * "fileName" |
29 * "methodName" |
30 * "lineNumber" )
31 * </pre>
32 *
33 * <h3>Examples</h3>
34 *
35 * Resolve the line number:
36 *
37 * <pre>
38 * {
39 * "$resolver": "stackTraceElement",
40 * "field": "lineNumber"
41 * }
42 * </pre>
43 */
44 final class StackTraceElementResolver implements TemplateResolver<StackTraceElement> {
45
46 private static final TemplateResolver<StackTraceElement> CLASS_NAME_RESOLVER =
47 (final StackTraceElement stackTraceElement, final JsonWriter jsonWriter) ->
48 jsonWriter.writeString(stackTraceElement.getClassName());
49
50 private static final TemplateResolver<StackTraceElement> METHOD_NAME_RESOLVER =
51 (final StackTraceElement stackTraceElement, final JsonWriter jsonWriter) ->
52 jsonWriter.writeString(stackTraceElement.getMethodName());
53
54 private static final TemplateResolver<StackTraceElement> FILE_NAME_RESOLVER =
55 (final StackTraceElement stackTraceElement, final JsonWriter jsonWriter) ->
56 jsonWriter.writeString(stackTraceElement.getFileName());
57
58 private static final TemplateResolver<StackTraceElement> LINE_NUMBER_RESOLVER =
59 (final StackTraceElement stackTraceElement, final JsonWriter jsonWriter) ->
60 jsonWriter.writeNumber(stackTraceElement.getLineNumber());
61
62 private final TemplateResolver<StackTraceElement> internalResolver;
63
64 StackTraceElementResolver(final TemplateResolverConfig config) {
65 this.internalResolver = createInternalResolver(config);
66 }
67
68 static String getName() {
69 return "stackTraceElement";
70 }
71
72 private TemplateResolver<StackTraceElement> createInternalResolver(
73 final TemplateResolverConfig config) {
74 final String fieldName = config.getString("field");
75 if ("className".equals(fieldName)) {
76 return CLASS_NAME_RESOLVER;
77 } else if ("methodName".equals(fieldName)) {
78 return METHOD_NAME_RESOLVER;
79 } else if ("fileName".equals(fieldName)) {
80 return FILE_NAME_RESOLVER;
81 } else if ("lineNumber".equals(fieldName)) {
82 return LINE_NUMBER_RESOLVER;
83 }
84 throw new IllegalArgumentException("unknown field: " + config);
85 }
86
87 @Override
88 public void resolve(
89 final StackTraceElement stackTraceElement,
90 final JsonWriter jsonWriter) {
91 internalResolver.resolve(stackTraceElement, jsonWriter);
92 }
93
94 }
+0
-121
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceElementResolverContext.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
19
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Objects;
24
25 /**
26 * {@link TemplateResolverContext} specialized for {@link StackTraceElement}s.
27 *
28 * @see StackTraceElementResolver
29 * @see StackTraceElementResolverFactory
30 */
31 final class StackTraceElementResolverContext
32 implements TemplateResolverContext<StackTraceElement, StackTraceElementResolverContext> {
33
34 private final Map<String, StackTraceElementResolverFactory> resolverFactoryByName;
35
36 private final StackTraceElementResolverStringSubstitutor substitutor;
37
38 private final JsonWriter jsonWriter;
39
40 private StackTraceElementResolverContext(final Builder builder) {
41 this.resolverFactoryByName = builder.resolverFactoryByName;
42 this.substitutor = builder.substitutor;
43 this.jsonWriter = builder.jsonWriter;
44 }
45
46 @Override
47 public final Class<StackTraceElementResolverContext> getContextClass() {
48 return StackTraceElementResolverContext.class;
49 }
50
51 @Override
52 public Map<String, StackTraceElementResolverFactory> getResolverFactoryByName() {
53 return resolverFactoryByName;
54 }
55
56 @Override
57 public List<? extends TemplateResolverInterceptor<StackTraceElement, StackTraceElementResolverContext>> getResolverInterceptors() {
58 return Collections.emptyList();
59 }
60
61 @Override
62 public StackTraceElementResolverStringSubstitutor getSubstitutor() {
63 return substitutor;
64 }
65
66 @Override
67 public JsonWriter getJsonWriter() {
68 return jsonWriter;
69 }
70
71 static Builder newBuilder() {
72 return new Builder();
73 }
74
75 static class Builder {
76
77 private Map<String, StackTraceElementResolverFactory> resolverFactoryByName;
78
79 private StackTraceElementResolverStringSubstitutor substitutor;
80
81 private JsonWriter jsonWriter;
82
83 private Builder() {
84 // Do nothing.
85 }
86
87 Builder setResolverFactoryByName(
88 final Map<String, StackTraceElementResolverFactory> resolverFactoryByName) {
89 this.resolverFactoryByName = resolverFactoryByName;
90 return this;
91 }
92
93 Builder setSubstitutor(
94 final StackTraceElementResolverStringSubstitutor substitutor) {
95 this.substitutor = substitutor;
96 return this;
97 }
98
99 Builder setJsonWriter(final JsonWriter jsonWriter) {
100 this.jsonWriter = jsonWriter;
101 return this;
102 }
103
104 StackTraceElementResolverContext build() {
105 validate();
106 return new StackTraceElementResolverContext(this);
107 }
108
109 private void validate() {
110 Objects.requireNonNull(resolverFactoryByName, "resolverFactoryByName");
111 if (resolverFactoryByName.isEmpty()) {
112 throw new IllegalArgumentException("empty resolverFactoryByName");
113 }
114 Objects.requireNonNull(substitutor, "substitutor");
115 Objects.requireNonNull(jsonWriter, "jsonWriter");
116 }
117
118 }
119
120 }
+0
-56
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceElementResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 /**
19 * {@link StackTraceElementResolver} factory.
20 */
21 final class StackTraceElementResolverFactory
22 implements TemplateResolverFactory<StackTraceElement, StackTraceElementResolverContext> {
23
24 private static final StackTraceElementResolverFactory INSTANCE =
25 new StackTraceElementResolverFactory();
26
27 private StackTraceElementResolverFactory() {}
28
29 static StackTraceElementResolverFactory getInstance() {
30 return INSTANCE;
31 }
32
33 @Override
34 public Class<StackTraceElement> getValueClass() {
35 return StackTraceElement.class;
36 }
37
38 @Override
39 public Class<StackTraceElementResolverContext> getContextClass() {
40 return StackTraceElementResolverContext.class;
41 }
42
43 @Override
44 public String getName() {
45 return StackTraceElementResolver.getName();
46 }
47
48 @Override
49 public StackTraceElementResolver create(
50 final StackTraceElementResolverContext context,
51 final TemplateResolverConfig config) {
52 return new StackTraceElementResolver(config);
53 }
54
55 }
+0
-51
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceElementResolverStringSubstitutor.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
19
20 import java.util.Objects;
21
22 /**
23 * {@link TemplateResolverStringSubstitutor} specialized for {@link StackTraceElement}s.
24 */
25 final class StackTraceElementResolverStringSubstitutor
26 implements TemplateResolverStringSubstitutor<StackTraceElement> {
27
28 private final StrSubstitutor substitutor;
29
30 StackTraceElementResolverStringSubstitutor(
31 final StrSubstitutor substitutor) {
32 this.substitutor = Objects.requireNonNull(substitutor, "substitutor");
33 }
34
35 @Override
36 public StrSubstitutor getInternalSubstitutor() {
37 return substitutor;
38 }
39
40 @Override
41 public boolean isStable() {
42 return true;
43 }
44
45 @Override
46 public String replace(final StackTraceElement ignored, final String source) {
47 return substitutor.replace(null, source);
48 }
49
50 }
+0
-57
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceObjectResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
19
20 /**
21 * Exception stack trace to JSON object resolver used by {@link ExceptionResolver}.
22 */
23 final class StackTraceObjectResolver implements StackTraceResolver {
24
25 private final TemplateResolver<StackTraceElement> stackTraceElementResolver;
26
27 StackTraceObjectResolver(final TemplateResolver<StackTraceElement> stackTraceElementResolver) {
28 this.stackTraceElementResolver = stackTraceElementResolver;
29 }
30
31 @Override
32 public void resolve(
33 final Throwable throwable,
34 final JsonWriter jsonWriter) {
35 // Following check against the stacktrace element count is not
36 // implemented in isResolvable(), since Throwable#getStackTrace() incurs
37 // a significant cloning cost.
38 final StackTraceElement[] stackTraceElements = throwable.getStackTrace();
39 if (stackTraceElements.length == 0) {
40 jsonWriter.writeNull();
41 } else {
42 jsonWriter.writeArrayStart();
43 for (int stackTraceElementIndex = 0;
44 stackTraceElementIndex < stackTraceElements.length;
45 stackTraceElementIndex++) {
46 if (stackTraceElementIndex > 0) {
47 jsonWriter.writeSeparator();
48 }
49 final StackTraceElement stackTraceElement = stackTraceElements[stackTraceElementIndex];
50 stackTraceElementResolver.resolve(stackTraceElement, jsonWriter);
51 }
52 jsonWriter.writeArrayEnd();
53 }
54 }
55
56 }
+0
-22
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceResolver.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.logging.log4j.layout.template.json.resolver;
17
18 /**
19 * {@link TemplateResolver} specialized for {@link Throwable}s.
20 */
21 interface StackTraceResolver extends TemplateResolver<Throwable> {}
+0
-130
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/StackTraceStringResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20 import org.apache.logging.log4j.layout.template.json.util.Recycler;
21
22 import java.util.List;
23 import java.util.function.Supplier;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 import java.util.stream.Collectors;
27
28 /**
29 * Exception stack trace to JSON string resolver used by {@link ExceptionResolver}.
30 */
31 final class StackTraceStringResolver implements StackTraceResolver {
32
33 private final Recycler<TruncatingBufferedPrintWriter> writerRecycler;
34
35 private final boolean truncationEnabled;
36
37 private final String truncationSuffix;
38
39 private final List<String> truncationPointMatcherStrings;
40
41 private final List<Pattern> groupedTruncationPointMatcherRegexes;
42
43 StackTraceStringResolver(
44 final EventResolverContext context,
45 final String truncationSuffix,
46 final List<String> truncationPointMatcherStrings,
47 final List<String> truncationPointMatcherRegexes) {
48 final Supplier<TruncatingBufferedPrintWriter> writerSupplier =
49 () -> TruncatingBufferedPrintWriter.ofCapacity(
50 context.getMaxStringByteCount());
51 this.writerRecycler = context
52 .getRecyclerFactory()
53 .create(writerSupplier, TruncatingBufferedPrintWriter::close);
54 this.truncationEnabled =
55 !truncationPointMatcherStrings.isEmpty() ||
56 !truncationPointMatcherRegexes.isEmpty();
57 this.truncationSuffix = truncationSuffix;
58 this.truncationPointMatcherStrings = truncationPointMatcherStrings;
59 this.groupedTruncationPointMatcherRegexes =
60 groupTruncationPointMatcherRegexes(truncationPointMatcherRegexes);
61 }
62
63 private static List<Pattern> groupTruncationPointMatcherRegexes(
64 final List<String> regexes) {
65 return regexes
66 .stream()
67 .map(regex -> Pattern.compile(
68 "^.*(" + regex + ")(.*)$",
69 Pattern.MULTILINE | Pattern.DOTALL))
70 .collect(Collectors.toList());
71 }
72
73 @Override
74 public void resolve(
75 final Throwable throwable,
76 final JsonWriter jsonWriter) {
77 final TruncatingBufferedPrintWriter writer = writerRecycler.acquire();
78 try {
79 throwable.printStackTrace(writer);
80 truncate(writer);
81 jsonWriter.writeString(writer.buffer(), 0, writer.position());
82 } finally {
83 writerRecycler.release(writer);
84 }
85 }
86
87 private void truncate(final TruncatingBufferedPrintWriter writer) {
88
89 // Short-circuit if truncation is not enabled.
90 if (!truncationEnabled) {
91 return;
92 }
93
94 // Check for string matches.
95 // noinspection ForLoopReplaceableByForEach (avoid iterator allocation)
96 for (int i = 0; i < truncationPointMatcherStrings.size(); i++) {
97 final String matcher = truncationPointMatcherStrings.get(i);
98 final int matchIndex = writer.indexOf(matcher);
99 if (matchIndex > 0) {
100 final int truncationPointIndex = matchIndex + matcher.length();
101 truncate(writer, truncationPointIndex);
102 return;
103 }
104 }
105
106 // Check for regex matches.
107 // noinspection ForLoopReplaceableByForEach (avoid iterator allocation)
108 for (int i = 0; i < groupedTruncationPointMatcherRegexes.size(); i++) {
109 final Pattern pattern = groupedTruncationPointMatcherRegexes.get(i);
110 final Matcher matcher = pattern.matcher(writer);
111 final boolean matched = matcher.matches();
112 if (matched) {
113 final int lastGroup = matcher.groupCount();
114 final int truncationPointIndex = matcher.start(lastGroup);
115 truncate(writer, truncationPointIndex);
116 return;
117 }
118 }
119
120 }
121
122 private void truncate(
123 final TruncatingBufferedPrintWriter writer,
124 final int index) {
125 writer.position(index);
126 writer.print(truncationSuffix);
127 }
128
129 }
+0
-69
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
19
20 @FunctionalInterface
21 public interface TemplateResolver<V> {
22
23 /**
24 * Indicates if the resolution should be appended to the parent JSON object.
25 * <p>
26 * For instance, {@link ThreadContextDataResolver}, i.e., MDC resolver,
27 * uses this flag to indicate whether the contents should be appended to the
28 * parent JSON object or not.
29 */
30 default boolean isFlattening() {
31 return false;
32 }
33
34 /**
35 * Indicates if the resolver if applicable at all.
36 * <p>
37 * For instance, the source line resolver can be short-circuited using this
38 * check if the location information is disabled in the layout configuration.
39 */
40 default boolean isResolvable() {
41 return true;
42 }
43
44 /**
45 * Indicates if the resolver if applicable for the given {@code value}.
46 * <p>
47 * For instance, the stack trace resolver can be short-circuited using this
48 * check if the stack traces are disabled in the layout configuration.
49 */
50 default boolean isResolvable(V value) {
51 return true;
52 }
53
54 /**
55 * Resolves the given {@code value} using the provided {@link JsonWriter}.
56 */
57 void resolve(V value, JsonWriter jsonWriter);
58
59 /**
60 * Resolves the given {@code value} using the provided {@link JsonWriter}.
61 *
62 * @param succeedingEntry false, if this is the first element in a collection; true, otherwise
63 */
64 default void resolve(V value, JsonWriter jsonWriter, boolean succeedingEntry) {
65 resolve(value, jsonWriter);
66 }
67
68 }
+0
-89
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverConfig.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults;
19 import org.apache.logging.log4j.layout.template.json.util.MapAccessor;
20
21 import java.util.Arrays;
22 import java.util.Locale;
23 import java.util.Map;
24
25 /**
26 * Accessor to the resolver configuration JSON object read from the template.
27 * {@link TemplateResolver Template resolvers} can use this class to
28 * read the configuration associated with them.
29 * <p>
30 * For instance, given the following template:
31 * <pre>
32 * {
33 * "@version": 1,
34 * "message": {
35 * "$resolver": "message",
36 * "stringified": true
37 * },
38 * "level": {
39 * "$resolver": "level",
40 * "field": "severity",
41 * "severity": {
42 * "field": "code"
43 * }
44 * }
45 * }
46 * </pre>
47 * {@link LevelResolverFactory#create(EventResolverContext, TemplateResolverConfig)}
48 * will be called with a {@link TemplateResolverConfig} accessor to the
49 * following configuration JSON object block:
50 * <pre>
51 * {
52 * "$resolver": "level",
53 * "field": "severity",
54 * "severity": {
55 * "field": "code"
56 * }
57 * }
58 * </pre>
59 */
60 public class TemplateResolverConfig extends MapAccessor {
61
62 TemplateResolverConfig(final Map<String, Object> map) {
63 super(map);
64 }
65
66 public Locale getLocale(final String key) {
67 final String[] path = {key};
68 return getLocale(path);
69 }
70
71 public Locale getLocale(final String[] path) {
72 final String spec = getString(path);
73 if (spec == null) {
74 return JsonTemplateLayoutDefaults.getLocale();
75 }
76 final String[] specFields = spec.split("_", 3);
77 switch (specFields.length) {
78 case 1: return new Locale(specFields[0]);
79 case 2: return new Locale(specFields[0], specFields[1]);
80 case 3: return new Locale(specFields[0], specFields[1], specFields[2]);
81 }
82 final String message = String.format(
83 "was expecting a locale at path %s: %s",
84 Arrays.asList(path), this);
85 throw new IllegalArgumentException(message);
86 }
87
88 }
+0
-60
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverContext.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
19
20 import java.util.List;
21 import java.util.Map;
22
23 /**
24 * Context used to compile a template and passed to
25 * {@link TemplateResolverFactory#create(TemplateResolverContext, TemplateResolverConfig)
26 * template resolver factory creator}s.
27 *
28 * @param <V> type of the value passed to the resolver as input
29 * @param <C> type of the context passed to the {@link TemplateResolverFactory resolver factory}
30 *
31 * @see TemplateResolverFactory
32 */
33 interface TemplateResolverContext<V, C extends TemplateResolverContext<V, C>> {
34
35 Class<C> getContextClass();
36
37 Map<String, ? extends TemplateResolverFactory<V, C>> getResolverFactoryByName();
38
39 List<? extends TemplateResolverInterceptor<V, C>> getResolverInterceptors();
40
41 TemplateResolverStringSubstitutor<V> getSubstitutor();
42
43 JsonWriter getJsonWriter();
44
45 /**
46 * Process the read template before compiler (i.e.,
47 * {@link TemplateResolvers#ofTemplate(TemplateResolverContext, String)}
48 * starts injecting resolvers.
49 * <p>
50 * This is the right place to introduce, say, contextual additional fields.
51 *
52 * @param node the root object of the read template
53 * @return the root object of the template to be compiled
54 */
55 default Object processTemplateBeforeResolverInjection(Object node) {
56 return node;
57 }
58
59 }
+0
-146
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
20 import org.apache.logging.log4j.core.config.plugins.util.PluginUtil;
21 import org.apache.logging.log4j.status.StatusLogger;
22
23 import java.util.LinkedHashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 /**
29 * Utility class for {@link TemplateResolverFactory}.
30 */
31 public final class TemplateResolverFactories {
32
33 private static final Logger LOGGER = StatusLogger.getLogger();
34
35 private TemplateResolverFactories() {}
36
37 /**
38 * Populates plugins implementing
39 * {@link TemplateResolverFactory TemplateResolverFactory&lt;V, C&gt;},
40 * where {@code V} and {@code C} denote the value and context class types,
41 * respectively.
42 */
43 public static <V, C extends TemplateResolverContext<V, C>, F extends TemplateResolverFactory<V, C>> Map<String, F> populateFactoryByName(
44 final List<String> pluginPackages,
45 final Class<V> valueClass,
46 final Class<C> contextClass) {
47
48 // Populate template resolver factories.
49 final Map<String, PluginType<?>> pluginTypeByName =
50 PluginUtil.collectPluginsByCategoryAndPackage(
51 TemplateResolverFactory.CATEGORY,
52 pluginPackages);
53 if (LOGGER.isDebugEnabled()) {
54 LOGGER.debug(
55 "found {} plugins of category \"{}\": {}",
56 pluginTypeByName.size(),
57 TemplateResolverFactory.CATEGORY,
58 pluginTypeByName.keySet());
59 }
60
61 // Filter matching resolver factories.
62 final Map<String, F> factoryByName =
63 populateFactoryByName(pluginTypeByName, valueClass, contextClass);
64 if (LOGGER.isDebugEnabled()) {
65 LOGGER.debug(
66 "matched {} resolver factories out of {} for value class {} and context class {}: {}",
67 factoryByName.size(),
68 pluginTypeByName.size(),
69 valueClass,
70 contextClass,
71 factoryByName.keySet());
72 }
73 return factoryByName;
74
75 }
76
77 private static <V, C extends TemplateResolverContext<V, C>, F extends TemplateResolverFactory<V, C>> Map<String, F> populateFactoryByName(
78 final Map<String, PluginType<?>> pluginTypeByName,
79 final Class<V> valueClass,
80 final Class<C> contextClass) {
81 final Map<String, F> factoryByName = new LinkedHashMap<>();
82 final Set<String> pluginNames = pluginTypeByName.keySet();
83 for (final String pluginName : pluginNames) {
84 final PluginType<?> pluginType = pluginTypeByName.get(pluginName);
85 final Class<?> pluginClass = pluginType.getPluginClass();
86 final boolean pluginClassMatched =
87 TemplateResolverFactory.class.isAssignableFrom(pluginClass);
88 if (pluginClassMatched) {
89 final TemplateResolverFactory<?, ?> rawFactory =
90 instantiateFactory(pluginName, pluginClass);
91 final F factory = castFactory(valueClass, contextClass, rawFactory);
92 if (factory != null) {
93 addFactory(factoryByName, factory);
94 }
95 }
96 }
97 return factoryByName;
98 }
99
100 private static TemplateResolverFactory<?, ?> instantiateFactory(
101 final String pluginName,
102 final Class<?> pluginClass) {
103 try {
104 return (TemplateResolverFactory<?, ?>)
105 PluginUtil.instantiatePlugin(pluginClass);
106 } catch (final Exception error) {
107 final String message = String.format(
108 "failed instantiating resolver factory plugin %s of name %s",
109 pluginClass, pluginName);
110 throw new RuntimeException(message, error);
111 }
112 }
113
114 private static <V, C extends TemplateResolverContext<V, C>, F extends TemplateResolverFactory<V, C>> F castFactory(
115 final Class<V> valueClass,
116 final Class<C> contextClass,
117 final TemplateResolverFactory<?, ?> factory) {
118 final Class<?> factoryValueClass = factory.getValueClass();
119 final Class<?> factoryContextClass = factory.getContextClass();
120 final boolean factoryValueClassMatched =
121 valueClass.isAssignableFrom(factoryValueClass);
122 final boolean factoryContextClassMatched =
123 contextClass.isAssignableFrom(factoryContextClass);
124 if (factoryValueClassMatched && factoryContextClassMatched) {
125 @SuppressWarnings("unchecked")
126 final F typedFactory = (F) factory;
127 return typedFactory;
128 }
129 return null;
130 }
131
132 private static <V, C extends TemplateResolverContext<V, C>, F extends TemplateResolverFactory<V, C>> void addFactory(
133 final Map<String, F> factoryByName,
134 final F factory) {
135 final String factoryName = factory.getName();
136 final F conflictingFactory = factoryByName.putIfAbsent(factoryName, factory);
137 if (conflictingFactory != null) {
138 final String message = String.format(
139 "found resolver factories with overlapping names: %s (%s and %s)",
140 factoryName, conflictingFactory, factory);
141 throw new IllegalArgumentException(message);
142 }
143 }
144
145 }
+0
-46
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 /**
19 * {@link TemplateResolver} factory.
20 *
21 * @param <V> type of the value passed to the {@link TemplateResolver resolver}
22 * @param <C> type of the context passed to the {@link TemplateResolverFactory#create(TemplateResolverContext, TemplateResolverConfig)} creator}
23 */
24 public interface TemplateResolverFactory<V, C extends TemplateResolverContext<V, C>> {
25
26 /**
27 * Main plugin category for {@link TemplateResolverFactory} implementations.
28 */
29 String CATEGORY = "JsonTemplateResolverFactory";
30
31 /**
32 * The targeted value class.
33 */
34 Class<V> getValueClass();
35
36 /**
37 * The targeted {@link TemplateResolverContext} class.
38 */
39 Class<C> getContextClass();
40
41 String getName();
42
43 TemplateResolver<V> create(C context, TemplateResolverConfig config);
44
45 }
+0
-56
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptor.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.logging.log4j.layout.template.json.resolver;
17
18 /**
19 * Main {@link TemplateResolver} compilation interception interface.
20 *
21 * @param <V> type of the value passed to the {@link TemplateResolver resolver}
22 * @param <C> type of the context employed
23 */
24 public interface TemplateResolverInterceptor<V, C extends TemplateResolverContext<V, C>> {
25
26 /**
27 * Main plugin category for {@link TemplateResolverInterceptor} implementations.
28 */
29 String CATEGORY = "JsonTemplateResolverInterceptor";
30
31 /**
32 * The targeted value class.
33 */
34 Class<V> getValueClass();
35
36 /**
37 * The targeted {@link TemplateResolverContext} class.
38 */
39 Class<C> getContextClass();
40
41 /**
42 * Intercept the read template before compiler (i.e.,
43 * {@link TemplateResolvers#ofTemplate(TemplateResolverContext, String)}
44 * starts injecting resolvers.
45 * <p>
46 * This is the right place to introduce, say, contextual additional fields.
47 *
48 * @param node the root object of the read template
49 * @return the root object of the template to be compiled
50 */
51 default Object processTemplateBeforeResolverInjection(C context, Object node) {
52 return node;
53 }
54
55 }
+0
-131
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptors.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
20 import org.apache.logging.log4j.core.config.plugins.util.PluginUtil;
21 import org.apache.logging.log4j.status.StatusLogger;
22
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 /**
29 * Utility class for {@link TemplateResolverInterceptor}.
30 */
31 public class TemplateResolverInterceptors {
32
33 private static final Logger LOGGER = StatusLogger.getLogger();
34
35 private TemplateResolverInterceptors() {}
36
37 /**
38 * Populates plugins implementing
39 * {@link TemplateResolverInterceptor TemplateResolverInterceptor&lt;V, C&gt;},
40 * where {@code V} and {@code C} denote the value and context class types,
41 * respectively.
42 */
43 public static <V, C extends TemplateResolverContext<V, C>, I extends TemplateResolverInterceptor<V, C>> List<I> populateInterceptors(
44 final List<String> pluginPackages,
45 final Class<V> valueClass,
46 final Class<C> contextClass) {
47
48 // Populate interceptors.
49 final Map<String, PluginType<?>> pluginTypeByName =
50 PluginUtil.collectPluginsByCategoryAndPackage(
51 TemplateResolverInterceptor.CATEGORY,
52 pluginPackages);
53 if (LOGGER.isDebugEnabled()) {
54 LOGGER.debug(
55 "found {} plugins of category \"{}\": {}",
56 pluginTypeByName.size(),
57 TemplateResolverFactory.CATEGORY,
58 pluginTypeByName.keySet());
59 }
60
61 // Filter matching interceptors.
62 final List<I> interceptors =
63 populateInterceptors(pluginTypeByName, valueClass, contextClass);
64 LOGGER.debug(
65 "{} interceptors matched out of {} for value class {} and context class {}",
66 interceptors.size(),
67 pluginTypeByName.size(),
68 valueClass,
69 contextClass);
70 return interceptors;
71
72 }
73
74 private static <V, C extends TemplateResolverContext<V, C>, I extends TemplateResolverInterceptor<V, C>> List<I> populateInterceptors(
75 final Map<String, PluginType<?>> pluginTypeByName,
76 final Class<V> valueClass,
77 final Class<C> contextClass) {
78 final List<I> interceptors = new LinkedList<>();
79 final Set<String> pluginNames = pluginTypeByName.keySet();
80 for (final String pluginName : pluginNames) {
81 final PluginType<?> pluginType = pluginTypeByName.get(pluginName);
82 final Class<?> pluginClass = pluginType.getPluginClass();
83 final boolean pluginClassMatched =
84 TemplateResolverInterceptor.class.isAssignableFrom(pluginClass);
85 if (pluginClassMatched) {
86 final TemplateResolverInterceptor<?, ?> rawInterceptor =
87 instantiateInterceptor(pluginName, pluginClass);
88 final I interceptor =
89 castInterceptor(valueClass, contextClass, rawInterceptor);
90 if (interceptor != null) {
91 interceptors.add(interceptor);
92 }
93 }
94 }
95 return interceptors;
96 }
97
98 private static TemplateResolverInterceptor<?, ?> instantiateInterceptor(
99 final String pluginName,
100 final Class<?> pluginClass) {
101 try {
102 return (TemplateResolverInterceptor<?, ?>)
103 PluginUtil.instantiatePlugin(pluginClass);
104 } catch (final Exception error) {
105 final String message = String.format(
106 "failed instantiating resolver interceptor plugin %s of name %s",
107 pluginClass, pluginName);
108 throw new RuntimeException(message, error);
109 }
110 }
111
112 private static <V, C extends TemplateResolverContext<V, C>, I extends TemplateResolverInterceptor<V, C>> I castInterceptor(
113 final Class<V> valueClass,
114 final Class<C> contextClass,
115 final TemplateResolverInterceptor<?, ?> interceptor) {
116 final Class<?> interceptorValueClass = interceptor.getValueClass();
117 final Class<?> interceptorContextClass = interceptor.getContextClass();
118 final boolean interceptorValueClassMatched =
119 valueClass.isAssignableFrom(interceptorValueClass);
120 final boolean interceptorContextClassMatched =
121 contextClass.isAssignableFrom(interceptorContextClass);
122 if (interceptorValueClassMatched && interceptorContextClassMatched) {
123 @SuppressWarnings({"unchecked"})
124 final I typedInterceptor = (I) interceptor;
125 return typedInterceptor;
126 }
127 return null;
128 }
129
130 }
+0
-38
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverStringSubstitutor.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
19
20 /**
21 * A contextual {@link StrSubstitutor} abstraction.
22 *
23 * @param <V> {@link TemplateResolver} value
24 */
25 public interface TemplateResolverStringSubstitutor<V> {
26
27 StrSubstitutor getInternalSubstitutor();
28
29 /**
30 * A substitutor is stable if the replacement doesn't vary with the provided
31 * value. In such a case, value is always set to {@code null}.
32 */
33 boolean isStable();
34
35 String replace(V value, String source);
36
37 }
+0
-385
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25 import java.util.stream.Collectors;
26
27 /**
28 * Main class for compiling {@link TemplateResolver}s from a template.
29 */
30 public final class TemplateResolvers {
31
32 private TemplateResolvers() {}
33
34 private static final String RESOLVER_FIELD_NAME = "$resolver";
35
36 private static abstract class UnresolvableTemplateResolver
37 implements TemplateResolver<Object> {
38
39 @Override
40 public final boolean isResolvable() {
41 return false;
42 }
43
44 @Override
45 public final boolean isResolvable(Object value) {
46 return false;
47 }
48
49 }
50
51 private static final TemplateResolver<?> EMPTY_ARRAY_RESOLVER =
52 new UnresolvableTemplateResolver() {
53 @Override
54 public void resolve(final Object value, final JsonWriter jsonWriter) {
55 jsonWriter.writeArrayStart();
56 jsonWriter.writeArrayEnd();
57 }
58 };
59
60 private static final TemplateResolver<?> EMPTY_OBJECT_RESOLVER =
61 new UnresolvableTemplateResolver() {
62 @Override
63 public void resolve(final Object value, final JsonWriter jsonWriter) {
64 jsonWriter.writeObjectStart();
65 jsonWriter.writeObjectEnd();
66 }
67 };
68
69 private static final TemplateResolver<?> NULL_RESOLVER =
70 new UnresolvableTemplateResolver() {
71 @Override
72 public void resolve(final Object value, final JsonWriter jsonWriter) {
73 jsonWriter.writeNull();
74 }
75 };
76
77 public static <V, C extends TemplateResolverContext<V, C>> TemplateResolver<V> ofTemplate(
78 final C context,
79 final String template) {
80
81 // Check arguments.
82 Objects.requireNonNull(context, "context");
83 Objects.requireNonNull(template, "template");
84
85 // Read the template.
86 Object node;
87 try {
88 node = JsonReader.read(template);
89 } catch (final Exception error) {
90 final String message = String.format("failed parsing template (template=%s)", template);
91 throw new RuntimeException(message, error);
92 }
93
94 // Perform contextual interception.
95 final List<? extends TemplateResolverInterceptor<V, C>> interceptors =
96 context.getResolverInterceptors();
97 // noinspection ForLoopReplaceableByForEach
98 for (int interceptorIndex = 0;
99 interceptorIndex < interceptors.size();
100 interceptorIndex++) {
101 final TemplateResolverInterceptor<V, C> interceptor =
102 interceptors.get(interceptorIndex);
103 node = interceptor.processTemplateBeforeResolverInjection(context, node);
104 }
105
106 // Resolve the template.
107 return ofObject(context, node);
108
109 }
110
111 static <V, C extends TemplateResolverContext<V, C>> TemplateResolver<V> ofObject(
112 final C context,
113 final Object object) {
114 if (object == null) {
115 @SuppressWarnings("unchecked")
116 final TemplateResolver<V> nullResolver = (TemplateResolver<V>) NULL_RESOLVER;
117 return nullResolver;
118 } else if (object instanceof List) {
119 @SuppressWarnings("unchecked")
120 final List<Object> list = (List<Object>) object;
121 return ofList(context, list);
122 } else if (object instanceof Map) {
123 @SuppressWarnings("unchecked")
124 final Map<String, Object> map = (Map<String, Object>) object;
125 return ofMap(context, map);
126 } else if (object instanceof String) {
127 final String string = (String) object;
128 return ofString(context, string);
129 } else if (object instanceof Number) {
130 final Number number = (Number) object;
131 return ofNumber(number);
132 } else if (object instanceof Boolean) {
133 final boolean value = (boolean) object;
134 return ofBoolean(value);
135 } else {
136 final String message = String.format(
137 "invalid JSON node type (class=%s)",
138 object.getClass().getName());
139 throw new IllegalArgumentException(message);
140 }
141 }
142
143 private static <V, C extends TemplateResolverContext<V, C>> TemplateResolver<V> ofList(
144 final C context,
145 final List<Object> list) {
146
147 // Create resolver for each children.
148 final List<TemplateResolver<V>> itemResolvers = list
149 .stream()
150 .map(item -> {
151 final TemplateResolver<V> itemResolver = ofObject(context, item);
152 if (itemResolver.isFlattening()) {
153 throw new IllegalArgumentException(
154 "flattening resolvers are not allowed in lists");
155 }
156 return itemResolver;
157 })
158 .collect(Collectors.toList());
159
160 // Short-circuit if the array is empty.
161 if (itemResolvers.isEmpty()) {
162 @SuppressWarnings("unchecked")
163 final TemplateResolver<V> emptyArrayResolver =
164 (TemplateResolver<V>) EMPTY_ARRAY_RESOLVER;
165 return emptyArrayResolver;
166 }
167
168 // Create a parent resolver collecting each child resolver execution.
169 return (final V value, final JsonWriter jsonWriter) -> {
170 jsonWriter.writeArrayStart();
171 for (int itemResolverIndex = 0;
172 itemResolverIndex < itemResolvers.size();
173 itemResolverIndex++) {
174 if (itemResolverIndex > 0) {
175 jsonWriter.writeSeparator();
176 }
177 final TemplateResolver<V> itemResolver = itemResolvers.get(itemResolverIndex);
178 itemResolver.resolve(value, jsonWriter);
179 }
180 jsonWriter.writeArrayEnd();
181 };
182
183 }
184
185 private static <V, C extends TemplateResolverContext<V, C>> TemplateResolver<V> ofMap(
186 final C context,
187 final Map<String, Object> map) {
188
189 // Check if this is a resolver request.
190 if (map.containsKey(RESOLVER_FIELD_NAME)) {
191 return ofResolver(context, map);
192 }
193
194 // Create resolver for each object field.
195 final List<String> fieldNames = new ArrayList<>();
196 final List<TemplateResolver<V>> fieldResolvers = new ArrayList<>();
197 map.forEach((fieldName, fieldValue) -> {
198 final TemplateResolver<V> fieldResolver = ofObject(context, fieldValue);
199 final boolean resolvable = fieldResolver.isResolvable();
200 if (resolvable) {
201 fieldNames.add(fieldName);
202 fieldResolvers.add(fieldResolver);
203 }
204 });
205
206 // Short-circuit if the object is empty.
207 final int fieldCount = fieldNames.size();
208 if (fieldCount == 0) {
209 @SuppressWarnings("unchecked")
210 final TemplateResolver<V> emptyObjectResolver =
211 (TemplateResolver<V>) EMPTY_OBJECT_RESOLVER;
212 return emptyObjectResolver;
213 }
214
215 // Prepare field names to avoid escape and truncation costs at runtime.
216 final List<String> fieldPrefixes = fieldNames
217 .stream()
218 .map(fieldName -> {
219 try (JsonWriter jsonWriter = context.getJsonWriter()) {
220 jsonWriter.writeString(fieldName);
221 jsonWriter.getStringBuilder().append(':');
222 return jsonWriter.getStringBuilder().toString();
223 }
224 })
225 .collect(Collectors.toList());
226
227 return new TemplateResolver<V>() {
228
229 @Override
230 public boolean isResolvable() {
231 // We have already excluded unresolvable ones while collecting
232 // the resolvers. Hence it is safe to return true here.
233 return true;
234 }
235
236 /**
237 * The parent resolver checking if each child is resolvable given
238 * the passed {@code value}.
239 *
240 * This is an optimization to skip the rendering of a parent if all
241 * its children are not resolvable given the passed {@code value}.
242 */
243 @Override
244 public boolean isResolvable(final V value) {
245 for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
246 final TemplateResolver<V> fieldResolver = fieldResolvers.get(fieldIndex);
247 final boolean resolvable = fieldResolver.isResolvable(value);
248 if (resolvable) {
249 return true;
250 }
251 }
252 return false;
253 }
254
255 /**
256 * The parent resolver combining all child resolver executions.
257 */
258 @Override
259 public void resolve(final V value, final JsonWriter jsonWriter) {
260 final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
261 jsonWriter.writeObjectStart();
262 for (int resolvedFieldCount = 0, fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
263 final TemplateResolver<V> fieldResolver = fieldResolvers.get(fieldIndex);
264 final boolean resolvable = fieldResolver.isResolvable(value);
265 if (!resolvable) {
266 continue;
267 }
268 final boolean succeedingEntry = resolvedFieldCount > 0;
269 final boolean flattening = fieldResolver.isFlattening();
270 if (flattening) {
271 final int initLength = jsonWriterStringBuilder.length();
272 fieldResolver.resolve(value, jsonWriter, succeedingEntry);
273 final boolean resolved = jsonWriterStringBuilder.length() > initLength;
274 if (resolved) {
275 resolvedFieldCount++;
276 }
277 } else {
278 if (succeedingEntry) {
279 jsonWriter.writeSeparator();
280 }
281 final String fieldPrefix = fieldPrefixes.get(fieldIndex);
282 jsonWriter.writeRawString(fieldPrefix);
283 fieldResolver.resolve(value, jsonWriter, succeedingEntry);
284 resolvedFieldCount++;
285 }
286 }
287 jsonWriter.writeObjectEnd();
288 }
289
290 };
291
292 }
293
294 private static <V, C extends TemplateResolverContext<V, C>> TemplateResolver<V> ofResolver(
295 final C context,
296 final Map<String, Object> configMap) {
297
298 // Check arguments.
299 Objects.requireNonNull(context, "context");
300 Objects.requireNonNull(configMap, "configMap");
301
302 // Extract the resolver name.
303 final Object resolverNameObject = configMap.get(RESOLVER_FIELD_NAME);
304 if (!(resolverNameObject instanceof String)) {
305 throw new IllegalArgumentException(
306 "invalid resolver name: " + resolverNameObject);
307 }
308 final String resolverName = (String) resolverNameObject;
309
310 // Retrieve the resolver.
311 final TemplateResolverFactory<V, C> resolverFactory =
312 context.getResolverFactoryByName().get(resolverName);
313 if (resolverFactory == null) {
314 throw new IllegalArgumentException("unknown resolver: " + resolverName);
315 }
316 final TemplateResolverConfig resolverConfig = new TemplateResolverConfig(configMap);
317 return resolverFactory.create(context, resolverConfig);
318
319 }
320
321 private static <V, C extends TemplateResolverContext<V, C>> TemplateResolver<V> ofString(
322 final C context,
323 final String fieldValue) {
324
325 // Check if substitution is needed.
326 final boolean substitutionNeeded = fieldValue.contains("${");
327 final JsonWriter contextJsonWriter = context.getJsonWriter();
328 if (substitutionNeeded) {
329 final TemplateResolverStringSubstitutor<V> substitutor = context.getSubstitutor();
330
331 // If the substitutor is stable, we can get the replacement right
332 // away and avoid runtime substitution.
333 if (substitutor.isStable()) {
334 final String replacedText = substitutor.replace(null, fieldValue);
335 if (replacedText == null) {
336 @SuppressWarnings("unchecked")
337 final TemplateResolver<V> resolver =
338 (TemplateResolver<V>) NULL_RESOLVER;
339 return resolver;
340 } else {
341 // Prepare the escaped replacement first.
342 final String escapedReplacedText =
343 contextJsonWriter.use(() ->
344 contextJsonWriter.writeString(replacedText));
345 // Create a resolver dedicated to the escaped replacement.
346 return (final V value, final JsonWriter jsonWriter) ->
347 jsonWriter.writeRawString(escapedReplacedText);
348 }
349 }
350
351 // Otherwise, the unstable substitutor needs to be invoked always at
352 // runtime.
353 else {
354 return (final V value, final JsonWriter jsonWriter) -> {
355 final String replacedText = substitutor.replace(value, fieldValue);
356 jsonWriter.writeString(replacedText);
357 };
358 }
359
360 }
361
362 // Write the field value as is.
363 else {
364 final String escapedFieldValue =
365 contextJsonWriter.use(() ->
366 contextJsonWriter.writeString(fieldValue));
367 return (final V value, final JsonWriter jsonWriter) ->
368 jsonWriter.writeRawString(escapedFieldValue);
369 }
370
371 }
372
373 private static <V> TemplateResolver<V> ofNumber(final Number number) {
374 final String numberString = String.valueOf(number);
375 return (final V ignored, final JsonWriter jsonWriter) ->
376 jsonWriter.writeRawString(numberString);
377 }
378
379 private static <V> TemplateResolver<V> ofBoolean(final boolean value) {
380 return (final V ignored, final JsonWriter jsonWriter) ->
381 jsonWriter.writeBoolean(value);
382 }
383
384 }
+0
-38
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ThreadContextDataResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19
20 /**
21 * Mapped Diagnostic Context (MDC), aka. Thread Context Data, resolver.
22 *
23 * @see ReadOnlyStringMapResolver
24 */
25 public final class ThreadContextDataResolver extends ReadOnlyStringMapResolver {
26
27 ThreadContextDataResolver(
28 final EventResolverContext context,
29 final TemplateResolverConfig config) {
30 super(context, config, LogEvent::getContextData);
31 }
32
33 static String getName() {
34 return "mdc";
35 }
36
37 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ThreadContextDataResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link ThreadContextDataResolver} factory.
23 */
24 @Plugin(name = "ThreadContextDataResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class ThreadContextDataResolverFactory implements EventResolverFactory {
26
27 private static final ThreadContextDataResolverFactory INSTANCE =
28 new ThreadContextDataResolverFactory();
29
30 private ThreadContextDataResolverFactory() {}
31
32 @PluginFactory
33 public static ThreadContextDataResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return ThreadContextDataResolver.getName();
40 }
41
42 @Override
43 public ThreadContextDataResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return new ThreadContextDataResolver(context, config);
47 }
48
49 }
+0
-107
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ThreadContextStackResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.ThreadContext;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
21
22 import java.util.Optional;
23 import java.util.regex.Pattern;
24
25 /**
26 * Nested Diagnostic Context (NDC), aka. Thread Context Stack, resolver.
27 *
28 * <h3>Configuration</h3>
29 *
30 * <pre>
31 * config = [ pattern ]
32 * pattern = "pattern" -> string
33 * </pre>
34 *
35 * <h3>Examples</h3>
36 *
37 * Resolve all NDC values into a list:
38 *
39 * <pre>
40 * {
41 * "$resolver": "ndc"
42 * }
43 * </pre>
44 *
45 * Resolve all NDC values matching with the <tt>pattern</tt> regex:
46 *
47 * <pre>
48 * {
49 * "$resolver": "ndc",
50 * "pattern": "user(Role|Rank):\\w+"
51 * }
52 * </pre>
53 */
54 public final class ThreadContextStackResolver implements EventResolver {
55
56 private final Pattern itemPattern;
57
58 ThreadContextStackResolver(final TemplateResolverConfig config) {
59 this.itemPattern = Optional
60 .ofNullable(config.getString("pattern"))
61 .map(Pattern::compile)
62 .orElse(null);
63 }
64
65 static String getName() {
66 return "ndc";
67 }
68
69 @Override
70 public boolean isResolvable(final LogEvent logEvent) {
71 final ThreadContext.ContextStack contextStack = logEvent.getContextStack();
72 return contextStack.getDepth() > 0;
73 }
74
75 @Override
76 public void resolve(
77 final LogEvent logEvent,
78 final JsonWriter jsonWriter) {
79 final ThreadContext.ContextStack contextStack = logEvent.getContextStack();
80 if (contextStack.getDepth() == 0) {
81 jsonWriter.writeNull();
82 return;
83 }
84 boolean arrayStarted = false;
85 for (final String contextStackItem : contextStack.asList()) {
86 final boolean matched =
87 itemPattern == null ||
88 itemPattern.matcher(contextStackItem).matches();
89 if (matched) {
90 if (arrayStarted) {
91 jsonWriter.writeSeparator();
92 } else {
93 jsonWriter.writeArrayStart();
94 arrayStarted = true;
95 }
96 jsonWriter.writeString(contextStackItem);
97 }
98 }
99 if (arrayStarted) {
100 jsonWriter.writeArrayEnd();
101 } else {
102 jsonWriter.writeNull();
103 }
104 }
105
106 }
+0
-50
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ThreadContextStackResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link ThreadContextStackResolver} factory.
23 */
24 @Plugin(name = "ThreadContextStackResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class ThreadContextStackResolverFactory implements EventResolverFactory {
26
27 private static final ThreadContextStackResolverFactory INSTANCE =
28 new ThreadContextStackResolverFactory();
29
30 private ThreadContextStackResolverFactory() {}
31
32 @PluginFactory
33 public static ThreadContextStackResolverFactory getInstance() {
34 return INSTANCE;
35 }
36
37 @Override
38 public String getName() {
39 return ThreadContextStackResolver.getName();
40 }
41
42 @Override
43 public ThreadContextStackResolver create(
44 final EventResolverContext context,
45 final TemplateResolverConfig config) {
46 return new ThreadContextStackResolver(config);
47 }
48
49 }
+0
-92
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ThreadResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
20
21 /**
22 * Thread resolver.
23 *
24 * <h3>Configuration</h3>
25 *
26 * <pre>
27 * config = "field" -> ( "name" | "id" | "priority" )
28 * </pre>
29 *
30 * <h3>Examples</h3>
31 *
32 * Resolve the thread name:
33 *
34 * <pre>
35 * {
36 * "$resolver": "thread",
37 * "field": "name"
38 * }
39 * </pre>
40 */
41 public final class ThreadResolver implements EventResolver {
42
43 private static final EventResolver NAME_RESOLVER =
44 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
45 final String threadName = logEvent.getThreadName();
46 jsonWriter.writeString(threadName);
47 };
48
49 private static final EventResolver ID_RESOLVER =
50 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
51 final long threadId = logEvent.getThreadId();
52 jsonWriter.writeNumber(threadId);
53 };
54
55 private static final EventResolver PRIORITY_RESOLVER =
56 (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
57 final int threadPriority = logEvent.getThreadPriority();
58 jsonWriter.writeNumber(threadPriority);
59 };
60
61 private final EventResolver internalResolver;
62
63 ThreadResolver(final TemplateResolverConfig config) {
64 this.internalResolver = createInternalResolver(config);
65 }
66
67 private static EventResolver createInternalResolver(
68 final TemplateResolverConfig config) {
69 final String fieldName = config.getString("field");
70 if ("name".equals(fieldName)) {
71 return NAME_RESOLVER;
72 } else if ("id".equals(fieldName)) {
73 return ID_RESOLVER;
74 } else if ("priority".equals(fieldName)) {
75 return PRIORITY_RESOLVER;
76 }
77 throw new IllegalArgumentException("unknown field: " + config);
78 }
79
80 static String getName() {
81 return "thread";
82 }
83
84 @Override
85 public void resolve(
86 final LogEvent logEvent,
87 final JsonWriter jsonWriter) {
88 internalResolver.resolve(logEvent, jsonWriter);
89 }
90
91 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ThreadResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link ThreadResolver} factory.
23 */
24 @Plugin(name = "ThreadResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class ThreadResolverFactory implements EventResolverFactory {
26
27 private static final ThreadResolverFactory INSTANCE = new ThreadResolverFactory();
28
29 private ThreadResolverFactory() {}
30
31 @PluginFactory
32 public static ThreadResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return ThreadResolver.getName();
39 }
40
41 @Override
42 public ThreadResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new ThreadResolver(config);
46 }
47
48 }
+0
-486
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TimestampResolver.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.time.Instant;
20 import org.apache.logging.log4j.core.time.MutableInstant;
21 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults;
22 import org.apache.logging.log4j.layout.template.json.util.InstantFormatter;
23 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
24
25 import java.util.Locale;
26 import java.util.TimeZone;
27
28 /**
29 * Timestamp resolver.
30 *
31 * <h3>Configuration</h3>
32 *
33 * <pre>
34 * config = [ patternConfig | epochConfig ]
35 *
36 * patternConfig = "pattern" -> ( [ format ] , [ timeZone ] , [ locale ] )
37 * format = "format" -> string
38 * timeZone = "timeZone" -> string
39 * locale = "locale" -> (
40 * language |
41 * ( language , "_" , country ) |
42 * ( language , "_" , country , "_" , variant )
43 * )
44 *
45 * epochConfig = "epoch" -> ( unit , [ rounded ] )
46 * unit = "unit" -> (
47 * "nanos" |
48 * "millis" |
49 * "secs" |
50 * "millis.nanos" |
51 * "secs.nanos" |
52 * )
53 * rounded = "rounded" -> boolean
54 * </pre>
55 *
56 * If no configuration options are provided, <tt>pattern-config</tt> is
57 * employed. There {@link
58 * JsonTemplateLayoutDefaults#getTimestampFormatPattern()}, {@link
59 * JsonTemplateLayoutDefaults#getTimeZone()}, {@link
60 * JsonTemplateLayoutDefaults#getLocale()} are used as defaults for
61 * <tt>pattern</tt>, <tt>timeZone</tt>, and <tt>locale</tt>, respectively.
62 *
63 * In <tt>epoch-config</tt>, <tt>millis.nanos</tt>, <tt>secs.nanos</tt> stand
64 * for the fractional component in nanoseconds.
65 *
66 * <h3>Examples</h3>
67 *
68 * <table>
69 * <tr>
70 * <td>Configuration</td>
71 * <td>Output</td>
72 * </tr>
73 * <tr>
74 * <td><pre>
75 * {
76 * "$resolver": "timestamp"
77 * }
78 * </pre></td>
79 * <td><pre>
80 * 2020-02-07T13:38:47.098+02:00
81 * </pre></td>
82 * </tr>
83 * <tr>
84 * <td><pre>
85 * {
86 * "$resolver": "timestamp",
87 * "pattern": {
88 * "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
89 * "timeZone": "UTC",
90 * "locale": "en_US"
91 * }
92 * }
93 * </pre></td>
94 * <td><pre>
95 * 2020-02-07T13:38:47.098Z
96 * </pre></td>
97 * </tr>
98 * <tr>
99 * <td><pre>
100 * {
101 * "$resolver": "timestamp",
102 * "epoch": {
103 * "unit": "secs"
104 * }
105 * }
106 * </pre></td>
107 * <td><pre>
108 * 1581082727.982123456
109 * </pre></td>
110 * </tr>
111 * <tr>
112 * <td><pre>
113 * {
114 * "$resolver": "timestamp",
115 * "epoch": {
116 * "unit": "secs",
117 * "rounded": true
118 * }
119 * }
120 * </pre></td>
121 * <td><pre>
122 * 1581082727
123 * </pre></td>
124 * </tr>
125 * <tr>
126 * <td><pre>
127 * {
128 * "$resolver": "timestamp",
129 * "epoch": {
130 * "unit": "secs.nanos"
131 * }
132 * }
133 * </pre></td>
134 * <td><pre>
135 * 982123456
136 * </pre></td>
137 * </tr>
138 * <tr>
139 * <td><pre>
140 * {
141 * "$resolver": "timestamp",
142 * "epoch": {
143 * "unit": "millis"
144 * }
145 * }
146 * </pre></td>
147 * <td><pre>
148 * 1581082727982.123456
149 * </pre></td>
150 * </tr>
151 * <tr>
152 * <td><pre>
153 * {
154 * "$resolver": "timestamp",
155 * "epoch": {
156 * "unit": "millis",
157 * "rounded": true
158 * }
159 * }
160 * </pre></td>
161 * <td><pre>
162 * 1581082727982
163 * </pre></td>
164 * </tr>
165 * <tr>
166 * <td><pre>
167 * {
168 * "$resolver": "timestamp",
169 * "epoch": {
170 * "unit": "millis.nanos"
171 * }
172 * }
173 * </pre></td>
174 * <td><pre>
175 * 123456
176 * </pre></td>
177 * </tr>
178 * <tr>
179 * <td><pre>
180 * {
181 * "$resolver": "timestamp",
182 * "epoch": {
183 * "unit": "nanos"
184 * }
185 * }
186 * </pre></td>
187 * <td><pre>
188 * 1581082727982123456
189 * </pre></td>
190 * </tr>
191 * </table>
192 */
193 public final class TimestampResolver implements EventResolver {
194
195 private final EventResolver internalResolver;
196
197 TimestampResolver(final TemplateResolverConfig config) {
198 this.internalResolver = createResolver(config);
199 }
200
201 private static EventResolver createResolver(
202 final TemplateResolverConfig config) {
203 final boolean patternProvided = config.exists("pattern");
204 final boolean epochProvided = config.exists("epoch");
205 if (patternProvided && epochProvided) {
206 throw new IllegalArgumentException(
207 "conflicting configuration options are provided: " + config);
208 }
209 return epochProvided
210 ? createEpochResolver(config)
211 : createPatternResolver(config);
212 }
213
214 private static final class PatternResolverContext {
215
216 private final InstantFormatter formatter;
217
218 private final StringBuilder lastFormattedInstantBuffer = new StringBuilder();
219
220 private final MutableInstant lastFormattedInstant = new MutableInstant();
221
222 private PatternResolverContext(
223 final String pattern,
224 final TimeZone timeZone,
225 final Locale locale) {
226 this.formatter = InstantFormatter
227 .newBuilder()
228 .setPattern(pattern)
229 .setTimeZone(timeZone)
230 .setLocale(locale)
231 .build();
232 lastFormattedInstant.initFromEpochSecond(-1, 0);
233 }
234
235 private static PatternResolverContext fromConfig(
236 final TemplateResolverConfig config) {
237 final String pattern = readPattern(config);
238 final TimeZone timeZone = readTimeZone(config);
239 final Locale locale = config.getLocale(new String[]{"pattern", "locale"});
240 return new PatternResolverContext(pattern, timeZone, locale);
241 }
242
243 private static String readPattern(final TemplateResolverConfig config) {
244 final String format = config.getString(new String[]{"pattern", "format"});
245 return format != null
246 ? format
247 : JsonTemplateLayoutDefaults.getTimestampFormatPattern();
248 }
249
250 private static TimeZone readTimeZone(final TemplateResolverConfig config) {
251 final String timeZoneId = config.getString(new String[]{"pattern", "timeZone"});
252 if (timeZoneId == null) {
253 return JsonTemplateLayoutDefaults.getTimeZone();
254 }
255 boolean found = false;
256 for (final String availableTimeZone : TimeZone.getAvailableIDs()) {
257 if (availableTimeZone.equalsIgnoreCase(timeZoneId)) {
258 found = true;
259 break;
260 }
261 }
262 if (!found) {
263 throw new IllegalArgumentException(
264 "invalid timestamp time zone: " + config);
265 }
266 return TimeZone.getTimeZone(timeZoneId);
267 }
268
269 }
270
271 private static final class PatternResolver implements EventResolver {
272
273 private final PatternResolverContext patternResolverContext;
274
275 private PatternResolver(final PatternResolverContext patternResolverContext) {
276 this.patternResolverContext = patternResolverContext;
277 }
278
279 @Override
280 public synchronized void resolve(
281 final LogEvent logEvent,
282 final JsonWriter jsonWriter) {
283
284 // Format timestamp if it doesn't match the last cached one.
285 final boolean instantMatching = patternResolverContext.formatter.isInstantMatching(
286 patternResolverContext.lastFormattedInstant,
287 logEvent.getInstant());
288 if (!instantMatching) {
289
290 // Format the timestamp.
291 patternResolverContext.lastFormattedInstantBuffer.setLength(0);
292 patternResolverContext.lastFormattedInstant.initFrom(logEvent.getInstant());
293 patternResolverContext.formatter.format(
294 patternResolverContext.lastFormattedInstant,
295 patternResolverContext.lastFormattedInstantBuffer);
296
297 // Write the formatted timestamp.
298 final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
299 final int startIndex = jsonWriterStringBuilder.length();
300 jsonWriter.writeString(patternResolverContext.lastFormattedInstantBuffer);
301
302 // Cache the written value.
303 patternResolverContext.lastFormattedInstantBuffer.setLength(0);
304 patternResolverContext.lastFormattedInstantBuffer.append(
305 jsonWriterStringBuilder,
306 startIndex,
307 jsonWriterStringBuilder.length());
308
309 }
310
311 // Write the cached formatted timestamp.
312 else {
313 jsonWriter.writeRawString(
314 patternResolverContext.lastFormattedInstantBuffer);
315 }
316
317 }
318
319 }
320
321 private static EventResolver createPatternResolver(
322 final TemplateResolverConfig config) {
323 final PatternResolverContext patternResolverContext =
324 PatternResolverContext.fromConfig(config);
325 return new PatternResolver(patternResolverContext);
326 }
327
328 private static EventResolver createEpochResolver(
329 final TemplateResolverConfig config) {
330 final String unit = config.getString(new String[]{"epoch", "unit"});
331 final Boolean rounded = config.getBoolean(new String[]{"epoch", "rounded"});
332 if ("nanos".equals(unit) && !Boolean.FALSE.equals(rounded)) {
333 return EPOCH_NANOS_RESOLVER;
334 } else if ("millis".equals(unit)) {
335 return !Boolean.TRUE.equals(rounded)
336 ? EPOCH_MILLIS_RESOLVER
337 : EPOCH_MILLIS_ROUNDED_RESOLVER;
338 } else if ("millis.nanos".equals(unit) && rounded == null) {
339 return EPOCH_MILLIS_NANOS_RESOLVER;
340 } else if ("secs".equals(unit)) {
341 return !Boolean.TRUE.equals(rounded)
342 ? EPOCH_SECS_RESOLVER
343 : EPOCH_SECS_ROUNDED_RESOLVER;
344 } else if ("secs.nanos".equals(unit) && rounded == null) {
345 return EPOCH_SECS_NANOS_RESOLVER;
346 }
347 throw new IllegalArgumentException(
348 "invalid epoch configuration: " + config);
349 }
350
351 private static final class EpochResolutionRecord {
352
353 private static final int MAX_LONG_LENGTH =
354 String.valueOf(Long.MAX_VALUE).length();
355
356 private final MutableInstant instant = new MutableInstant();
357
358 private final char[] resolution = new char[
359 /* integral: */ MAX_LONG_LENGTH +
360 /* dot: */ 1 +
361 /* fractional: */ MAX_LONG_LENGTH];
362
363 private int resolutionLength;
364
365 private EpochResolutionRecord() {
366 instant.initFromEpochSecond(-1, 0);
367 }
368
369 }
370
371 private static abstract class EpochResolver implements EventResolver {
372
373 private final EpochResolutionRecord resolutionRecord =
374 new EpochResolutionRecord();
375
376 @Override
377 public synchronized void resolve(
378 final LogEvent logEvent,
379 final JsonWriter jsonWriter) {
380 final Instant logEventInstant = logEvent.getInstant();
381 if (logEventInstant.equals(resolutionRecord.instant)) {
382 jsonWriter.writeRawString(
383 resolutionRecord.resolution,
384 0,
385 resolutionRecord.resolutionLength);
386 } else {
387 resolutionRecord.instant.initFrom(logEventInstant);
388 final StringBuilder stringBuilder = jsonWriter.getStringBuilder();
389 final int startIndex = stringBuilder.length();
390 resolve(logEventInstant, jsonWriter);
391 resolutionRecord.resolutionLength = stringBuilder.length() - startIndex;
392 stringBuilder.getChars(
393 startIndex,
394 stringBuilder.length(),
395 resolutionRecord.resolution,
396 0);
397 }
398 }
399
400 abstract void resolve(Instant logEventInstant, JsonWriter jsonWriter);
401
402 }
403
404 private static final EventResolver EPOCH_NANOS_RESOLVER =
405 new EpochResolver() {
406 @Override
407 void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
408 final long nanos = epochNanos(logEventInstant);
409 jsonWriter.writeNumber(nanos);
410 }
411 };
412
413 private static final EventResolver EPOCH_MILLIS_RESOLVER =
414 new EpochResolver() {
415 @Override
416 void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
417 final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
418 final long nanos = epochNanos(logEventInstant);
419 jsonWriterStringBuilder.append(nanos);
420 jsonWriterStringBuilder.insert(jsonWriterStringBuilder.length() - 6, '.');
421 }
422 };
423
424 private static final EventResolver EPOCH_MILLIS_ROUNDED_RESOLVER =
425 new EpochResolver() {
426 @Override
427 void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
428 jsonWriter.writeNumber(logEventInstant.getEpochMillisecond());
429 }
430 };
431
432 private static final EventResolver EPOCH_MILLIS_NANOS_RESOLVER =
433 new EpochResolver() {
434 @Override
435 void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
436 final long nanos = epochNanos(logEventInstant);
437 final long fraction = nanos % 1_000_000L;
438 jsonWriter.writeNumber(fraction);
439 }
440 };
441
442 private static final EventResolver EPOCH_SECS_RESOLVER =
443 new EpochResolver() {
444 @Override
445 void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
446 final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
447 final long nanos = epochNanos(logEventInstant);
448 jsonWriterStringBuilder.append(nanos);
449 jsonWriterStringBuilder.insert(jsonWriterStringBuilder.length() - 9, '.');
450 }
451 };
452
453 private static final EventResolver EPOCH_SECS_ROUNDED_RESOLVER =
454 new EpochResolver() {
455 @Override
456 void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
457 jsonWriter.writeNumber(logEventInstant.getEpochSecond());
458 }
459 };
460
461 private static final EventResolver EPOCH_SECS_NANOS_RESOLVER =
462 new EpochResolver() {
463 @Override
464 void resolve(final Instant logEventInstant, final JsonWriter jsonWriter) {
465 jsonWriter.writeNumber(logEventInstant.getNanoOfSecond());
466 }
467 };
468
469 private static long epochNanos(final Instant instant) {
470 final long nanos = Math.multiplyExact(1_000_000_000L, instant.getEpochSecond());
471 return Math.addExact(nanos, instant.getNanoOfSecond());
472 }
473
474 static String getName() {
475 return "timestamp";
476 }
477
478 @Override
479 public void resolve(
480 final LogEvent logEvent,
481 final JsonWriter jsonWriter) {
482 internalResolver.resolve(logEvent, jsonWriter);
483 }
484
485 }
+0
-49
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TimestampResolverFactory.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
20
21 /**
22 * {@link TimestampResolver} factory.
23 */
24 @Plugin(name = "TimestampResolverFactory", category = TemplateResolverFactory.CATEGORY)
25 public final class TimestampResolverFactory implements EventResolverFactory {
26
27 private static final TimestampResolverFactory INSTANCE = new TimestampResolverFactory();
28
29 private TimestampResolverFactory() {}
30
31 @PluginFactory
32 public static TimestampResolverFactory getInstance() {
33 return INSTANCE;
34 }
35
36 @Override
37 public String getName() {
38 return TimestampResolver.getName();
39 }
40
41 @Override
42 public TimestampResolver create(
43 final EventResolverContext context,
44 final TemplateResolverConfig config) {
45 return new TimestampResolver(config);
46 }
47
48 }
+0
-37
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/DummyRecycler.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.logging.log4j.layout.template.json.util;
17
18 import java.util.function.Supplier;
19
20 public class DummyRecycler<V> implements Recycler<V> {
21
22 private final Supplier<V> supplier;
23
24 public DummyRecycler(final Supplier<V> supplier) {
25 this.supplier = supplier;
26 }
27
28 @Override
29 public V acquire() {
30 return supplier.get();
31 }
32
33 @Override
34 public void release(final V value) {}
35
36 }
+0
-39
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/DummyRecyclerFactory.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.logging.log4j.layout.template.json.util;
17
18 import java.util.function.Consumer;
19 import java.util.function.Supplier;
20
21 public class DummyRecyclerFactory implements RecyclerFactory {
22
23 private static final DummyRecyclerFactory INSTANCE = new DummyRecyclerFactory();
24
25 private DummyRecyclerFactory() {}
26
27 public static DummyRecyclerFactory getInstance() {
28 return INSTANCE;
29 }
30
31 @Override
32 public <V> Recycler<V> create(
33 final Supplier<V> supplier,
34 final Consumer<V> cleaner) {
35 return new DummyRecycler<>(supplier);
36 }
37
38 }
+0
-371
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/InstantFormatter.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.core.time.Instant;
19 import org.apache.logging.log4j.core.time.MutableInstant;
20 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
21 import org.apache.logging.log4j.core.util.datetime.FixedDateFormat;
22 import org.apache.logging.log4j.util.Strings;
23
24 import java.time.format.DateTimeFormatter;
25 import java.util.Arrays;
26 import java.util.Calendar;
27 import java.util.Locale;
28 import java.util.Objects;
29 import java.util.TimeZone;
30
31 /**
32 * A composite {@link Instant} formatter trying to employ either
33 * {@link FixedDateFormat}, {@link FastDateFormat}, or {@link DateTimeFormatter}
34 * in the given order due to performance reasons.
35 * <p>
36 * Note that {@link FixedDateFormat} and {@link FastDateFormat} only support
37 * millisecond precision. If the pattern asks for a higher precision,
38 * {@link DateTimeFormatter} will be employed, which is significantly slower.
39 */
40 public final class InstantFormatter {
41
42 /**
43 * The list of formatter factories in decreasing efficiency order.
44 */
45 private static final FormatterFactory[] FORMATTER_FACTORIES = {
46 new Log4jFixedFormatterFactory(),
47 new Log4jFastFormatterFactory(),
48 new JavaDateTimeFormatterFactory()
49 };
50
51 private final Formatter formatter;
52
53 private InstantFormatter(final Builder builder) {
54 this.formatter = Arrays
55 .stream(FORMATTER_FACTORIES)
56 .map(formatterFactory -> formatterFactory.createIfSupported(
57 builder.getPattern(),
58 builder.getLocale(),
59 builder.getTimeZone()))
60 .filter(Objects::nonNull)
61 .findFirst()
62 .orElseThrow(() -> new AssertionError("could not find a matching formatter"));
63 }
64
65 public String format(final Instant instant) {
66 Objects.requireNonNull(instant, "instant");
67 final StringBuilder stringBuilder = new StringBuilder();
68 formatter.format(instant, stringBuilder);
69 return stringBuilder.toString();
70 }
71
72 public void format(final Instant instant, final StringBuilder stringBuilder) {
73 Objects.requireNonNull(instant, "instant");
74 Objects.requireNonNull(stringBuilder, "stringBuilder");
75 formatter.format(instant, stringBuilder);
76 }
77
78 /**
79 * Checks if the given {@link Instant}s are equal from the point of view of
80 * the employed formatter.
81 * <p>
82 * This method should be preferred over {@link Instant#equals(Object)}. For
83 * instance, {@link FixedDateFormat} and {@link FastDateFormat} discard
84 * nanoseconds, hence, from their point of view, two different
85 * {@link Instant}s are equal if they match up to millisecond precision.
86 */
87 public boolean isInstantMatching(final Instant instant1, final Instant instant2) {
88 return formatter.isInstantMatching(instant1, instant2);
89 }
90
91 public Class<?> getInternalImplementationClass() {
92 return formatter.getInternalImplementationClass();
93 }
94
95 public static Builder newBuilder() {
96 return new Builder();
97 }
98
99 public static final class Builder {
100
101 private String pattern;
102
103 private Locale locale = Locale.getDefault();
104
105 private TimeZone timeZone = TimeZone.getDefault();
106
107 private Builder() {}
108
109 public String getPattern() {
110 return pattern;
111 }
112
113 public Builder setPattern(final String pattern) {
114 this.pattern = pattern;
115 return this;
116 }
117
118 public Locale getLocale() {
119 return locale;
120 }
121
122 public Builder setLocale(final Locale locale) {
123 this.locale = locale;
124 return this;
125 }
126
127 public TimeZone getTimeZone() {
128 return timeZone;
129 }
130
131 public Builder setTimeZone(final TimeZone timeZone) {
132 this.timeZone = timeZone;
133 return this;
134 }
135
136 public InstantFormatter build() {
137 validate();
138 return new InstantFormatter(this);
139 }
140
141 private void validate() {
142 if (Strings.isBlank(pattern)) {
143 throw new IllegalArgumentException("blank pattern");
144 }
145 Objects.requireNonNull(locale, "locale");
146 Objects.requireNonNull(timeZone, "timeZone");
147 }
148
149 }
150
151 private interface FormatterFactory {
152
153 Formatter createIfSupported(
154 String pattern,
155 Locale locale,
156 TimeZone timeZone);
157
158 }
159
160 private interface Formatter {
161
162 Class<?> getInternalImplementationClass();
163
164 void format(Instant instant, StringBuilder stringBuilder);
165
166 boolean isInstantMatching(Instant instant1, Instant instant2);
167
168 }
169
170 private static final class JavaDateTimeFormatterFactory implements FormatterFactory {
171
172 @Override
173 public Formatter createIfSupported(
174 final String pattern,
175 final Locale locale,
176 final TimeZone timeZone) {
177 return new JavaDateTimeFormatter(pattern, locale, timeZone);
178 }
179
180 }
181
182 private static final class JavaDateTimeFormatter implements Formatter {
183
184 private final DateTimeFormatter formatter;
185
186 private final MutableInstant mutableInstant;
187
188 private JavaDateTimeFormatter(
189 final String pattern,
190 final Locale locale,
191 final TimeZone timeZone) {
192 this.formatter = DateTimeFormatter
193 .ofPattern(pattern)
194 .withLocale(locale)
195 .withZone(timeZone.toZoneId());
196 this.mutableInstant = new MutableInstant();
197 }
198
199 @Override
200 public Class<?> getInternalImplementationClass() {
201 return DateTimeFormatter.class;
202 }
203
204 @Override
205 public void format(
206 final Instant instant,
207 final StringBuilder stringBuilder) {
208 if (instant instanceof MutableInstant) {
209 formatMutableInstant((MutableInstant) instant, stringBuilder);
210 } else {
211 formatInstant(instant, stringBuilder);
212 }
213 }
214
215 private void formatMutableInstant(
216 final MutableInstant instant,
217 final StringBuilder stringBuilder) {
218 formatter.formatTo(instant, stringBuilder);
219 }
220
221 private void formatInstant(
222 final Instant instant,
223 final StringBuilder stringBuilder) {
224 mutableInstant.initFrom(instant);
225 formatMutableInstant(mutableInstant, stringBuilder);
226 }
227
228 @Override
229 public boolean isInstantMatching(final Instant instant1, final Instant instant2) {
230 return instant1.getEpochSecond() == instant2.getEpochSecond() &&
231 instant1.getNanoOfSecond() == instant2.getNanoOfSecond();
232 }
233
234 }
235
236 private static final class Log4jFastFormatterFactory implements FormatterFactory {
237
238 @Override
239 public Formatter createIfSupported(
240 final String pattern,
241 final Locale locale,
242 final TimeZone timeZone) {
243 final Log4jFastFormatter formatter =
244 new Log4jFastFormatter(pattern, locale, timeZone);
245 final boolean patternSupported =
246 patternSupported(pattern, locale, timeZone, formatter);
247 return patternSupported ? formatter : null;
248 }
249
250 }
251
252 private static final class Log4jFastFormatter implements Formatter {
253
254 private final FastDateFormat formatter;
255
256 private final Calendar calendar;
257
258 private Log4jFastFormatter(
259 final String pattern,
260 final Locale locale,
261 final TimeZone timeZone) {
262 this.formatter = FastDateFormat.getInstance(pattern, timeZone, locale);
263 this.calendar = Calendar.getInstance(timeZone, locale);
264 }
265
266 @Override
267 public Class<?> getInternalImplementationClass() {
268 return FastDateFormat.class;
269 }
270
271 @Override
272 public void format(
273 final Instant instant,
274 final StringBuilder stringBuilder) {
275 calendar.setTimeInMillis(instant.getEpochMillisecond());
276 formatter.format(calendar, stringBuilder);
277 }
278
279 @Override
280 public boolean isInstantMatching(final Instant instant1, final Instant instant2) {
281 return instant1.getEpochMillisecond() == instant2.getEpochMillisecond();
282 }
283
284 }
285
286 private static final class Log4jFixedFormatterFactory implements FormatterFactory {
287
288 @Override
289 public Formatter createIfSupported(
290 final String pattern,
291 final Locale locale,
292 final TimeZone timeZone) {
293 final FixedDateFormat internalFormatter =
294 FixedDateFormat.createIfSupported(pattern, timeZone.getID());
295 if (internalFormatter == null) {
296 return null;
297 }
298 final Log4jFixedFormatter formatter =
299 new Log4jFixedFormatter(internalFormatter);
300 final boolean patternSupported =
301 patternSupported(pattern, locale, timeZone, formatter);
302 return patternSupported ? formatter : null;
303 }
304
305 }
306
307 private static final class Log4jFixedFormatter implements Formatter {
308
309 private final FixedDateFormat formatter;
310
311 private final char[] buffer;
312
313 private Log4jFixedFormatter(final FixedDateFormat formatter) {
314 this.formatter = formatter;
315 this.buffer = new char[formatter.getFormat().length()];
316 }
317
318 @Override
319 public Class<?> getInternalImplementationClass() {
320 return FixedDateFormat.class;
321 }
322
323 @Override
324 public void format(
325 final Instant instant,
326 final StringBuilder stringBuilder) {
327 final int length = formatter.formatInstant(instant, buffer, 0);
328 stringBuilder.append(buffer, 0, length);
329 }
330
331 @Override
332 public boolean isInstantMatching(final Instant instant1, final Instant instant2) {
333 return formatter.isEquivalent(
334 instant1.getEpochSecond(),
335 instant1.getNanoOfSecond(),
336 instant2.getEpochSecond(),
337 instant2.getNanoOfSecond());
338 }
339
340 }
341
342 /**
343 * Checks if the provided formatter output matches with the one generated by
344 * {@link DateTimeFormatter}.
345 */
346 private static boolean patternSupported(
347 final String pattern,
348 final Locale locale,
349 final TimeZone timeZone,
350 final Formatter formatter) {
351 final DateTimeFormatter javaFormatter = DateTimeFormatter
352 .ofPattern(pattern)
353 .withLocale(locale)
354 .withZone(timeZone.toZoneId());
355 final MutableInstant instant = new MutableInstant();
356 instant.initFromEpochSecond(
357 // 2021-05-17 21:41:10
358 1621280470,
359 // Using the highest nanosecond precision possible to
360 // differentiate formatters only supporting millisecond
361 // precision.
362 123_456_789);
363 final String expectedFormat = javaFormatter.format(instant);
364 final StringBuilder stringBuilder = new StringBuilder();
365 formatter.format(instant, stringBuilder);
366 final String actualFormat = stringBuilder.toString();
367 return expectedFormat.equals(actualFormat);
368 }
369
370 }
+0
-451
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonReader.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.logging.log4j.layout.template.json.util;
17
18 import java.math.BigDecimal;
19 import java.math.BigInteger;
20 import java.text.CharacterIterator;
21 import java.text.StringCharacterIterator;
22 import java.util.LinkedHashMap;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27
28 /**
29 * A simple JSON parser mapping tokens to basic Java types.
30 * <p>
31 * The type mapping is as follows:
32 * <p>
33 * <ul>
34 * <li><tt>object</tt>s are mapped to {@link LinkedHashMap LinkedHashMap&lt;String,Object&gt;}
35 * <li><tt>array</tt>s are mapped to {@link LinkedList}
36 * <li><tt>string</tt>s are mapped to {@link String} with proper Unicode and
37 * escape character conversion
38 * <li><tt>true</tt>, <tt>false</tt>, and <tt>null</tt> are mapped to their Java
39 * counterparts
40 * <li>floating point <tt>number</tt>s are mapped to {@link BigDecimal}
41 * <li>integral <tt>number</tt>s are mapped to either primitive types
42 * (<tt>int</tt>, <tt>long</tt>) or {@link BigInteger}
43 * </ul>
44 * <p>
45 * This code is heavily influenced by the reader of
46 * <a href="https://github.com/bolerio/mjson/blob/e7a4da2daa6e17a63ec057948bc30818e8f44686/src/java/mjson/Json.java#L2684">mjson</a>.
47 */
48 public final class JsonReader {
49
50 private enum Delimiter {
51
52 OBJECT_START("{"),
53
54 OBJECT_END("}"),
55
56 ARRAY_START("["),
57
58 ARRAY_END("]"),
59
60 COLON(":"),
61
62 COMMA(",");
63
64 private final String string;
65
66 Delimiter(final String string) {
67 this.string = string;
68 }
69
70 private static boolean exists(final Object token) {
71 for (Delimiter delimiter : values()) {
72 if (delimiter.string.equals(token)) {
73 return true;
74 }
75 }
76 return false;
77 }
78
79 }
80
81 private CharacterIterator it;
82
83 private int readCharIndex = -1;
84
85 private char readChar;
86
87 private int readTokenStartIndex = -1;
88
89 private Object readToken;
90
91 private final StringBuilder buffer;
92
93 private JsonReader() {
94 this.buffer = new StringBuilder();
95 }
96
97 public static Object read(final String json) {
98 Objects.requireNonNull(json, "json");
99 final JsonReader reader = new JsonReader();
100 return reader.read(new StringCharacterIterator(json));
101 }
102
103 private Object read(final CharacterIterator ci) {
104 it = ci;
105 readCharIndex = 0;
106 readChar = it.first();
107 final Object token = readToken();
108 if (token instanceof Delimiter) {
109 final String message = String.format(
110 "was not expecting %s at index %d",
111 readToken, readTokenStartIndex);
112 throw new IllegalArgumentException(message);
113 }
114 skipWhiteSpace();
115 if (it.getIndex() != it.getEndIndex()) {
116 final String message = String.format(
117 "was not expecting input at index %d: %c",
118 readCharIndex, readChar);
119 throw new IllegalArgumentException(message);
120 }
121 return token;
122 }
123
124 private Object readToken() {
125 skipWhiteSpace();
126 readTokenStartIndex = readCharIndex;
127 final char prevChar = readChar;
128 readChar();
129 switch (prevChar) {
130
131 case '"':
132 readToken = readString();
133 break;
134
135 case '[':
136 readToken = readArray();
137 break;
138
139 case ']':
140 readToken = Delimiter.ARRAY_END;
141 break;
142
143 case ',':
144 readToken = Delimiter.COMMA;
145 break;
146
147 case '{':
148 readToken = readObject();
149 break;
150
151 case '}':
152 readToken = Delimiter.OBJECT_END;
153 break;
154
155 case ':':
156 readToken = Delimiter.COLON;
157 break;
158
159 case 't':
160 readToken = readTrue();
161 break;
162
163 case 'f':
164 readToken = readFalse();
165 break;
166
167 case 'n':
168 readToken = readNull();
169 break;
170
171 default:
172 unreadChar();
173 if (Character.isDigit(readChar) || readChar == '-') {
174 readToken = readNumber();
175 } else {
176 String message = String.format(
177 "invalid character at index %d: %c",
178 readCharIndex, readChar);
179 throw new IllegalArgumentException(message);
180 }
181
182 }
183 return readToken;
184 }
185
186 private void skipWhiteSpace() {
187 do {
188 if (!Character.isWhitespace(readChar)) {
189 break;
190 }
191 } while (readChar() != CharacterIterator.DONE);
192 }
193
194 private char readChar() {
195 if (it.getIndex() == it.getEndIndex()) {
196 throw new IllegalArgumentException("premature end of input");
197 }
198 readChar = it.next();
199 readCharIndex = it.getIndex();
200 return readChar;
201 }
202
203 private void unreadChar() {
204 readChar = it.previous();
205 readCharIndex = it.getIndex();
206 }
207
208 private String readString() {
209 buffer.setLength(0);
210 while (readChar != '"') {
211 if (readChar == '\\') {
212 readChar();
213 if (readChar == 'u') {
214 final char unicodeChar = readUnicodeChar();
215 bufferChar(unicodeChar);
216 } else {
217 switch (readChar) {
218 case '"':
219 case '\\':
220 bufferReadChar();
221 break;
222 case 'b':
223 bufferChar('\b');
224 break;
225 case 'f':
226 bufferChar('\f');
227 break;
228 case 'n':
229 bufferChar('\n');
230 break;
231 case 'r':
232 bufferChar('\r');
233 break;
234 case 't':
235 bufferChar('\t');
236 break;
237 default: {
238 final String message = String.format(
239 "was expecting an escape character at index %d: %c",
240 readCharIndex, readChar);
241 throw new IllegalArgumentException(message);
242 }
243 }
244 }
245 } else {
246 bufferReadChar();
247 }
248 }
249 readChar();
250 return buffer.toString();
251 }
252
253 private void bufferReadChar() {
254 bufferChar(readChar);
255 }
256
257 private void bufferChar(final char c) {
258 buffer.append(c);
259 readChar();
260 }
261
262 private char readUnicodeChar() {
263 int value = 0;
264 for (int i = 0; i < 4; i++) {
265 readChar();
266 if (readChar >= '0' && readChar <= '9') {
267 value = (value << 4) + readChar - '0';
268 } else if (readChar >= 'a' && readChar <= 'f') {
269 value = (value << 4) + (readChar - 'a') + 10;
270 } else if (readChar >= 'A' && readChar <= 'F') {
271 value = (value << 4) + (readChar - 'A') + 10;
272 } else {
273 final String message = String.format(
274 "was expecting a unicode character at index %d: %c",
275 readCharIndex, readChar);
276 throw new IllegalArgumentException(message);
277 }
278 }
279 return (char) value;
280 }
281
282 private Map<String, Object> readObject() {
283 final Map<String, Object> object = new LinkedHashMap<>();
284 String key = readObjectKey();
285 while (readToken != Delimiter.OBJECT_END) {
286 expectDelimiter(Delimiter.COLON, readToken());
287 if (readToken != Delimiter.OBJECT_END) {
288 Object value = readToken();
289 object.put(key, value);
290 if (readToken() == Delimiter.COMMA) {
291 key = readObjectKey();
292 if (key == null || Delimiter.exists(key)) {
293 String message = String.format(
294 "was expecting an object key at index %d: %s",
295 readTokenStartIndex, readToken);
296 throw new IllegalArgumentException(message);
297 }
298 } else {
299 expectDelimiter(Delimiter.OBJECT_END, readToken);
300 }
301 }
302 }
303 return object;
304 }
305
306 private List<Object> readArray() {
307 @SuppressWarnings("JdkObsolete")
308 final List<Object> array = new LinkedList<>();
309 readToken();
310 while (readToken != Delimiter.ARRAY_END) {
311 if (readToken instanceof Delimiter) {
312 final String message = String.format(
313 "was expecting an array element at index %d: %s",
314 readTokenStartIndex, readToken);
315 throw new IllegalArgumentException(message);
316 }
317 array.add(readToken);
318 if (readToken() == Delimiter.COMMA) {
319 if (readToken() == Delimiter.ARRAY_END) {
320 final String message = String.format(
321 "was expecting an array element at index %d: %s",
322 readTokenStartIndex, readToken);
323 throw new IllegalArgumentException(message);
324 }
325 } else {
326 expectDelimiter(Delimiter.ARRAY_END, readToken);
327 }
328 }
329 return array;
330 }
331
332 private String readObjectKey() {
333 readToken();
334 if (readToken == Delimiter.OBJECT_END) {
335 return null;
336 } else if (readToken instanceof String) {
337 return (String) readToken;
338 } else {
339 final String message = String.format(
340 "was expecting an object key at index %d: %s",
341 readTokenStartIndex, readToken);
342 throw new IllegalArgumentException(message);
343 }
344 }
345
346 private void expectDelimiter(
347 final Delimiter expectedDelimiter,
348 final Object actualToken) {
349 if (!expectedDelimiter.equals(actualToken)) {
350 String message = String.format(
351 "was expecting %s at index %d: %s",
352 expectedDelimiter, readTokenStartIndex, actualToken);
353 throw new IllegalArgumentException(message);
354 }
355 }
356
357 private boolean readTrue() {
358 if (readChar != 'r' || readChar() != 'u' || readChar() != 'e') {
359 String message = String.format(
360 "was expecting keyword 'true' at index %d: %s",
361 readCharIndex, readChar);
362 throw new IllegalArgumentException(message);
363 }
364 readChar();
365 return true;
366 }
367
368 private boolean readFalse() {
369 if (readChar != 'a' || readChar() != 'l' || readChar() != 's' || readChar() != 'e') {
370 String message = String.format(
371 "was expecting keyword 'false' at index %d: %s",
372 readCharIndex, readChar);
373 throw new IllegalArgumentException(message);
374 }
375 readChar();
376 return false;
377 }
378
379 private Object readNull() {
380 if (readChar != 'u' || readChar() != 'l' || readChar() != 'l') {
381 String message = String.format(
382 "was expecting keyword 'null' at index %d: %s",
383 readCharIndex, readChar);
384 throw new IllegalArgumentException(message);
385 }
386 readChar();
387 return null;
388 }
389
390 private Number readNumber() {
391
392 // Read sign.
393 buffer.setLength(0);
394 if (readChar == '-') {
395 bufferReadChar();
396 }
397
398 // Read fraction.
399 boolean floatingPoint = false;
400 bufferDigits();
401 if (readChar == '.') {
402 bufferReadChar();
403 bufferDigits();
404 floatingPoint = true;
405 }
406
407 // Read exponent.
408 if (readChar == 'e' || readChar == 'E') {
409 floatingPoint = true;
410 bufferReadChar();
411 if (readChar == '+' || readChar == '-') {
412 bufferReadChar();
413 }
414 bufferDigits();
415 }
416
417 // Convert the read number.
418 final String string = buffer.toString();
419 if (floatingPoint) {
420 return new BigDecimal(string);
421 } else {
422 final BigInteger bigInteger = new BigInteger(string);
423 try {
424 return bigInteger.intValueExact();
425 } catch (ArithmeticException ignoredIntOverflow) {
426 try {
427 return bigInteger.longValueExact();
428 } catch (ArithmeticException ignoredLongOverflow) {
429 return bigInteger;
430 }
431 }
432 }
433
434 }
435
436 private void bufferDigits() {
437 boolean found = false;
438 while (Character.isDigit(readChar)) {
439 found = true;
440 bufferReadChar();
441 }
442 if (!found) {
443 final String message = String.format(
444 "was expecting a digit at index %d: %c",
445 readCharIndex, readChar);
446 throw new IllegalArgumentException(message);
447 }
448 }
449
450 }
+0
-919
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.util.BiConsumer;
19 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
20 import org.apache.logging.log4j.util.StringBuilderFormattable;
21 import org.apache.logging.log4j.util.StringMap;
22
23 import java.math.BigDecimal;
24 import java.math.BigInteger;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Objects;
29
30 /**
31 * A simple JSON writer with support for common Java data types.
32 * <p>
33 * The following types have specific handlers:
34 * <p>
35 * <ul>
36 * <li> <tt>null</tt> input
37 * <li>{@link Map}, {@link IndexedReadOnlyStringMap}, {@link StringMap}
38 * <li>{@link Collection} and {@link List}
39 * <li>{@link Number} ({@link BigDecimal}, {@link BigInteger}, {@link Float},
40 * {@link Double}, {@link Byte}, {@link Short}, {@link Integer}, and
41 * {@link Long})
42 * <li>{@link Boolean}
43 * <li>{@link StringBuilderFormattable}
44 * <li>arrays of primitive types
45 * <tt>char/boolean/byte/short/int/long/float/double</tt> and {@link Object}
46 * <li>{@link CharSequence} and <tt>char[]</tt> with necessary escaping
47 * </ul>
48 * <p>
49 * JSON standard quoting routines are borrowed from
50 * <a href="https://github.com/FasterXML/jackson-core">Jackson</a>.
51 * <p>
52 * Note that this class provides no protection against recursive collections,
53 * e.g., an array where one or more elements reference to the array itself.
54 */
55 public final class JsonWriter implements AutoCloseable, Cloneable {
56
57 private final static char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
58
59 /**
60 * Lookup table used for determining which output characters in 7-bit ASCII
61 * range (i.e., first 128 Unicode code points, single-byte UTF-8 characters)
62 * need to be quoted.
63 * <p>
64 * Value of 0 means "no escaping"; other positive values, that value is
65 * character to use after backslash; and negative values, that generic
66 * (backslash - u) escaping is to be used.
67 */
68 private final static int[] ESC_CODES;
69 static {
70 int[] table = new int[128];
71 // Control chars need generic escape sequence
72 for (int i = 0; i < 32; ++i) {
73 // 04-Mar-2011, tatu: Used to use "-(i + 1)", replaced with constant
74 table[i] = -1;
75 }
76 // Others (and some within that range too) have explicit shorter sequences
77 table['"'] = '"';
78 table['\\'] = '\\';
79 // Escaping of slash is optional, so let's not add it
80 table[0x08] = 'b';
81 table[0x09] = 't';
82 table[0x0C] = 'f';
83 table[0x0A] = 'n';
84 table[0x0D] = 'r';
85 ESC_CODES = table;
86 }
87
88 private final char[] quoteBuffer;
89
90 private final StringBuilder stringBuilder;
91
92 private final StringBuilder formattableBuffer;
93
94 private final int maxStringLength;
95
96 private final String truncatedStringSuffix;
97
98 private final String quotedTruncatedStringSuffix;
99
100 private JsonWriter(final Builder builder) {
101 this.quoteBuffer = new char[]{'\\', '-', '0', '0', '-', '-'};
102 this.stringBuilder = new StringBuilder(builder.maxStringLength);
103 this.formattableBuffer = new StringBuilder(builder.maxStringLength);
104 this.maxStringLength = builder.maxStringLength;
105 this.truncatedStringSuffix = builder.truncatedStringSuffix;
106 this.quotedTruncatedStringSuffix = quoteString(builder.truncatedStringSuffix);
107 }
108
109 private String quoteString(final String string) {
110 final int startIndex = stringBuilder.length();
111 quoteString(string, 0, string.length());
112 final StringBuilder quotedStringBuilder = new StringBuilder();
113 quotedStringBuilder.append(stringBuilder, startIndex, stringBuilder.length());
114 final String quotedString = quotedStringBuilder.toString();
115 stringBuilder.setLength(startIndex);
116 return quotedString;
117 }
118
119 public String use(final Runnable runnable) {
120 Objects.requireNonNull(runnable, "runnable");
121 final int startIndex = stringBuilder.length();
122 try {
123 runnable.run();
124 final StringBuilder sliceStringBuilder = new StringBuilder();
125 sliceStringBuilder.append(stringBuilder, startIndex, stringBuilder.length());
126 return sliceStringBuilder.toString();
127 } finally {
128 trimStringBuilder(stringBuilder, startIndex);
129 }
130 }
131
132 public StringBuilder getStringBuilder() {
133 return stringBuilder;
134 }
135
136 public int getMaxStringLength() {
137 return maxStringLength;
138 }
139
140 public String getTruncatedStringSuffix() {
141 return truncatedStringSuffix;
142 }
143
144 public void writeValue(final Object value) {
145
146 // null
147 if (value == null) {
148 writeNull();
149 }
150
151 // map
152 else if (value instanceof IndexedReadOnlyStringMap) {
153 final IndexedReadOnlyStringMap map = (IndexedReadOnlyStringMap) value;
154 writeObject(map);
155 } else if (value instanceof StringMap) {
156 final StringMap map = (StringMap) value;
157 writeObject(map);
158 } else if (value instanceof Map) {
159 @SuppressWarnings("unchecked")
160 final Map<String, Object> map = (Map<String, Object>) value;
161 writeObject(map);
162 }
163
164 // list & collection
165 else if (value instanceof List) {
166 @SuppressWarnings("unchecked")
167 final List<Object> list = (List<Object>) value;
168 writeArray(list);
169 } else if (value instanceof Collection) {
170 @SuppressWarnings("unchecked")
171 final Collection<Object> collection = (Collection<Object>) value;
172 writeArray(collection);
173 }
174
175 // number & boolean
176 else if (value instanceof Number) {
177 final Number number = (Number) value;
178 writeNumber(number);
179 } else if (value instanceof Boolean) {
180 final boolean booleanValue = (boolean) value;
181 writeBoolean(booleanValue);
182 }
183
184 // formattable
185 else if (value instanceof StringBuilderFormattable) {
186 final StringBuilderFormattable formattable = (StringBuilderFormattable) value;
187 writeString(formattable);
188 }
189
190 // arrays
191 else if (value instanceof char[]) {
192 final char[] charValues = (char[]) value;
193 writeArray(charValues);
194 } else if (value instanceof boolean[]) {
195 final boolean[] booleanValues = (boolean[]) value;
196 writeArray(booleanValues);
197 } else if (value instanceof byte[]) {
198 final byte[] byteValues = (byte[]) value;
199 writeArray(byteValues);
200 } else if (value instanceof short[]) {
201 final short[] shortValues = (short[]) value;
202 writeArray(shortValues);
203 } else if (value instanceof int[]) {
204 final int[] intValues = (int[]) value;
205 writeArray(intValues);
206 } else if (value instanceof long[]) {
207 final long[] longValues = (long[]) value;
208 writeArray(longValues);
209 } else if (value instanceof float[]) {
210 final float[] floatValues = (float[]) value;
211 writeArray(floatValues);
212 } else if (value instanceof double[]) {
213 final double[] doubleValues = (double[]) value;
214 writeArray(doubleValues);
215 } else if (value instanceof Object[]) {
216 final Object[] values = (Object[]) value;
217 writeArray(values);
218 }
219
220 // string
221 else {
222 final String stringValue = value instanceof String
223 ? (String) value
224 : String.valueOf(value);
225 writeString(stringValue);
226 }
227
228 }
229
230 public void writeObject(final StringMap map) {
231 if (map == null) {
232 writeNull();
233 } else {
234 writeObjectStart();
235 final boolean[] firstEntry = {true};
236 map.forEach((final String key, final Object value) -> {
237 if (key == null) {
238 throw new IllegalArgumentException("null keys are not allowed");
239 }
240 if (firstEntry[0]) {
241 firstEntry[0] = false;
242 } else {
243 writeSeparator();
244 }
245 writeObjectKey(key);
246 writeValue(value);
247 });
248 writeObjectEnd();
249 }
250 }
251
252 public void writeObject(final IndexedReadOnlyStringMap map) {
253 if (map == null) {
254 writeNull();
255 } else {
256 writeObjectStart();
257 for (int entryIndex = 0; entryIndex < map.size(); entryIndex++) {
258 final String key = map.getKeyAt(entryIndex);
259 final Object value = map.getValueAt(entryIndex);
260 if (entryIndex > 0) {
261 writeSeparator();
262 }
263 writeObjectKey(key);
264 writeValue(value);
265 }
266 writeObjectEnd();
267 }
268 }
269
270 public void writeObject(final Map<String, Object> map) {
271 if (map == null) {
272 writeNull();
273 } else {
274 writeObjectStart();
275 final boolean[] firstEntry = {true};
276 map.forEach((final String key, final Object value) -> {
277 if (key == null) {
278 throw new IllegalArgumentException("null keys are not allowed");
279 }
280 if (firstEntry[0]) {
281 firstEntry[0] = false;
282 } else {
283 writeSeparator();
284 }
285 writeObjectKey(key);
286 writeValue(value);
287 });
288 writeObjectEnd();
289 }
290 }
291
292 public void writeObjectStart() {
293 stringBuilder.append('{');
294 }
295
296 public void writeObjectEnd() {
297 stringBuilder.append('}');
298 }
299
300 public void writeObjectKey(final CharSequence key) {
301 writeString(key);
302 stringBuilder.append(':');
303 }
304
305 public void writeArray(final List<Object> items) {
306 if (items == null) {
307 writeNull();
308 } else {
309 writeArrayStart();
310 for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) {
311 if (itemIndex > 0) {
312 writeSeparator();
313 }
314 final Object item = items.get(itemIndex);
315 writeValue(item);
316 }
317 writeArrayEnd();
318 }
319 }
320
321 public void writeArray(final Collection<Object> items) {
322 if (items == null) {
323 writeNull();
324 } else {
325 writeArrayStart();
326 final boolean[] firstItem = {true};
327 items.forEach((final Object item) -> {
328 if (firstItem[0]) {
329 firstItem[0] = false;
330 } else {
331 writeSeparator();
332 }
333 writeValue(item);
334 });
335 writeArrayEnd();
336 }
337 }
338
339 public void writeArray(final char[] items) {
340 if (items == null) {
341 writeNull();
342 } else {
343 writeArrayStart();
344 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
345 if (itemIndex > 0) {
346 writeSeparator();
347 }
348 stringBuilder.append('"');
349 quoteString(items, itemIndex, 1);
350 stringBuilder.append('"');
351 }
352 writeArrayEnd();
353 }
354 }
355
356 public void writeArray(final boolean[] items) {
357 if (items == null) {
358 writeNull();
359 } else {
360 writeArrayStart();
361 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
362 if (itemIndex > 0) {
363 writeSeparator();
364 }
365 final boolean item = items[itemIndex];
366 writeBoolean(item);
367 }
368 writeArrayEnd();
369 }
370 }
371
372 public void writeArray(final byte[] items) {
373 if (items == null) {
374 writeNull();
375 } else {
376 writeArrayStart();
377 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
378 if (itemIndex > 0) {
379 writeSeparator();
380 }
381 final byte item = items[itemIndex];
382 writeNumber(item);
383 }
384 writeArrayEnd();
385 }
386 }
387
388 public void writeArray(final short[] items) {
389 if (items == null) {
390 writeNull();
391 } else {
392 writeArrayStart();
393 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
394 if (itemIndex > 0) {
395 writeSeparator();
396 }
397 final short item = items[itemIndex];
398 writeNumber(item);
399 }
400 writeArrayEnd();
401 }
402 }
403
404 public void writeArray(final int[] items) {
405 if (items == null) {
406 writeNull();
407 } else {
408 writeArrayStart();
409 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
410 if (itemIndex > 0) {
411 writeSeparator();
412 }
413 final int item = items[itemIndex];
414 writeNumber(item);
415 }
416 writeArrayEnd();
417 }
418 }
419
420 public void writeArray(final long[] items) {
421 if (items == null) {
422 writeNull();
423 } else {
424 writeArrayStart();
425 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
426 if (itemIndex > 0) {
427 writeSeparator();
428 }
429 final long item = items[itemIndex];
430 writeNumber(item);
431 }
432 writeArrayEnd();
433 }
434 }
435
436 public void writeArray(final float[] items) {
437 if (items == null) {
438 writeNull();
439 } else {
440 writeArrayStart();
441 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
442 if (itemIndex > 0) {
443 writeSeparator();
444 }
445 final float item = items[itemIndex];
446 writeNumber(item);
447 }
448 writeArrayEnd();
449 }
450 }
451
452 public void writeArray(final double[] items) {
453 if (items == null) {
454 writeNull();
455 } else {
456 writeArrayStart();
457 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
458 if (itemIndex > 0) {
459 writeSeparator();
460 }
461 final double item = items[itemIndex];
462 writeNumber(item);
463 }
464 writeArrayEnd();
465 }
466 }
467
468 public void writeArray(final Object[] items) {
469 if (items == null) {
470 writeNull();
471 } else {
472 writeArrayStart();
473 for (int itemIndex = 0; itemIndex < items.length; itemIndex++) {
474 if (itemIndex > 0) {
475 writeSeparator();
476 }
477 final Object item = items[itemIndex];
478 writeValue(item);
479 }
480 writeArrayEnd();
481 }
482 }
483
484 public void writeArrayStart() {
485 stringBuilder.append('[');
486 }
487
488 public void writeArrayEnd() {
489 stringBuilder.append(']');
490 }
491
492 public void writeSeparator() {
493 stringBuilder.append(',');
494 }
495
496 public <S> void writeString(
497 final BiConsumer<StringBuilder, S> emitter,
498 final S state) {
499 Objects.requireNonNull(emitter, "emitter");
500 stringBuilder.append('"');
501 try {
502 emitter.accept(formattableBuffer, state);
503 final int length = formattableBuffer.length();
504 // Handle max. string length complying input.
505 if (length <= maxStringLength) {
506 quoteString(formattableBuffer, 0, length);
507 }
508 // Handle max. string length violating input.
509 else {
510 quoteString(formattableBuffer, 0, maxStringLength);
511 stringBuilder.append(quotedTruncatedStringSuffix);
512 }
513 stringBuilder.append('"');
514 } finally {
515 trimStringBuilder(formattableBuffer, 0);
516 }
517 }
518
519 public void writeString(final StringBuilderFormattable formattable) {
520 if (formattable == null) {
521 writeNull();
522 } else {
523 stringBuilder.append('"');
524 try {
525 formattable.formatTo(formattableBuffer);
526 final int length = formattableBuffer.length();
527 // Handle max. string length complying input.
528 if (length <= maxStringLength) {
529 quoteString(formattableBuffer, 0, length);
530 }
531 // Handle max. string length violating input.
532 else {
533 quoteString(formattableBuffer, 0, maxStringLength);
534 stringBuilder.append(quotedTruncatedStringSuffix);
535 }
536 stringBuilder.append('"');
537 } finally {
538 trimStringBuilder(formattableBuffer, 0);
539 }
540 }
541 }
542
543 public void writeString(final CharSequence seq) {
544 if (seq == null) {
545 writeNull();
546 } else {
547 writeString(seq, 0, seq.length());
548 }
549 }
550
551 public void writeString(
552 final CharSequence seq,
553 final int offset,
554 final int length) {
555
556 // Handle null input.
557 if (seq == null) {
558 writeNull();
559 return;
560 }
561
562 // Check arguments.
563 if (offset < 0) {
564 throw new IllegalArgumentException(
565 "was expecting a positive offset: " + offset);
566 }
567 if (length < 0) {
568 throw new IllegalArgumentException(
569 "was expecting a positive length: " + length);
570 }
571
572 stringBuilder.append('"');
573 // Handle max. string length complying input.
574 if (length <= maxStringLength) {
575 quoteString(seq, offset, length);
576 }
577 // Handle max. string length violating input.
578 else {
579 quoteString(seq, offset, maxStringLength);
580 stringBuilder.append(quotedTruncatedStringSuffix);
581 }
582 stringBuilder.append('"');
583
584 }
585
586 /**
587 * Quote text contents using JSON standard quoting.
588 */
589 private void quoteString(
590 final CharSequence seq,
591 final int offset,
592 final int length) {
593 final int surrogateCorrection =
594 length > 0 && Character.isHighSurrogate(seq.charAt(offset + length - 1))
595 ? -1
596 : 0;
597 final int limit = offset + length + surrogateCorrection;
598 int i = offset;
599 outer:
600 while (i < limit) {
601 while (true) {
602 final char c = seq.charAt(i);
603 if (c < ESC_CODES.length && ESC_CODES[c] != 0) {
604 break;
605 }
606 stringBuilder.append(c);
607 if (++i >= limit) {
608 break outer;
609 }
610 }
611 final char d = seq.charAt(i++);
612 final int escCode = ESC_CODES[d];
613 final int quoteBufferLength = escCode < 0
614 ? quoteNumeric(d)
615 : quoteNamed(escCode);
616 stringBuilder.append(quoteBuffer, 0, quoteBufferLength);
617 }
618 }
619
620 public void writeString(final char[] buffer) {
621 if (buffer == null) {
622 writeNull();
623 } else {
624 writeString(buffer, 0, buffer.length);
625 }
626 }
627
628 public void writeString(
629 final char[] buffer,
630 final int offset,
631 final int length) {
632
633 // Handle null input.
634 if (buffer == null) {
635 writeNull();
636 return;
637 }
638
639 // Check arguments.
640 if (offset < 0) {
641 throw new IllegalArgumentException(
642 "was expecting a positive offset: " + offset);
643 }
644 if (length < 0) {
645 throw new IllegalArgumentException(
646 "was expecting a positive length: " + length);
647 }
648
649 stringBuilder.append('"');
650 // Handle max. string length complying input.
651 if (length <= maxStringLength) {
652 quoteString(buffer, offset, length);
653 }
654 // Handle max. string length violating input.
655 else {
656 quoteString(buffer, offset, maxStringLength);
657 stringBuilder.append(quotedTruncatedStringSuffix);
658 }
659 stringBuilder.append('"');
660
661 }
662
663 /**
664 * Quote text contents using JSON standard quoting.
665 */
666 private void quoteString(
667 final char[] buffer,
668 final int offset,
669 final int length) {
670 final int surrogateCorrection =
671 length > 0 && Character.isHighSurrogate(buffer[offset + length - 1])
672 ? -1
673 : 0;
674 final int limit = offset + length + surrogateCorrection;
675 int i = offset;
676 outer:
677 while (i < limit) {
678 while (true) {
679 final char c = buffer[i];
680 if (c < ESC_CODES.length && ESC_CODES[c] != 0) {
681 break;
682 }
683 stringBuilder.append(c);
684 if (++i >= limit) {
685 break outer;
686 }
687 }
688 final char d = buffer[i++];
689 final int escCode = ESC_CODES[d];
690 final int quoteBufferLength = escCode < 0
691 ? quoteNumeric(d)
692 : quoteNamed(escCode);
693 stringBuilder.append(quoteBuffer, 0, quoteBufferLength);
694 }
695 }
696
697 private int quoteNumeric(final int value) {
698 quoteBuffer[1] = 'u';
699 // We know it's a control char, so only the last 2 chars are non-0
700 quoteBuffer[4] = HEX_CHARS[value >> 4];
701 quoteBuffer[5] = HEX_CHARS[value & 0xF];
702 return 6;
703 }
704
705 private int quoteNamed(final int esc) {
706 quoteBuffer[1] = (char) esc;
707 return 2;
708 }
709
710 private void writeNumber(final Number number) {
711 if (number instanceof BigDecimal) {
712 final BigDecimal decimalNumber = (BigDecimal) number;
713 writeNumber(decimalNumber);
714 } else if (number instanceof BigInteger) {
715 final BigInteger integerNumber = (BigInteger) number;
716 writeNumber(integerNumber);
717 } else if (number instanceof Double) {
718 final double doubleNumber = (Double) number;
719 writeNumber(doubleNumber);
720 } else if (number instanceof Float) {
721 final float floatNumber = (float) number;
722 writeNumber(floatNumber);
723 } else if (number instanceof Byte ||
724 number instanceof Short ||
725 number instanceof Integer ||
726 number instanceof Long) {
727 final long longNumber = number.longValue();
728 writeNumber(longNumber);
729 } else {
730 final long longNumber = number.longValue();
731 final double doubleValue = number.doubleValue();
732 if (Double.compare(longNumber, doubleValue) == 0) {
733 writeNumber(longNumber);
734 } else {
735 writeNumber(doubleValue);
736 }
737 }
738 }
739
740 public void writeNumber(final BigDecimal number) {
741 if (number == null) {
742 writeNull();
743 } else {
744 stringBuilder.append(number);
745 }
746 }
747
748 public void writeNumber(final BigInteger number) {
749 if (number == null) {
750 writeNull();
751 } else {
752 stringBuilder.append(number);
753 }
754 }
755
756 public void writeNumber(final float number) {
757 stringBuilder.append(number);
758 }
759
760 public void writeNumber(final double number) {
761 stringBuilder.append(number);
762 }
763
764 public void writeNumber(final short number) {
765 stringBuilder.append(number);
766 }
767
768 public void writeNumber(final int number) {
769 stringBuilder.append(number);
770 }
771
772 public void writeNumber(final long number) {
773 stringBuilder.append(number);
774 }
775
776 public void writeNumber(final long integralPart, final long fractionalPart) {
777 if (fractionalPart < 0) {
778 throw new IllegalArgumentException(
779 "was expecting a positive fraction: " + fractionalPart);
780 }
781 stringBuilder.append(integralPart);
782 if (fractionalPart != 0) {
783 stringBuilder.append('.');
784 stringBuilder.append(fractionalPart);
785 }
786 }
787
788 public void writeBoolean(final boolean value) {
789 writeRawString(value ? "true" : "false");
790 }
791
792 public void writeNull() {
793 writeRawString("null");
794 }
795
796 public void writeRawString(final CharSequence seq) {
797 Objects.requireNonNull(seq, "seq");
798 writeRawString(seq, 0, seq.length());
799 }
800
801 public void writeRawString(
802 final CharSequence seq,
803 final int offset,
804 final int length) {
805
806 // Check arguments.
807 Objects.requireNonNull(seq, "seq");
808 if (offset < 0) {
809 throw new IllegalArgumentException(
810 "was expecting a positive offset: " + offset);
811 }
812 if (length < 0) {
813 throw new IllegalArgumentException(
814 "was expecting a positive length: " + length);
815 }
816
817 // Write characters.
818 final int limit = offset + length;
819 stringBuilder.append(seq, offset, limit);
820
821 }
822
823 public void writeRawString(final char[] buffer) {
824 Objects.requireNonNull(buffer, "buffer");
825 writeRawString(buffer, 0, buffer.length);
826 }
827
828 public void writeRawString(
829 final char[] buffer,
830 final int offset,
831 final int length) {
832
833 // Check arguments.
834 Objects.requireNonNull(buffer, "buffer");
835 if (offset < 0) {
836 throw new IllegalArgumentException(
837 "was expecting a positive offset: " + offset);
838 }
839 if (length < 0) {
840 throw new IllegalArgumentException(
841 "was expecting a positive length: " + length);
842 }
843
844 // Write characters.
845 stringBuilder.append(buffer, offset, length);
846
847 }
848
849 @Override
850 public void close() {
851 trimStringBuilder(stringBuilder, 0);
852 }
853
854 private void trimStringBuilder(final StringBuilder stringBuilder, final int length) {
855 final int trimLength = Math.max(maxStringLength, length);
856 if (stringBuilder.length() > trimLength) {
857 stringBuilder.setLength(trimLength);
858 stringBuilder.trimToSize();
859 }
860 stringBuilder.setLength(length);
861 }
862
863 @Override
864 @SuppressWarnings("MethodDoesntCallSuperMethod")
865 public JsonWriter clone() {
866 final JsonWriter jsonWriter = newBuilder()
867 .setMaxStringLength(maxStringLength)
868 .setTruncatedStringSuffix(truncatedStringSuffix)
869 .build();
870 jsonWriter.stringBuilder.append(stringBuilder);
871 return jsonWriter;
872 }
873
874 public static Builder newBuilder() {
875 return new Builder();
876 }
877
878 public static final class Builder {
879
880 private int maxStringLength;
881
882 private String truncatedStringSuffix;
883
884 public int getMaxStringLength() {
885 return maxStringLength;
886 }
887
888 public Builder setMaxStringLength(final int maxStringLength) {
889 this.maxStringLength = maxStringLength;
890 return this;
891 }
892
893 public String getTruncatedStringSuffix() {
894 return truncatedStringSuffix;
895 }
896
897 public Builder setTruncatedStringSuffix(final String truncatedStringSuffix) {
898 this.truncatedStringSuffix = truncatedStringSuffix;
899 return this;
900 }
901
902 public JsonWriter build() {
903 validate();
904 return new JsonWriter(this);
905 }
906
907 private void validate() {
908 if (maxStringLength <= 0) {
909 throw new IllegalArgumentException(
910 "was expecting maxStringLength > 0: " +
911 maxStringLength);
912 }
913 Objects.requireNonNull(truncatedStringSuffix, "truncatedStringSuffix");
914 }
915
916 }
917
918 }
+0
-192
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/MapAccessor.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.logging.log4j.layout.template.json.util;
17
18 import java.util.Arrays;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Objects;
22
23 public class MapAccessor {
24
25 private final Map<String, Object> map;
26
27 public MapAccessor(final Map<String, Object> map) {
28 this.map = Objects.requireNonNull(map, "map");
29 }
30
31 public String getString(final String key) {
32 final String[] path = {key};
33 return getObject(path, String.class);
34 }
35
36 public String getString(final String[] path) {
37 return getObject(path, String.class);
38 }
39
40 public boolean getBoolean(final String key, final boolean defaultValue) {
41 final String[] path = {key};
42 return getBoolean(path, defaultValue);
43 }
44
45 public boolean getBoolean(final String[] path, final boolean defaultValue) {
46 final Boolean value = getObject(path, Boolean.class);
47 return value == null ? defaultValue : value;
48 }
49
50 public Boolean getBoolean(final String key) {
51 final String[] path = {key};
52 return getObject(path, Boolean.class);
53 }
54
55 public Boolean getBoolean(final String[] path) {
56 return getObject(path, Boolean.class);
57 }
58
59 public Integer getInteger(final String key) {
60 final String[] path = {key};
61 return getInteger(path);
62 }
63
64 public Integer getInteger(final String[] path) {
65 return getObject(path, Integer.class);
66 }
67
68 public boolean exists(final String key) {
69 final String[] path = {key};
70 return exists(path);
71 }
72
73 public boolean exists(final String[] path) {
74 final Object value = getObject(path);
75 return value != null;
76 }
77
78 public <E> List<E> getList(final String key, final Class<E> clazz) {
79 final String[] path = {key};
80 return getList(path, clazz);
81 }
82
83 public <E> List<E> getList(final String[] path, final Class<E> clazz) {
84
85 // Access the object.
86 final Object value = getObject(path);
87 if (value == null) {
88 return null;
89 }
90
91 // Check the type.
92 if (!(value instanceof List)) {
93 final String message = String.format(
94 "was expecting a List<%s> at path %s: %s (of type %s)",
95 clazz,
96 Arrays.asList(path),
97 value,
98 value.getClass().getCanonicalName());
99 throw new IllegalArgumentException(message);
100 }
101
102 // Check the element types.
103 @SuppressWarnings("unchecked")
104 final List<Object> items = (List<Object>) value;
105 for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) {
106 final Object item = items.get(itemIndex);
107 if (!clazz.isInstance(item)) {
108 final String message = String.format(
109 "was expecting a List<%s> item at path %s and index %d: %s (of type %s)",
110 clazz,
111 Arrays.asList(path),
112 itemIndex,
113 item,
114 item != null ? item.getClass().getCanonicalName() : null);
115 throw new IllegalArgumentException(message);
116 }
117 }
118
119 // Return the typed list.
120 @SuppressWarnings("unchecked")
121 final List<E> typedItems = (List<E>) items;
122 return typedItems;
123
124 }
125
126 public Object getObject(final String key) {
127 final String[] path = {key};
128 return getObject(path, Object.class);
129 }
130
131 public <T> T getObject(final String key, final Class<T> clazz) {
132 final String[] path = {key};
133 return getObject(path, clazz);
134 }
135
136 public Object getObject(final String[] path) {
137 return getObject(path, Object.class);
138 }
139
140 public <T> T getObject(final String[] path, final Class<T> clazz) {
141 Objects.requireNonNull(path, "path");
142 Objects.requireNonNull(clazz, "clazz");
143 if (path.length == 0) {
144 throw new IllegalArgumentException("empty path");
145 }
146 Object parent = map;
147 for (final String key : path) {
148 if (!(parent instanceof Map)) {
149 return null;
150 }
151 @SuppressWarnings("unchecked")
152 final Map<String, Object> parentMap = (Map<String, Object>) parent;
153 parent = parentMap.get(key);
154 }
155 if (parent != null && !clazz.isInstance(parent)) {
156 final String message = String.format(
157 "was expecting %s at path %s: %s (of type %s)",
158 clazz.getSimpleName(),
159 Arrays.asList(path),
160 parent,
161 parent.getClass().getCanonicalName());
162 throw new IllegalArgumentException(message);
163 }
164 @SuppressWarnings("unchecked")
165 final T typedValue = (T) parent;
166 return typedValue;
167 }
168
169 @Override
170 public boolean equals(final Object instance) {
171 if (this == instance) {
172 return true;
173 }
174 if (!(instance instanceof MapAccessor)) {
175 return false;
176 }
177 final MapAccessor that = (MapAccessor) instance;
178 return map.equals(that.map);
179 }
180
181 @Override
182 public int hashCode() {
183 return 31 + Objects.hashCode(map);
184 }
185
186 @Override
187 public String toString() {
188 return map.toString();
189 }
190
191 }
+0
-61
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/QueueingRecycler.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.logging.log4j.layout.template.json.util;
17
18 import java.util.Queue;
19 import java.util.function.Consumer;
20 import java.util.function.Supplier;
21
22 public class QueueingRecycler<V> implements Recycler<V> {
23
24 private final Supplier<V> supplier;
25
26 private final Consumer<V> cleaner;
27
28 private final Queue<V> queue;
29
30 public QueueingRecycler(
31 final Supplier<V> supplier,
32 final Consumer<V> cleaner,
33 final Queue<V> queue) {
34 this.supplier = supplier;
35 this.cleaner = cleaner;
36 this.queue = queue;
37 }
38
39 // Visible for tests.
40 Queue<V> getQueue() {
41 return queue;
42 }
43
44 @Override
45 public V acquire() {
46 final V value = queue.poll();
47 if (value == null) {
48 return supplier.get();
49 } else {
50 cleaner.accept(value);
51 return value;
52 }
53 }
54
55 @Override
56 public void release(final V value) {
57 queue.offer(value);
58 }
59
60 }
+0
-40
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/QueueingRecyclerFactory.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.logging.log4j.layout.template.json.util;
17
18 import java.util.Queue;
19 import java.util.function.Consumer;
20 import java.util.function.Supplier;
21
22 public class QueueingRecyclerFactory implements RecyclerFactory {
23
24 private final Supplier<Queue<Object>> queueSupplier;
25
26 public QueueingRecyclerFactory(final Supplier<Queue<Object>> queueSupplier) {
27 this.queueSupplier = queueSupplier;
28 }
29
30 @Override
31 public <V> Recycler<V> create(
32 final Supplier<V> supplier,
33 final Consumer<V> cleaner) {
34 @SuppressWarnings("unchecked")
35 final Queue<V> queue = (Queue<V>) queueSupplier.get();
36 return new QueueingRecycler<>(supplier, cleaner, queue);
37 }
38
39 }
+0
-25
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/Recycler.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.logging.log4j.layout.template.json.util;
17
18 public interface Recycler<V> {
19
20 V acquire();
21
22 void release(V value);
23
24 }
+0
-196
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.core.util.Constants;
19 import org.apache.logging.log4j.util.LoaderUtil;
20 import org.jctools.queues.MpmcArrayQueue;
21
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.Method;
24 import java.util.Arrays;
25 import java.util.LinkedHashSet;
26 import java.util.Map;
27 import java.util.Queue;
28 import java.util.concurrent.ArrayBlockingQueue;
29 import java.util.function.Supplier;
30
31 public final class RecyclerFactories {
32
33 private RecyclerFactories() {}
34
35 private static final String JCTOOLS_QUEUE_CLASS_SUPPLIER_PATH =
36 "org.jctools.queues.MpmcArrayQueue.new";
37
38 private static final boolean JCTOOLS_QUEUE_CLASS_AVAILABLE =
39 isJctoolsQueueClassAvailable();
40
41 private static boolean isJctoolsQueueClassAvailable() {
42 try {
43 final String className = JCTOOLS_QUEUE_CLASS_SUPPLIER_PATH
44 .replaceAll("\\.new$", "");
45 LoaderUtil.loadClass(className);
46 return true;
47 } catch (final ClassNotFoundException ignored) {
48 return false;
49 }
50 }
51
52 public static RecyclerFactory ofSpec(final String recyclerFactorySpec) {
53
54 // Determine the default capacity.
55 int defaultCapacity = Math.max(
56 2 * Runtime.getRuntime().availableProcessors() + 1,
57 8);
58
59 // TLA-, MPMC-, or ABQ-based queueing factory -- if nothing is specified.
60 if (recyclerFactorySpec == null) {
61 if (Constants.ENABLE_THREADLOCALS) {
62 return ThreadLocalRecyclerFactory.getInstance();
63 } else {
64 final Supplier<Queue<Object>> queueSupplier =
65 JCTOOLS_QUEUE_CLASS_AVAILABLE
66 ? () -> new MpmcArrayQueue<>(defaultCapacity)
67 : () -> new ArrayBlockingQueue<>(defaultCapacity);
68 return new QueueingRecyclerFactory(queueSupplier);
69 }
70 }
71
72 // Is a dummy factory requested?
73 else if (recyclerFactorySpec.equals("dummy")) {
74 return DummyRecyclerFactory.getInstance();
75 }
76
77 // Is a TLA factory requested?
78 else if (recyclerFactorySpec.equals("threadLocal")) {
79 return ThreadLocalRecyclerFactory.getInstance();
80 }
81
82 // Is a queueing factory requested?
83 else if (recyclerFactorySpec.startsWith("queue")) {
84 return readQueueingRecyclerFactory(recyclerFactorySpec, defaultCapacity);
85 }
86
87 // Bogus input, bail out.
88 else {
89 throw new IllegalArgumentException(
90 "invalid recycler factory: " + recyclerFactorySpec);
91 }
92
93 }
94
95 private static RecyclerFactory readQueueingRecyclerFactory(
96 final String recyclerFactorySpec,
97 final int defaultCapacity) {
98
99 // Parse the spec.
100 final String queueFactorySpec = recyclerFactorySpec.substring(
101 "queue".length() +
102 (recyclerFactorySpec.startsWith("queue:")
103 ? 1
104 : 0));
105 final Map<String, StringParameterParser.Value> parsedValues =
106 StringParameterParser.parse(
107 queueFactorySpec,
108 new LinkedHashSet<>(Arrays.asList("supplier", "capacity")));
109
110 // Read the supplier path.
111 final StringParameterParser.Value supplierValue = parsedValues.get("supplier");
112 final String supplierPath;
113 if (supplierValue == null || supplierValue instanceof StringParameterParser.NullValue) {
114 supplierPath = JCTOOLS_QUEUE_CLASS_AVAILABLE
115 ? JCTOOLS_QUEUE_CLASS_SUPPLIER_PATH
116 : "java.util.concurrent.ArrayBlockingQueue.new";
117 } else {
118 supplierPath = supplierValue.toString();
119 }
120
121 // Read the capacity.
122 final StringParameterParser.Value capacityValue = parsedValues.get("capacity");
123 final int capacity;
124 if (capacityValue == null || capacityValue instanceof StringParameterParser.NullValue) {
125 capacity = defaultCapacity;
126 } else {
127 try {
128 capacity = Integer.parseInt(capacityValue.toString());
129 } catch (final NumberFormatException error) {
130 throw new IllegalArgumentException(
131 "failed reading capacity in queueing recycler " +
132 "factory: " + queueFactorySpec, error);
133 }
134 }
135
136 // Execute the read spec.
137 return createRecyclerFactory(queueFactorySpec, supplierPath, capacity);
138
139 }
140
141 private static RecyclerFactory createRecyclerFactory(
142 final String queueFactorySpec,
143 final String supplierPath,
144 final int capacity) {
145 final int supplierPathSplitterIndex = supplierPath.lastIndexOf('.');
146 if (supplierPathSplitterIndex < 0) {
147 throw new IllegalArgumentException(
148 "invalid supplier in queueing recycler factory: " +
149 queueFactorySpec);
150 }
151 final String supplierClassName = supplierPath.substring(0, supplierPathSplitterIndex);
152 final String supplierMethodName = supplierPath.substring(supplierPathSplitterIndex + 1);
153 try {
154 final Class<?> supplierClass = LoaderUtil.loadClass(supplierClassName);
155 final Supplier<Queue<Object>> queueSupplier;
156 if ("new".equals(supplierMethodName)) {
157 final Constructor<?> supplierCtor =
158 supplierClass.getDeclaredConstructor(int.class);
159 queueSupplier = () -> {
160 try {
161 @SuppressWarnings("unchecked")
162 final Queue<Object> typedQueue =
163 (Queue<Object>) supplierCtor.newInstance(capacity);
164 return typedQueue;
165 } catch (final Exception error) {
166 throw new RuntimeException(
167 "recycler queue construction failed for factory: " +
168 queueFactorySpec, error);
169 }
170 };
171 } else {
172 final Method supplierMethod =
173 supplierClass.getMethod(supplierMethodName, int.class);
174 queueSupplier = () -> {
175 try {
176 @SuppressWarnings("unchecked")
177 final Queue<Object> typedQueue =
178 (Queue<Object>) supplierMethod.invoke(null, capacity);
179 return typedQueue;
180 } catch (final Exception error) {
181 throw new RuntimeException(
182 "recycler queue construction failed for factory: " +
183 queueFactorySpec, error);
184 }
185 };
186 }
187 return new QueueingRecyclerFactory(queueSupplier);
188 } catch (final Exception error) {
189 throw new RuntimeException(
190 "failed executing queueing recycler factory: " +
191 queueFactorySpec, error);
192 }
193 }
194
195 }
+0
-31
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactory.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.logging.log4j.layout.template.json.util;
17
18 import java.util.function.Consumer;
19 import java.util.function.Supplier;
20
21 @FunctionalInterface
22 public interface RecyclerFactory {
23
24 default <V> Recycler<V> create(Supplier<V> supplier) {
25 return create(supplier, ignored -> {});
26 }
27
28 <V> Recycler<V> create(Supplier<V> supplier, Consumer<V> cleaner);
29
30 }
+0
-34
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverter.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.convert.TypeConverter;
20 import org.apache.logging.log4j.core.config.plugins.convert.TypeConverters;
21
22 /**
23 * The default string (i.e., recycler factory spec) to {@link RecyclerFactory} type converter.
24 */
25 @Plugin(name = "RecyclerFactoryConverter", category = TypeConverters.CATEGORY)
26 public final class RecyclerFactoryConverter implements TypeConverter<RecyclerFactory> {
27
28 @Override
29 public RecyclerFactory convert(final String recyclerFactorySpec) {
30 return RecyclerFactories.ofSpec(recyclerFactorySpec);
31 }
32
33 }
+0
-320
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/StringParameterParser.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.util.Strings;
19
20 import java.util.Collections;
21 import java.util.LinkedHashMap;
22 import java.util.Map;
23 import java.util.Objects;
24 import java.util.Set;
25 import java.util.concurrent.Callable;
26
27 public final class StringParameterParser {
28
29 private StringParameterParser() {}
30
31 public static final class Values {
32
33 private Values() {}
34
35 static NullValue nullValue() {
36 return NullValue.INSTANCE;
37 }
38
39 static StringValue stringValue(final String string) {
40 return new StringValue(string);
41 }
42
43 static DoubleQuotedStringValue doubleQuotedStringValue(
44 final String doubleQuotedString) {
45 return new DoubleQuotedStringValue(doubleQuotedString);
46 }
47
48 }
49
50 public interface Value {}
51
52 public static final class NullValue implements Value {
53
54 private static final NullValue INSTANCE = new NullValue();
55
56 private NullValue() {}
57
58 @Override
59 public String toString() {
60 return "null";
61 }
62
63 }
64
65 public static final class StringValue implements Value {
66
67 private final String string;
68
69 private StringValue(String string) {
70 this.string = string;
71 }
72
73 public String getString() {
74 return string;
75 }
76
77 @Override
78 public boolean equals(Object object) {
79 if (this == object) {
80 return true;
81 }
82 if (object == null || getClass() != object.getClass()) {
83 return false;
84 }
85 StringValue that = (StringValue) object;
86 return string.equals(that.string);
87 }
88
89 @Override
90 public int hashCode() {
91 return 31 + Objects.hashCode(string);
92 }
93
94 @Override
95 public String toString() {
96 return string;
97 }
98
99 }
100
101 public static final class DoubleQuotedStringValue implements Value {
102
103 private final String doubleQuotedString;
104
105 private DoubleQuotedStringValue(String doubleQuotedString) {
106 this.doubleQuotedString = doubleQuotedString;
107 }
108
109 public String getDoubleQuotedString() {
110 return doubleQuotedString;
111 }
112
113 @Override
114 public boolean equals(Object object) {
115 if (this == object) {
116 return true;
117 }
118 if (object == null || getClass() != object.getClass()) {
119 return false;
120 }
121 DoubleQuotedStringValue that = (DoubleQuotedStringValue) object;
122 return doubleQuotedString.equals(that.doubleQuotedString);
123 }
124
125 @Override
126 public int hashCode() {
127 return 31 + Objects.hashCode(doubleQuotedString);
128 }
129
130 @Override
131 public String toString() {
132 return doubleQuotedString.replaceAll("\\\\\"", "\"");
133 }
134
135 }
136
137 private enum State { READING_KEY, READING_VALUE }
138
139 private static final class Parser implements Callable<Map<String, Value>> {
140
141 private final String input;
142
143 private final Map<String, Value> map;
144
145 private State state;
146
147 private int i;
148
149 private String key;
150
151 private Parser(final String input) {
152 this.input = Objects.requireNonNull(input, "input");
153 this.map = new LinkedHashMap<>();
154 this.state = State.READING_KEY;
155 this.i = 0;
156 this.key = null;
157 }
158
159 @Override
160 public Map<String, Value> call() {
161 while (true) {
162 skipWhitespace();
163 if (i >= input.length()) {
164 break;
165 }
166 switch (state) {
167 case READING_KEY:
168 readKey();
169 break;
170 case READING_VALUE:
171 readValue();
172 break;
173 default:
174 throw new IllegalStateException("unknown state: " + state);
175 }
176 }
177 if (state == State.READING_VALUE) {
178 map.put(key, Values.nullValue());
179 }
180 return map;
181 }
182
183 private void readKey() {
184 final int eq = input.indexOf('=', i);
185 final int co = input.indexOf(',', i);
186 final int j;
187 final int nextI;
188 if (eq < 0 && co < 0) {
189 // Neither '=', nor ',' was found.
190 j = nextI = input.length();
191 } else if (eq < 0) {
192 // Found ','.
193 j = nextI = co;
194 } else if (co < 0) {
195 // Found '='.
196 j = eq;
197 nextI = eq + 1;
198 } else if (eq < co) {
199 // Found '=...,'.
200 j = eq;
201 nextI = eq + 1;
202 } else {
203 // Found ',...='.
204 j = co;
205 nextI = co;
206 }
207 key = input.substring(i, j).trim();
208 if (Strings.isEmpty(key)) {
209 final String message = String.format(
210 "failed to locate key at index %d: %s",
211 i, input);
212 throw new IllegalArgumentException(message);
213 }
214 if (map.containsKey(key)) {
215 final String message = String.format(
216 "conflicting key at index %d: %s",
217 i, input);
218 throw new IllegalArgumentException(message);
219 }
220 state = State.READING_VALUE;
221 i = nextI;
222 }
223
224 private void readValue() {
225 final boolean doubleQuoted = input.charAt(i) == '"';
226 if (doubleQuoted) {
227 readDoubleQuotedStringValue();
228 } else {
229 readStringValue();
230 }
231 key = null;
232 state = State.READING_KEY;
233 }
234
235 private void readDoubleQuotedStringValue() {
236 int j = i + 1;
237 while (j < input.length()) {
238 if (input.charAt(j) == '"' && input.charAt(j - 1) != '\\') {
239 break;
240 } else {
241 j++;
242 }
243 }
244 if (j >= input.length()) {
245 final String message = String.format(
246 "failed to locate the end of double-quoted content starting at index %d: %s",
247 i, input);
248 throw new IllegalArgumentException(message);
249 }
250 final String content = input
251 .substring(i + 1, j)
252 .replaceAll("\\\\\"", "\"");
253 final Value value = Values.doubleQuotedStringValue(content);
254 map.put(key, value);
255 i = j + 1;
256 skipWhitespace();
257 if (i < input.length()) {
258 if (input.charAt(i) != ',') {
259 final String message = String.format(
260 "was expecting comma at index %d: %s",
261 i, input);
262 throw new IllegalArgumentException(message);
263 }
264 i++;
265 }
266 }
267
268 private void skipWhitespace() {
269 while (i < input.length()) {
270 final char c = input.charAt(i);
271 if (!Character.isWhitespace(c)) {
272 break;
273 } else {
274 i++;
275 }
276 }
277 }
278
279 private void readStringValue() {
280 int j = input.indexOf(',', i/* + 1*/);
281 if (j < 0) {
282 j = input.length();
283 }
284 final String content = input.substring(i, j);
285 final String trimmedContent = content.trim();
286 final Value value = trimmedContent.isEmpty()
287 ? Values.nullValue()
288 : Values.stringValue(trimmedContent);
289 map.put(key, value);
290 i += content.length() + 1;
291 }
292
293 }
294
295 public static Map<String, Value> parse(final String input) {
296 return parse(input, null);
297 }
298
299 public static Map<String, Value> parse(
300 final String input,
301 final Set<String> allowedKeys) {
302 if (Strings.isBlank(input)) {
303 return Collections.emptyMap();
304 }
305 final Map<String, Value> map = new Parser(input).call();
306 final Set<String> actualKeys = map.keySet();
307 for (final String actualKey : actualKeys) {
308 final boolean allowed = allowedKeys == null || allowedKeys.contains(actualKey);
309 if (!allowed) {
310 final String message = String.format(
311 "unknown key \"%s\" is found in input: %s",
312 actualKey, input);
313 throw new IllegalArgumentException(message);
314 }
315 }
316 return map;
317 }
318
319 }
+0
-45
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/ThreadLocalRecycler.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.logging.log4j.layout.template.json.util;
17
18 import java.util.function.Consumer;
19 import java.util.function.Supplier;
20
21 public class ThreadLocalRecycler<V> implements Recycler<V> {
22
23 private final Consumer<V> cleaner;
24
25 private final ThreadLocal<V> holder;
26
27 public ThreadLocalRecycler(
28 final Supplier<V> supplier,
29 final Consumer<V> cleaner) {
30 this.cleaner = cleaner;
31 this.holder = ThreadLocal.withInitial(supplier);
32 }
33
34 @Override
35 public V acquire() {
36 final V value = holder.get();
37 cleaner.accept(value);
38 return value;
39 }
40
41 @Override
42 public void release(final V value) {}
43
44 }
+0
-40
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/ThreadLocalRecyclerFactory.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.logging.log4j.layout.template.json.util;
17
18 import java.util.function.Consumer;
19 import java.util.function.Supplier;
20
21 public class ThreadLocalRecyclerFactory implements RecyclerFactory {
22
23 private static final ThreadLocalRecyclerFactory INSTANCE =
24 new ThreadLocalRecyclerFactory();
25
26 private ThreadLocalRecyclerFactory() {}
27
28 public static ThreadLocalRecyclerFactory getInstance() {
29 return INSTANCE;
30 }
31
32 @Override
33 public <V> Recycler<V> create(
34 final Supplier<V> supplier,
35 final Consumer<V> cleaner) {
36 return new ThreadLocalRecycler<>(supplier, cleaner);
37 }
38
39 }
+0
-92
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/TruncatingBufferedPrintWriter.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.logging.log4j.layout.template.json.util;
17
18 import java.io.PrintWriter;
19 import java.util.Objects;
20
21 public final class TruncatingBufferedPrintWriter
22 extends PrintWriter
23 implements CharSequence {
24
25 private final TruncatingBufferedWriter writer;
26
27 private TruncatingBufferedPrintWriter(final TruncatingBufferedWriter writer) {
28 super(writer, false);
29 this.writer = writer;
30 }
31
32 public static TruncatingBufferedPrintWriter ofCapacity(final int capacity) {
33 if (capacity < 0) {
34 throw new IllegalArgumentException(
35 "was expecting a non-negative capacity: " + capacity);
36 }
37 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(capacity);
38 return new TruncatingBufferedPrintWriter(writer);
39 }
40
41 public char[] buffer() {
42 return writer.buffer();
43 }
44
45 public int position() {
46 return writer.position();
47 }
48
49 public void position(final int index) {
50 writer.position(index);
51 }
52
53 public int capacity() {
54 return writer.capacity();
55 }
56
57 public boolean truncated() {
58 return writer.truncated();
59 }
60
61 public int indexOf(final CharSequence seq) {
62 Objects.requireNonNull(seq, "seq");
63 return writer.indexOf(seq);
64 }
65
66 @Override
67 public int length() {
68 return writer.length();
69 }
70
71 @Override
72 public char charAt(final int index) {
73 return writer.charAt(index);
74 }
75
76 @Override
77 public CharSequence subSequence(final int startIndex, final int endIndex) {
78 return writer.subSequence(startIndex, endIndex);
79 }
80
81 @Override
82 public void close() {
83 writer.close();
84 }
85
86 @Override
87 public String toString() {
88 return writer.toString();
89 }
90
91 }
+0
-267
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/TruncatingBufferedWriter.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.logging.log4j.layout.template.json.util;
17
18 import java.io.Writer;
19 import java.util.Objects;
20
21 final class TruncatingBufferedWriter extends Writer implements CharSequence {
22
23 private final char[] buffer;
24
25 private int position;
26
27 private boolean truncated;
28
29 TruncatingBufferedWriter(final int capacity) {
30 this.buffer = new char[capacity];
31 this.position = 0;
32 this.truncated = false;
33 }
34
35 char[] buffer() {
36 return buffer;
37 }
38
39 int position() {
40 return position;
41 }
42
43 void position(final int index) {
44 if (index < 0 || index >= buffer.length) {
45 throw new IllegalArgumentException("invalid index: " + index);
46 }
47 position = index;
48 }
49
50 int capacity() {
51 return buffer.length;
52 }
53
54 boolean truncated() {
55 return truncated;
56 }
57
58 @Override
59 public void write(final int c) {
60 if (position < buffer.length) {
61 buffer[position++] = (char) c;
62 } else {
63 truncated = true;
64 }
65 }
66
67 @Override
68 public void write(final char[] source) {
69 Objects.requireNonNull(source, "source");
70 write(source, 0, source.length);
71 }
72
73 @Override
74 public void write(final char[] source, final int offset, final int length) {
75
76 // Check arguments.
77 Objects.requireNonNull(source, "source");
78 if (offset < 0 || offset >= source.length) {
79 throw new IndexOutOfBoundsException("invalid offset: " + offset);
80 }
81 if (length < 0 || Math.addExact(offset, length) > source.length) {
82 throw new IndexOutOfBoundsException("invalid length: " + length);
83 }
84
85 // If input fits as is.
86 final int maxLength = buffer.length - position;
87 if (length < maxLength) {
88 System.arraycopy(source, offset, buffer, position, length);
89 position += length;
90 }
91
92 // If truncation is possible.
93 else if (maxLength > 0) {
94 System.arraycopy(source, offset, buffer, position, maxLength);
95 position += maxLength;
96 truncated = true;
97 }
98
99 }
100
101 @Override
102 public void write(final String string) {
103
104 // Check arguments.
105 Objects.requireNonNull(string, "string");
106 final int length = string.length();
107 final int maxLength = buffer.length - position;
108
109 // If input fits as is.
110 if (length < maxLength) {
111 string.getChars(0, length, buffer, position);
112 position += length;
113 }
114
115 // If truncation is possible.
116 else if (maxLength > 0) {
117 string.getChars(0, maxLength, buffer, position);
118 position += maxLength;
119 truncated = true;
120 }
121
122 }
123
124 @Override
125 public void write(final String string, final int offset, final int length) {
126
127 // Check arguments.
128 Objects.requireNonNull(string, "string");
129 if (offset < 0 || offset >= string.length()) {
130 throw new IndexOutOfBoundsException("invalid offset: " + offset);
131 }
132 if (length < 0 || Math.addExact(offset, length) > string.length()) {
133 throw new IndexOutOfBoundsException("invalid length: " + length);
134 }
135
136 // If input fits as is.
137 final int maxLength = buffer.length - position;
138 if (length < maxLength) {
139 string.getChars(offset, offset + length, buffer, position);
140 position += length;
141 }
142
143 // If truncation is possible.
144 else if (maxLength > 0) {
145 string.getChars(offset, offset + maxLength, buffer, position);
146 position += maxLength;
147 truncated = true;
148 }
149
150 }
151
152 @Override
153 public Writer append(final char c) {
154 write(c);
155 return this;
156 }
157
158 @Override
159 public Writer append(final CharSequence seq) {
160 return seq == null
161 ? append("null", 0, 4)
162 : append(seq, 0, seq.length());
163 }
164
165 @Override
166 public Writer append(final CharSequence seq, final int start, final int end) {
167
168 // Short-circuit on null sequence.
169 if (seq == null) {
170 write("null");
171 return this;
172 }
173
174 // Check arguments.
175 if (start < 0 || start >= seq.length()) {
176 throw new IndexOutOfBoundsException("invalid start: " + start);
177 }
178 if (end < start || end > seq.length()) {
179 throw new IndexOutOfBoundsException("invalid end: " + end);
180 }
181
182 // If input fits as is.
183 final int length = end - start;
184 final int maxLength = buffer.length - position;
185 if (length < maxLength) {
186 for (int i = start; i < end; i++) {
187 final char c = seq.charAt(i);
188 buffer[position++] = c;
189 }
190 }
191
192 // If truncation is possible.
193 else if (maxLength > 0) {
194 final int truncatedEnd = start + maxLength;
195 for (int i = start; i < truncatedEnd; i++) {
196 final char c = seq.charAt(i);
197 buffer[position++] = c;
198 }
199 truncated = true;
200 }
201 return this;
202
203 }
204
205 int indexOf(final CharSequence seq) {
206
207 // Short-circuit if there is nothing to match.
208 final int seqLength = seq.length();
209 if (seqLength == 0) {
210 return 0;
211 }
212
213 // Short-circuit if the given input is longer than the buffer.
214 if (seqLength > position) {
215 return -1;
216 }
217
218 // Perform the search.
219 for (int bufferIndex = 0; bufferIndex < position; bufferIndex++) {
220 boolean found = true;
221 for (int seqIndex = 0; seqIndex < seqLength; seqIndex++) {
222 final char s = seq.charAt(seqIndex);
223 final char b = buffer[bufferIndex + seqIndex];
224 if (s != b) {
225 found = false;
226 break;
227 }
228 }
229 if (found) {
230 return bufferIndex;
231 }
232 }
233 return -1;
234
235 }
236
237 @Override
238 public int length() {
239 return position + 1;
240 }
241
242 @Override
243 public char charAt(final int index) {
244 return buffer[index];
245 }
246
247 @Override
248 public String subSequence(final int startIndex, final int endIndex) {
249 return new String(buffer, startIndex, endIndex - startIndex);
250 }
251
252 @Override
253 public void flush() {}
254
255 @Override
256 public void close() {
257 position = 0;
258 truncated = false;
259 }
260
261 @Override
262 public String toString() {
263 return new String(buffer, 0, position);
264 }
265
266 }
+0
-140
log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/Uris.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.status.StatusLogger;
20 import org.apache.logging.log4j.util.LoaderUtil;
21
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.net.URI;
27 import java.net.URL;
28 import java.nio.charset.Charset;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Objects;
35
36 public final class Uris {
37
38 private Uris() {}
39
40 private static final Logger LOGGER = StatusLogger.getLogger();
41
42 /**
43 * Reads {@link URI} specs of scheme <tt>classpath</tt> and <tt>file</tt>.
44 *
45 * @param spec the {@link URI} spec, e.g., <tt>file:/holy/cow.txt</tt> or
46 * <tt>classpath:/holy/cat.txt</tt>
47 * @param charset used {@link Charset} for decoding the file
48 */
49 public static String readUri(final String spec, final Charset charset) {
50 Objects.requireNonNull(spec, "spec");
51 Objects.requireNonNull(charset, "charset");
52 try {
53 final URI uri = new URI(spec);
54 return unsafeReadUri(uri, charset);
55 } catch (final Exception error) {
56 throw new RuntimeException("failed reading URI: " + spec, error);
57 }
58 }
59
60 /**
61 * Reads {@link URI}s of scheme <tt>classpath</tt> and <tt>file</tt>.
62 *
63 * @param uri the {@link URI}, e.g., <tt>file:/holy/cow.txt</tt> or
64 * <tt>classpath:/holy/cat.txt</tt>
65 * @param charset used {@link Charset} for decoding the file
66 */
67 public static String readUri(final URI uri, final Charset charset) {
68 Objects.requireNonNull(uri, "uri");
69 Objects.requireNonNull(charset, "charset");
70 try {
71 return unsafeReadUri(uri, charset);
72 } catch (final Exception error) {
73 throw new RuntimeException("failed reading URI: " + uri, error);
74 }
75 }
76
77 private static String unsafeReadUri(
78 final URI uri,
79 final Charset charset)
80 throws Exception {
81 final String uriScheme = uri.getScheme().toLowerCase();
82 switch (uriScheme) {
83 case "classpath":
84 return readClassPathUri(uri, charset);
85 case "file":
86 return readFileUri(uri, charset);
87 default: {
88 throw new IllegalArgumentException("unknown scheme in URI: " + uri);
89 }
90 }
91 }
92
93 private static String readFileUri(
94 final URI uri,
95 final Charset charset)
96 throws IOException {
97 final Path path = Paths.get(uri);
98 try (final BufferedReader fileReader = Files.newBufferedReader(path, charset)) {
99 return consumeReader(fileReader);
100 }
101 }
102
103 private static String readClassPathUri(
104 final URI uri,
105 final Charset charset)
106 throws IOException {
107 final String spec = uri.toString();
108 final String path = spec.substring("classpath:".length());
109 final List<URL> resources = new ArrayList<>(LoaderUtil.findResources(path));
110 if (resources.isEmpty()) {
111 final String message = String.format(
112 "could not locate classpath resource (path=%s)", path);
113 throw new RuntimeException(message);
114 }
115 final URL resource = resources.get(0);
116 if (resources.size() > 1) {
117 final String message = String.format(
118 "for URI %s found %d resources, using the first one: %s",
119 uri, resources.size(), resource);
120 LOGGER.warn(message);
121 }
122 try (final InputStream inputStream = resource.openStream()) {
123 try (final InputStreamReader reader = new InputStreamReader(inputStream, charset);
124 final BufferedReader bufferedReader = new BufferedReader(reader)) {
125 return consumeReader(bufferedReader);
126 }
127 }
128 }
129
130 private static String consumeReader(final BufferedReader reader) throws IOException {
131 final StringBuilder builder = new StringBuilder();
132 String line;
133 while ((line = reader.readLine()) != null) {
134 builder.append(line);
135 }
136 return builder.toString();
137 }
138
139 }
+0
-49
log4j-layout-template-json/src/main/resources/EcsLayout.json less more
0 {
1 "@timestamp": {
2 "$resolver": "timestamp",
3 "pattern": {
4 "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
5 "timeZone": "UTC"
6 }
7 },
8 "ecs.version": "1.2.0",
9 "log.level": {
10 "$resolver": "level",
11 "field": "name"
12 },
13 "message": {
14 "$resolver": "message",
15 "stringified": true
16 },
17 "process.thread.name": {
18 "$resolver": "thread",
19 "field": "name"
20 },
21 "log.logger": {
22 "$resolver": "logger",
23 "field": "name"
24 },
25 "labels": {
26 "$resolver": "mdc",
27 "flatten": true,
28 "stringified": true
29 },
30 "tags": {
31 "$resolver": "ndc"
32 },
33 "error.type": {
34 "$resolver": "exception",
35 "field": "className"
36 },
37 "error.message": {
38 "$resolver": "exception",
39 "field": "message"
40 },
41 "error.stack_trace": {
42 "$resolver": "exception",
43 "field": "stackTrace",
44 "stackTrace": {
45 "stringified": true
46 }
47 }
48 }
+0
-65
log4j-layout-template-json/src/main/resources/GcpLayout.json less more
0 {
1 "timestamp": {
2 "$resolver": "timestamp",
3 "pattern": {
4 "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
5 "timeZone": "UTC",
6 "locale": "en_US"
7 }
8 },
9 "severity": {
10 "$resolver": "pattern",
11 "pattern": "%level{WARN=WARNING, TRACE=DEBUG, FATAL=EMERGENCY}",
12 "stackTraceEnabled": false
13 },
14 "message": {
15 "$resolver": "pattern",
16 "pattern": "%m",
17 "stackTraceEnabled": true
18 },
19 "logging.googleapis.com/labels": {
20 "$resolver": "mdc",
21 "stringified": true
22 },
23 "logging.googleapis.com/sourceLocation": {
24 "file": {
25 "$resolver": "source",
26 "field": "fileName"
27 },
28 "line": {
29 "$resolver": "source",
30 "field": "lineNumber"
31 },
32 "function": {
33 "$resolver": "pattern",
34 "pattern": "%replace{%C.%M}{^\\?\\.$}{}",
35 "stackTraceEnabled": false
36 }
37 },
38 "logging.googleapis.com/insertId": {
39 "$resolver": "counter",
40 "stringified": true
41 },
42 "_exception": {
43 "class": {
44 "$resolver": "exception",
45 "field": "className"
46 },
47 "message": {
48 "$resolver": "exception",
49 "field": "message"
50 },
51 "stackTrace": {
52 "$resolver": "pattern",
53 "pattern": "%xEx"
54 }
55 },
56 "_thread": {
57 "$resolver": "thread",
58 "field": "name"
59 },
60 "_logger": {
61 "$resolver": "logger",
62 "field": "name"
63 }
64 }
+0
-43
log4j-layout-template-json/src/main/resources/GelfLayout.json less more
0 {
1 "version": "1.1",
2 "host": "${hostName}",
3 "short_message": {
4 "$resolver": "message",
5 "stringified": true
6 },
7 "full_message": {
8 "$resolver": "exception",
9 "field": "stackTrace",
10 "stackTrace": {
11 "stringified": true
12 }
13 },
14 "timestamp": {
15 "$resolver": "timestamp",
16 "epoch": {
17 "unit": "secs"
18 }
19 },
20 "level": {
21 "$resolver": "level",
22 "field": "severity",
23 "severity": {
24 "field": "code"
25 }
26 },
27 "_logger": {
28 "$resolver": "logger",
29 "field": "name"
30 },
31 "_thread": {
32 "$resolver": "thread",
33 "field": "name"
34 },
35 "_mdc": {
36 "$resolver": "mdc",
37 "flatten": {
38 "prefix": "_"
39 },
40 "stringified": true
41 }
42 }
+0
-83
log4j-layout-template-json/src/main/resources/JsonLayout.json less more
0 {
1 "instant": {
2 "epochSecond": {
3 "$resolver": "timestamp",
4 "epoch": {
5 "unit": "secs",
6 "rounded": true
7 }
8 },
9 "nanoOfSecond": {
10 "$resolver": "timestamp",
11 "epoch": {
12 "unit": "secs.nanos"
13 }
14 }
15 },
16 "thread": {
17 "$resolver": "thread",
18 "field": "name"
19 },
20 "level": {
21 "$resolver": "level",
22 "field": "name"
23 },
24 "loggerName": {
25 "$resolver": "logger",
26 "field": "name"
27 },
28 "message": {
29 "$resolver": "message",
30 "stringified": true
31 },
32 "thrown": {
33 "message": {
34 "$resolver": "exception",
35 "field": "message"
36 },
37 "name": {
38 "$resolver": "exception",
39 "field": "className"
40 },
41 "extendedStackTrace": {
42 "$resolver": "exception",
43 "field": "stackTrace"
44 }
45 },
46 "contextStack": {
47 "$resolver": "ndc"
48 },
49 "endOfBatch": {
50 "$resolver": "endOfBatch"
51 },
52 "loggerFqcn": {
53 "$resolver": "logger",
54 "field": "fqcn"
55 },
56 "threadId": {
57 "$resolver": "thread",
58 "field": "id"
59 },
60 "threadPriority": {
61 "$resolver": "thread",
62 "field": "priority"
63 },
64 "source": {
65 "class": {
66 "$resolver": "source",
67 "field": "className"
68 },
69 "method": {
70 "$resolver": "source",
71 "field": "methodName"
72 },
73 "file": {
74 "$resolver": "source",
75 "field": "fileName"
76 },
77 "line": {
78 "$resolver": "source",
79 "field": "lineNumber"
80 }
81 }
82 }
+0
-60
log4j-layout-template-json/src/main/resources/LogstashJsonEventLayoutV1.json less more
0 {
1 "mdc": {
2 "$resolver": "mdc"
3 },
4 "exception": {
5 "exception_class": {
6 "$resolver": "exception",
7 "field": "className"
8 },
9 "exception_message": {
10 "$resolver": "exception",
11 "field": "message",
12 "stringified": true
13 },
14 "stacktrace": {
15 "$resolver": "exception",
16 "field": "stackTrace",
17 "stackTrace": {
18 "stringified": true
19 }
20 }
21 },
22 "line_number": {
23 "$resolver": "source",
24 "field": "lineNumber"
25 },
26 "class": {
27 "$resolver": "source",
28 "field": "className"
29 },
30 "@version": 1,
31 "source_host": "${hostName}",
32 "message": {
33 "$resolver": "message",
34 "stringified": true
35 },
36 "thread_name": {
37 "$resolver": "thread",
38 "field": "name"
39 },
40 "@timestamp": {
41 "$resolver": "timestamp"
42 },
43 "level": {
44 "$resolver": "level",
45 "field": "name"
46 },
47 "file": {
48 "$resolver": "source",
49 "field": "fileName"
50 },
51 "method": {
52 "$resolver": "source",
53 "field": "methodName"
54 },
55 "logger_name": {
56 "$resolver": "logger",
57 "field": "name"
58 }
59 }
+0
-18
log4j-layout-template-json/src/main/resources/StackTraceElementLayout.json less more
0 {
1 "class": {
2 "$resolver": "stackTraceElement",
3 "field": "className"
4 },
5 "method": {
6 "$resolver": "stackTraceElement",
7 "field": "methodName"
8 },
9 "file": {
10 "$resolver": "stackTraceElement",
11 "field": "fileName"
12 },
13 "line": {
14 "$resolver": "stackTraceElement",
15 "field": "lineNumber"
16 }
17 }
+0
-32
log4j-layout-template-json/src/site/manual/index.md less more
0 <!-- vim: set syn=markdown : -->
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17
18 # Apache Log4j JSON Template Layout module
19
20 This module provides a customizable and efficient JSON layout.
21
22 ## Requirements
23
24 This module was introduced in Log4j 3.0.0 and requires Jackson.
25
26 Some features may require optional [dependencies](../runtime-dependencies.html).
27 These dependencies are specified in the documentation for those features.
28
29 Some Log4j features require external dependencies. See the
30 [Dependency Tree](dependencies.html#Dependency_Tree) for the exact list of JAR
31 files needed for these features.
+0
-55
log4j-layout-template-json/src/site/site.xml 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 <project name="Log4j Core"
17 xmlns="http://maven.apache.org/DECORATION/1.4.0"
18 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
20
21 <body>
22
23 <links>
24 <item name="Apache" href="http://www.apache.org/" />
25 <item name="Logging Services" href="http://logging.apache.org/"/>
26 <item name="Log4j" href="../index.html"/>
27 </links>
28
29 <!-- Component-specific reports -->
30 <menu ref="reports"/>
31
32 <!-- Overall Project Info -->
33 <menu name="Log4j Project Information" img="icon-info-sign">
34 <item name="Dependencies" href="../dependencies.html" />
35 <item name="Dependency Convergence" href="../dependency-convergence.html" />
36 <item name="Dependency Management" href="../dependency-management.html" />
37 <item name="Project Team" href="../team-list.html" />
38 <item name="Mailing Lists" href="../mail-lists.html" />
39 <item name="Issue Tracking" href="../issue-tracking.html" />
40 <item name="Project License" href="../license.html" />
41 <item name="Source Repository" href="../source-repository.html" />
42 <item name="Project Summary" href="../project-summary.html" />
43 </menu>
44
45 <menu name="Log4j Project Reports" img="icon-cog">
46 <item name="Changes Report" href="../changes-report.html" />
47 <item name="JIRA Report" href="../jira-report.html" />
48 <item name="Surefire Report" href="../surefire-report.html" />
49 <item name="RAT Report" href="../rat-report.html" />
50 </menu>
51
52 </body>
53
54 </project>
+0
-50
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
19
20 import java.nio.ByteBuffer;
21
22 class BlackHoleByteBufferDestination implements ByteBufferDestination {
23
24 private final ByteBuffer byteBuffer;
25
26 BlackHoleByteBufferDestination(final int maxByteCount) {
27 this.byteBuffer = ByteBuffer.allocate(maxByteCount);
28 }
29
30 @Override
31 public ByteBuffer getByteBuffer() {
32 return byteBuffer;
33 }
34
35 @Override
36 public ByteBuffer drain(final ByteBuffer byteBuffer) {
37 byteBuffer.clear();
38 return byteBuffer;
39 }
40
41 @Override
42 public void writeBytes(final ByteBuffer byteBuffer) {
43 byteBuffer.clear();
44 }
45
46 @Override
47 public void writeBytes(final byte[] buffer, final int offset, final int length) {}
48
49 }
+0
-111
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.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.logging.log4j.layout.template.json;
17
18 import co.elastic.logging.log4j2.EcsLayout;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.config.Configuration;
21 import org.apache.logging.log4j.core.config.DefaultConfiguration;
22 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
23 import org.assertj.core.api.Assertions;
24 import org.junit.jupiter.api.Test;
25
26 import java.nio.charset.Charset;
27 import java.nio.charset.StandardCharsets;
28 import java.util.Collection;
29 import java.util.List;
30 import java.util.Map;
31
32 import static org.apache.logging.log4j.layout.template.json.TestHelpers.serializeUsingLayout;
33
34 class EcsLayoutTest {
35
36 private static final Configuration CONFIGURATION = new DefaultConfiguration();
37
38 private static final Charset CHARSET = StandardCharsets.UTF_8;
39
40 private static final String SERVICE_NAME = "test";
41
42 private static final String EVENT_DATASET = SERVICE_NAME + ".log";
43
44 private static final JsonTemplateLayout JSON_TEMPLATE_LAYOUT = JsonTemplateLayout
45 .newBuilder()
46 .setConfiguration(CONFIGURATION)
47 .setCharset(CHARSET)
48 .setEventTemplateUri("classpath:EcsLayout.json")
49 .setEventTemplateAdditionalFields(
50 new EventTemplateAdditionalField[]{
51 EventTemplateAdditionalField
52 .newBuilder()
53 .setKey("service.name")
54 .setValue(SERVICE_NAME)
55 .build(),
56 EventTemplateAdditionalField
57 .newBuilder()
58 .setKey("event.dataset")
59 .setValue(EVENT_DATASET)
60 .build()
61 })
62 .build();
63
64 private static final EcsLayout ECS_LAYOUT = EcsLayout
65 .newBuilder()
66 .setConfiguration(CONFIGURATION)
67 .setServiceName(SERVICE_NAME)
68 .setEventDataset(EVENT_DATASET)
69 .build();
70
71 @Test
72 void test_EcsLayout_charset() {
73 Assertions.assertThat(ECS_LAYOUT.getCharset()).isEqualTo(CHARSET);
74 }
75
76 @Test
77 void test_lite_log_events() {
78 final List<LogEvent> logEvents = LogEventFixture.createLiteLogEvents(1_000);
79 test(logEvents);
80 }
81
82 @Test
83 void test_full_log_events() {
84 final List<LogEvent> logEvents = LogEventFixture.createFullLogEvents(1_000);
85 test(logEvents);
86 }
87
88 private static void test(final Collection<LogEvent> logEvents) {
89 for (final LogEvent logEvent : logEvents) {
90 test(logEvent);
91 }
92 }
93
94 private static void test(final LogEvent logEvent) {
95 final Map<String, Object> jsonTemplateLayoutMap = renderUsingJsonTemplateLayout(logEvent);
96 final Map<String, Object> ecsLayoutMap = renderUsingEcsLayout(logEvent);
97 Assertions.assertThat(jsonTemplateLayoutMap).isEqualTo(ecsLayoutMap);
98 }
99
100 private static Map<String, Object> renderUsingJsonTemplateLayout(
101 final LogEvent logEvent) {
102 return serializeUsingLayout(logEvent, JSON_TEMPLATE_LAYOUT);
103 }
104
105 private static Map<String, Object> renderUsingEcsLayout(
106 final LogEvent logEvent) {
107 return serializeUsingLayout(logEvent, ECS_LAYOUT);
108 }
109
110 }
+0
-195
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GcpLayoutTest.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.junit.jupiter.api.Test;
21
22 import java.time.Instant;
23 import java.time.ZoneId;
24 import java.time.ZonedDateTime;
25 import java.time.format.DateTimeFormatter;
26 import java.util.Locale;
27
28 import static org.apache.logging.log4j.layout.template.json.TestHelpers.CONFIGURATION;
29 import static org.apache.logging.log4j.layout.template.json.TestHelpers.usingSerializedLogEventAccessor;
30 import static org.assertj.core.api.Assertions.assertThat;
31
32 class GcpLayoutTest {
33
34 private static final JsonTemplateLayout LAYOUT = JsonTemplateLayout
35 .newBuilder()
36 .setConfiguration(CONFIGURATION)
37 .setStackTraceEnabled(true)
38 .setLocationInfoEnabled(true)
39 .setEventTemplateUri("classpath:GcpLayout.json")
40 .build();
41
42 private static final int LOG_EVENT_COUNT = 1_000;
43
44 private static final DateTimeFormatter DATE_TIME_FORMATTER =
45 DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
46
47 @Test
48 void test_lite_log_events() {
49 LogEventFixture
50 .createLiteLogEvents(LOG_EVENT_COUNT)
51 .forEach(GcpLayoutTest::verifySerialization);
52 }
53
54 @Test
55 void test_full_log_events() {
56 LogEventFixture
57 .createFullLogEvents(LOG_EVENT_COUNT)
58 .forEach(GcpLayoutTest::verifySerialization);
59 }
60
61 private static void verifySerialization(final LogEvent logEvent) {
62 usingSerializedLogEventAccessor(LAYOUT, logEvent, accessor -> {
63
64 // Verify timestamp.
65 final String expectedTimestamp = formatLogEventInstant(logEvent);
66 assertThat(accessor.getString("timestamp")).isEqualTo(expectedTimestamp);
67
68 // Verify severity.
69 final Level level = logEvent.getLevel();
70 final String expectedSeverity;
71 if (Level.WARN.equals(level)) {
72 expectedSeverity = "WARNING";
73 } else if (Level.TRACE.equals(level)) {
74 expectedSeverity = "TRACE";
75 } else if (Level.FATAL.equals(level)) {
76 expectedSeverity = "EMERGENCY";
77 } else {
78 expectedSeverity = level.name();
79 }
80 assertThat(accessor.getString("severity")).isEqualTo(expectedSeverity);
81
82 // Verify message.
83 final Throwable exception = logEvent.getThrown();
84 if (exception != null) {
85 final String actualMessage = accessor.getString("message");
86 assertThat(actualMessage)
87 .contains(logEvent.getMessage().getFormattedMessage())
88 .contains(exception.getLocalizedMessage())
89 .contains("at org.apache.logging.log4j.layout.template.json")
90 .contains("at java.lang.reflect.Method")
91 .contains("at org.junit.platform.engine");
92 }
93
94 // Verify labels.
95 logEvent.getContextData().forEach((key, value) -> {
96 final String expectedValue = String.valueOf(value);
97 final String actualValue =
98 accessor.getString(new String[]{
99 "logging.googleapis.com/labels", key});
100 assertThat(actualValue).isEqualTo(expectedValue);
101 });
102
103 final StackTraceElement source = logEvent.getSource();
104 if (source != null) {
105
106 // Verify file name.
107 final String actualFileName =
108 accessor.getString(new String[]{
109 "logging.googleapis.com/sourceLocation", "file"});
110 assertThat(actualFileName).isEqualTo(source.getFileName());
111
112 // Verify line number.
113 final int actualLineNumber =
114 accessor.getInteger(new String[]{
115 "logging.googleapis.com/sourceLocation", "line"});
116 assertThat(actualLineNumber).isEqualTo(source.getLineNumber());
117
118 // Verify function.
119 final String expectedFunction =
120 source.getClassName() + "." + source.getMethodName();
121 final String actualFunction =
122 accessor.getString(new String[]{
123 "logging.googleapis.com/sourceLocation", "function"});
124 assertThat(actualFunction).isEqualTo(expectedFunction);
125
126 } else {
127 assertThat(accessor.exists(
128 new String[]{"logging.googleapis.com/sourceLocation", "file"}))
129 .isFalse();
130 assertThat(accessor.exists(
131 new String[]{"logging.googleapis.com/sourceLocation", "line"}))
132 .isFalse();
133 assertThat(accessor.getString(
134 new String[]{"logging.googleapis.com/sourceLocation", "function"}))
135 .isEmpty();
136 }
137
138 // Verify insert id.
139 assertThat(accessor.getString("logging.googleapis.com/insertId"))
140 .matches("[-]?[0-9]+");
141
142 // Verify exception.
143 if (exception != null) {
144
145 // Verify exception class.
146 assertThat(accessor.getString(
147 new String[]{"_exception", "class"}))
148 .isEqualTo(exception.getClass().getCanonicalName());
149
150 // Verify exception message.
151 assertThat(accessor.getString(
152 new String[]{"_exception", "message"}))
153 .isEqualTo(exception.getMessage());
154
155 // Verify exception stack trace.
156 assertThat(accessor.getString(
157 new String[]{"_exception", "stackTrace"}))
158 .contains(exception.getLocalizedMessage())
159 .contains("at org.apache.logging.log4j.layout.template.json")
160 .contains("at java.lang.reflect.Method")
161 .contains("at org.junit.platform.engine");
162
163 } else {
164 assertThat(accessor.getObject(
165 new String[]{"_exception", "class"}))
166 .isNull();
167 assertThat(accessor.getObject(
168 new String[]{"_exception", "message"}))
169 .isNull();
170 assertThat(accessor.getString(
171 new String[]{"_exception", "stackTrace"}))
172 .isEmpty();
173 }
174
175 // Verify thread name.
176 assertThat(accessor.getString("_thread"))
177 .isEqualTo(logEvent.getThreadName());
178
179 // Verify logger name.
180 assertThat(accessor.getString("_logger"))
181 .isEqualTo(logEvent.getLoggerName());
182
183 });
184 }
185
186 private static String formatLogEventInstant(final LogEvent logEvent) {
187 org.apache.logging.log4j.core.time.Instant instant = logEvent.getInstant();
188 ZonedDateTime dateTime = Instant.ofEpochSecond(
189 instant.getEpochSecond(),
190 instant.getNanoOfSecond()).atZone(ZoneId.of("UTC"));
191 return DATE_TIME_FORMATTER.format(dateTime);
192 }
193
194 }
+0
-120
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.Configuration;
20 import org.apache.logging.log4j.core.config.DefaultConfiguration;
21 import org.apache.logging.log4j.core.layout.GelfLayout;
22 import org.apache.logging.log4j.core.time.Instant;
23 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
24 import org.assertj.core.api.Assertions;
25 import org.junit.jupiter.api.Test;
26
27 import java.math.BigDecimal;
28 import java.util.Collection;
29 import java.util.List;
30 import java.util.Map;
31
32 import static org.apache.logging.log4j.layout.template.json.TestHelpers.serializeUsingLayout;
33
34 class GelfLayoutTest {
35
36 private static final Configuration CONFIGURATION = new DefaultConfiguration();
37
38 private static final String HOST_NAME = "localhost";
39
40 private static final JsonTemplateLayout JSON_TEMPLATE_LAYOUT = JsonTemplateLayout
41 .newBuilder()
42 .setConfiguration(CONFIGURATION)
43 .setEventTemplateUri("classpath:GelfLayout.json")
44 .setEventTemplateAdditionalFields(
45 new EventTemplateAdditionalField[]{
46 EventTemplateAdditionalField
47 .newBuilder()
48 .setKey("host")
49 .setValue(HOST_NAME)
50 .build()
51 })
52 .build();
53
54 private static final GelfLayout GELF_LAYOUT = GelfLayout
55 .newBuilder()
56 .setConfiguration(CONFIGURATION)
57 .setHost(HOST_NAME)
58 .setCompressionType(GelfLayout.CompressionType.OFF)
59 .build();
60
61 @Test
62 void test_lite_log_events() {
63 final List<LogEvent> logEvents = LogEventFixture.createLiteLogEvents(1_000);
64 test(logEvents);
65 }
66
67 @Test
68 void test_full_log_events() {
69 final List<LogEvent> logEvents = LogEventFixture.createFullLogEvents(1_000);
70 test(logEvents);
71 }
72
73 private static void test(final Collection<LogEvent> logEvents) {
74 for (final LogEvent logEvent : logEvents) {
75 test(logEvent);
76 }
77 }
78
79 private static void test(final LogEvent logEvent) {
80 final Map<String, Object> jsonTemplateLayoutMap = renderUsingJsonTemplateLayout(logEvent);
81 final Map<String, Object> gelfLayoutMap = renderUsingGelfLayout(logEvent);
82 verifyTimestamp(logEvent.getInstant(), jsonTemplateLayoutMap, gelfLayoutMap);
83 Assertions.assertThat(jsonTemplateLayoutMap).isEqualTo(gelfLayoutMap);
84 }
85
86 private static Map<String, Object> renderUsingJsonTemplateLayout(
87 final LogEvent logEvent) {
88 return serializeUsingLayout(logEvent, JSON_TEMPLATE_LAYOUT);
89 }
90
91 private static Map<String, Object> renderUsingGelfLayout(
92 final LogEvent logEvent) {
93 return serializeUsingLayout(logEvent, GELF_LAYOUT);
94 }
95
96 /**
97 * Handle timestamps individually to avoid floating-point comparison hiccups.
98 */
99 private static void verifyTimestamp(
100 final Instant logEventInstant,
101 final Map<String, Object> jsonTemplateLayoutMap,
102 final Map<String, Object> gelfLayoutMap) {
103 final BigDecimal jsonTemplateLayoutTimestamp =
104 (BigDecimal) jsonTemplateLayoutMap.remove("timestamp");
105 final BigDecimal gelfLayoutTimestamp =
106 (BigDecimal) gelfLayoutMap.remove("timestamp");
107 final String description = String.format(
108 "instantEpochSecs=%d.%d, jsonTemplateLayoutTimestamp=%s, gelfLayoutTimestamp=%s",
109 logEventInstant.getEpochSecond(),
110 logEventInstant.getNanoOfSecond(),
111 jsonTemplateLayoutTimestamp,
112 gelfLayoutTimestamp);
113 Assertions
114 .assertThat(jsonTemplateLayoutTimestamp.compareTo(gelfLayoutTimestamp))
115 .as(description)
116 .isEqualTo(0);
117 }
118
119 }
+0
-31
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JacksonFixture.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.logging.log4j.layout.template.json;
17
18 import com.fasterxml.jackson.databind.ObjectMapper;
19
20 public final class JacksonFixture {
21
22 private JacksonFixture() {}
23
24 private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
25
26 public static ObjectMapper getObjectMapper() {
27 return OBJECT_MAPPER;
28 }
29
30 }
+0
-87
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonLayoutTest.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.Configuration;
20 import org.apache.logging.log4j.core.config.DefaultConfiguration;
21 import org.apache.logging.log4j.core.layout.JsonLayout;
22 import org.assertj.core.api.Assertions;
23 import org.junit.jupiter.api.Test;
24
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Map;
28
29 import static org.apache.logging.log4j.layout.template.json.TestHelpers.serializeUsingLayout;
30
31 class JsonLayoutTest {
32
33 private static final Configuration CONFIGURATION = new DefaultConfiguration();
34
35 private static final JsonTemplateLayout JSON_TEMPLATE_LAYOUT = JsonTemplateLayout
36 .newBuilder()
37 .setConfiguration(CONFIGURATION)
38 .setEventTemplateUri("classpath:JsonLayout.json")
39 .build();
40
41 private static final JsonLayout JSON_LAYOUT = JsonLayout
42 .newBuilder()
43 .setConfiguration(CONFIGURATION)
44 .build();
45
46 @Test
47 void test_lite_log_events() {
48 final List<LogEvent> logEvents = LogEventFixture.createLiteLogEvents(1_000);
49 test(logEvents);
50 }
51
52 @Test
53 void test_full_log_events() {
54 final List<LogEvent> logEvents = LogEventFixture.createFullLogEvents(1_000);
55 test(logEvents);
56 }
57
58 private static void test(final Collection<LogEvent> logEvents) {
59 for (final LogEvent logEvent : logEvents) {
60 test(logEvent);
61 }
62 }
63
64 private static void test(final LogEvent logEvent) {
65 final Map<String, Object> jsonTemplateLayoutMap = renderUsingJsonTemplateLayout(logEvent);
66 final Map<String, Object> jsonLayoutMap = renderUsingJsonLayout(logEvent);
67 // JsonLayout blindly serializes the Throwable as a POJO, this is,
68 // to say the least, quite wrong, and I ain't gonna try to emulate
69 // this behaviour in JsonTemplateLayout. Hence, discarding the "thrown"
70 // field.
71 jsonTemplateLayoutMap.remove("thrown");
72 jsonLayoutMap.remove("thrown");
73 Assertions.assertThat(jsonTemplateLayoutMap).isEqualTo(jsonLayoutMap);
74 }
75
76 private static Map<String, Object> renderUsingJsonTemplateLayout(
77 final LogEvent logEvent) {
78 return serializeUsingLayout(logEvent, JSON_TEMPLATE_LAYOUT);
79 }
80
81 private static Map<String, Object> renderUsingJsonLayout(
82 final LogEvent logEvent) {
83 return serializeUsingLayout(logEvent, JSON_LAYOUT);
84 }
85
86 }
+0
-104
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutAdditionalFieldTest.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.assertj.core.api.Assertions;
25 import org.junit.jupiter.api.Test;
26 import org.junit.jupiter.api.parallel.Execution;
27 import org.junit.jupiter.api.parallel.ExecutionMode;
28
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.List;
32 import java.util.Map;
33
34 @Execution(ExecutionMode.SAME_THREAD)
35 class JsonTemplateLayoutAdditionalFieldTest {
36
37 @Test
38 @LoggerContextSource("additionalFieldEnrichedJsonTemplateLayoutLogging.json")
39 void test_JSON_config_additional_fields(
40 final LoggerContext loggerContext,
41 final @Named(value = "List") ListAppender appender) {
42 assertAdditionalFields(loggerContext, appender);
43 }
44
45 @Test
46 @LoggerContextSource("additionalFieldEnrichedJsonTemplateLayoutLogging.properties")
47 void test_Properties_config_additional_fields(
48 final LoggerContext loggerContext,
49 final @Named(value = "List") ListAppender appender) {
50 assertAdditionalFields(loggerContext, appender);
51 }
52
53 @Test
54 @LoggerContextSource("additionalFieldEnrichedJsonTemplateLayoutLogging.xml")
55 void test_XML_config_additional_fields(
56 final LoggerContext loggerContext,
57 final @Named(value = "List") ListAppender appender) {
58 assertAdditionalFields(loggerContext, appender);
59 }
60
61 @Test
62 @LoggerContextSource("additionalFieldEnrichedJsonTemplateLayoutLogging.yaml")
63 void test_YAML_config_additional_fields(
64 final LoggerContext loggerContext,
65 final @Named(value = "List") ListAppender appender) {
66 assertAdditionalFields(loggerContext, appender);
67 }
68
69 private static void assertAdditionalFields(
70 final LoggerContext loggerContext,
71 final ListAppender appender) {
72
73 // Log an event.
74 final Logger logger =
75 loggerContext.getLogger(JsonTemplateLayoutAdditionalFieldTest.class);
76 logger.info("trigger");
77
78 // Verify that the appender has logged the event.
79 final List<byte[]> serializedEvents = appender.getData();
80 Assertions.assertThat(serializedEvents).hasSize(1);
81
82 // Deserialize the serialized event.
83 final byte[] serializedEvent = serializedEvents.get(0);
84 final String serializedEventJson =
85 new String(
86 serializedEvent,
87 JsonTemplateLayoutDefaults.getCharset());
88 final Object serializedEventObject = JsonReader.read(serializedEventJson);
89 Assertions.assertThat(serializedEventObject).isInstanceOf(Map.class);
90 @SuppressWarnings("unchecked") final Map<String, Object> serializedEventMap =
91 (Map<String, Object>) serializedEventObject;
92
93 // Verify the serialized additional fields.
94 Assertions
95 .assertThat(serializedEventMap)
96 .containsEntry("stringField", "string")
97 .containsEntry("numberField", 1)
98 .containsEntry("objectField", Collections.singletonMap("numberField", 1))
99 .containsEntry("listField", Arrays.asList(1, "two"));
100
101 }
102
103 }
+0
-235
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutConcurrentEncodeTest.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.apache.logging.log4j.core.config.Configurator;
23 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
24 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
25 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
26 import org.apache.logging.log4j.core.layout.StringBuilderEncoder;
27 import org.apache.logging.log4j.util.Strings;
28 import org.junit.jupiter.api.parallel.Execution;
29 import org.junit.jupiter.api.parallel.ExecutionMode;
30 import org.junit.jupiter.params.ParameterizedTest;
31 import org.junit.jupiter.params.provider.ValueSource;
32
33 import java.io.*;
34 import java.nio.charset.StandardCharsets;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.util.List;
39 import java.util.function.Consumer;
40 import java.util.stream.Collectors;
41 import java.util.stream.IntStream;
42
43 import static org.apache.logging.log4j.layout.template.json.TestHelpers.asMap;
44 import static org.apache.logging.log4j.layout.template.json.TestHelpers.writeJson;
45 import static org.assertj.core.api.Assertions.assertThat;
46
47 /**
48 * Tests {@link JsonTemplateLayout} doesn't exhibit unexpected behavior when accessed concurrently.
49 * <p>
50 * Earlier the test was designed to pass a specially crafted {@link ByteBufferDestination} implementation raising a flag when a concurrent access was detected.
51 * Though this doesn't play along well with the {@link ThreadLocal}s employed in {@link StringBuilderEncoder}.
52 * Those do concurrently access to {@link ByteBufferDestination} in ways with certain assumptions for the appender due to efficiency reasons.
53 * Eventually we converged to the current state of the test where the output is written to a file and is checked for any interleaved lines.
54 * </p>
55 */
56 @SuppressWarnings("SameParameterValue")
57 // Running tests in parallel is causing strange issues at the Log4j configuration level.
58 // Falling back to sequential test run for the moment.
59 @Execution(ExecutionMode.SAME_THREAD)
60 class JsonTemplateLayoutConcurrentEncodeTest {
61
62 @ParameterizedTest
63 @ValueSource(strings = {
64 "dummy",
65 "threadLocal",
66 "queue:supplier=java.util.concurrent.ArrayBlockingQueue.new",
67 "queue:supplier=org.jctools.queues.MpmcArrayQueue.new"
68 })
69 void test_concurrent_encode(final String recyclerFactory) throws IOException {
70 final Path appenderFilepath = createAppenderFilepath(recyclerFactory);
71 final int workerCount = 10;
72 final int messageLength = 1_000;
73 final int messageCount = 1_000;
74 try {
75 withContextFromTemplate(appenderFilepath, recyclerFactory, loggerContext -> {
76 final Logger logger = loggerContext.getLogger(JsonTemplateLayoutConcurrentEncodeTest.class);
77 runWorkers(workerCount, messageLength, messageCount, logger);
78 });
79 verifyLines(appenderFilepath, messageLength, workerCount * messageCount);
80 } catch (final Throwable error) {
81 final String message = String.format(
82 "test failure for appender pointing to file: `%s`",
83 appenderFilepath);
84 throw new AssertionError(message, error);
85 }
86 Files.delete(appenderFilepath);
87 }
88
89 private static Path createAppenderFilepath(final String recyclerFactory) {
90 final String appenderFilename = String.format(
91 "%s-%s.log",
92 JsonTemplateLayoutConcurrentEncodeTest.class.getSimpleName(),
93 recyclerFactory.replaceAll("[^A-Za-z0-9]+", ""));
94 return Paths.get(
95 System.getProperty("java.io.tmpdir"),
96 appenderFilename);
97 }
98
99 private static void withContextFromTemplate(
100 final Path appenderFilepath,
101 final String recyclerFactory,
102 final Consumer<LoggerContext> loggerContextConsumer) {
103
104 // Create the configuration builder.
105 final String configName = String.format(
106 "%s-%s",
107 JsonTemplateLayoutConcurrentEncodeTest.class.getSimpleName(),
108 recyclerFactory.replaceAll("[^A-Za-z0-9]+", ""));
109 final ConfigurationBuilder<?> configBuilder = ConfigurationBuilderFactory
110 .newConfigurationBuilder()
111 .setStatusLevel(Level.ERROR)
112 .setConfigurationName(configName);
113
114 // Create the configuration.
115 final Object eventTemplate = asMap("$resolver", "message");
116 final String eventTemplateJson = writeJson(eventTemplate);
117 final String appenderName = "File";
118 final Configuration config = configBuilder
119 .add(configBuilder
120 .newAppender(appenderName, "File")
121 .addAttribute("fileName", appenderFilepath.toAbsolutePath().toString())
122 .addAttribute("append", false)
123 .addAttribute("immediateFlush", false)
124 .addAttribute("ignoreExceptions", false)
125 .add(configBuilder
126 .newLayout("JsonTemplateLayout")
127 .addAttribute("eventTemplate", eventTemplateJson)
128 .addAttribute("recyclerFactory", recyclerFactory)))
129 .add(configBuilder
130 .newRootLogger(Level.ALL)
131 .add(configBuilder.newAppenderRef(appenderName)))
132 .build(false);
133
134 // Initialize the configuration and pass it to the consumer.
135 try (final LoggerContext loggerContext = Configurator.initialize(config)) {
136 loggerContextConsumer.accept(loggerContext);
137 }
138
139 }
140
141 private static void runWorkers(
142 final int workerCount,
143 final int messageLength,
144 final int messageCount,
145 final Logger logger) {
146 final List<Thread> workers = IntStream
147 .range(0, workerCount)
148 .mapToObj((final int threadIndex) ->
149 createWorker(messageLength, messageCount, logger, threadIndex))
150 .collect(Collectors.toList());
151 workers.forEach(Thread::start);
152 workers.forEach((final Thread worker) -> {
153 try {
154 worker.join();
155 } catch (final InterruptedException ignored) {
156 Thread.currentThread().interrupt();
157 System.err.format("join to `%s` interrupted%n", worker.getName());
158 }
159 });
160 }
161
162 private static Thread createWorker(
163 final int messageLength,
164 final int messageCount,
165 final Logger logger,
166 final int threadIndex) {
167
168 // Check thread index.
169 final int maxThreadIndex = 'Z' - 'A';
170 if (threadIndex > maxThreadIndex) {
171 String message = String.format(
172 "was expecting `threadIndex <= %d`, found: %d",
173 maxThreadIndex, threadIndex);
174 throw new IndexOutOfBoundsException(message);
175 }
176
177 // Determine the message to be logged.
178 final String messageLetter = String.valueOf((char) ('A' + threadIndex));
179 final String message = Strings.repeat(messageLetter, messageLength);
180
181 // Create the worker thread.
182 final String threadName = String.format("Worker-%d", threadIndex);
183 return new Thread(
184 () -> {
185 for (int i = 0; i < messageCount; i++) {
186 logger.info(message);
187 }
188 },
189 threadName);
190
191 }
192
193 private static void verifyLines(
194 final Path appenderFilepath,
195 final int messageLength,
196 final int messageCount) {
197 try (final InputStream inputStream = new FileInputStream(appenderFilepath.toFile());
198 final Reader reader = new InputStreamReader(inputStream, StandardCharsets.US_ASCII);
199 final BufferedReader bufferedReader = new BufferedReader(reader)) {
200 int lineCount = 0;
201 String line;
202 while ((line = bufferedReader.readLine()) != null) {
203 try {
204 verifyLine(messageLength, line);
205 } catch (final Throwable error) {
206 final String message = String.format(
207 "verification failure at line %d: `%s`",
208 (lineCount + 1), line);
209 throw new AssertionError(message, error);
210 }
211 lineCount++;
212 }
213 assertThat(lineCount).isEqualTo(messageCount);
214 } catch (final IOException error) {
215 final String message = String.format("error verifying file: `%s`", appenderFilepath);
216 throw new RuntimeException(message, error);
217 }
218 }
219
220 private static void verifyLine(final int messageLength, final String line) {
221 assertThat(line).hasSize(messageLength + 2);
222 final char c0 = line.charAt(0);
223 final char cN = line.charAt(messageLength + 1);
224 assertThat(c0).isEqualTo('"').isEqualTo(cN);
225 final char c1 = line.charAt(1);
226 for (int i = 1; i < messageLength; i++) {
227 final char c = line.charAt(1 + i);
228 assertThat(c)
229 .describedAs("character at index %d", i)
230 .isEqualTo(c1);
231 }
232 }
233
234 }
+0
-43
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutGcFreeTest.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.core.GcFreeLoggingTestUtil;
19 import org.junit.jupiter.api.Test;
20 import org.junit.jupiter.api.Tag;
21
22 @Tag("allocation")
23 @Tag("functional")
24 public class JsonTemplateLayoutGcFreeTest {
25
26 @Test
27 void test_no_allocation_during_steady_state_logging() throws Exception {
28 GcFreeLoggingTestUtil.runTest(getClass());
29 }
30
31 /**
32 * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
33 */
34 public static void main(final String[] args) throws Exception {
35 System.setProperty("log4j.layout.jsonTemplate.recyclerFactory", "threadLocal");
36 System.setProperty("log4j2.garbagefree.threadContextMap", "true");
37 GcFreeLoggingTestUtil.executeLogging(
38 "gcFreeJsonTemplateLayoutLogging.xml",
39 JsonTemplateLayoutGcFreeTest.class);
40 }
41
42 }
+0
-152
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutNullEventDelimiterTest.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.assertj.core.api.Assertions;
22 import org.awaitility.Awaitility;
23 import org.junit.jupiter.api.Test;
24
25 import java.io.ByteArrayOutputStream;
26 import java.io.EOFException;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.net.ServerSocket;
30 import java.net.Socket;
31 import java.time.Duration;
32
33 class JsonTemplateLayoutNullEventDelimiterTest {
34
35 @Test
36 void test() throws Exception {
37
38 // Start the TCP server.
39 try (final TcpServer server = new TcpServer(0)) {
40
41 // Set the configuration.
42 System.setProperty(
43 "serverPort",
44 String.valueOf(server.getPort()));
45 System.setProperty(
46 "log4j.configurationFile",
47 "nullEventDelimitedJsonTemplateLayoutLogging.xml");
48
49 // Produce log events.
50 final Logger logger = LogManager.getLogger(JsonTemplateLayoutNullEventDelimiterTest.class);
51 logger.log(Level.INFO, "foo");
52 logger.log(Level.INFO, "bar");
53
54 // Set the expected bytes.
55 final byte[] expectedBytes = {
56 '"', 'f', 'o', 'o', '"', '\0',
57 '"', 'b', 'a', 'r', '"', '\0'
58 };
59
60 // Wait for the log events.
61 Awaitility
62 .await()
63 .atMost(Duration.ofSeconds(10))
64 .pollDelay(Duration.ofSeconds(1))
65 .until(() -> server.getTotalReadByteCount() >= expectedBytes.length);
66
67 // Verify the received log events.
68 final byte[] actualBytes = server.getReceivedBytes();
69 Assertions.assertThat(actualBytes).startsWith(expectedBytes);
70
71 }
72
73 }
74
75 private static final class TcpServer extends Thread implements AutoCloseable {
76
77 private final ServerSocket serverSocket;
78
79 private final ByteArrayOutputStream outputStream;
80
81 private volatile int totalReadByteCount = 0;
82
83 private volatile boolean closed = false;
84
85 private TcpServer(final int port) throws IOException {
86 this.serverSocket = new ServerSocket(port);
87 this.outputStream = new ByteArrayOutputStream();
88 serverSocket.setReuseAddress(true);
89 serverSocket.setSoTimeout(5_000);
90 setDaemon(true);
91 start();
92 }
93
94 @Override
95 public void run() {
96 try {
97 try (final Socket socket = serverSocket.accept()) {
98 final InputStream inputStream = socket.getInputStream();
99 final byte[] buffer = new byte[1024];
100 // noinspection InfiniteLoopStatement
101 while (true) {
102 final int readByteCount = inputStream.read(buffer);
103 if (readByteCount > 0) {
104 synchronized (this) {
105 totalReadByteCount += readByteCount;
106 outputStream.write(buffer, 0, readByteCount);
107 }
108 }
109 }
110 }
111 } catch (final EOFException ignored) {
112 // Socket is closed.
113 } catch (final Exception error) {
114 if (!closed) {
115 throw new RuntimeException(error);
116 }
117 }
118 }
119
120 public int getPort() {
121 return serverSocket.getLocalPort();
122 }
123
124 public synchronized byte[] getReceivedBytes() {
125 return outputStream.toByteArray();
126 }
127
128 public synchronized int getTotalReadByteCount() {
129 return totalReadByteCount;
130 }
131
132 @Override
133 public synchronized void close() {
134 if (closed) {
135 throw new IllegalStateException("shutdown has already been invoked");
136 }
137 closed = true;
138 interrupt();
139 try {
140 join(3_000L);
141 } catch (InterruptedException ignored) {
142 // Due to JDK-7027157, we shouldn't throw an InterruptedException
143 // from an AutoCloseable#close() method. Hence we catch it and
144 // then restore the interrupted flag.
145 Thread.currentThread().interrupt();
146 }
147 }
148
149 }
150
151 }
+0
-1886
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.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.logging.log4j.layout.template.json;
17
18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.fasterxml.jackson.databind.MappingIterator;
20 import com.fasterxml.jackson.databind.ObjectMapper;
21 import org.apache.logging.log4j.Level;
22 import org.apache.logging.log4j.Marker;
23 import org.apache.logging.log4j.MarkerManager;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.appender.SocketAppender;
26 import org.apache.logging.log4j.core.config.Configuration;
27 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
28 import org.apache.logging.log4j.core.config.plugins.Plugin;
29 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
31 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
32 import org.apache.logging.log4j.core.lookup.MainMapLookup;
33 import org.apache.logging.log4j.core.net.Severity;
34 import org.apache.logging.log4j.core.time.MutableInstant;
35 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
36 import org.apache.logging.log4j.layout.template.json.resolver.EventResolver;
37 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext;
38 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory;
39 import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver;
40 import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverConfig;
41 import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory;
42 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
43 import org.apache.logging.log4j.message.Message;
44 import org.apache.logging.log4j.message.MessageFactory;
45 import org.apache.logging.log4j.message.ObjectMessage;
46 import org.apache.logging.log4j.message.ParameterizedMessageFactory;
47 import org.apache.logging.log4j.message.ReusableMessageFactory;
48 import org.apache.logging.log4j.message.SimpleMessage;
49 import org.apache.logging.log4j.message.StringMapMessage;
50 import org.apache.logging.log4j.test.AvailablePortFinder;
51 import org.apache.logging.log4j.util.Strings;
52 import org.assertj.core.api.Assertions;
53 import org.junit.jupiter.api.Test;
54
55 import java.io.ByteArrayOutputStream;
56 import java.io.EOFException;
57 import java.io.IOException;
58 import java.io.InputStream;
59 import java.io.PrintStream;
60 import java.io.UnsupportedEncodingException;
61 import java.math.BigDecimal;
62 import java.net.ServerSocket;
63 import java.net.Socket;
64 import java.nio.ByteBuffer;
65 import java.nio.charset.Charset;
66 import java.time.Instant;
67 import java.time.temporal.ChronoField;
68 import java.time.temporal.TemporalAccessor;
69 import java.util.ArrayList;
70 import java.util.Arrays;
71 import java.util.Collections;
72 import java.util.List;
73 import java.util.Map;
74 import java.util.concurrent.ArrayBlockingQueue;
75 import java.util.concurrent.BlockingQueue;
76 import java.util.concurrent.TimeUnit;
77 import java.util.concurrent.atomic.AtomicInteger;
78 import java.util.stream.Collectors;
79 import java.util.stream.IntStream;
80
81 import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
82 import static org.assertj.core.api.Assertions.assertThat;
83
84 @SuppressWarnings("DoubleBraceInitialization")
85 class JsonTemplateLayoutTest {
86
87 private static final List<LogEvent> LOG_EVENTS = LogEventFixture.createFullLogEvents(5);
88
89 private static final ObjectMapper OBJECT_MAPPER = JacksonFixture.getObjectMapper();
90
91 private static final String LOGGER_NAME = JsonTemplateLayoutTest.class.getSimpleName();
92
93 @Test
94 void test_serialized_event() throws IOException {
95 final String lookupTestKey = "lookup_test_key";
96 final String lookupTestVal =
97 String.format("lookup_test_value_%d", (int) (1000 * Math.random()));
98 System.setProperty(lookupTestKey, lookupTestVal);
99 for (final LogEvent logEvent : LOG_EVENTS) {
100 checkLogEvent(logEvent, lookupTestKey, lookupTestVal);
101 }
102 }
103
104 private void checkLogEvent(
105 final LogEvent logEvent,
106 @SuppressWarnings("SameParameterValue")
107 final String lookupTestKey,
108 final String lookupTestVal) throws IOException {
109 final JsonTemplateLayout layout = JsonTemplateLayout
110 .newBuilder()
111 .setConfiguration(CONFIGURATION)
112 .setEventTemplateUri("classpath:testJsonTemplateLayout.json")
113 .setStackTraceEnabled(true)
114 .setLocationInfoEnabled(true)
115 .build();
116 final String serializedLogEvent = layout.toSerializable(logEvent);
117 final JsonNode rootNode = OBJECT_MAPPER.readValue(serializedLogEvent, JsonNode.class);
118 checkConstants(rootNode);
119 checkBasicFields(logEvent, rootNode);
120 checkSource(logEvent, rootNode);
121 checkException(layout.getCharset(), logEvent, rootNode);
122 checkLookupTest(lookupTestKey, lookupTestVal, rootNode);
123 }
124
125 private static void checkConstants(final JsonNode rootNode) {
126 assertThat(point(rootNode, "@version").asInt()).isEqualTo(1);
127 }
128
129 private static void checkBasicFields(final LogEvent logEvent, final JsonNode rootNode) {
130 assertThat(point(rootNode, "message").asText())
131 .isEqualTo(logEvent.getMessage().getFormattedMessage());
132 assertThat(point(rootNode, "level").asText())
133 .isEqualTo(logEvent.getLevel().name());
134 assertThat(point(rootNode, "logger_fqcn").asText())
135 .isEqualTo(logEvent.getLoggerFqcn());
136 assertThat(point(rootNode, "logger_name").asText())
137 .isEqualTo(logEvent.getLoggerName());
138 assertThat(point(rootNode, "thread_id").asLong())
139 .isEqualTo(logEvent.getThreadId());
140 assertThat(point(rootNode, "thread_name").asText())
141 .isEqualTo(logEvent.getThreadName());
142 assertThat(point(rootNode, "thread_priority").asInt())
143 .isEqualTo(logEvent.getThreadPriority());
144 assertThat(point(rootNode, "end_of_batch").asBoolean())
145 .isEqualTo(logEvent.isEndOfBatch());
146 }
147
148 private static void checkSource(final LogEvent logEvent, final JsonNode rootNode) {
149 assertThat(point(rootNode, "class").asText()).isEqualTo(logEvent.getSource().getClassName());
150 assertThat(point(rootNode, "file").asText()).isEqualTo(logEvent.getSource().getFileName());
151 assertThat(point(rootNode, "line_number").asInt()).isEqualTo(logEvent.getSource().getLineNumber());
152 }
153
154 private static void checkException(
155 final Charset charset,
156 final LogEvent logEvent,
157 final JsonNode rootNode) {
158 final Throwable thrown = logEvent.getThrown();
159 if (thrown != null) {
160 assertThat(point(rootNode, "exception_class").asText()).isEqualTo(thrown.getClass().getCanonicalName());
161 assertThat(point(rootNode, "exception_message").asText()).isEqualTo(thrown.getMessage());
162 final String stackTrace = serializeStackTrace(charset, thrown);
163 assertThat(point(rootNode, "stacktrace").asText()).isEqualTo(stackTrace);
164 }
165 }
166
167 private static String serializeStackTrace(
168 final Charset charset,
169 final Throwable exception) {
170 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
171 final String charsetName = charset.name();
172 try (final PrintStream printStream =
173 new PrintStream(outputStream, false, charsetName)) {
174 exception.printStackTrace(printStream);
175 return outputStream.toString(charsetName);
176 } catch (final UnsupportedEncodingException error) {
177 throw new RuntimeException("failed converting the stack trace to string", error);
178 }
179 }
180
181 private static void checkLookupTest(
182 final String lookupTestKey,
183 final String lookupTestVal,
184 final JsonNode rootNode) {
185 assertThat(point(rootNode, lookupTestKey).asText()).isEqualTo(lookupTestVal);
186 }
187
188 private static JsonNode point(final JsonNode node, final Object... fields) {
189 final String pointer = createJsonPointer(fields);
190 return node.at(pointer);
191 }
192
193 private static String createJsonPointer(final Object... fields) {
194 final StringBuilder jsonPathBuilder = new StringBuilder();
195 for (final Object field : fields) {
196 jsonPathBuilder.append("/").append(field);
197 }
198 return jsonPathBuilder.toString();
199 }
200
201 @Test
202 void test_inline_template() {
203
204 // Create the log event.
205 final SimpleMessage message = new SimpleMessage("Hello, World");
206 final String formattedInstant = "2017-09-28T17:13:29.098Z";
207 final TemporalAccessor instantAccessor = Instant.parse(formattedInstant);
208 final long instantEpochSeconds = instantAccessor.getLong(ChronoField.INSTANT_SECONDS);
209 final int instantEpochSecondsNanos = instantAccessor.get(ChronoField.NANO_OF_SECOND);
210 final MutableInstant instant = new MutableInstant();
211 instant.initFromEpochSecond(instantEpochSeconds, instantEpochSecondsNanos);
212 final LogEvent logEvent = Log4jLogEvent
213 .newBuilder()
214 .setLoggerName(LOGGER_NAME)
215 .setLevel(Level.INFO)
216 .setMessage(message)
217 .setInstant(instant)
218 .build();
219
220 // Create the event template.
221 final String timestampFieldName = "@timestamp";
222 final String staticFieldName = "staticFieldName";
223 final String staticFieldValue = "staticFieldValue";
224 final String eventTemplate = writeJson(asMap(
225 timestampFieldName, asMap(
226 "$resolver", "timestamp",
227 "pattern", asMap(
228 "format", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
229 "timeZone", "UTC")),
230 staticFieldName, staticFieldValue));
231
232 // Create the layout.
233 final JsonTemplateLayout layout = JsonTemplateLayout
234 .newBuilder()
235 .setConfiguration(CONFIGURATION)
236 .setEventTemplate(eventTemplate)
237 .build();
238
239 // Check the serialized event.
240 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
241 assertThat(accessor.getString(timestampFieldName)).isEqualTo(formattedInstant);
242 assertThat(accessor.getString(staticFieldName)).isEqualTo(staticFieldValue);
243 });
244
245 }
246
247 @Test
248 void test_log4j_deferred_runtime_resolver_for_MapMessage() {
249
250 // Create the event template.
251 final String eventTemplate = writeJson(asMap(
252 "mapValue3", asMap("$resolver", "message"),
253 "mapValue1", "${map:key1}",
254 "mapValue2", "${map:key2}",
255 "nestedLookupEmptyValue", "${map:noExist:-${map:noExist2:-${map:noExist3:-}}}",
256 "nestedLookupStaticValue", "${map:noExist:-${map:noExist2:-${map:noExist3:-Static Value}}}"));
257
258 // Create the layout.
259 final JsonTemplateLayout layout = JsonTemplateLayout
260 .newBuilder()
261 .setConfiguration(CONFIGURATION)
262 .setEventTemplate(eventTemplate)
263 .build();
264
265 // Create the log event with a MapMessage.
266 final StringMapMessage mapMessage = new StringMapMessage()
267 .with("key1", "val1")
268 .with("key2", "val2")
269 .with("key3", Collections.singletonMap("foo", "bar"));
270 final LogEvent logEvent = Log4jLogEvent
271 .newBuilder()
272 .setLoggerName(LOGGER_NAME)
273 .setLevel(Level.INFO)
274 .setMessage(mapMessage)
275 .setTimeMillis(System.currentTimeMillis())
276 .build();
277
278 // Check the serialized event.
279 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
280 assertThat(accessor.getString("mapValue1")).isEqualTo("val1");
281 assertThat(accessor.getString("mapValue2")).isEqualTo("val2");
282 assertThat(accessor.getString("nestedLookupEmptyValue")).isEmpty();
283 assertThat(accessor.getString("nestedLookupStaticValue")).isEqualTo("Static Value");
284 });
285
286 }
287
288 @Test
289 void test_property_injection() {
290
291 // Create the log event.
292 final SimpleMessage message = new SimpleMessage("Hello, World");
293 final LogEvent logEvent = Log4jLogEvent
294 .newBuilder()
295 .setLoggerName(LOGGER_NAME)
296 .setLevel(Level.INFO)
297 .setMessage(message)
298 .build();
299
300 // Create the event template with property.
301 final String propertyName = "propertyName";
302 final String eventTemplate = writeJson(asMap(
303 propertyName, "${" + propertyName + "}"));
304
305 // Create the layout with property.
306 final String propertyValue = "propertyValue";
307 final Configuration config = ConfigurationBuilderFactory
308 .newConfigurationBuilder()
309 .addProperty(propertyName, propertyValue)
310 .build();
311 final JsonTemplateLayout layout = JsonTemplateLayout
312 .newBuilder()
313 .setConfiguration(config)
314 .setEventTemplate(eventTemplate)
315 .build();
316
317 // Check the serialized event.
318 usingSerializedLogEventAccessor(layout, logEvent, accessor ->
319 assertThat(accessor.getString(propertyName)).isEqualTo(propertyValue));
320
321 }
322
323 @Test
324 void test_empty_root_cause() {
325
326 // Create the log event.
327 final SimpleMessage message = new SimpleMessage("Hello, World!");
328 final RuntimeException exception = new RuntimeException("failure for test purposes");
329 final LogEvent logEvent = Log4jLogEvent
330 .newBuilder()
331 .setLoggerName(LOGGER_NAME)
332 .setLevel(Level.ERROR)
333 .setMessage(message)
334 .setThrown(exception)
335 .build();
336
337 // Create the event template.
338 final String eventTemplate = writeJson(asMap(
339 "ex_class", asMap(
340 "$resolver", "exception",
341 "field", "className"),
342 "ex_message", asMap(
343 "$resolver", "exception",
344 "field", "message"),
345 "ex_stacktrace", asMap(
346 "$resolver", "exception",
347 "field", "stackTrace",
348 "stackTrace", asMap(
349 "stringified", true)),
350 "root_ex_class", asMap(
351 "$resolver", "exceptionRootCause",
352 "field", "className"),
353 "root_ex_message", asMap(
354 "$resolver", "exceptionRootCause",
355 "field", "message"),
356 "root_ex_stacktrace", asMap(
357 "$resolver", "exceptionRootCause",
358 "field", "stackTrace",
359 "stackTrace", asMap(
360 "stringified", true))));
361
362 // Create the layout.
363 final JsonTemplateLayout layout = JsonTemplateLayout
364 .newBuilder()
365 .setConfiguration(CONFIGURATION)
366 .setStackTraceEnabled(true)
367 .setEventTemplate(eventTemplate)
368 .build();
369
370 // Check the serialized event.
371 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
372 assertThat(accessor.getString("ex_class"))
373 .isEqualTo(exception.getClass().getCanonicalName());
374 assertThat(accessor.getString("ex_message"))
375 .isEqualTo(exception.getMessage());
376 assertThat(accessor.getString("ex_stacktrace"))
377 .startsWith(exception.getClass().getCanonicalName() + ": " + exception.getMessage());
378 assertThat(accessor.getString("root_ex_class"))
379 .isEqualTo(accessor.getString("ex_class"));
380 assertThat(accessor.getString("root_ex_message"))
381 .isEqualTo(accessor.getString("ex_message"));
382 assertThat(accessor.getString("root_ex_stacktrace"))
383 .isEqualTo(accessor.getString("ex_stacktrace"));
384 });
385
386 }
387
388 @Test
389 void test_root_cause() {
390
391 // Create the log event.
392 final SimpleMessage message = new SimpleMessage("Hello, World!");
393 final RuntimeException exceptionCause = new RuntimeException("failure cause for test purposes");
394 final RuntimeException exception = new RuntimeException("failure for test purposes", exceptionCause);
395 final LogEvent logEvent = Log4jLogEvent
396 .newBuilder()
397 .setLoggerName(LOGGER_NAME)
398 .setLevel(Level.ERROR)
399 .setMessage(message)
400 .setThrown(exception)
401 .build();
402
403 // Create the event template.
404 final String eventTemplate = writeJson(asMap(
405 "ex_class", asMap(
406 "$resolver", "exception",
407 "field", "className"),
408 "ex_message", asMap(
409 "$resolver", "exception",
410 "field", "message"),
411 "ex_stacktrace", asMap(
412 "$resolver", "exception",
413 "field", "stackTrace",
414 "stringified", true),
415 "root_ex_class", asMap(
416 "$resolver", "exceptionRootCause",
417 "field", "className"),
418 "root_ex_message", asMap(
419 "$resolver", "exceptionRootCause",
420 "field", "message"),
421 "root_ex_stacktrace", asMap(
422 "$resolver", "exceptionRootCause",
423 "field", "stackTrace",
424 "stackTrace", asMap(
425 "stringified", true))));
426
427 // Create the layout.
428 final JsonTemplateLayout layout = JsonTemplateLayout
429 .newBuilder()
430 .setConfiguration(CONFIGURATION)
431 .setStackTraceEnabled(true)
432 .setEventTemplate(eventTemplate)
433 .build();
434
435 // Check the serialized event.
436 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
437 assertThat(accessor.getString("ex_class"))
438 .isEqualTo(exception.getClass().getCanonicalName());
439 assertThat(accessor.getString("ex_message"))
440 .isEqualTo(exception.getMessage());
441 assertThat(accessor.getString("ex_stacktrace"))
442 .startsWith(exception.getClass().getCanonicalName() + ": " + exception.getMessage());
443 assertThat(accessor.getString("root_ex_class"))
444 .isEqualTo(exceptionCause.getClass().getCanonicalName());
445 assertThat(accessor.getString("root_ex_message"))
446 .isEqualTo(exceptionCause.getMessage());
447 assertThat(accessor.getString("root_ex_stacktrace"))
448 .startsWith(exceptionCause.getClass().getCanonicalName() + ": " + exceptionCause.getMessage());
449 });
450
451 }
452
453 @Test
454 void test_marker_name() {
455
456 // Create the log event.
457 final SimpleMessage message = new SimpleMessage("Hello, World!");
458 final String markerName = "test";
459 final Marker marker = MarkerManager.getMarker(markerName);
460 final LogEvent logEvent = Log4jLogEvent
461 .newBuilder()
462 .setLoggerName(LOGGER_NAME)
463 .setLevel(Level.ERROR)
464 .setMessage(message)
465 .setMarker(marker)
466 .build();
467
468 // Create the event template.
469 final String messageKey = "message";
470 final String markerNameKey = "marker";
471 final String eventTemplate = writeJson(asMap(
472 "message", asMap("$resolver", "message"),
473 "marker", asMap(
474 "$resolver", "marker",
475 "field", "name")));
476
477 // Create the layout.
478 final JsonTemplateLayout layout = JsonTemplateLayout
479 .newBuilder()
480 .setConfiguration(CONFIGURATION)
481 .setEventTemplate(eventTemplate)
482 .build();
483
484 // Check the serialized event.
485 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
486 assertThat(accessor.getString(messageKey)).isEqualTo(message.getFormattedMessage());
487 assertThat(accessor.getString(markerNameKey)).isEqualTo(markerName);
488 });
489
490 }
491
492 @Test
493 void test_lineSeparator_suffix() {
494
495 // Create the log event.
496 final SimpleMessage message = new SimpleMessage("Hello, World!");
497 final LogEvent logEvent = Log4jLogEvent
498 .newBuilder()
499 .setLoggerName(LOGGER_NAME)
500 .setLevel(Level.INFO)
501 .setMessage(message)
502 .build();
503
504 // Check line separators.
505 test_lineSeparator_suffix(logEvent, true);
506 test_lineSeparator_suffix(logEvent, false);
507
508 }
509
510 private void test_lineSeparator_suffix(
511 final LogEvent logEvent,
512 final boolean prettyPrintEnabled) {
513
514 // Create the layout.
515 final JsonTemplateLayout layout = JsonTemplateLayout
516 .newBuilder()
517 .setConfiguration(CONFIGURATION)
518 .setEventTemplateUri("classpath:LogstashJsonEventLayoutV1.json")
519 .build();
520
521 // Check the serialized event.
522 final String serializedLogEvent = layout.toSerializable(logEvent);
523 final String assertionCaption = String.format("testing lineSeperator (prettyPrintEnabled=%s)", prettyPrintEnabled);
524 assertThat(serializedLogEvent).as(assertionCaption).endsWith("}" + System.lineSeparator());
525
526 }
527
528 @Test
529 void test_main_key_access() {
530
531 // Set main() arguments.
532 final String kwKey = "--name";
533 final String kwVal = "aNameValue";
534 final String positionArg = "position2Value";
535 final String missingKwKey = "--missing";
536 final String[] mainArgs = {kwKey, kwVal, positionArg};
537 MainMapLookup.setMainArguments(mainArgs);
538
539 // Create the log event.
540 final SimpleMessage message = new SimpleMessage("Hello, World!");
541 final LogEvent logEvent = Log4jLogEvent
542 .newBuilder()
543 .setLoggerName(LOGGER_NAME)
544 .setLevel(Level.INFO)
545 .setMessage(message)
546 .build();
547
548 // Create the template.
549 final String template = writeJson(asMap(
550 "name", asMap(
551 "$resolver", "main",
552 "key", kwKey),
553 "positionArg", asMap(
554 "$resolver", "main",
555 "index", 2),
556 "notFoundArg", asMap(
557 "$resolver", "main",
558 "key", missingKwKey)));
559
560 // Create the layout.
561 final JsonTemplateLayout layout = JsonTemplateLayout
562 .newBuilder()
563 .setConfiguration(CONFIGURATION)
564 .setEventTemplate(template)
565 .build();
566
567 // Check the serialized event.
568 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
569 assertThat(accessor.getString("name")).isEqualTo(kwVal);
570 assertThat(accessor.getString("positionArg")).isEqualTo(positionArg);
571 assertThat(accessor.exists("notFoundArg")).isFalse();
572 });
573
574 }
575
576 @Test
577 void test_StackTraceElement_template() {
578
579 // Create the stack trace element template.
580 final String classNameFieldName = "className";
581 final String methodNameFieldName = "methodName";
582 final String fileNameFieldName = "fileName";
583 final String lineNumberFieldName = "lineNumber";
584 final String stackTraceElementTemplate = writeJson(asMap(
585 classNameFieldName, asMap(
586 "$resolver", "stackTraceElement",
587 "field", "className"),
588 methodNameFieldName, asMap(
589 "$resolver", "stackTraceElement",
590 "field", "methodName"),
591 fileNameFieldName, asMap(
592 "$resolver", "stackTraceElement",
593 "field", "fileName"),
594 lineNumberFieldName, asMap(
595 "$resolver", "stackTraceElement",
596 "field", "lineNumber")));
597
598 // Create the event template.
599 final String stackTraceFieldName = "stackTrace";
600 final String eventTemplate = writeJson(asMap(
601 stackTraceFieldName, asMap(
602 "$resolver", "exception",
603 "field", "stackTrace")));
604
605 // Create the layout.
606 final JsonTemplateLayout layout = JsonTemplateLayout
607 .newBuilder()
608 .setConfiguration(CONFIGURATION)
609 .setStackTraceEnabled(true)
610 .setStackTraceElementTemplate(stackTraceElementTemplate)
611 .setEventTemplate(eventTemplate)
612 .build();
613
614 // Create the log event.
615 final SimpleMessage message = new SimpleMessage("Hello, World!");
616 final RuntimeException exceptionCause = new RuntimeException("failure cause for test purposes");
617 final RuntimeException exception = new RuntimeException("failure for test purposes", exceptionCause);
618 final LogEvent logEvent = Log4jLogEvent
619 .newBuilder()
620 .setLoggerName(LOGGER_NAME)
621 .setLevel(Level.ERROR)
622 .setMessage(message)
623 .setThrown(exception)
624 .build();
625
626 // Check the serialized event.
627 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
628 assertThat(accessor.exists(stackTraceFieldName)).isTrue();
629 @SuppressWarnings("unchecked")
630 final List<Map<String, Object>> deserializedStackTraceElements =
631 accessor.getObject(stackTraceFieldName, List.class);
632 final StackTraceElement[] stackTraceElements = exception.getStackTrace();
633 assertThat(deserializedStackTraceElements.size()).isEqualTo(stackTraceElements.length);
634 for (int stackTraceElementIndex = 0;
635 stackTraceElementIndex < stackTraceElements.length;
636 stackTraceElementIndex++) {
637 final StackTraceElement stackTraceElement = stackTraceElements[stackTraceElementIndex];
638 final Map<String, Object> deserializedStackTraceElement = deserializedStackTraceElements.get(stackTraceElementIndex);
639 assertThat(deserializedStackTraceElement.size()).isEqualTo(4);
640 assertThat(deserializedStackTraceElement.get(classNameFieldName))
641 .isEqualTo(stackTraceElement.getClassName());
642 assertThat(deserializedStackTraceElement.get(methodNameFieldName))
643 .isEqualTo(stackTraceElement.getMethodName());
644 assertThat(deserializedStackTraceElement.get(fileNameFieldName))
645 .isEqualTo(stackTraceElement.getFileName());
646 assertThat(deserializedStackTraceElement.get(lineNumberFieldName))
647 .isEqualTo(stackTraceElement.getLineNumber());
648 }
649 });
650
651 }
652
653 @Test
654 void test_toSerializable_toByteArray_encode_outputs() {
655
656 // Create the layout.
657 final JsonTemplateLayout layout = JsonTemplateLayout
658 .newBuilder()
659 .setConfiguration(CONFIGURATION)
660 .setEventTemplateUri("classpath:LogstashJsonEventLayoutV1.json")
661 .setStackTraceEnabled(true)
662 .build();
663
664 // Create the log event.
665 final LogEvent logEvent = LogEventFixture.createFullLogEvents(1).get(0);
666
667 // Get toSerializable() output.
668 final String toSerializableOutput = layout.toSerializable(logEvent);
669
670 // Get toByteArrayOutput().
671 final byte[] toByteArrayOutputBytes = layout.toByteArray(logEvent);
672 final String toByteArrayOutput = new String(
673 toByteArrayOutputBytes,
674 0,
675 toByteArrayOutputBytes.length,
676 layout.getCharset());
677
678 // Get encode() output.
679 final ByteBuffer byteBuffer = ByteBuffer.allocate(512 * 1024);
680 final ByteBufferDestination byteBufferDestination = new ByteBufferDestination() {
681
682 @Override
683 public ByteBuffer getByteBuffer() {
684 return byteBuffer;
685 }
686
687 @Override
688 public ByteBuffer drain(final ByteBuffer ignored) {
689 throw new UnsupportedOperationException();
690 }
691
692 @Override
693 public void writeBytes(final ByteBuffer data) {
694 byteBuffer.put(data);
695 }
696
697 @Override
698 public void writeBytes(final byte[] buffer, final int offset, final int length) {
699 byteBuffer.put(buffer, offset, length);
700 }
701
702 };
703 layout.encode(logEvent, byteBufferDestination);
704 String encodeOutput = new String(
705 byteBuffer.array(),
706 0,
707 byteBuffer.position(),
708 layout.getCharset());
709
710 // Compare outputs.
711 assertThat(toSerializableOutput).isEqualTo(toByteArrayOutput);
712 assertThat(toByteArrayOutput).isEqualTo(encodeOutput);
713
714 }
715
716 @Test
717 void test_maxStringLength() {
718
719 // Create the log event.
720 final int maxStringLength = 30;
721 final String excessiveMessageString = Strings.repeat("m", maxStringLength) + 'M';
722 final SimpleMessage message = new SimpleMessage(excessiveMessageString);
723 final Throwable thrown = new RuntimeException();
724 final LogEvent logEvent = Log4jLogEvent
725 .newBuilder()
726 .setLoggerName(LOGGER_NAME)
727 .setLevel(Level.INFO)
728 .setMessage(message)
729 .setThrown(thrown)
730 .build();
731
732 // Create the event template node with map values.
733 final String messageKey = "message";
734 final String excessiveKey = Strings.repeat("k", maxStringLength) + 'K';
735 final String excessiveValue = Strings.repeat("v", maxStringLength) + 'V';
736 final String nullValueKey = "nullValueKey";
737 final String eventTemplate = writeJson(asMap(
738 messageKey, asMap("$resolver", "message"),
739 excessiveKey, excessiveValue,
740 nullValueKey, asMap(
741 "$resolver", "exception",
742 "field", "message")));
743
744 // Create the layout.
745 final JsonTemplateLayout layout = JsonTemplateLayout
746 .newBuilder()
747 .setConfiguration(CONFIGURATION)
748 .setEventTemplate(eventTemplate)
749 .setMaxStringLength(maxStringLength)
750 .build();
751
752 // Check serialized event.
753 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
754 final String truncatedStringSuffix =
755 JsonTemplateLayoutDefaults.getTruncatedStringSuffix();
756 final String truncatedMessageString =
757 excessiveMessageString.substring(0, maxStringLength) +
758 truncatedStringSuffix;
759 assertThat(accessor.getString(messageKey)).isEqualTo(truncatedMessageString);
760 final String truncatedKey =
761 excessiveKey.substring(0, maxStringLength) +
762 truncatedStringSuffix;
763 final String truncatedValue =
764 excessiveValue.substring(0, maxStringLength) +
765 truncatedStringSuffix;
766 assertThat(accessor.getString(truncatedKey)).isEqualTo(truncatedValue);
767 assertThat(accessor.getString(nullValueKey)).isNull();
768 });
769
770 }
771
772 private static final class NonAsciiUtf8MethodNameContainingException extends RuntimeException {
773
774 public static final long serialVersionUID = 0;
775
776 private static final String NON_ASCII_UTF8_TEXT = "அஆஇฬ๘";
777
778 private static final NonAsciiUtf8MethodNameContainingException INSTANCE =
779 createInstance();
780
781 private static NonAsciiUtf8MethodNameContainingException createInstance() {
782 try {
783 throwException_அஆஇฬ๘();
784 throw new IllegalStateException("should not have reached here");
785 } catch (final NonAsciiUtf8MethodNameContainingException exception) {
786 return exception;
787 }
788 }
789
790 @SuppressWarnings("NonAsciiCharacters")
791 private static void throwException_அஆஇฬ๘() {
792 throw new NonAsciiUtf8MethodNameContainingException(
793 "exception with non-ASCII UTF-8 method name");
794 }
795
796 private NonAsciiUtf8MethodNameContainingException(final String message) {
797 super(message);
798 }
799
800 }
801
802 @Test
803 void test_exception_with_nonAscii_utf8_method_name() {
804
805 // Create the log event.
806 final SimpleMessage message = new SimpleMessage("Hello, World!");
807 final RuntimeException exception = NonAsciiUtf8MethodNameContainingException.INSTANCE;
808 final LogEvent logEvent = Log4jLogEvent
809 .newBuilder()
810 .setLoggerName(LOGGER_NAME)
811 .setLevel(Level.ERROR)
812 .setMessage(message)
813 .setThrown(exception)
814 .build();
815
816 // Create the event template.
817 final String eventTemplate = writeJson(asMap(
818 "ex_stacktrace", asMap(
819 "$resolver", "exception",
820 "field", "stackTrace",
821 "stringified", true)));
822
823 // Create the layout.
824 final JsonTemplateLayout layout = JsonTemplateLayout
825 .newBuilder()
826 .setConfiguration(CONFIGURATION)
827 .setStackTraceEnabled(true)
828 .setEventTemplate(eventTemplate)
829 .build();
830
831 // Check the serialized event.
832 usingSerializedLogEventAccessor(layout, logEvent, accessor ->
833 assertThat(accessor.getString("ex_stacktrace"))
834 .contains(NonAsciiUtf8MethodNameContainingException.NON_ASCII_UTF8_TEXT));
835
836 }
837
838 @Test
839 void test_event_template_additional_fields() {
840
841 // Create the log event.
842 final SimpleMessage message = new SimpleMessage("Hello, World!");
843 final RuntimeException exception = NonAsciiUtf8MethodNameContainingException.INSTANCE;
844 final Level level = Level.ERROR;
845 final LogEvent logEvent = Log4jLogEvent
846 .newBuilder()
847 .setLoggerName(LOGGER_NAME)
848 .setLevel(level)
849 .setMessage(message)
850 .setThrown(exception)
851 .build();
852
853 // Create the event template.
854 final String eventTemplate = "{}";
855
856 // Create the layout.
857 final EventTemplateAdditionalField[] additionalFields = {
858 EventTemplateAdditionalField
859 .newBuilder()
860 .setKey("number")
861 .setValue("1")
862 .setFormat(EventTemplateAdditionalField.Format.JSON)
863 .build(),
864 EventTemplateAdditionalField
865 .newBuilder()
866 .setKey("string")
867 .setValue("foo")
868 .build(),
869 EventTemplateAdditionalField
870 .newBuilder()
871 .setKey("level")
872 .setValue("{\"$resolver\": \"level\", \"field\": \"name\"}")
873 .setFormat(EventTemplateAdditionalField.Format.JSON)
874 .build()
875 };
876 final JsonTemplateLayout layout = JsonTemplateLayout
877 .newBuilder()
878 .setConfiguration(CONFIGURATION)
879 .setStackTraceEnabled(true)
880 .setEventTemplate(eventTemplate)
881 .setEventTemplateAdditionalFields(additionalFields)
882 .build();
883
884 // Check the serialized event.
885 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
886 assertThat(accessor.getInteger("number")).isEqualTo(1);
887 assertThat(accessor.getString("string")).isEqualTo("foo");
888 assertThat(accessor.getString("level")).isEqualTo(level.name());
889 });
890
891 }
892
893 @Test
894 @SuppressWarnings("FloatingPointLiteralPrecision")
895 void test_timestamp_epoch_resolvers() {
896
897 final List<Map<String, Object>> testCases = Arrays.asList(
898 asMap(
899 "epochSecs", new BigDecimal("1581082727.982123456"),
900 "epochSecsRounded", 1581082727,
901 "epochSecsNanos", 982123456,
902 "epochMillis", new BigDecimal("1581082727982.123456"),
903 "epochMillisRounded", 1581082727982L,
904 "epochMillisNanos", 123456,
905 "epochNanos", 1581082727982123456L),
906 asMap(
907 "epochSecs", new BigDecimal("1591177590.005000001"),
908 "epochSecsRounded", 1591177590,
909 "epochSecsNanos", 5000001,
910 "epochMillis", new BigDecimal("1591177590005.000001"),
911 "epochMillisRounded", 1591177590005L,
912 "epochMillisNanos", 1,
913 "epochNanos", 1591177590005000001L));
914
915 // Create the event template.
916 final String eventTemplate = writeJson(asMap(
917 "epochSecs", asMap(
918 "$resolver", "timestamp",
919 "epoch", asMap("unit", "secs")),
920 "epochSecsRounded", asMap(
921 "$resolver", "timestamp",
922 "epoch", asMap(
923 "unit", "secs",
924 "rounded", true)),
925 "epochSecsNanos", asMap(
926 "$resolver", "timestamp",
927 "epoch", asMap("unit", "secs.nanos")),
928 "epochMillis", asMap(
929 "$resolver", "timestamp",
930 "epoch", asMap("unit", "millis")),
931 "epochMillisRounded", asMap(
932 "$resolver", "timestamp",
933 "epoch", asMap(
934 "unit", "millis",
935 "rounded", true)),
936 "epochMillisNanos", asMap(
937 "$resolver", "timestamp",
938 "epoch", asMap("unit", "millis.nanos")),
939 "epochNanos", asMap(
940 "$resolver", "timestamp",
941 "epoch", asMap("unit", "nanos"))));
942
943 // Create the layout.
944 final JsonTemplateLayout layout = JsonTemplateLayout
945 .newBuilder()
946 .setConfiguration(CONFIGURATION)
947 .setEventTemplate(eventTemplate)
948 .build();
949
950 testCases.forEach(testCase -> {
951
952 // Create the log event.
953 final SimpleMessage message = new SimpleMessage("Hello, World!");
954 final Level level = Level.ERROR;
955 final MutableInstant instant = new MutableInstant();
956 final Object instantSecsObject = testCase.get("epochSecsRounded");
957 final long instantSecs = instantSecsObject instanceof Long
958 ? (long) instantSecsObject
959 : (int) instantSecsObject;
960 final int instantSecsNanos = (int) testCase.get("epochSecsNanos");
961 instant.initFromEpochSecond(instantSecs, instantSecsNanos);
962 final LogEvent logEvent = Log4jLogEvent
963 .newBuilder()
964 .setLoggerName(LOGGER_NAME)
965 .setLevel(level)
966 .setMessage(message)
967 .setInstant(instant)
968 .build();
969
970 // Verify the test case.
971 usingSerializedLogEventAccessor(layout, logEvent, accessor ->
972 testCase.forEach((key, expectedValue) ->
973 Assertions
974 .assertThat(accessor.getObject(key))
975 .describedAs("key=%s", key)
976 .isEqualTo(expectedValue)));
977
978 });
979
980 }
981
982 @Test
983 void test_timestamp_pattern_resolver() {
984
985 // Create log events.
986 final String logEvent1FormattedInstant = "2019-01-02T09:34:11Z";
987 final LogEvent logEvent1 = createLogEventAtInstant(logEvent1FormattedInstant);
988 final String logEvent2FormattedInstant = "2019-01-02T09:34:12Z";
989 final LogEvent logEvent2 = createLogEventAtInstant(logEvent2FormattedInstant);
990 @SuppressWarnings("UnnecessaryLocalVariable")
991 final String logEvent3FormattedInstant = logEvent2FormattedInstant;
992 final LogEvent logEvent3 = createLogEventAtInstant(logEvent3FormattedInstant);
993 final String logEvent4FormattedInstant = "2019-01-02T09:34:13Z";
994 final LogEvent logEvent4 = createLogEventAtInstant(logEvent4FormattedInstant);
995
996 // Create the event template.
997 final String eventTemplate = writeJson(asMap(
998 "timestamp", asMap(
999 "$resolver", "timestamp",
1000 "pattern", asMap(
1001 "format", "yyyy-MM-dd'T'HH:mm:ss'Z'",
1002 "timeZone", "UTC"))));
1003
1004 // Create the layout.
1005 final JsonTemplateLayout layout = JsonTemplateLayout
1006 .newBuilder()
1007 .setConfiguration(CONFIGURATION)
1008 .setEventTemplate(eventTemplate)
1009 .build();
1010
1011 // Check the serialized 1st event.
1012 usingSerializedLogEventAccessor(layout, logEvent1, accessor ->
1013 assertThat(accessor.getString("timestamp"))
1014 .isEqualTo(logEvent1FormattedInstant));
1015
1016 // Check the serialized 2nd event.
1017 usingSerializedLogEventAccessor(layout, logEvent2, accessor ->
1018 assertThat(accessor.getString("timestamp"))
1019 .isEqualTo(logEvent2FormattedInstant));
1020
1021 // Check the serialized 3rd event.
1022 usingSerializedLogEventAccessor(layout, logEvent3, accessor ->
1023 assertThat(accessor.getString("timestamp"))
1024 .isEqualTo(logEvent3FormattedInstant));
1025
1026 // Check the serialized 4th event.
1027 usingSerializedLogEventAccessor(layout, logEvent4, accessor ->
1028 assertThat(accessor.getString("timestamp"))
1029 .isEqualTo(logEvent4FormattedInstant));
1030
1031 }
1032
1033 private static LogEvent createLogEventAtInstant(final String formattedInstant) {
1034 final SimpleMessage message = new SimpleMessage("LogEvent at instant " + formattedInstant);
1035 final long instantEpochMillis = Instant.parse(formattedInstant).toEpochMilli();
1036 final MutableInstant instant = new MutableInstant();
1037 instant.initFromEpochMilli(instantEpochMillis, 0);
1038 return Log4jLogEvent
1039 .newBuilder()
1040 .setLoggerName(LOGGER_NAME)
1041 .setMessage(message)
1042 .setInstant(instant)
1043 .build();
1044 }
1045
1046 @Test
1047 void test_level_severity() {
1048
1049 // Create the event template.
1050 final String eventTemplate = writeJson(asMap(
1051 "severityKeyword", asMap(
1052 "$resolver", "level",
1053 "field", "severity",
1054 "severity", asMap("field", "keyword")),
1055 "severityCode", asMap(
1056 "$resolver", "level",
1057 "field", "severity",
1058 "severity", asMap("field", "code"))));
1059
1060 // Create the layout.
1061 final JsonTemplateLayout layout = JsonTemplateLayout
1062 .newBuilder()
1063 .setConfiguration(CONFIGURATION)
1064 .setEventTemplate(eventTemplate)
1065 .build();
1066
1067 for (final Level level : Level.values()) {
1068
1069 // Create the log event.
1070 final SimpleMessage message = new SimpleMessage("Hello, World!");
1071 final LogEvent logEvent = Log4jLogEvent
1072 .newBuilder()
1073 .setLoggerName(LOGGER_NAME)
1074 .setLevel(level)
1075 .setMessage(message)
1076 .build();
1077
1078 // Check the serialized event.
1079 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
1080 final Severity expectedSeverity = Severity.getSeverity(level);
1081 final String expectedSeverityKeyword = expectedSeverity.name();
1082 final int expectedSeverityCode = expectedSeverity.getCode();
1083 assertThat(accessor.getString("severityKeyword")).isEqualTo(expectedSeverityKeyword);
1084 assertThat(accessor.getInteger("severityCode")).isEqualTo(expectedSeverityCode);
1085 });
1086
1087 }
1088
1089 }
1090
1091 @Test
1092 void test_exception_resolvers_against_no_exceptions() {
1093
1094 // Create the log event.
1095 final SimpleMessage message = new SimpleMessage("Hello, World!");
1096 final LogEvent logEvent = Log4jLogEvent
1097 .newBuilder()
1098 .setLoggerName(LOGGER_NAME)
1099 .setMessage(message)
1100 .build();
1101
1102 // Create the event template.
1103 final String eventTemplate = writeJson(asMap(
1104 "exStackTrace", asMap(
1105 "$resolver", "exception",
1106 "field", "stackTrace"),
1107 "exStackTraceString", asMap(
1108 "$resolver", "exception",
1109 "field", "stackTrace",
1110 "stackTrace", asMap(
1111 "stringified", true)),
1112 "exRootCauseStackTrace", asMap(
1113 "$resolver", "exceptionRootCause",
1114 "field", "stackTrace"),
1115 "exRootCauseStackTraceString", asMap(
1116 "$resolver", "exceptionRootCause",
1117 "field", "stackTrace",
1118 "stackTrace", asMap(
1119 "stringified", true)),
1120 "requiredFieldTriggeringError", true));
1121
1122 // Create the layout.
1123 final JsonTemplateLayout layout = JsonTemplateLayout
1124 .newBuilder()
1125 .setConfiguration(CONFIGURATION)
1126 .setEventTemplate(eventTemplate)
1127 .setStackTraceEnabled(true)
1128 .build();
1129
1130 // Check the serialized event.
1131 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
1132 assertThat(accessor.getObject("exStackTrace")).isNull();
1133 assertThat(accessor.getObject("exStackTraceString")).isNull();
1134 assertThat(accessor.getObject("exRootCauseStackTrace")).isNull();
1135 assertThat(accessor.getObject("exRootCauseStackTraceString")).isNull();
1136 assertThat(accessor.getBoolean("requiredFieldTriggeringError")).isTrue();
1137 });
1138
1139 }
1140
1141 @Test
1142 void test_stringified_exception_resolver_with_maxStringLength() {
1143
1144 // Create the event template.
1145 final String eventTemplate = writeJson(asMap(
1146 "stackTrace", asMap(
1147 "$resolver", "exception",
1148 "field", "stackTrace",
1149 "stringified", true)));
1150
1151 // Create the layout.
1152 final int maxStringLength = eventTemplate.length();
1153 final JsonTemplateLayout layout = JsonTemplateLayout
1154 .newBuilder()
1155 .setConfiguration(CONFIGURATION)
1156 .setEventTemplate(eventTemplate)
1157 .setMaxStringLength(maxStringLength)
1158 .setStackTraceEnabled(true)
1159 .build();
1160
1161 // Create the log event.
1162 final SimpleMessage message = new SimpleMessage("foo");
1163 final LogEvent logEvent = Log4jLogEvent
1164 .newBuilder()
1165 .setLoggerName(LOGGER_NAME)
1166 .setMessage(message)
1167 .setThrown(NonAsciiUtf8MethodNameContainingException.INSTANCE)
1168 .build();
1169
1170 // Check the serialized event.
1171 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
1172 final int expectedLength = maxStringLength +
1173 JsonTemplateLayoutDefaults.getTruncatedStringSuffix().length();
1174 assertThat(accessor.getString("stackTrace").length()).isEqualTo(expectedLength);
1175 });
1176
1177 }
1178
1179 @Test
1180 void test_stack_trace_truncation() {
1181
1182 // Create the exception to be logged.
1183 final Exception childError =
1184 new Exception("unique child exception message");
1185 final Exception parentError =
1186 new Exception("unique parent exception message", childError);
1187
1188 // Create the event template.
1189 final String truncationSuffix = "~";
1190 final String eventTemplate = writeJson(asMap(
1191 // Raw exception.
1192 "ex", asMap(
1193 "$resolver", "exception",
1194 "field", "stackTrace",
1195 "stackTrace", asMap(
1196 "stringified", true)),
1197 // Exception matcher using strings.
1198 "stringMatchedEx", asMap(
1199 "$resolver", "exception",
1200 "field", "stackTrace",
1201 "stackTrace", asMap(
1202 "stringified", asMap(
1203 "truncation", asMap(
1204 "suffix", truncationSuffix,
1205 "pointMatcherStrings", Arrays.asList(
1206 "this string shouldn't match with anything",
1207 parentError.getMessage()))))),
1208 // Exception matcher using regexes.
1209 "regexMatchedEx", asMap(
1210 "$resolver", "exception",
1211 "field", "stackTrace",
1212 "stackTrace", asMap(
1213 "stringified", asMap(
1214 "truncation", asMap(
1215 "suffix", truncationSuffix,
1216 "pointMatcherRegexes", Arrays.asList(
1217 "this string shouldn't match with anything",
1218 parentError
1219 .getMessage()
1220 .replace("unique", "[xu]n.que")))))),
1221 // Raw exception root cause.
1222 "rootEx", asMap(
1223 "$resolver", "exceptionRootCause",
1224 "field", "stackTrace",
1225 "stackTrace", asMap(
1226 "stringified", true)),
1227 // Exception root cause matcher using strings.
1228 "stringMatchedRootEx", asMap(
1229 "$resolver", "exceptionRootCause",
1230 "field", "stackTrace",
1231 "stackTrace", asMap(
1232 "stringified", asMap(
1233 "truncation", asMap(
1234 "suffix", truncationSuffix,
1235 "pointMatcherStrings", Arrays.asList(
1236 "this string shouldn't match with anything",
1237 childError.getMessage()))))),
1238 // Exception root cause matcher using regexes.
1239 "regexMatchedRootEx", asMap(
1240 "$resolver", "exceptionRootCause",
1241 "field", "stackTrace",
1242 "stackTrace", asMap(
1243 "stringified", asMap(
1244 "truncation", asMap(
1245 "suffix", truncationSuffix,
1246 "pointMatcherRegexes", Arrays.asList(
1247 "this string shouldn't match with anything",
1248 childError
1249 .getMessage()
1250 .replace("unique", "[xu]n.que"))))))));
1251
1252 // Create the layout.
1253 final JsonTemplateLayout layout = JsonTemplateLayout
1254 .newBuilder()
1255 .setConfiguration(CONFIGURATION)
1256 .setEventTemplate(eventTemplate)
1257 .setStackTraceEnabled(true)
1258 .build();
1259
1260 // Create the log event.
1261 final LogEvent logEvent = Log4jLogEvent
1262 .newBuilder()
1263 .setLoggerName(LOGGER_NAME)
1264 .setThrown(parentError)
1265 .build();
1266
1267 // Check the serialized event.
1268 final String expectedMatchedExEnd =
1269 parentError.getMessage() + truncationSuffix;
1270 final String expectedMatchedRootExEnd =
1271 childError.getMessage() + truncationSuffix;
1272 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
1273
1274 // Check the serialized exception.
1275 assertThat(accessor.getString("ex"))
1276 .doesNotEndWith(expectedMatchedExEnd)
1277 .doesNotEndWith(expectedMatchedRootExEnd);
1278 assertThat(accessor.getString("stringMatchedEx"))
1279 .endsWith(expectedMatchedExEnd);
1280 assertThat(accessor.getString("regexMatchedEx"))
1281 .endsWith(expectedMatchedExEnd);
1282
1283 // Check the serialized exception root cause.
1284 assertThat(accessor.getString("rootEx"))
1285 .doesNotEndWith(expectedMatchedExEnd)
1286 .doesNotEndWith(expectedMatchedRootExEnd);
1287 assertThat(accessor.getString("stringMatchedRootEx"))
1288 .endsWith(expectedMatchedRootExEnd);
1289 assertThat(accessor.getString("regexMatchedRootEx"))
1290 .endsWith(expectedMatchedRootExEnd);
1291
1292 });
1293
1294 }
1295
1296 @Test
1297 void test_inline_stack_trace_element_template() {
1298
1299 // Create the event template.
1300 final String eventTemplate = writeJson(asMap(
1301 "stackTrace", asMap(
1302 "$resolver", "exception",
1303 "field", "stackTrace",
1304 "stackTrace", asMap(
1305 "elementTemplate", asMap(
1306 "$resolver", "stackTraceElement",
1307 "field", "className")))));
1308
1309 // Create the layout.
1310 final JsonTemplateLayout layout = JsonTemplateLayout
1311 .newBuilder()
1312 .setConfiguration(CONFIGURATION)
1313 .setEventTemplate(eventTemplate)
1314 .build();
1315
1316 // Create the log event.
1317 final Throwable error = new RuntimeException("foo");
1318 final SimpleMessage message = new SimpleMessage("foo");
1319 final LogEvent logEvent = Log4jLogEvent
1320 .newBuilder()
1321 .setLoggerName(LOGGER_NAME)
1322 .setMessage(message)
1323 .setThrown(error)
1324 .build();
1325
1326 // Check the serialized log event.
1327 final String expectedClassName = JsonTemplateLayoutTest.class.getCanonicalName();
1328 usingSerializedLogEventAccessor(layout, logEvent, accessor -> Assertions
1329 .assertThat(accessor.getList("stackTrace", String.class))
1330 .contains(expectedClassName));
1331
1332 }
1333
1334 @Test
1335 void test_custom_resolver() {
1336
1337 // Create the event template.
1338 final String eventTemplate = writeJson(asMap(
1339 "customField", asMap("$resolver", "custom")));
1340
1341 // Create the layout.
1342 final JsonTemplateLayout layout = JsonTemplateLayout
1343 .newBuilder()
1344 .setConfiguration(CONFIGURATION)
1345 .setEventTemplate(eventTemplate)
1346 .build();
1347
1348 // Create the log event.
1349 final SimpleMessage message = new SimpleMessage("foo");
1350 final LogEvent logEvent = Log4jLogEvent
1351 .newBuilder()
1352 .setLoggerName(LOGGER_NAME)
1353 .setMessage(message)
1354 .build();
1355
1356 // Check the serialized log event.
1357 usingSerializedLogEventAccessor(layout, logEvent, accessor -> Assertions
1358 .assertThat(accessor.getString("customField"))
1359 .matches("CustomValue-[0-9]+"));
1360
1361 }
1362
1363 private static final class CustomResolver implements EventResolver {
1364
1365 private static final AtomicInteger COUNTER = new AtomicInteger(0);
1366
1367 private CustomResolver() {}
1368
1369 @Override
1370 public void resolve(
1371 final LogEvent value,
1372 final JsonWriter jsonWriter) {
1373 jsonWriter.writeString("CustomValue-" + COUNTER.getAndIncrement());
1374 }
1375
1376 }
1377
1378 @Plugin(name = "CustomResolverFactory", category = TemplateResolverFactory.CATEGORY)
1379 public static final class CustomResolverFactory implements EventResolverFactory {
1380
1381 private static final CustomResolverFactory INSTANCE = new CustomResolverFactory();
1382
1383 private CustomResolverFactory() {}
1384
1385 @PluginFactory
1386 public static CustomResolverFactory getInstance() {
1387 return INSTANCE;
1388 }
1389
1390 @Override
1391 public String getName() {
1392 return "custom";
1393 }
1394
1395 @Override
1396 public TemplateResolver<LogEvent> create(
1397 final EventResolverContext context,
1398 final TemplateResolverConfig config) {
1399 return new CustomResolver();
1400 }
1401
1402 }
1403
1404 @Test
1405 void test_null_eventDelimiter() {
1406
1407 // Create the event template.
1408 final String eventTemplate = writeJson(asMap("key", "val"));
1409
1410 // Create the layout.
1411 final JsonTemplateLayout layout = JsonTemplateLayout
1412 .newBuilder()
1413 .setConfiguration(CONFIGURATION)
1414 .setEventTemplate(eventTemplate)
1415 .setEventDelimiter("\0")
1416 .build();
1417
1418 // Create the log event.
1419 final SimpleMessage message = new SimpleMessage("foo");
1420 final LogEvent logEvent = Log4jLogEvent
1421 .newBuilder()
1422 .setLoggerName(LOGGER_NAME)
1423 .setMessage(message)
1424 .setThrown(NonAsciiUtf8MethodNameContainingException.INSTANCE)
1425 .build();
1426
1427 // Check the serialized event.
1428 final String serializedLogEvent = layout.toSerializable(logEvent);
1429 assertThat(serializedLogEvent).isEqualTo(eventTemplate + '\0');
1430
1431 }
1432
1433 @Test
1434 void test_against_SocketAppender() throws Exception {
1435
1436 // Craft nasty events.
1437 final List<LogEvent> logEvents = createNastyLogEvents();
1438
1439 // Create the event template.
1440 final String eventTemplate = writeJson(asMap(
1441 "message", asMap("$resolver", "message")));
1442
1443 // Create the layout.
1444 final JsonTemplateLayout layout = JsonTemplateLayout
1445 .newBuilder()
1446 .setConfiguration(CONFIGURATION)
1447 .setEventTemplate(eventTemplate)
1448 .build();
1449
1450 // Create the server.
1451 final int port = AvailablePortFinder.getNextAvailable();
1452 try (final JsonAcceptingTcpServer server = new JsonAcceptingTcpServer(port, 1)) {
1453
1454 // Create the appender.
1455 final SocketAppender appender = SocketAppender
1456 .newBuilder()
1457 .withHost("localhost")
1458 .withBufferedIo(false)
1459 .withPort(port)
1460 .withReconnectDelayMillis(100)
1461 .setName("test")
1462 .withImmediateFail(false)
1463 .setIgnoreExceptions(false)
1464 .setLayout(layout)
1465 .build();
1466
1467 // Start the appender.
1468 appender.start();
1469
1470 // Transfer and verify the log events.
1471 for (int logEventIndex = 0; logEventIndex < logEvents.size(); logEventIndex++) {
1472
1473 // Send the log event.
1474 final LogEvent logEvent = logEvents.get(logEventIndex);
1475 appender.append(logEvent);
1476 appender.getManager().flush();
1477
1478 // Pull the parsed log event.
1479 final JsonNode node = server.receivedNodes.poll(3, TimeUnit.SECONDS);
1480 assertThat(node)
1481 .as("logEventIndex=%d", logEventIndex)
1482 .isNotNull();
1483
1484 // Verify the received content.
1485 final String expectedMessage = logEvent.getMessage().getFormattedMessage();
1486 final String expectedMessageChars = explainChars(expectedMessage);
1487 final String actualMessage = point(node, "message").asText();
1488 final String actualMessageChars = explainChars(actualMessage);
1489 assertThat(actualMessageChars)
1490 .as("logEventIndex=%d", logEventIndex)
1491 .isEqualTo(expectedMessageChars);
1492
1493 }
1494
1495 // Verify that there were no overflows.
1496 assertThat(server.droppedNodeCount).isZero();
1497
1498 }
1499
1500 }
1501
1502 private static List<LogEvent> createNastyLogEvents() {
1503 return createNastyMessages()
1504 .stream()
1505 .map(message -> Log4jLogEvent
1506 .newBuilder()
1507 .setLoggerName(LOGGER_NAME)
1508 .setMessage(message)
1509 .build())
1510 .collect(Collectors.toList());
1511 }
1512
1513 private static List<SimpleMessage> createNastyMessages() {
1514
1515 // Determine the message count and character offset.
1516 final int messageCount = 1024;
1517 final int minChar = Character.MIN_VALUE;
1518 final int maxChar = Character.MIN_HIGH_SURROGATE - 1;
1519 final int totalCharCount = maxChar - minChar + 1;
1520 final int charOffset = totalCharCount / messageCount;
1521
1522 // Populate messages.
1523 List<SimpleMessage> messages = new ArrayList<>(messageCount);
1524 for (int messageIndex = 0; messageIndex < messageCount; messageIndex++) {
1525 final StringBuilder stringBuilder = new StringBuilder(messageIndex + "@");
1526 for (int charIndex = 0; charIndex < charOffset; charIndex++) {
1527 final char c = (char) (minChar + messageIndex * charOffset + charIndex);
1528 stringBuilder.append(c);
1529 }
1530 final String messageString = stringBuilder.toString();
1531 final SimpleMessage message = new SimpleMessage(messageString);
1532 messages.add(message);
1533 }
1534 return messages;
1535
1536 }
1537
1538 private static final class JsonAcceptingTcpServer extends Thread implements AutoCloseable {
1539
1540 private final ServerSocket serverSocket;
1541
1542 private final BlockingQueue<JsonNode> receivedNodes;
1543
1544 private volatile int droppedNodeCount = 0;
1545
1546 private volatile boolean closed = false;
1547
1548 private JsonAcceptingTcpServer(
1549 final int port,
1550 final int capacity) throws IOException {
1551 this.serverSocket = new ServerSocket(port);
1552 this.receivedNodes = new ArrayBlockingQueue<>(capacity);
1553 serverSocket.setReuseAddress(true);
1554 serverSocket.setSoTimeout(5_000);
1555 setDaemon(true);
1556 start();
1557 }
1558
1559 @Override
1560 public void run() {
1561 try {
1562 try (final Socket socket = serverSocket.accept()) {
1563 final InputStream inputStream = socket.getInputStream();
1564 while (!closed) {
1565 final MappingIterator<JsonNode> iterator = JacksonFixture
1566 .getObjectMapper()
1567 .readerFor(JsonNode.class)
1568 .readValues(inputStream);
1569 while (iterator.hasNextValue()) {
1570 final JsonNode value = iterator.nextValue();
1571 synchronized (this) {
1572 final boolean added = receivedNodes.offer(value);
1573 if (!added) {
1574 droppedNodeCount++;
1575 }
1576 }
1577 }
1578 }
1579 }
1580 } catch (final EOFException ignored) {
1581 // Socket is closed.
1582 } catch (final Exception error) {
1583 if (!closed) {
1584 throw new RuntimeException(error);
1585 }
1586 }
1587 }
1588
1589 @Override
1590 public synchronized void close() {
1591 if (closed) {
1592 throw new IllegalStateException("shutdown has already been invoked");
1593 }
1594 closed = true;
1595 interrupt();
1596 try {
1597 join(3_000L);
1598 } catch (InterruptedException ignored) {
1599 // Due to JDK-7027157, we shouldn't throw an InterruptedException
1600 // from an AutoCloseable#close() method. Hence we catch it and
1601 // then restore the interrupted flag.
1602 Thread.currentThread().interrupt();
1603 }
1604 }
1605
1606 }
1607
1608 private static String explainChars(final String input) {
1609 return IntStream
1610 .range(0, input.length())
1611 .mapToObj(i -> {
1612 final char c = input.charAt(i);
1613 return String.format("'%c' (%04X)", c, (int) c);
1614 })
1615 .collect(Collectors.joining(", "));
1616 }
1617
1618 @Test
1619 void test_PatternResolver() {
1620
1621 // Create the event template.
1622 final String eventTemplate = writeJson(asMap(
1623 "message", asMap(
1624 "$resolver", "pattern",
1625 "pattern", "%p:%m")));
1626
1627 // Create the layout.
1628 final JsonTemplateLayout layout = JsonTemplateLayout
1629 .newBuilder()
1630 .setConfiguration(CONFIGURATION)
1631 .setEventTemplate(eventTemplate)
1632 .build();
1633
1634 // Create the log event.
1635 final SimpleMessage message = new SimpleMessage("foo");
1636 final Level level = Level.FATAL;
1637 final LogEvent logEvent = Log4jLogEvent
1638 .newBuilder()
1639 .setLoggerName(LOGGER_NAME)
1640 .setMessage(message)
1641 .setLevel(level)
1642 .build();
1643
1644 // Check the serialized event.
1645 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
1646 final String expectedMessage = String.format(
1647 "%s:%s",
1648 level, message.getFormattedMessage());
1649 assertThat(accessor.getString("message")).isEqualTo(expectedMessage);
1650 });
1651
1652 }
1653
1654 @Test
1655 void test_MessageParameterResolver_with_ParameterizedMessageFactory() {
1656 testMessageParameterResolver(ParameterizedMessageFactory.INSTANCE);
1657 }
1658
1659 @Test
1660 void test_MessageParameterResolver_noParameters_with_ParameterizedMessageFactory() {
1661 testMessageParameterResolverNoParameters(ParameterizedMessageFactory.INSTANCE);
1662 }
1663
1664 @Test
1665 void test_MessageParameterResolver_with_ReusableMessageFactory() {
1666 testMessageParameterResolver(ReusableMessageFactory.INSTANCE);
1667 }
1668
1669 @Test
1670 void test_MessageParameterResolver_noParameters_with_ReusableMessageFactory() {
1671 testMessageParameterResolverNoParameters(ReusableMessageFactory.INSTANCE);
1672 }
1673
1674 private static void testMessageParameterResolver(final MessageFactory messageFactory) {
1675
1676 // Create the event template.
1677 final String eventTemplate = writeJson(asMap(
1678 "po*", asMap(
1679 "$resolver", "messageParameter"),
1680 "ps*", asMap(
1681 "$resolver", "messageParameter",
1682 "stringified", true),
1683 "po2", asMap(
1684 "$resolver", "messageParameter",
1685 "index", 2),
1686 "ps2", asMap(
1687 "$resolver", "messageParameter",
1688 "index", 2,
1689 "stringified", true),
1690 "po3", asMap(
1691 "$resolver", "messageParameter",
1692 "index", 3)));
1693
1694 // Create the layout.
1695 final JsonTemplateLayout layout = JsonTemplateLayout
1696 .newBuilder()
1697 .setConfiguration(CONFIGURATION)
1698 .setEventTemplate(eventTemplate)
1699 .build();
1700
1701 // Create the log event.
1702 final Object[] parameters = {1L + (long) Integer.MAX_VALUE, "foo", 56};
1703 final Message message = messageFactory.newMessage("foo", parameters);
1704 final Level level = Level.FATAL;
1705 final LogEvent logEvent = Log4jLogEvent
1706 .newBuilder()
1707 .setLoggerName(LOGGER_NAME)
1708 .setMessage(message)
1709 .setLevel(level)
1710 .build();
1711
1712 // Check the serialized event.
1713 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
1714 assertThat(accessor.getObject("po*")).isEqualTo(Arrays.asList(parameters));
1715 List<String> stringifiedParameters = Arrays
1716 .stream(parameters)
1717 .map(String::valueOf)
1718 .collect(Collectors.toList());
1719 assertThat(accessor.getObject("ps*")).isEqualTo(stringifiedParameters);
1720 assertThat(accessor.getObject("po2")).isEqualTo(parameters[2]);
1721 assertThat(accessor.getString("ps2")).isEqualTo(stringifiedParameters.get(2));
1722 assertThat(accessor.getString("ps3")).isNull();
1723 });
1724
1725 }
1726
1727 private static void testMessageParameterResolverNoParameters(
1728 final MessageFactory messageFactory) {
1729
1730 // Create the event template.
1731 final String eventTemplate = writeJson(asMap(
1732 "po*", asMap(
1733 "$resolver", "messageParameter"),
1734 "ps*", asMap(
1735 "$resolver", "messageParameter",
1736 "stringified", true)));
1737
1738 // Create the layout.
1739 final JsonTemplateLayout layout = JsonTemplateLayout
1740 .newBuilder()
1741 .setConfiguration(CONFIGURATION)
1742 .setEventTemplate(eventTemplate)
1743 .build();
1744
1745 // Create the log event.
1746 final Message message = messageFactory.newMessage("foo", new Object[0]);
1747 final Level level = Level.FATAL;
1748 final LogEvent logEvent = Log4jLogEvent
1749 .newBuilder()
1750 .setLoggerName(LOGGER_NAME)
1751 .setMessage(message)
1752 .setLevel(level)
1753 .build();
1754
1755 // Check the serialized event.
1756 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
1757 assertThat(accessor.getObject("po*")).isEqualTo(Collections.emptyList());
1758 assertThat(accessor.getObject("ps*")).isEqualTo(Collections.emptyList());
1759 });
1760
1761 }
1762
1763 @Test
1764 void test_unresolvable_nested_fields_are_skipped() {
1765
1766 // Create the event template.
1767 final String eventTemplate = writeJson(asMap(
1768 "exception", asMap(
1769 "message", asMap(
1770 "$resolver", "exception",
1771 "field", "message"),
1772 "className", asMap(
1773 "$resolver", "exception",
1774 "field", "className")),
1775 "exceptionRootCause", asMap(
1776 "message", asMap(
1777 "$resolver", "exceptionRootCause",
1778 "field", "message"),
1779 "className", asMap(
1780 "$resolver", "exceptionRootCause",
1781 "field", "className")),
1782 "source", asMap(
1783 "lineNumber", asMap(
1784 "$resolver", "source",
1785 "field", "lineNumber"),
1786 "fileName", asMap(
1787 "$resolver", "source",
1788 "field", "fileName")),
1789 "emptyMap", Collections.emptyMap(),
1790 "emptyList", Collections.emptyList(),
1791 "null", null));
1792
1793 // Create the layout.
1794 final JsonTemplateLayout layout = JsonTemplateLayout
1795 .newBuilder()
1796 .setConfiguration(CONFIGURATION)
1797 .setEventTemplate(eventTemplate)
1798 .setStackTraceEnabled(false) // Disable "exception" and "exceptionRootCause" resolvers.
1799 .setLocationInfoEnabled(false) // Disable the "source" resolver.
1800 .build();
1801
1802 // Create the log event.
1803 final SimpleMessage message = new SimpleMessage("foo");
1804 final Exception thrown = new RuntimeException("bar");
1805 final LogEvent logEvent = Log4jLogEvent
1806 .newBuilder()
1807 .setLoggerName(LOGGER_NAME)
1808 .setMessage(message)
1809 .setThrown(thrown)
1810 .build();
1811
1812 // Check the serialized event.
1813 final String expectedSerializedLogEventJson =
1814 "{}" + JsonTemplateLayoutDefaults.getEventDelimiter();
1815 final String actualSerializedLogEventJson = layout.toSerializable(logEvent);
1816 Assertions
1817 .assertThat(actualSerializedLogEventJson)
1818 .isEqualTo(expectedSerializedLogEventJson);
1819
1820 }
1821
1822 @Test
1823 void test_recursive_collections() {
1824
1825 // Create the event template.
1826 final String eventTemplate = writeJson(asMap(
1827 "message", asMap("$resolver", "message")));
1828
1829 // Create the layout.
1830 final JsonTemplateLayout layout = JsonTemplateLayout
1831 .newBuilder()
1832 .setConfiguration(CONFIGURATION)
1833 .setEventTemplate(eventTemplate)
1834 .build();
1835
1836 // Create a recursive collection.
1837 final Object[] recursiveCollection = new Object[1];
1838 recursiveCollection[0] = recursiveCollection;
1839
1840 // Create the log event.
1841 final Message message = new ObjectMessage(recursiveCollection);
1842 final LogEvent logEvent = Log4jLogEvent
1843 .newBuilder()
1844 .setLoggerName(LOGGER_NAME)
1845 .setMessage(message)
1846 .build();
1847
1848 // Check the serialized event.
1849 Assertions
1850 .assertThatThrownBy(() -> layout.toSerializable(logEvent))
1851 .isInstanceOf(StackOverflowError.class);
1852
1853 }
1854
1855 @Test
1856 void test_eventTemplateRootObjectKey() {
1857
1858 // Create the event template.
1859 final String eventTemplate = writeJson(asMap(
1860 "message", asMap("$resolver", "message")));
1861
1862 // Create the layout.
1863 final JsonTemplateLayout layout = JsonTemplateLayout
1864 .newBuilder()
1865 .setConfiguration(CONFIGURATION)
1866 .setEventTemplate(eventTemplate)
1867 .setEventTemplateRootObjectKey("event")
1868 .build();
1869
1870 // Create the log event.
1871 final Message message = new SimpleMessage("LOG4J2-2985");
1872 final LogEvent logEvent = Log4jLogEvent
1873 .newBuilder()
1874 .setLoggerName(LOGGER_NAME)
1875 .setMessage(message)
1876 .build();
1877
1878 // Check the serialized event.
1879 usingSerializedLogEventAccessor(layout, logEvent, accessor ->
1880 assertThat(accessor.getObject(new String[]{"event", "message"}))
1881 .isEqualTo("LOG4J2-2985"));
1882
1883 }
1884
1885 }
+0
-153
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogEventFixture.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.impl.ContextDataFactory;
21 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
22 import org.apache.logging.log4j.message.SimpleMessage;
23 import org.apache.logging.log4j.spi.MutableThreadContextStack;
24 import org.apache.logging.log4j.spi.ThreadContextStack;
25 import org.apache.logging.log4j.util.StringMap;
26
27 import java.io.IOException;
28 import java.math.BigDecimal;
29 import java.util.ArrayList;
30 import java.util.List;
31
32 final class LogEventFixture {
33
34 private LogEventFixture() {}
35
36 private static final int TIME_OVERLAPPING_CONSECUTIVE_EVENT_COUNT = 10;
37
38 static List<LogEvent> createLiteLogEvents(final int logEventCount) {
39 final List<LogEvent> logEvents = new ArrayList<>(logEventCount);
40 final long startTimeMillis = System.currentTimeMillis();
41 for (int logEventIndex = 0; logEventIndex < logEventCount; logEventIndex++) {
42 final String logEventId = String.valueOf(logEventIndex);
43 final long logEventTimeMillis = createLogEventTimeMillis(startTimeMillis, logEventIndex);
44 final LogEvent logEvent = LogEventFixture.createLiteLogEvent(logEventId, logEventTimeMillis);
45 logEvents.add(logEvent);
46 }
47 return logEvents;
48 }
49
50 private static LogEvent createLiteLogEvent(final String id, final long timeMillis) {
51 final SimpleMessage message = new SimpleMessage("lite LogEvent message " + id);
52 final Level level = Level.DEBUG;
53 final String loggerFqcn = "f.q.c.n" + id;
54 final String loggerName = "a.B" + id;
55 final long nanoTime = timeMillis * 2;
56 return Log4jLogEvent
57 .newBuilder()
58 .setLoggerName(loggerName)
59 .setLoggerFqcn(loggerFqcn)
60 .setLevel(level)
61 .setMessage(message)
62 .setTimeMillis(timeMillis)
63 .setNanoTime(nanoTime)
64 .build();
65 }
66
67 static List<LogEvent> createFullLogEvents(final int logEventCount) {
68 final List<LogEvent> logEvents = new ArrayList<>(logEventCount);
69 final long startTimeMillis = System.currentTimeMillis();
70 for (int logEventIndex = 0; logEventIndex < logEventCount; logEventIndex++) {
71 final String logEventId = String.valueOf(logEventIndex);
72 final long logEventTimeMillis = createLogEventTimeMillis(startTimeMillis, logEventIndex);
73 final LogEvent logEvent = LogEventFixture.createFullLogEvent(logEventId, logEventTimeMillis);
74 logEvents.add(logEvent);
75 }
76 return logEvents;
77 }
78
79 private static long createLogEventTimeMillis(
80 final long startTimeMillis,
81 final int logEventIndex) {
82 // Create event time repeating every certain number of consecutive
83 // events. This is better aligned with the real-world use case and
84 // gives surface to timestamp formatter caches to perform their
85 // magic, which is implemented for almost all layouts.
86 return startTimeMillis + logEventIndex / TIME_OVERLAPPING_CONSECUTIVE_EVENT_COUNT;
87 }
88
89 private static LogEvent createFullLogEvent(
90 final String id,
91 final long timeMillis) {
92
93 // Create exception.
94 final Exception sourceHelper = new Exception();
95 sourceHelper.fillInStackTrace();
96 final Exception cause = new NullPointerException("testNPEx-" + id);
97 sourceHelper.fillInStackTrace();
98 final StackTraceElement source = sourceHelper.getStackTrace()[0];
99 final IOException ioException = new IOException("testIOEx-" + id, cause);
100 ioException.addSuppressed(new IndexOutOfBoundsException("I am suppressed exception 1" + id));
101 ioException.addSuppressed(new IndexOutOfBoundsException("I am suppressed exception 2" + id));
102
103 // Create rest of the event attributes.
104 final SimpleMessage message = new SimpleMessage("full LogEvent message " + id);
105 final StringMap contextData = createContextData(id);
106 final ThreadContextStack contextStack = createContextStack(id);
107 final int threadId = id.hashCode();
108 final String threadName = "MyThreadName" + id;
109 final int threadPriority = threadId % 10;
110 final Level level = Level.DEBUG;
111 final String loggerFqcn = "f.q.c.n" + id;
112 final String loggerName = "a.B" + id;
113 final long nanoTime = timeMillis * 2;
114
115 // Create the event.
116 return Log4jLogEvent
117 .newBuilder()
118 .setLoggerName(loggerName)
119 .setLoggerFqcn(loggerFqcn)
120 .setLevel(level)
121 .setMessage(message)
122 .setThrown(ioException)
123 .setContextData(contextData)
124 .setContextStack(contextStack)
125 .setThreadId(threadId)
126 .setThreadName(threadName)
127 .setThreadPriority(threadPriority)
128 .setSource(source)
129 .setTimeMillis(timeMillis)
130 .setNanoTime(nanoTime)
131 .build();
132
133 }
134
135 private static StringMap createContextData(final String id) {
136 final StringMap contextData = ContextDataFactory.createContextData();
137 contextData.putValue("MDC.String." + id, "String");
138 contextData.putValue("MDC.BigDecimal." + id, BigDecimal.valueOf(Math.PI));
139 contextData.putValue("MDC.Integer." + id, 10);
140 contextData.putValue("MDC.Long." + id, Long.MAX_VALUE);
141 return contextData;
142 }
143
144 private static ThreadContextStack createContextStack(final String id) {
145 final ThreadContextStack contextStack = new MutableThreadContextStack();
146 contextStack.clear();
147 contextStack.push("stack_msg1" + id);
148 contextStack.add("stack_msg2" + id);
149 return contextStack;
150 }
151
152 }
+0
-517
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.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.logging.log4j.layout.template.json;
17
18 import co.elastic.logging.log4j2.EcsLayout;
19 import org.apache.http.HttpHost;
20 import org.apache.logging.log4j.Level;
21 import org.apache.logging.log4j.core.Appender;
22 import org.apache.logging.log4j.core.Layout;
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.appender.SocketAppender;
25 import org.apache.logging.log4j.core.config.DefaultConfiguration;
26 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
27 import org.apache.logging.log4j.core.layout.GelfLayout;
28 import org.apache.logging.log4j.core.util.NetUtils;
29 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
30 import org.apache.logging.log4j.layout.template.json.util.ThreadLocalRecyclerFactory;
31 import org.apache.logging.log4j.message.SimpleMessage;
32 import org.apache.logging.log4j.status.StatusLogger;
33 import org.assertj.core.api.Assertions;
34 import org.awaitility.Awaitility;
35 import org.elasticsearch.ElasticsearchStatusException;
36 import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
37 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
38 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
39 import org.elasticsearch.action.search.SearchRequest;
40 import org.elasticsearch.action.search.SearchResponse;
41 import org.elasticsearch.action.support.master.AcknowledgedResponse;
42 import org.elasticsearch.client.RequestOptions;
43 import org.elasticsearch.client.RestClient;
44 import org.elasticsearch.client.RestClientBuilder;
45 import org.elasticsearch.client.RestHighLevelClient;
46 import org.elasticsearch.cluster.health.ClusterHealthStatus;
47 import org.elasticsearch.rest.RestStatus;
48 import org.elasticsearch.search.SearchHit;
49 import org.elasticsearch.search.builder.SearchSourceBuilder;
50 import org.junit.jupiter.api.Test;
51 import org.junit.jupiter.api.parallel.Execution;
52 import org.junit.jupiter.api.parallel.ExecutionMode;
53
54 import java.io.ByteArrayOutputStream;
55 import java.io.IOException;
56 import java.io.PrintStream;
57 import java.nio.charset.Charset;
58 import java.nio.charset.StandardCharsets;
59 import java.time.Duration;
60 import java.time.Instant;
61 import java.util.Arrays;
62 import java.util.Collections;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.Objects;
66 import java.util.Set;
67 import java.util.function.Function;
68 import java.util.stream.Collectors;
69 import java.util.stream.Stream;
70
71 @Execution(ExecutionMode.SAME_THREAD)
72 class LogstashIT {
73
74 private static final StatusLogger LOGGER = StatusLogger.getLogger();
75
76 private static final DefaultConfiguration CONFIGURATION = new DefaultConfiguration();
77
78 private static final Charset CHARSET = StandardCharsets.UTF_8;
79
80 private static final String HOST_NAME = NetUtils.getLocalHostname();
81
82 private static final String SERVICE_NAME = "LogstashIT";
83
84 private static final String EVENT_DATASET = SERVICE_NAME + ".log";
85
86 private static final GelfLayout GELF_LAYOUT = GelfLayout
87 .newBuilder()
88 .setConfiguration(CONFIGURATION)
89 .setCharset(CHARSET)
90 .setCompressionType(GelfLayout.CompressionType.OFF)
91 .setIncludeNullDelimiter(true)
92 .setHost(HOST_NAME)
93 .build();
94
95 private static final JsonTemplateLayout JSON_TEMPLATE_GELF_LAYOUT = JsonTemplateLayout
96 .newBuilder()
97 .setConfiguration(CONFIGURATION)
98 .setCharset(CHARSET)
99 .setEventTemplateUri("classpath:GelfLayout.json")
100 .setEventDelimiter("\0")
101 .setEventTemplateAdditionalFields(
102 new EventTemplateAdditionalField[]{
103 EventTemplateAdditionalField
104 .newBuilder()
105 .setKey("host")
106 .setValue(HOST_NAME)
107 .build()
108 })
109 .build();
110
111 // Note that EcsLayout doesn't support charset configuration, though it uses
112 // UTF-8 internally.
113 private static final EcsLayout ECS_LAYOUT = EcsLayout
114 .newBuilder()
115 .setConfiguration(CONFIGURATION)
116 .setServiceName(SERVICE_NAME)
117 .setEventDataset(EVENT_DATASET)
118 .build();
119
120 private static final JsonTemplateLayout JSON_TEMPLATE_ECS_LAYOUT = JsonTemplateLayout
121 .newBuilder()
122 .setConfiguration(CONFIGURATION)
123 .setCharset(CHARSET)
124 .setEventTemplateUri("classpath:EcsLayout.json")
125 .setRecyclerFactory(ThreadLocalRecyclerFactory.getInstance())
126 .setEventTemplateAdditionalFields(
127 new EventTemplateAdditionalField[]{
128 EventTemplateAdditionalField
129 .newBuilder()
130 .setKey("service.name")
131 .setValue(SERVICE_NAME)
132 .build(),
133 EventTemplateAdditionalField
134 .newBuilder()
135 .setKey("event.dataset")
136 .setValue(EVENT_DATASET)
137 .build()
138 })
139 .build();
140
141 private static final int LOG_EVENT_COUNT = 100;
142
143 private static final String ES_INDEX_MESSAGE_FIELD_NAME = "message";
144
145 /**
146 * Constants hardcoded in docker-maven-plugin configuration, do not change!
147 */
148 private static final class MavenHardcodedConstants {
149
150 private MavenHardcodedConstants() {}
151
152 private static final int LS_GELF_INPUT_PORT = 12222;
153
154 private static final int LS_TCP_INPUT_PORT = 12345;
155
156 private static final int ES_PORT = 9200;
157
158 private static final String ES_INDEX_NAME = "log4j";
159
160 }
161
162 @Test
163 void test_lite_events() throws IOException {
164 final List<LogEvent> logEvents =
165 LogEventFixture.createLiteLogEvents(LOG_EVENT_COUNT);
166 testEvents(logEvents);
167 }
168
169 @Test
170 void test_full_events() throws IOException {
171 final List<LogEvent> logEvents =
172 LogEventFixture.createFullLogEvents(LOG_EVENT_COUNT);
173 testEvents(logEvents);
174 }
175
176 private static void testEvents(final List<LogEvent> logEvents) throws IOException {
177 try (final RestHighLevelClient client = createClient()) {
178 final Appender appender = createStartedAppender(
179 JSON_TEMPLATE_GELF_LAYOUT,
180 MavenHardcodedConstants.LS_GELF_INPUT_PORT);
181 try {
182
183 // Append events.
184 LOGGER.info("appending events");
185 logEvents.forEach(appender::append);
186 LOGGER.info("completed appending events");
187
188 // Wait all messages to arrive.
189 Awaitility
190 .await()
191 .atMost(Duration.ofSeconds(60))
192 .pollDelay(Duration.ofSeconds(2))
193 .until(() -> queryDocumentCount(client) == LOG_EVENT_COUNT);
194
195 // Verify indexed messages.
196 final Set<String> expectedMessages = logEvents
197 .stream()
198 .map(LogstashIT::expectedLogstashMessageField)
199 .collect(Collectors.toSet());
200 final Set<String> actualMessages = queryDocuments(client)
201 .stream()
202 .map(source -> (String) source.get(ES_INDEX_MESSAGE_FIELD_NAME))
203 .filter(Objects::nonNull)
204 .collect(Collectors.toSet());
205 Assertions
206 .assertThat(actualMessages)
207 .isEqualTo(expectedMessages);
208
209 } finally {
210 appender.stop();
211 }
212 }
213 }
214
215 private static String expectedLogstashMessageField(final LogEvent logEvent) {
216 final Throwable throwable = logEvent.getThrown();
217 if (throwable != null) {
218 try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
219 final PrintStream printStream = new PrintStream(outputStream, false, CHARSET.name())) {
220 throwable.printStackTrace(printStream);
221 return outputStream.toString(CHARSET.name());
222 } catch (final Exception error) {
223 throw new RuntimeException(
224 "failed printing stack trace",
225 error);
226 }
227 } else {
228 return logEvent.getMessage().getFormattedMessage();
229 }
230 }
231
232 @Test
233 void test_newlines() throws IOException {
234
235 // Create two log events containing new lines.
236 final Level level = Level.DEBUG;
237 final String loggerFqcn = "f.q.c.n";
238 final String loggerName = "A";
239 final SimpleMessage message1 = new SimpleMessage("line1\nline2\r\nline3");
240 final long instantMillis1 = Instant.EPOCH.toEpochMilli();
241 final LogEvent logEvent1 = Log4jLogEvent
242 .newBuilder()
243 .setLoggerName(loggerName)
244 .setLoggerFqcn(loggerFqcn)
245 .setLevel(level)
246 .setMessage(message1)
247 .setTimeMillis(instantMillis1)
248 .build();
249 final SimpleMessage message2 = new SimpleMessage("line4\nline5\r\nline6");
250 final long instantMillis2 = instantMillis1 + Duration.ofDays(1).toMillis();
251 final LogEvent logEvent2 = Log4jLogEvent
252 .newBuilder()
253 .setLoggerName(loggerName)
254 .setLoggerFqcn(loggerFqcn)
255 .setLevel(level)
256 .setMessage(message2)
257 .setTimeMillis(instantMillis2)
258 .build();
259
260 try (final RestHighLevelClient client = createClient()) {
261 final Appender appender = createStartedAppender(
262 JSON_TEMPLATE_GELF_LAYOUT,
263 MavenHardcodedConstants.LS_GELF_INPUT_PORT);
264 try {
265
266 // Append the event.
267 LOGGER.info("appending events");
268 appender.append(logEvent1);
269 appender.append(logEvent2);
270 LOGGER.info("completed appending events");
271
272 // Wait the message to arrive.
273 Awaitility
274 .await()
275 .atMost(Duration.ofSeconds(60))
276 .pollDelay(Duration.ofSeconds(2))
277 .until(() -> queryDocumentCount(client) == 2);
278
279 // Verify indexed messages.
280 final Set<String> expectedMessages = Stream
281 .of(logEvent1, logEvent2)
282 .map(LogstashIT::expectedLogstashMessageField)
283 .collect(Collectors.toSet());
284 final Set<String> actualMessages = queryDocuments(client)
285 .stream()
286 .map(source -> (String) source.get(ES_INDEX_MESSAGE_FIELD_NAME))
287 .filter(Objects::nonNull)
288 .collect(Collectors.toSet());
289 Assertions
290 .assertThat(actualMessages)
291 .isEqualTo(expectedMessages);
292
293 } finally {
294 appender.stop();
295 }
296 }
297
298 }
299
300 @Test
301 void test_GelfLayout() throws IOException {
302
303 // Create log events.
304 final List<LogEvent> logEvents =
305 LogEventFixture.createFullLogEvents(LOG_EVENT_COUNT);
306
307 // Append log events and collect persisted sources.
308 final Function<Map<String, Object>, Integer> keyMapper =
309 (final Map<String, Object> source) -> {
310 final String timestamp = (String) source.get("timestamp");
311 final String shortMessage = (String) source.get("short_message");
312 final String fullMessage = (String) source.get("full_message");
313 return Objects.hash(timestamp, shortMessage, fullMessage);
314 };
315 final Map<Integer, Object> expectedSourceByKey =
316 appendAndCollect(
317 logEvents,
318 GELF_LAYOUT,
319 MavenHardcodedConstants.LS_GELF_INPUT_PORT,
320 keyMapper,
321 Collections.emptySet());
322 final Map<Integer, Object> actualSourceByKey =
323 appendAndCollect(
324 logEvents,
325 JSON_TEMPLATE_GELF_LAYOUT,
326 MavenHardcodedConstants.LS_GELF_INPUT_PORT,
327 keyMapper,
328 Collections.emptySet());
329
330 // Compare persisted sources.
331 Assertions.assertThat(actualSourceByKey).isEqualTo(expectedSourceByKey);
332
333 }
334
335 @Test
336 void test_EcsLayout() throws IOException {
337
338 // Create log events.
339 final List<LogEvent> logEvents =
340 LogEventFixture.createFullLogEvents(LOG_EVENT_COUNT);
341
342 // Append log events and collect persisted sources.
343 final Function<Map<String, Object>, Integer> keyMapper =
344 (final Map<String, Object> source) -> {
345 final String timestamp = (String) source.get("@timestamp");
346 final String message = (String) source.get("message");
347 final String errorMessage = (String) source.get("error.message");
348 return Objects.hash(timestamp, message, errorMessage);
349 };
350 final Set<String> excludedKeys = Collections.singleton("port");
351 final Map<Integer, Object> expectedSourceByKey =
352 appendAndCollect(
353 logEvents,
354 ECS_LAYOUT,
355 MavenHardcodedConstants.LS_TCP_INPUT_PORT,
356 keyMapper,
357 excludedKeys);
358 final Map<Integer, Object> actualSourceByKey =
359 appendAndCollect(
360 logEvents,
361 JSON_TEMPLATE_ECS_LAYOUT,
362 MavenHardcodedConstants.LS_TCP_INPUT_PORT,
363 keyMapper,
364 excludedKeys);
365
366 // Compare persisted sources.
367 Assertions.assertThat(actualSourceByKey).isEqualTo(expectedSourceByKey);
368
369 }
370
371 private static <K> Map<K, Object> appendAndCollect(
372 final List<LogEvent> logEvents,
373 final Layout<?> layout,
374 final int port,
375 final Function<Map<String, Object>, K> keyMapper,
376 final Set<String> excludedKeys) throws IOException {
377 try (final RestHighLevelClient client = createClient()) {
378 final Appender appender = createStartedAppender(layout, port);
379 try {
380
381 // Append the event.
382 LOGGER.info("appending events");
383 logEvents.forEach(appender::append);
384 LOGGER.info("completed appending events");
385
386 // Wait the message to arrive.
387 Awaitility
388 .await()
389 .atMost(Duration.ofSeconds(60))
390 .pollDelay(Duration.ofSeconds(2))
391 .until(() -> queryDocumentCount(client) == LOG_EVENT_COUNT);
392
393 // Retrieve the persisted messages.
394 return queryDocuments(client)
395 .stream()
396 .collect(Collectors.toMap(
397 keyMapper,
398 (final Map<String, Object> source) -> {
399 excludedKeys.forEach(source::remove);
400 return source;
401 }));
402
403 } finally {
404 appender.stop();
405 }
406 }
407 }
408
409 private static RestHighLevelClient createClient() throws IOException {
410
411 // Instantiate the client.
412 LOGGER.info("instantiating the ES client");
413 final HttpHost httpHost = new HttpHost(HOST_NAME, MavenHardcodedConstants.ES_PORT);
414 final RestClientBuilder clientBuilder =
415 RestClient.builder(httpHost);
416 final RestHighLevelClient client = new RestHighLevelClient(clientBuilder);
417
418 // Verify the connection.
419 LOGGER.info("verifying the ES connection");
420 final ClusterHealthResponse healthResponse = client
421 .cluster()
422 .health(new ClusterHealthRequest(), RequestOptions.DEFAULT);
423 Assertions
424 .assertThat(healthResponse.getStatus())
425 .isNotEqualTo(ClusterHealthStatus.RED);
426
427 // Delete the index.
428 LOGGER.info("deleting the ES index");
429 final DeleteIndexRequest deleteRequest =
430 new DeleteIndexRequest(MavenHardcodedConstants.ES_INDEX_NAME);
431 try {
432 final AcknowledgedResponse deleteResponse = client
433 .indices()
434 .delete(deleteRequest, RequestOptions.DEFAULT);
435 Assertions
436 .assertThat(deleteResponse.isAcknowledged())
437 .isTrue();
438 } catch (ElasticsearchStatusException error) {
439 Assertions.assertThat(error)
440 .satisfies(ignored -> Assertions
441 .assertThat(error.status())
442 .isEqualTo(RestStatus.NOT_FOUND));
443 }
444
445 return client;
446
447 }
448
449 private static SocketAppender createStartedAppender(
450 final Layout<?> layout,
451 final int port) {
452 LOGGER.info("creating the appender");
453 final SocketAppender appender = SocketAppender
454 .newBuilder()
455 .setConfiguration(CONFIGURATION)
456 .withHost(HOST_NAME)
457 .withPort(port)
458 .withReconnectDelayMillis(100)
459 .setName("LogstashItAppender")
460 .withBufferedIo(false)
461 .withImmediateFail(true)
462 .setIgnoreExceptions(false)
463 .setLayout(layout)
464 .build();
465 appender.start();
466 return appender;
467 }
468
469 private static long queryDocumentCount(
470 final RestHighLevelClient client)
471 throws IOException {
472 final SearchSourceBuilder searchSourceBuilder =
473 new SearchSourceBuilder()
474 .size(0)
475 .fetchSource(false);
476 final SearchRequest searchRequest =
477 new SearchRequest(MavenHardcodedConstants.ES_INDEX_NAME)
478 .source(searchSourceBuilder);
479 try {
480 final SearchResponse searchResponse =
481 client.search(searchRequest, RequestOptions.DEFAULT);
482 return searchResponse.getHits().getTotalHits().value;
483 } catch (ElasticsearchStatusException error) {
484 if (RestStatus.NOT_FOUND.equals(error.status())) {
485 return 0L;
486 }
487 throw new IOException(error);
488 }
489 }
490
491 private static List<Map<String, Object>> queryDocuments(
492 final RestHighLevelClient client
493 ) throws IOException {
494 final SearchSourceBuilder searchSourceBuilder =
495 new SearchSourceBuilder()
496 .size(LOG_EVENT_COUNT)
497 .fetchSource(true);
498 final SearchRequest searchRequest =
499 new SearchRequest(MavenHardcodedConstants.ES_INDEX_NAME)
500 .source(searchSourceBuilder);
501 try {
502 final SearchResponse searchResponse =
503 client.search(searchRequest, RequestOptions.DEFAULT);
504 return Arrays
505 .stream(searchResponse.getHits().getHits())
506 .map(SearchHit::getSourceAsMap)
507 .collect(Collectors.toList());
508 } catch (ElasticsearchStatusException error) {
509 if (RestStatus.NOT_FOUND.equals(error.status())) {
510 return Collections.emptyList();
511 }
512 throw new IOException(error);
513 }
514 }
515
516 }
+0
-156
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.Layout;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.Configuration;
23 import org.apache.logging.log4j.core.config.Configurator;
24 import org.apache.logging.log4j.core.config.DefaultConfiguration;
25 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
26 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
27 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
28 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
29 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
30 import org.apache.logging.log4j.layout.template.json.util.MapAccessor;
31 import org.apache.logging.log4j.test.appender.ListAppender;
32
33 import java.util.LinkedHashMap;
34 import java.util.Map;
35 import java.util.function.BiConsumer;
36 import java.util.function.Consumer;
37
38 public final class TestHelpers {
39
40 public static final Configuration CONFIGURATION = new DefaultConfiguration();
41
42 private static final JsonWriter JSON_WRITER = JsonWriter
43 .newBuilder()
44 .setMaxStringLength(10_000)
45 .setTruncatedStringSuffix("…")
46 .build();
47
48 private TestHelpers() {}
49
50 @SuppressWarnings("unchecked")
51 static Map<String, Object> serializeUsingLayout(
52 final LogEvent logEvent,
53 final Layout<String> layout) {
54 final String json = layout.toSerializable(logEvent);
55 return (Map<String, Object>) JsonReader.read(json);
56 }
57
58 public static String writeJson(final Object value) {
59 synchronized (JSON_WRITER) {
60 final StringBuilder stringBuilder = JSON_WRITER.getStringBuilder();
61 stringBuilder.setLength(0);
62 try {
63 JSON_WRITER.writeValue(value);
64 return stringBuilder.toString();
65 } finally {
66 stringBuilder.setLength(0);
67 }
68 }
69 }
70
71 public static void usingSerializedLogEventAccessor(
72 final Layout<String> layout,
73 final LogEvent logEvent,
74 final Consumer<MapAccessor> accessorConsumer) {
75 final String serializedLogEventJson = layout.toSerializable(logEvent);
76 @SuppressWarnings("unchecked")
77 final Map<String, Object> deserializedLogEvent =
78 (Map<String, Object>) readJson(serializedLogEventJson);
79 final MapAccessor serializedLogEventAccessor = new MapAccessor(deserializedLogEvent);
80 accessorConsumer.accept(serializedLogEventAccessor);
81 }
82
83 public static Object readJson(final String json) {
84 return JsonReader.read(json);
85 }
86
87 public static Map<String, Object> asMap(final Object... pairs) {
88 final Map<String, Object> map = new LinkedHashMap<>();
89 if (pairs.length % 2 != 0) {
90 throw new IllegalArgumentException("odd number of arguments: " + pairs.length);
91 }
92 for (int i = 0; i < pairs.length; i += 2) {
93 final String key = (String) pairs[i];
94 final Object value = pairs[i + 1];
95 map.put(key, value);
96 }
97 return map;
98 }
99
100 /**
101 * Provides a configuration using the given JSON event template to the given consumer.
102 * <p>
103 * A {@link ListAppender} (named {@code List}) wrapping the layout is used to store the log events.
104 * The root logger level is set to {@link Level#ALL}.
105 * </p>
106 * @param configName a configuration name
107 * @param eventTemplate a JSON template
108 * @param consumer a consumer accepting the created logger context and the list appender
109 */
110 public static void withContextFromTemplate(
111 final String configName,
112 final Object eventTemplate,
113 final BiConsumer<LoggerContext, ListAppender> consumer) {
114
115 // Create the configuration builder.
116 final ConfigurationBuilder<BuiltConfiguration> configBuilder = ConfigurationBuilderFactory
117 .newConfigurationBuilder()
118 .setStatusLevel(Level.ERROR)
119 .setConfigurationName(configName);
120
121 // Create the configuration.
122 final String eventTemplateJson = writeJson(eventTemplate);
123 final String appenderName = "List";
124 Configuration config = configBuilder
125 .add(configBuilder
126 .newAppender(appenderName, "List")
127 .addAttribute("raw", true)
128 .add(configBuilder
129 .newLayout("JsonTemplateLayout")
130 .addAttribute(
131 "eventTemplate",
132 eventTemplateJson)))
133 .add(configBuilder
134 .newRootLogger(Level.ALL)
135 .add(configBuilder.newAppenderRef(appenderName)))
136 .build(false);
137
138 // Initialize the configuration and pass it to the consumer.
139 try (final LoggerContext loggerContext = Configurator.initialize(config)) {
140 final ListAppender appender = loggerContext.getConfiguration().getAppender("List");
141 consumer.accept(loggerContext, appender);
142 }
143
144 }
145
146 public static void uncheckedSleep(final long millis) {
147 try {
148 Thread.sleep(millis);
149 } catch (InterruptedException ignored) {
150 Thread.currentThread().interrupt();
151 throw new RuntimeException("interrupted");
152 }
153 }
154
155 }
+0
-141
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverTest.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
21 import org.apache.logging.log4j.util.SortedArrayStringMap;
22 import org.apache.logging.log4j.util.StringMap;
23 import org.apache.logging.log4j.util.Strings;
24 import org.junit.jupiter.params.ParameterizedTest;
25 import org.junit.jupiter.params.provider.CsvSource;
26
27 import static org.apache.logging.log4j.layout.template.json.TestHelpers.CONFIGURATION;
28 import static org.apache.logging.log4j.layout.template.json.TestHelpers.asMap;
29 import static org.apache.logging.log4j.layout.template.json.TestHelpers.readJson;
30 import static org.apache.logging.log4j.layout.template.json.TestHelpers.usingSerializedLogEventAccessor;
31 import static org.apache.logging.log4j.layout.template.json.TestHelpers.writeJson;
32 import static org.assertj.core.api.Assertions.assertThat;
33 import static org.assertj.core.api.Assertions.assertThatThrownBy;
34
35 class CaseConverterResolverTest {
36
37 @ParameterizedTest
38 @CsvSource({
39 // case | locale | input | output
40 "upper" + ",nl" + ",ioz" + ",IOZ",
41 "upper" + ",nl" + ",IOZ" + ",IOZ",
42 "lower" + ",nl" + ",ioz" + ",ioz",
43 "lower" + ",nl" + ",IOZ" + ",ioz",
44 "upper" + ",tr" + ",ıiğüşöç" + ",IİĞÜŞÖÇ",
45 "upper" + ",tr" + ",IİĞÜŞÖÇ" + ",IİĞÜŞÖÇ",
46 "lower" + ",tr" + ",ıiğüşöç" + ",ıiğüşöç",
47 "lower" + ",tr" + ",IİĞÜŞÖÇ" + ",ıiğüşöç"
48 })
49 void test_upper(
50 final String case_,
51 final String locale,
52 final String input,
53 final String output) {
54
55 // Create the event template.
56 final String eventTemplate = writeJson(asMap(
57 "output", asMap(
58 "$resolver", "caseConverter",
59 "case", case_,
60 "locale", locale,
61 "input", asMap(
62 "$resolver", "mdc",
63 "key", "input"))));
64
65 // Create the layout.
66 final JsonTemplateLayout layout = JsonTemplateLayout
67 .newBuilder()
68 .setConfiguration(CONFIGURATION)
69 .setEventTemplate(eventTemplate)
70 .build();
71
72 // Create the log event.
73 final StringMap contextData = new SortedArrayStringMap();
74 contextData.putValue("input", input);
75 final LogEvent logEvent = Log4jLogEvent
76 .newBuilder()
77 .setContextData(contextData)
78 .build();
79
80 // Check the serialized event.
81 usingSerializedLogEventAccessor(layout, logEvent, accessor ->
82 assertThat(accessor.getString("output")).isEqualTo(output));
83
84 }
85
86 @ParameterizedTest
87 @CsvSource({
88 // failure message | locale | input | strategy | replacement | output
89 "" + ",nl" + ",1" + ",pass" + ",null" + ",1",
90 "" + ",nl" + ",[2]" + ",pass" + ",null" + ",[2]",
91 "was expecting a string value" + ",nl" + ",1" + ",fail" + ",null" + ",null",
92 "" + ",nl" + ",1" + ",replace" + ",null" + ",null",
93 "" + ",nl" + ",1" + ",replace" + ",2" + ",2",
94 "" + ",nl" + ",1" + ",replace" + ",\"s\"" + ",\"s\""
95 })
96 void test_errorHandlingStrategy(
97 final String failureMessage,
98 final String locale,
99 final String inputJson,
100 final String errorHandlingStrategy,
101 final String replacementJson,
102 final String outputJson) {
103
104 // Parse arguments.
105 final Object input = readJson(inputJson);
106 final Object replacement = readJson(replacementJson);
107 final Object output = readJson(outputJson);
108
109 // Create the event template.
110 final String eventTemplate = writeJson(asMap(
111 "output", asMap(
112 "$resolver", "caseConverter",
113 "case", "lower",
114 "locale", locale,
115 "input", input,
116 "errorHandlingStrategy", errorHandlingStrategy,
117 "replacement", replacement)));
118
119 // Create the layout.
120 final JsonTemplateLayout layout = JsonTemplateLayout
121 .newBuilder()
122 .setConfiguration(CONFIGURATION)
123 .setEventTemplate(eventTemplate)
124 .build();
125
126 // Create the log event.
127 final LogEvent logEvent = Log4jLogEvent.newBuilder().build();
128
129 // Check the serialized event.
130 final boolean failureExpected = Strings.isNotBlank(failureMessage);
131 if (failureExpected) {
132 assertThatThrownBy(() -> layout.toSerializable(logEvent))
133 .hasMessageContaining(failureMessage);
134 } else {
135 usingSerializedLogEventAccessor(layout, logEvent, accessor ->
136 assertThat(accessor.getObject("output")).isEqualTo(output));
137 }
138 }
139
140 }
+0
-158
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/CounterResolverTest.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
21 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
22 import org.junit.jupiter.api.Test;
23
24 import java.math.BigInteger;
25
26 import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
27 import static org.assertj.core.api.Assertions.assertThat;
28
29 class CounterResolverTest {
30
31 @Test
32 void no_arg_setup_should_start_from_zero() {
33 final String eventTemplate = writeJson(asMap("$resolver", "counter"));
34 verify(eventTemplate, 0, 1);
35 }
36
37 @Test
38 void positive_start_should_work() {
39 final String eventTemplate = writeJson(asMap(
40 "$resolver", "counter",
41 "start", 3));
42 verify(eventTemplate, 3, 4);
43 }
44
45 @Test
46 void positive_start_should_work_when_stringified() {
47 final String eventTemplate = writeJson(asMap(
48 "$resolver", "counter",
49 "start", 3,
50 "stringified", true));
51 verify(eventTemplate, "3", "4");
52 }
53
54 @Test
55 void negative_start_should_work() {
56 final String eventTemplate = writeJson(asMap(
57 "$resolver", "counter",
58 "start", -3));
59 verify(eventTemplate, -3, -2);
60 }
61
62 @Test
63 void negative_start_should_work_when_stringified() {
64 final String eventTemplate = writeJson(asMap(
65 "$resolver", "counter",
66 "start", -3,
67 "stringified", true));
68 verify(eventTemplate, "-3", "-2");
69 }
70
71 @Test
72 void min_long_should_work_when_overflow_enabled() {
73 final String eventTemplate = writeJson(asMap(
74 "$resolver", "counter",
75 "start", Long.MIN_VALUE));
76 verify(eventTemplate, Long.MIN_VALUE, Long.MIN_VALUE + 1L);
77 }
78
79 @Test
80 void min_long_should_work_when_overflow_enabled_and_stringified() {
81 final String eventTemplate = writeJson(asMap(
82 "$resolver", "counter",
83 "start", Long.MIN_VALUE,
84 "stringified", true));
85 verify(eventTemplate, "" + Long.MIN_VALUE, "" + (Long.MIN_VALUE + 1L));
86 }
87
88 @Test
89 void max_long_should_work_when_overflowing() {
90 final String eventTemplate = writeJson(asMap(
91 "$resolver", "counter",
92 "start", Long.MAX_VALUE));
93 verify(eventTemplate, Long.MAX_VALUE, Long.MIN_VALUE);
94 }
95
96 @Test
97 void max_long_should_work_when_overflowing_and_stringified() {
98 final String eventTemplate = writeJson(asMap(
99 "$resolver", "counter",
100 "start", Long.MAX_VALUE,
101 "stringified", true));
102 verify(eventTemplate, "" + Long.MAX_VALUE, "" + Long.MIN_VALUE);
103 }
104
105 @Test
106 void max_long_should_work_when_not_overflowing() {
107 final String eventTemplate = writeJson(asMap(
108 "$resolver", "counter",
109 "start", Long.MAX_VALUE,
110 "overflowing", false));
111 verify(
112 eventTemplate,
113 Long.MAX_VALUE,
114 BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE));
115 }
116
117 @Test
118 void max_long_should_work_when_not_overflowing_and_stringified() {
119 final String eventTemplate = writeJson(asMap(
120 "$resolver", "counter",
121 "start", Long.MAX_VALUE,
122 "overflowing", false,
123 "stringified", true));
124 verify(
125 eventTemplate,
126 "" + Long.MAX_VALUE,
127 "" + BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE));
128 }
129
130 private static void verify(
131 final String eventTemplate,
132 final Object expectedNumber1,
133 final Object expectedNumber2) {
134
135 // Create the layout.
136 final JsonTemplateLayout layout = JsonTemplateLayout
137 .newBuilder()
138 .setConfiguration(CONFIGURATION)
139 .setEventTemplate(eventTemplate)
140 .build();
141
142 // Create the log event.
143 final LogEvent logEvent = Log4jLogEvent.newBuilder().build();
144
145 // Check the 1st serialized event.
146 final String serializedLogEvent1 = layout.toSerializable(logEvent);
147 final Object deserializedLogEvent1 = JsonReader.read(serializedLogEvent1);
148 assertThat(deserializedLogEvent1).isEqualTo(expectedNumber1);
149
150 // Check the 2nd serialized event.
151 final String serializedLogEvent2 = layout.toSerializable(logEvent);
152 final Object deserializedLogEvent2 = JsonReader.read(serializedLogEvent2);
153 assertThat(deserializedLogEvent2).isEqualTo(expectedNumber2);
154
155 }
156
157 }
+0
-235
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
23 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
24 import org.apache.logging.log4j.message.Message;
25 import org.apache.logging.log4j.message.ObjectMessage;
26 import org.apache.logging.log4j.message.SimpleMessage;
27 import org.apache.logging.log4j.message.StringMapMessage;
28 import org.apache.logging.log4j.test.appender.ListAppender;
29 import org.assertj.core.api.Assertions;
30 import org.junit.jupiter.api.Test;
31
32 import java.nio.charset.StandardCharsets;
33 import java.util.Collections;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
38
39 import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
40 import static org.assertj.core.api.Assertions.assertThat;
41
42 class MessageResolverTest {
43
44 /**
45 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-3080">LOG4J2-3080</a>
46 */
47 @Test
48 @LoggerContextSource("messageFallbackKeyUsingJsonTemplateLayout.xml")
49 void log4j1_logger_calls_should_use_fallbackKey(
50 final @Named(value = "List") ListAppender appender) {
51
52 // Log using legacy Log4j 1 API.
53 final String log4j1Message =
54 "Message logged using org.apache.log4j.Category.info(Object)";
55 org.apache.log4j.LogManager
56 .getLogger(MessageResolverTest.class)
57 .info(log4j1Message);
58
59 // Log using Log4j 2 API.
60 final String log4j2Message =
61 "Message logged using org.apache.logging.log4j.Logger.info(String)";
62 org.apache.logging.log4j.LogManager
63 .getLogger(MessageResolverTest.class)
64 .info(log4j2Message);
65
66 // Collect and parse logged messages.
67 final List<Object> actualLoggedEvents = appender
68 .getData()
69 .stream()
70 .map(jsonBytes -> {
71 final String json = new String(jsonBytes, StandardCharsets.UTF_8);
72 return JsonReader.read(json);
73 })
74 .collect(Collectors.toList());
75
76 // Verify logged messages.
77 final List<Object> expectedLoggedEvents = Stream
78 .of(log4j1Message, log4j2Message)
79 .map(message -> Collections.singletonMap(
80 "message", Collections.singletonMap(
81 "fallback", message)))
82 .collect(Collectors.toList());
83 Assertions.assertThat(actualLoggedEvents).isEqualTo(expectedLoggedEvents);
84
85 }
86
87 @Test
88 void test_message_fallbackKey() {
89
90 // Create the event template.
91 final String eventTemplate = writeJson(asMap(
92 "message", asMap(
93 "$resolver", "message",
94 "fallbackKey", "formattedMessage")));
95
96 // Create the layout.
97 final JsonTemplateLayout layout = JsonTemplateLayout
98 .newBuilder()
99 .setConfiguration(CONFIGURATION)
100 .setEventTemplate(eventTemplate)
101 .build();
102
103 // Create a log event with a MapMessage.
104 final Message mapMessage = new StringMapMessage()
105 .with("key1", "val1");
106 final LogEvent mapMessageLogEvent = Log4jLogEvent
107 .newBuilder()
108 .setMessage(mapMessage)
109 .setTimeMillis(System.currentTimeMillis())
110 .build();
111
112 // Check the serialized MapMessage.
113 usingSerializedLogEventAccessor(layout, mapMessageLogEvent, accessor ->
114 assertThat(accessor.getString(new String[]{"message", "key1"}))
115 .isEqualTo("val1"));
116
117 // Create a log event with a SimpleMessage.
118 final Message simpleMessage = new SimpleMessage("simple");
119 final LogEvent simpleMessageLogEvent = Log4jLogEvent
120 .newBuilder()
121 .setMessage(simpleMessage)
122 .setTimeMillis(System.currentTimeMillis())
123 .build();
124
125 // Check the serialized MapMessage.
126 usingSerializedLogEventAccessor(layout, simpleMessageLogEvent, accessor ->
127 assertThat(accessor.getString(new String[]{"message", "formattedMessage"}))
128 .isEqualTo("simple"));
129
130 }
131
132 @Test
133 void test_StringMapMessage() {
134
135 // Create the log event.
136 final StringMapMessage message = new StringMapMessage();
137 message.put("message", "Hello, World!");
138 message.put("bottle", "Kickapoo Joy Juice");
139 final LogEvent logEvent = Log4jLogEvent
140 .newBuilder()
141 .setMessage(message)
142 .build();
143
144 // Create the event template.
145 final String eventTemplate = writeJson(asMap(
146 "message", asMap("$resolver", "message")));
147
148 // Create the layout.
149 final JsonTemplateLayout layout = JsonTemplateLayout
150 .newBuilder()
151 .setConfiguration(CONFIGURATION)
152 .setStackTraceEnabled(true)
153 .setEventTemplate(eventTemplate)
154 .build();
155
156 // Check the serialized event.
157 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
158 assertThat(accessor.getString(new String[]{"message", "message"})).isEqualTo("Hello, World!");
159 assertThat(accessor.getString(new String[]{"message", "bottle"})).isEqualTo("Kickapoo Joy Juice");
160 });
161
162 }
163
164 @Test
165 void test_ObjectMessage() {
166
167 // Create the log event.
168 final int id = 0xDEADBEEF;
169 final String name = "name-" + id;
170 final Object attachment = new LinkedHashMap<String, Object>() {{
171 put("id", id);
172 put("name", name);
173 }};
174 final ObjectMessage message = new ObjectMessage(attachment);
175 final LogEvent logEvent = Log4jLogEvent
176 .newBuilder()
177 .setMessage(message)
178 .build();
179
180 // Create the event template.
181 final String eventTemplate = writeJson(asMap(
182 "message", asMap("$resolver", "message")));
183
184 // Create the layout.
185 JsonTemplateLayout layout = JsonTemplateLayout
186 .newBuilder()
187 .setConfiguration(CONFIGURATION)
188 .setStackTraceEnabled(true)
189 .setEventTemplate(eventTemplate)
190 .build();
191
192 // Check the serialized event.
193 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
194 assertThat(accessor.getInteger(new String[]{"message", "id"})).isEqualTo(id);
195 assertThat(accessor.getString(new String[]{"message", "name"})).isEqualTo(name);
196 });
197
198 }
199
200 @Test
201 void test_MapMessage_serialization() {
202
203 // Create the event template.
204 final String eventTemplate = writeJson(asMap(
205 "message", asMap("$resolver", "message")));
206
207 // Create the layout.
208 final JsonTemplateLayout layout = JsonTemplateLayout
209 .newBuilder()
210 .setConfiguration(CONFIGURATION)
211 .setEventTemplate(eventTemplate)
212 .build();
213
214 // Create the log event with a MapMessage.
215 final StringMapMessage mapMessage = new StringMapMessage()
216 .with("key1", "val1")
217 .with("key2", 0xDEADBEEF)
218 .with("key3", Collections.singletonMap("key3.1", "val3.1"));
219 final LogEvent logEvent = Log4jLogEvent
220 .newBuilder()
221 .setMessage(mapMessage)
222 .setTimeMillis(System.currentTimeMillis())
223 .build();
224
225 // Check the serialized event.
226 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
227 assertThat(accessor.getString(new String[]{"message", "key1"})).isEqualTo("val1");
228 assertThat(accessor.getInteger(new String[]{"message", "key2"})).isEqualTo(0xDEADBEEF);
229 assertThat(accessor.getString(new String[]{"message", "key3", "key3.1"})).isEqualTo("val3.1");
230 });
231
232 }
233
234 }
+0
-453
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
21 import org.apache.logging.log4j.message.Message;
22 import org.apache.logging.log4j.message.SimpleMessage;
23 import org.apache.logging.log4j.message.StringMapMessage;
24 import org.apache.logging.log4j.util.SortedArrayStringMap;
25 import org.apache.logging.log4j.util.StringMap;
26 import org.assertj.core.api.Assertions;
27 import org.junit.jupiter.api.Test;
28
29 import java.util.Arrays;
30 import java.util.List;
31 import java.util.regex.PatternSyntaxException;
32
33 import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
34 import static org.assertj.core.api.Assertions.assertThat;
35
36 class ReadOnlyStringMapResolverTest {
37
38 @Test
39 void key_should_not_be_allowed_with_flatten() {
40 verifyConfigFailure(
41 writeJson(asMap(
42 "$resolver", "mdc",
43 "key", "foo",
44 "flatten", true)),
45 IllegalArgumentException.class,
46 "key and flatten options cannot be combined");
47 }
48
49 @Test
50 void invalid_pattern_should_fail() {
51 verifyConfigFailure(
52 writeJson(asMap(
53 "$resolver", "mdc",
54 "pattern", "[1")),
55 PatternSyntaxException.class,
56 "Unclosed character");
57 }
58
59 @Test
60 void pattern_should_not_be_allowed_with_key() {
61 verifyConfigFailure(
62 writeJson(asMap(
63 "$resolver", "mdc",
64 "key", "foo",
65 "pattern", "bar")),
66 IllegalArgumentException.class,
67 "pattern and key options cannot be combined");
68 }
69
70 @Test
71 void replacement_should_not_be_allowed_without_pattern() {
72 verifyConfigFailure(
73 writeJson(asMap(
74 "$resolver", "mdc",
75 "replacement", "$1")),
76 IllegalArgumentException.class,
77 "replacement cannot be provided without a pattern");
78 }
79
80 private static void verifyConfigFailure(
81 final String eventTemplate,
82 final Class<? extends Throwable> failureClass,
83 final String failureMessage) {
84 Assertions
85 .assertThatThrownBy(() -> JsonTemplateLayout
86 .newBuilder()
87 .setConfiguration(CONFIGURATION)
88 .setEventTemplate(eventTemplate)
89 .build())
90 .isInstanceOf(failureClass)
91 .hasMessageContaining(failureMessage);
92 }
93
94 @Test
95 void pattern_replacement_should_work() {
96
97 // Create the event template.
98 final String eventTemplate = writeJson(asMap(
99 "$resolver", "mdc",
100 "pattern", "user:(role|rank)",
101 "replacement", "$1"));
102
103 // Create the layout.
104 final JsonTemplateLayout layout = JsonTemplateLayout
105 .newBuilder()
106 .setConfiguration(CONFIGURATION)
107 .setEventTemplate(eventTemplate)
108 .build();
109
110 // Create the log event.
111 final StringMap contextData = new SortedArrayStringMap();
112 contextData.putValue("user:role", "engineer");
113 contextData.putValue("user:rank", "senior");
114 final LogEvent logEvent = Log4jLogEvent
115 .newBuilder()
116 .setContextData(contextData)
117 .build();
118
119 // Check the serialized event.
120 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
121 assertThat(accessor.getString("role")).isEqualTo("engineer");
122 assertThat(accessor.getString("rank")).isEqualTo("senior");
123 });
124
125 }
126
127 @Test
128 void test_mdc_key_access() {
129
130 // Create the log event.
131 final SimpleMessage message = new SimpleMessage("Hello, World!");
132 final StringMap contextData = new SortedArrayStringMap();
133 final String mdcDirectlyAccessedKey = "mdcKey1";
134 final String mdcDirectlyAccessedValue = "mdcValue1";
135 contextData.putValue(mdcDirectlyAccessedKey, mdcDirectlyAccessedValue);
136 final String mdcDirectlyAccessedNullPropertyKey = "mdcKey2";
137 contextData.putValue(mdcDirectlyAccessedNullPropertyKey, null);
138 final LogEvent logEvent = Log4jLogEvent
139 .newBuilder()
140 .setMessage(message)
141 .setContextData(contextData)
142 .build();
143
144 // Check the serialized event.
145 testReadOnlyStringMapKeyAccess(
146 mdcDirectlyAccessedKey,
147 mdcDirectlyAccessedValue,
148 mdcDirectlyAccessedNullPropertyKey,
149 logEvent,
150 "mdc");
151
152 }
153
154 @Test
155 public void test_map_key_access() {
156
157 // Create the log event.
158 final String directlyAccessedKey = "mapKey1";
159 final String directlyAccessedValue = "mapValue1";
160 final String directlyAccessedNullPropertyKey = "mapKey2";
161 final Message message = new StringMapMessage()
162 .with(directlyAccessedKey, directlyAccessedValue);
163 final LogEvent logEvent = Log4jLogEvent
164 .newBuilder()
165 .setMessage(message)
166 .build();
167
168 // Check the serialized event.
169 testReadOnlyStringMapKeyAccess(
170 directlyAccessedKey,
171 directlyAccessedValue,
172 directlyAccessedNullPropertyKey,
173 logEvent,
174 "map");
175
176 }
177
178 private static void testReadOnlyStringMapKeyAccess(
179 final String directlyAccessedKey,
180 final String directlyAccessedValue,
181 final String directlyAccessedNullPropertyKey,
182 final LogEvent logEvent,
183 final String resolverName) {
184
185 // Create the event template.
186 String eventTemplate = writeJson(asMap(
187 directlyAccessedKey, asMap(
188 "$resolver", resolverName,
189 "key", directlyAccessedKey),
190 directlyAccessedNullPropertyKey, asMap(
191 "$resolver", resolverName,
192 "key", directlyAccessedNullPropertyKey)));
193
194 // Create the layout.
195 final JsonTemplateLayout layout = JsonTemplateLayout
196 .newBuilder()
197 .setConfiguration(CONFIGURATION)
198 .setStackTraceEnabled(true)
199 .setEventTemplate(eventTemplate)
200 .build();
201
202 // Check the serialized event.
203 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
204 assertThat(accessor.getString(directlyAccessedKey)).isEqualTo(directlyAccessedValue);
205 assertThat(accessor.getString(directlyAccessedNullPropertyKey)).isNull();
206 });
207
208 }
209
210 @Test
211 void test_mdc_pattern() {
212
213 // Create the log event.
214 final SimpleMessage message = new SimpleMessage("Hello, World!");
215 final StringMap contextData = new SortedArrayStringMap();
216 final String mdcPatternMatchedKey = "mdcKey1";
217 final String mdcPatternMatchedValue = "mdcValue1";
218 contextData.putValue(mdcPatternMatchedKey, mdcPatternMatchedValue);
219 final String mdcPatternMismatchedKey = "mdcKey2";
220 final String mdcPatternMismatchedValue = "mdcValue2";
221 contextData.putValue(mdcPatternMismatchedKey, mdcPatternMismatchedValue);
222 final LogEvent logEvent = Log4jLogEvent
223 .newBuilder()
224 .setMessage(message)
225 .setContextData(contextData)
226 .build();
227
228 // Check the serialized event.
229 testReadOnlyStringMapPattern(
230 mdcPatternMatchedKey,
231 mdcPatternMatchedValue,
232 mdcPatternMismatchedKey,
233 logEvent,
234 "mdc");
235
236 }
237
238 @Test
239 public void test_map_pattern() {
240
241 // Create the log event.
242 final String patternMatchedKey = "mapKey1";
243 final String patternMatchedValue = "mapValue1";
244 final String patternMismatchedKey = "mapKey2";
245 final String patternMismatchedValue = "mapValue2";
246 final Message message = new StringMapMessage()
247 .with(patternMatchedKey, patternMatchedValue)
248 .with(patternMismatchedKey, patternMismatchedValue);
249 final LogEvent logEvent = Log4jLogEvent
250 .newBuilder()
251 .setMessage(message)
252 .build();
253
254 // Check the serialized event.
255 testReadOnlyStringMapPattern(
256 patternMatchedKey,
257 patternMatchedValue,
258 patternMismatchedKey,
259 logEvent,
260 "map");
261
262 }
263
264 private static void testReadOnlyStringMapPattern(
265 final String patternMatchedKey,
266 final String patternMatchedValue,
267 final String patternMismatchedKey,
268 final LogEvent logEvent,
269 final String resolverName) {
270
271 // Create the event template.
272 final String mapFieldName = "map";
273 final String eventTemplate = writeJson(asMap(
274 mapFieldName, asMap(
275 "$resolver", resolverName,
276 "pattern", patternMatchedKey)));
277
278 // Create the layout.
279 final JsonTemplateLayout layout = JsonTemplateLayout
280 .newBuilder()
281 .setConfiguration(CONFIGURATION)
282 .setStackTraceEnabled(true)
283 .setEventTemplate(eventTemplate)
284 .build();
285
286 // Check the serialized event.
287 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
288 assertThat(accessor.getString(new String[]{mapFieldName, patternMatchedKey})).isEqualTo(patternMatchedValue);
289 assertThat(accessor.exists(new String[]{mapFieldName, patternMismatchedKey})).isFalse();
290 });
291
292 }
293
294 @Test
295 void test_mdc_flatten() {
296
297 // Create the log event.
298 final SimpleMessage message = new SimpleMessage("Hello, World!");
299 final StringMap contextData = new SortedArrayStringMap();
300 final String mdcPatternMatchedKey = "mdcKey1";
301 final String mdcPatternMatchedValue = "mdcValue1";
302 contextData.putValue(mdcPatternMatchedKey, mdcPatternMatchedValue);
303 final String mdcPatternMismatchedKey = "mdcKey2";
304 final String mdcPatternMismatchedValue = "mdcValue2";
305 contextData.putValue(mdcPatternMismatchedKey, mdcPatternMismatchedValue);
306 final LogEvent logEvent = Log4jLogEvent
307 .newBuilder()
308 .setMessage(message)
309 .setContextData(contextData)
310 .build();
311
312 // Check the serialized event.
313 testReadOnlyStringMapFlatten(
314 mdcPatternMatchedKey,
315 mdcPatternMatchedValue,
316 mdcPatternMismatchedKey,
317 logEvent,
318 "mdc");
319
320 }
321
322 @Test
323 public void test_map_flatten() {
324
325 // Create the log event.
326 final String patternMatchedKey = "mapKey1";
327 final String patternMatchedValue = "mapValue1";
328 final String patternMismatchedKey = "mapKey2";
329 final String patternMismatchedValue = "mapValue2";
330 final Message message = new StringMapMessage()
331 .with(patternMatchedKey, patternMatchedValue)
332 .with(patternMismatchedKey, patternMismatchedValue);
333 final LogEvent logEvent = Log4jLogEvent
334 .newBuilder()
335 .setMessage(message)
336 .build();
337
338 // Check the serialized event.
339 testReadOnlyStringMapFlatten(
340 patternMatchedKey,
341 patternMatchedValue,
342 patternMismatchedKey,
343 logEvent,
344 "map");
345
346 }
347
348 private static void testReadOnlyStringMapFlatten(
349 final String patternMatchedKey,
350 final String patternMatchedValue,
351 final String patternMismatchedKey,
352 final LogEvent logEvent,
353 final String resolverName) {
354
355 // Create the event template.
356 final String prefix = "_map.";
357 final String eventTemplate = writeJson(asMap(
358 "ignoredFieldName", asMap(
359 "$resolver", resolverName,
360 "pattern", patternMatchedKey,
361 "flatten", asMap("prefix", prefix))));
362
363 // Create the layout.
364 final JsonTemplateLayout layout = JsonTemplateLayout
365 .newBuilder()
366 .setConfiguration(CONFIGURATION)
367 .setStackTraceEnabled(true)
368 .setEventTemplate(eventTemplate)
369 .build();
370
371 // Check the serialized event.
372 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
373 assertThat(accessor.getString(prefix + patternMatchedKey)).isEqualTo(patternMatchedValue);
374 assertThat(accessor.exists(prefix + patternMismatchedKey)).isFalse();
375 });
376
377 }
378
379 @Test
380 void test_MapResolver() {
381
382 // Create the log event.
383 final StringMapMessage message = new StringMapMessage().with("key1", "val1");
384 final LogEvent logEvent = Log4jLogEvent
385 .newBuilder()
386 .setMessage(message)
387 .build();
388
389 // Create the event template node with map values.
390 final String eventTemplate = writeJson(asMap(
391 "mapValue1", asMap(
392 "$resolver", "map",
393 "key", "key1"),
394 "mapValue2", asMap(
395 "$resolver", "map",
396 "key", "key?")));
397
398 // Create the layout.
399 final JsonTemplateLayout layout = JsonTemplateLayout
400 .newBuilder()
401 .setConfiguration(CONFIGURATION)
402 .setEventTemplate(eventTemplate)
403 .build();
404
405 // Check serialized event.
406 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
407 assertThat(accessor.getString("mapValue1")).isEqualTo("val1");
408 assertThat(accessor.getString("mapValue2")).isNull();
409 });
410
411 }
412
413 @Test
414 void test_MapMessage_keyed_access() {
415
416 // Create the event template.
417 final String key = "list";
418 final String eventTemplate = writeJson(asMap(
419 "typedValue", asMap(
420 "$resolver", "map",
421 "key", key),
422 "stringifiedValue", asMap(
423 "$resolver", "map",
424 "key", key,
425 "stringified", true)));
426
427 // Create the layout.
428 final JsonTemplateLayout layout = JsonTemplateLayout
429 .newBuilder()
430 .setConfiguration(CONFIGURATION)
431 .setEventTemplate(eventTemplate)
432 .build();
433
434 // Create the log event with a MapMessage.
435 final List<Integer> value = Arrays.asList(1, 2);
436 final StringMapMessage mapMessage = new StringMapMessage()
437 .with(key, value);
438 final LogEvent logEvent = Log4jLogEvent
439 .newBuilder()
440 .setMessage(mapMessage)
441 .setTimeMillis(System.currentTimeMillis())
442 .build();
443
444 // Check the serialized event.
445 usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
446 assertThat(accessor.getObject("typedValue")).isEqualTo(value);
447 assertThat(accessor.getString("stringifiedValue")).isEqualTo(String.valueOf(value));
448 });
449
450 }
451
452 }
+0
-75
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/TimestampResolverTest.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.logging.log4j.layout.template.json.resolver;
17
18 import org.apache.logging.log4j.Logger;
19 import org.assertj.core.api.Assertions;
20 import org.junit.jupiter.api.Test;
21
22 import java.nio.charset.StandardCharsets;
23 import java.util.List;
24 import java.util.stream.Collectors;
25
26 import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
27
28 class TimestampResolverTest {
29
30 /**
31 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-3183">LOG4J2-3183</a>
32 */
33 @Test
34 void epoch_nanos_should_not_overlap() {
35
36 // Create the template.
37 final Object eventTemplate = asMap(
38 "$resolver", "timestamp",
39 "epoch", asMap("unit", "nanos"));
40
41 // Create the logging context.
42 withContextFromTemplate("TimestampResolverTest", eventTemplate, (loggerContext, appender) -> {
43
44 // Log some.
45 final Logger logger = loggerContext.getLogger(TimestampResolverTest.class);
46 final int logEventCount = 5;
47 for (int logEventIndex = 0; logEventIndex < logEventCount; logEventIndex++) {
48 if (logEventIndex > 0) {
49 uncheckedSleep(1);
50 }
51 logger.info("message #{}", logEventIndex);
52 }
53
54 // Read logged events.
55 final List<Long> logEvents = appender
56 .getData()
57 .stream()
58 .map(jsonBytes -> {
59 final String json = new String(jsonBytes, StandardCharsets.UTF_8);
60 return (long) readJson(json);
61 })
62 .collect(Collectors.toList());
63
64 // Verify logged events.
65 Assertions
66 .assertThat(logEvents)
67 .hasSize(logEventCount)
68 .doesNotHaveDuplicates();
69
70 });
71
72 }
73
74 }
+0
-63
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/InstantFormatterTest.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.core.time.MutableInstant;
19 import org.assertj.core.api.Assertions;
20 import org.junit.jupiter.api.Test;
21 import org.junit.jupiter.params.ParameterizedTest;
22 import org.junit.jupiter.params.provider.CsvSource;
23
24 import java.util.TimeZone;
25
26 class InstantFormatterTest {
27
28 @ParameterizedTest
29 @CsvSource({
30 "yyyy-MM-dd'T'HH:mm:ss.SSS" + ",FixedDateFormat",
31 "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + ",FastDateFormat",
32 "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z'" + ",DateTimeFormatter"
33 })
34 void all_internal_implementations_should_be_used(
35 final String pattern,
36 final String className) {
37 final InstantFormatter formatter = InstantFormatter
38 .newBuilder()
39 .setPattern(pattern)
40 .build();
41 Assertions
42 .assertThat(formatter.getInternalImplementationClass())
43 .asString()
44 .describedAs("pattern=%s", pattern)
45 .endsWith("." + className);
46 }
47
48 @Test
49 void nanoseconds_should_be_formatted() {
50 final InstantFormatter formatter = InstantFormatter
51 .newBuilder()
52 .setPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z'")
53 .setTimeZone(TimeZone.getTimeZone("UTC"))
54 .build();
55 MutableInstant instant = new MutableInstant();
56 instant.initFromEpochSecond(0, 123_456_789);
57 Assertions
58 .assertThat(formatter.format(instant))
59 .isEqualTo("1970-01-01T00:00:00.123456789Z");
60 }
61
62 }
+0
-388
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonReaderTest.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.logging.log4j.layout.template.json.util;
17
18 import org.assertj.core.api.Assertions;
19 import org.junit.jupiter.api.Test;
20
21 import java.math.BigDecimal;
22 import java.math.BigInteger;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.LinkedHashMap;
26
27 class JsonReaderTest {
28
29 @Test
30 void test_null() {
31 Assertions
32 .assertThatThrownBy(() -> JsonReader.read(null))
33 .isInstanceOf(NullPointerException.class)
34 .hasMessage("json");
35 }
36
37 @Test
38 void test_valid_null() {
39 test("null", null);
40 test("[null, null]", Arrays.asList(null, null));
41 }
42
43 @Test
44 void test_invalid_null() {
45 for (final String json : new String[]{"nuL", "nulL", "nul1"}) {
46 Assertions
47 .assertThatThrownBy(() -> JsonReader.read(json))
48 .as("json=%s", json)
49 .isInstanceOf(IllegalArgumentException.class)
50 .hasMessageStartingWith("was expecting keyword 'null' at index");
51
52 }
53 }
54
55 @Test
56 void test_valid_boolean() {
57 test("true", true);
58 test("false", false);
59 test("[true, false]", Arrays.asList(true, false));
60 }
61
62 @Test
63 void test_invalid_boolean() {
64 for (final String json : new String[]{"tru", "truE", "fals", "falsE"}) {
65 Assertions
66 .assertThatThrownBy(() -> JsonReader.read(json))
67 .as("json=%s", json)
68 .isInstanceOf(IllegalArgumentException.class)
69 .hasMessageMatching("^was expecting keyword '(true|false)' at index [0-9]+: .*$");
70
71 }
72 }
73
74 @Test
75 void test_valid_string() {
76 test("\"\"", "");
77 test("\" \"", " ");
78 test("\" a\"", " a");
79 test("\"a \"", "a ");
80 test("\"abc\"", "abc");
81 test("\"abc\\\"\"", "abc\"");
82 test("\"\\b\\f\\n\\r\\t\"", "\b\f\n\r\t");
83 }
84
85 @Test
86 void test_invalid_string_start() {
87 final String json = "abc\"";
88 Assertions
89 .assertThatThrownBy(() -> JsonReader.read(json))
90 .as("json=%s", json)
91 .isInstanceOf(IllegalArgumentException.class)
92 .hasMessage("invalid character at index 0: a");
93 }
94
95 @Test
96 void test_invalid_string_end() {
97 for (final String json : new String[]{"", " ", "\r", "\t", "\"abc"}) {
98 Assertions
99 .assertThatThrownBy(() -> JsonReader.read(json))
100 .as("json=%s", json)
101 .isInstanceOf(IllegalArgumentException.class)
102 .hasMessage("premature end of input");
103 }
104 }
105
106 @Test
107 void test_invalid_string_escape() {
108 for (final String json : new String[]{"\"\\k\"", "\"\\d\""}) {
109 Assertions
110 .assertThatThrownBy(() -> JsonReader.read(json))
111 .as("json=%s", json)
112 .isInstanceOf(IllegalArgumentException.class)
113 .hasMessageStartingWith(
114 "was expecting an escape character at index 2: ");
115 }
116 }
117
118 @Test
119 void test_invalid_string_concat() {
120 final String json = "\"foo\"\"bar\"";
121 Assertions
122 .assertThatThrownBy(() -> JsonReader.read(json))
123 .as("json=%s", json)
124 .isInstanceOf(IllegalArgumentException.class)
125 .hasMessage("was not expecting input at index 5: \"");
126 }
127
128 @Test
129 void test_valid_unicode_string() {
130 final String json = "\"a\\u00eF4bc\"";
131 Assertions
132 .assertThat(JsonReader.read(json))
133 .as("json=%s", json)
134 .isEqualTo("a\u00ef4bc");
135 }
136
137 @Test
138 void test_invalid_unicode() {
139 Assertions
140 .assertThatThrownBy(() -> JsonReader.read("\"\\u000x\""))
141 .isInstanceOf(IllegalArgumentException.class)
142 .hasMessage("was expecting a unicode character at index 6: x");
143 }
144
145 @Test
146 void test_valid_integers() {
147 for (final String integer : new String[]{
148 "0",
149 "1",
150 "" + Long.MAX_VALUE + "" + Long.MAX_VALUE}) {
151 for (final String signedInteger : new String[]{integer, '-' + integer}) {
152 final Object expectedToken =
153 signedInteger.length() < 3
154 ? Integer.parseInt(signedInteger)
155 : new BigInteger(signedInteger);
156 test(signedInteger, expectedToken);
157 }
158 }
159 }
160
161 @Test
162 void test_invalid_integers() {
163 for (final String integer : new String[]{
164 "0-",
165 "1a"}) {
166 for (final String signedInteger : new String[]{integer, '-' + integer}) {
167 Assertions
168 .assertThatThrownBy(() -> JsonReader.read(signedInteger))
169 .as("signedInteger=%s", signedInteger)
170 .isInstanceOf(IllegalArgumentException.class)
171 .hasMessageStartingWith("was not expecting input at index");
172 }
173 }
174 }
175
176 @Test
177 void test_valid_decimals() {
178 for (final String decimal : new String[]{
179 "0.0",
180 "1.0",
181 "1.2",
182 "1e2",
183 "1e-2",
184 "1.2e3",
185 "1.2e-3"}) {
186 for (final String signedDecimal : new String[]{decimal, '-' + decimal}) {
187 test(signedDecimal, new BigDecimal(signedDecimal));
188 }
189 }
190 }
191
192 @Test
193 void test_invalid_decimals() {
194 for (final String decimal : new String[]{
195 "0.",
196 ".1",
197 "1e",
198 "1e-",
199 "1.2e",
200 "1.2e-"}) {
201 for (final String signedDecimal : new String[]{decimal, '-' + decimal}) {
202 Assertions
203 .assertThatThrownBy(() -> JsonReader.read(signedDecimal))
204 .as("signedDecimal=%s", signedDecimal)
205 .isInstanceOf(IllegalArgumentException.class);
206 }
207 }
208 }
209
210 @Test
211 void test_valid_arrays() {
212 for (final String json : new String[]{
213 "[]",
214 "[ ]"}) {
215 test(json, Collections.emptyList());
216 }
217 for (final String json : new String[]{
218 "[1]",
219 "[ 1]",
220 "[1 ]",
221 "[ 1 ]"}) {
222 test(json, Collections.singletonList(1));
223 }
224 for (final String json : new String[]{
225 "[1,2]",
226 "[1, 2]",
227 "[ 1, 2]",
228 "[1 , 2]",
229 "[ 1 , 2 ]"}) {
230 test(json, Arrays.asList(1, 2));
231 }
232 }
233
234 @Test
235 void test_invalid_array_start() {
236 final String json = "[";
237 Assertions
238 .assertThatThrownBy(() -> JsonReader.read(json))
239 .as("json=%s", json)
240 .isInstanceOf(IllegalArgumentException.class)
241 .hasMessage("premature end of input");
242 }
243
244 @Test
245 void test_invalid_array_end_1() {
246 final String json = "]";
247 Assertions
248 .assertThatThrownBy(() -> JsonReader.read(json))
249 .as("json=%s", json)
250 .isInstanceOf(IllegalArgumentException.class)
251 .hasMessage("was not expecting ARRAY_END at index 0");
252 }
253
254 @Test
255 void test_invalid_array_comma() {
256 final String json = "[,";
257 Assertions
258 .assertThatThrownBy(() -> JsonReader.read(json))
259 .as("json=%s", json)
260 .isInstanceOf(IllegalArgumentException.class)
261 .hasMessage("was expecting an array element at index 1: COMMA");
262 }
263
264 @Test
265 void test_invalid_array_end_2() {
266 final String json = "[1,";
267 Assertions
268 .assertThatThrownBy(() -> JsonReader.read(json))
269 .as("json=%s", json)
270 .isInstanceOf(IllegalArgumentException.class)
271 .hasMessage("premature end of input");
272 }
273
274 @Test
275 void test_invalid_array_end_3() {
276 final String json = "[1,]";
277 Assertions
278 .assertThatThrownBy(() -> JsonReader.read(json))
279 .as("json=%s", json)
280 .isInstanceOf(IllegalArgumentException.class)
281 .hasMessage("was expecting an array element at index 3: ARRAY_END");
282 }
283
284 @Test
285 void test_valid_objects() {
286 test("{}", Collections.emptyMap());
287 test("{\"foo\":\"bar\"}", Collections.singletonMap("foo", "bar"));
288 }
289
290 @Test
291 void test_invalid_object_start() {
292 final String json = "{";
293 Assertions
294 .assertThatThrownBy(() -> JsonReader.read(json))
295 .as("json=%s", json)
296 .isInstanceOf(IllegalArgumentException.class)
297 .hasMessage("premature end of input");
298 }
299
300 @Test
301 void test_invalid_object_end() {
302 final String json = "}";
303 Assertions
304 .assertThatThrownBy(() -> JsonReader.read(json))
305 .as("json=%s", json)
306 .isInstanceOf(IllegalArgumentException.class)
307 .hasMessage("was not expecting OBJECT_END at index 0");
308 }
309
310 @Test
311 void test_invalid_object_colon_1() {
312 final String json = "{\"foo\"\"bar\"}";
313 Assertions
314 .assertThatThrownBy(() -> JsonReader.read(json))
315 .as("json=%s", json)
316 .isInstanceOf(IllegalArgumentException.class)
317 .hasMessage("was expecting COLON at index 6: bar");
318 }
319
320 @Test
321 void test_invalid_object_colon_2() {
322 final String json = "{\"foo\":}";
323 Assertions
324 .assertThatThrownBy(() -> JsonReader.read(json))
325 .as("json=%s", json)
326 .isInstanceOf(IllegalArgumentException.class)
327 .hasMessage("premature end of input");
328 }
329
330 @Test
331 void test_invalid_object_token() {
332 final String json = "{\"foo\":\"bar}";
333 Assertions
334 .assertThatThrownBy(() -> JsonReader.read(json))
335 .as("json=%s", json)
336 .isInstanceOf(IllegalArgumentException.class)
337 .hasMessage("premature end of input");
338 }
339
340 @Test
341 void test_invalid_object_comma() {
342 final String json = "{\"foo\":\"bar\",}";
343 Assertions
344 .assertThatThrownBy(() -> JsonReader.read(json))
345 .as("json=%s", json)
346 .isInstanceOf(IllegalArgumentException.class)
347 .hasMessage("was expecting an object key at index 13: OBJECT_END");
348 }
349
350 @Test
351 void test_invalid_object_key() {
352 final String json = "{\"foo\":\"bar\",]}";
353 Assertions
354 .assertThatThrownBy(() -> JsonReader.read(json))
355 .as("json=%s", json)
356 .isInstanceOf(IllegalArgumentException.class)
357 .hasMessage("was expecting an object key at index 13: ARRAY_END");
358 }
359
360 @Test
361 @SuppressWarnings("DoubleBraceInitialization")
362 public void test_nesting() {
363 test(
364 "{\"k1\": [true, null, 1e5, {\"k2\": \"v2\", \"k3\": {\"k4\": \"v4\"}}]}",
365 Collections.singletonMap(
366 "k1",
367 Arrays.asList(
368 true,
369 null,
370 new BigDecimal("1e5"),
371 new LinkedHashMap<String, Object>() {{
372 put("k2", "v2");
373 put("k3", Collections.singletonMap("k4", "v4"));
374 }})));
375 }
376
377 private void test(final String json, final Object expected) {
378 // Wrapping the assertion one more time to decorate it with the input.
379 Assertions
380 .assertThatCode(() -> Assertions
381 .assertThat(JsonReader.read(json))
382 .isEqualTo(expected))
383 .as("json=%s", json)
384 .doesNotThrowAnyException();
385 }
386
387 }
+0
-977
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.core.impl.JdkMapAdapterStringMap;
19 import org.apache.logging.log4j.layout.template.json.JacksonFixture;
20 import org.apache.logging.log4j.util.BiConsumer;
21 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
22 import org.apache.logging.log4j.util.SortedArrayStringMap;
23 import org.apache.logging.log4j.util.StringBuilderFormattable;
24 import org.apache.logging.log4j.util.StringMap;
25 import org.apache.logging.log4j.util.Strings;
26 import org.assertj.core.api.Assertions;
27 import org.assertj.core.api.SoftAssertions;
28 import org.junit.jupiter.api.Test;
29
30 import java.io.IOException;
31 import java.lang.reflect.Field;
32 import java.math.BigDecimal;
33 import java.math.BigInteger;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.LinkedHashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Random;
41 import java.util.function.Consumer;
42 import java.util.function.Function;
43
44 @SuppressWarnings("DoubleBraceInitialization")
45 class JsonWriterTest {
46
47 private static final JsonWriter WRITER = JsonWriter
48 .newBuilder()
49 .setMaxStringLength(128)
50 .setTruncatedStringSuffix("~")
51 .build();
52
53 private static final int SURROGATE_CODE_POINT = 65536;
54
55 private static final char[] SURROGATE_PAIR = new char[2];
56 static {
57 // noinspection ResultOfMethodCallIgnored
58 Character.toChars(SURROGATE_CODE_POINT, SURROGATE_PAIR, 0);
59 }
60
61 private static final char HI_SURROGATE = SURROGATE_PAIR[0];
62
63 private static final char LO_SURROGATE = SURROGATE_PAIR[1];
64
65 private static synchronized <V> V withLockedWriterReturning(
66 final Function<JsonWriter, V> consumer) {
67 synchronized (WRITER) {
68 return consumer.apply(WRITER);
69 }
70 }
71
72 private static synchronized void withLockedWriter(
73 final Consumer<JsonWriter> consumer) {
74 synchronized (WRITER) {
75 consumer.accept(WRITER);
76 }
77 }
78
79 @Test
80 void test_close() {
81 withLockedWriter(writer -> {
82 writer.writeString("x");
83 writer.close();
84 assertStringBuilderReset(writer);
85 });
86 }
87
88 @Test
89 void test_close_after_excessive_write() {
90 withLockedWriter(writer -> {
91 final String text = Strings.repeat("x", writer.getMaxStringLength());
92 writer.writeString(text);
93 writer.writeString(text);
94 writer.close();
95 assertStringBuilderReset(writer);
96 });
97 }
98
99 private static void assertStringBuilderReset(final JsonWriter writer) {
100 Assertions
101 .assertThat(writer.getStringBuilder().capacity())
102 .isEqualTo(writer.getMaxStringLength());
103 Assertions
104 .assertThat(writer.getStringBuilder().length())
105 .isEqualTo(0);
106 }
107
108 @Test
109 void test_surrogate_code_point() {
110 Assertions
111 .assertThat(HI_SURROGATE)
112 .matches(Character::isHighSurrogate, "is high surrogate");
113 Assertions
114 .assertThat(LO_SURROGATE)
115 .matches(Character::isLowSurrogate, "is low surrogate");
116 Assertions
117 .assertThat(Character.isSurrogatePair(HI_SURROGATE, LO_SURROGATE))
118 .as("is surrogate pair")
119 .isTrue();
120 Assertions
121 .assertThat(SURROGATE_CODE_POINT)
122 .matches(Character::isDefined, "is defined");
123 }
124
125 @Test
126 void test_use_null_Runnable() {
127 Assertions
128 .assertThatThrownBy(() -> withLockedWriter(writer -> writer.use(null)))
129 .isInstanceOf(NullPointerException.class)
130 .hasMessageContaining("runnable");
131 }
132
133 @Test
134 void test_use_failing_Runnable() {
135 final RuntimeException exception = new RuntimeException();
136 withLockedWriter(writer -> {
137 final int initialLength = writer.getStringBuilder().length();
138 Assertions
139 .assertThatThrownBy(() -> writer.use(() -> {
140 writer.writeString("extending the buffer");
141 throw exception;
142 }))
143 .isSameAs(exception);
144 Assertions.assertThat(writer.getStringBuilder()).hasSize(initialLength);
145 });
146 }
147
148 @Test
149 void test_writeValue_null_Object() {
150 expectNull(writer -> writer.writeValue(null));
151 }
152
153 @Test
154 void test_writeValue() {
155 final Object value = Collections.singletonMap("a", "b");
156 final String expectedJson = "{'a':'b'}".replace('\'', '"');
157 final String actualJson = withLockedWriterReturning(writer ->
158 writer.use(() -> writer.writeValue(value)));
159 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
160 }
161
162 @Test
163 void test_writeObject_null_StringMap() {
164 expectNull(writer -> writer.writeObject((StringMap) null));
165 }
166
167 @Test
168 void test_writeObject_StringMap() {
169 final StringMap map = new JdkMapAdapterStringMap(Collections.singletonMap("a", "b"));
170 final String expectedJson = "{'a':'b'}".replace('\'', '"');
171 final String actualJson = withLockedWriterReturning(writer ->
172 writer.use(() -> writer.writeObject(map)));
173 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
174 }
175
176 @Test
177 void test_writeObject_null_IndexedReadOnlyStringMap() {
178 expectNull(writer -> writer.writeObject((IndexedReadOnlyStringMap) null));
179 }
180
181 @Test
182 void test_writeObject_IndexedReadOnlyStringMap() {
183 final IndexedReadOnlyStringMap map =
184 new SortedArrayStringMap(new LinkedHashMap<String, Object>() {{
185 put("buzz", 1.2D);
186 put("foo", "bar");
187 }});
188 final String expectedJson = "{'buzz':1.2,'foo':'bar'}".replace('\'', '"');
189 final String actualJson = withLockedWriterReturning(writer ->
190 writer.use(() -> writer.writeObject(map)));
191 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
192 }
193
194 @Test
195 void test_writeObject_null_Map() {
196 expectNull(writer -> writer.writeObject((Map<String, Object>) null));
197 }
198
199 @Test
200 void test_writeObject_Map() {
201 final Map<String, Object> map = new LinkedHashMap<String, Object>() {{
202 put("key1", "val1");
203 put("key2", Collections.singletonMap("key2.1", "val2.1"));
204 put("key3", Arrays.asList(
205 3,
206 (byte) 127,
207 4.5D,
208 4.6F,
209 Arrays.asList(true, false),
210 new BigDecimal("30.12345678901234567890123456789"),
211 new BigInteger("12345678901234567890123456789"),
212 Collections.singleton('a'),
213 Collections.singletonMap("key3.3", "val3.3")));
214 put("key4", new LinkedHashMap<String, Object>() {{
215 put("chars", new char[]{'a', 'b', 'c'});
216 put("booleans", new boolean[]{true, false});
217 put("bytes", new byte[]{1, 2});
218 put("shorts", new short[]{3, 4});
219 put("ints", new int[]{256, 257});
220 put("longs", new long[]{2147483648L, 2147483649L});
221 put("floats", new float[]{1.0F, 1.1F});
222 put("doubles", new double[]{2.0D, 2.1D});
223 put("objects", new Object[]{"foo", "bar"});
224 }});
225 put("key5\t", new Object() {
226 @Override
227 public String toString() {
228 return "custom-object\r";
229 }
230 });
231 put("key6", Arrays.asList(
232 new SortedArrayStringMap(new LinkedHashMap<String, Object>() {{
233 put("buzz", 1.2D);
234 put("foo", "bar");
235 }}),
236 new JdkMapAdapterStringMap(Collections.singletonMap("a", "b"))));
237 put("key7", (StringBuilderFormattable) buffer ->
238 buffer.append(7.7777777777777D));
239 }};
240 final String expectedJson = ("{" +
241 "'key1':'val1'," +
242 "'key2':{'key2.1':'val2.1'}," +
243 "'key3':[" +
244 "3," +
245 "127," +
246 "4.5," +
247 "4.6," +
248 "[true,false]," +
249 "30.12345678901234567890123456789," +
250 "12345678901234567890123456789," +
251 "['a']," +
252 "{'key3.3':'val3.3'}" +
253 "]," +
254 "'key4':{" +
255 "'chars':['a','b','c']," +
256 "'booleans':[true,false]," +
257 "'bytes':[1,2]," +
258 "'shorts':[3,4]," +
259 "'ints':[256,257]," +
260 "'longs':[2147483648,2147483649]," +
261 "'floats':[1.0,1.1]," +
262 "'doubles':[2.0,2.1]," +
263 "'objects':['foo','bar']" +
264 "}," +
265 "'key5\\t':'custom-object\\r'," +
266 "'key6':[{'buzz':1.2,'foo':'bar'},{'a':'b'}]," +
267 "'key7':'7.7777777777777'" +
268 "}").replace('\'', '"');
269 final String actualJson = withLockedWriterReturning(writer ->
270 writer.use(() -> writer.writeObject(map)));
271 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
272 }
273
274 @Test
275 void test_writeArray_null_List() {
276 expectNull(writer -> writer.writeArray((List<Object>) null));
277 }
278
279 @Test
280 void test_writeArray_List() {
281 final List<Object> items = Arrays.asList(
282 1, 2, 3,
283 "yo",
284 Collections.singletonMap("foo", "bar"));
285 final String expectedJson = "[1,2,3,\"yo\",{\"foo\":\"bar\"}]";
286 final String actualJson = withLockedWriterReturning(writer ->
287 writer.use(() -> writer.writeArray(items)));
288 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
289 }
290
291 @Test
292 void test_writeArray_null_Collection() {
293 expectNull(writer -> writer.writeArray((Collection<Object>) null));
294 }
295
296 @Test
297 void test_writeArray_Collection() {
298 final Collection<Object> items = Arrays.asList(
299 1, 2, 3,
300 Collections.singletonMap("foo", "bar"));
301 final String expectedJson = "[1,2,3,{\"foo\":\"bar\"}]";
302 final String actualJson = withLockedWriterReturning(writer ->
303 writer.use(() -> writer.writeArray(items)));
304 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
305 }
306
307 @Test
308 void test_writeArray_null_char() {
309 expectNull(writer -> writer.writeArray((char[]) null));
310 }
311
312 @Test
313 void test_writeArray_char() {
314 final char[] items = {'\u0000', 'a', 'b', 'c', '\u007f'};
315 final String expectedJson = "[\"\\u0000\",\"a\",\"b\",\"c\",\"\u007F\"]";
316 final String actualJson = withLockedWriterReturning(writer ->
317 writer.use(() -> writer.writeArray(items)));
318 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
319 }
320
321 @Test
322 void test_writeArray_null_boolean() {
323 expectNull(writer -> writer.writeArray((boolean[]) null));
324 }
325
326 @Test
327 void test_writeArray_boolean() {
328 final boolean[] items = {true, false};
329 final String expectedJson = "[true,false]";
330 final String actualJson = withLockedWriterReturning(writer ->
331 writer.use(() -> writer.writeArray(items)));
332 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
333 }
334
335 @Test
336 void test_writeArray_null_byte() {
337 expectNull(writer -> writer.writeArray((byte[]) null));
338 }
339
340 @Test
341 void test_writeArray_byte() {
342 final byte[] items = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE};
343 final String expectedJson = Arrays
344 .toString(items)
345 .replaceAll(" ", "");
346 final String actualJson = withLockedWriterReturning(writer ->
347 writer.use(() -> writer.writeArray(items)));
348 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
349 }
350
351 @Test
352 void test_writeArray_null_short() {
353 expectNull(writer -> writer.writeArray((short[]) null));
354 }
355
356 @Test
357 void test_writeArray_short() {
358 final short[] items = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE};
359 final String expectedJson = Arrays
360 .toString(items)
361 .replaceAll(" ", "");
362 final String actualJson = withLockedWriterReturning(writer ->
363 writer.use(() -> writer.writeArray(items)));
364 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
365 }
366
367 @Test
368 void test_writeArray_null_int() {
369 expectNull(writer -> writer.writeArray((int[]) null));
370 }
371
372 @Test
373 void test_writeArray_int() {
374 final int[] items = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE};
375 final String expectedJson = Arrays
376 .toString(items)
377 .replaceAll(" ", "");
378 final String actualJson = withLockedWriterReturning(writer ->
379 writer.use(() -> writer.writeArray(items)));
380 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
381 }
382
383 @Test
384 void test_writeArray_null_long() {
385 expectNull(writer -> writer.writeArray((long[]) null));
386 }
387
388 @Test
389 void test_writeArray_long() {
390 final long[] items = {Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE};
391 final String expectedJson = Arrays
392 .toString(items)
393 .replaceAll(" ", "");
394 final String actualJson = withLockedWriterReturning(writer ->
395 writer.use(() -> writer.writeArray(items)));
396 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
397 }
398
399 @Test
400 void test_writeArray_null_float() {
401 expectNull(writer -> writer.writeArray((float[]) null));
402 }
403
404 @Test
405 void test_writeArray_float() {
406 final float[] items = {Float.MIN_VALUE, -1F, 0F, 1F, Float.MAX_VALUE};
407 final String expectedJson = Arrays
408 .toString(items)
409 .replaceAll(" ", "");
410 final String actualJson = withLockedWriterReturning(writer ->
411 writer.use(() -> writer.writeArray(items)));
412 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
413 }
414
415 @Test
416 void test_writeArray_null_double() {
417 expectNull(writer -> writer.writeArray((double[]) null));
418 }
419
420 @Test
421 void test_writeArray_double() {
422 final double[] items = {Double.MIN_VALUE, -1D, 0D, 1D, Double.MAX_VALUE};
423 final String expectedJson = Arrays
424 .toString(items)
425 .replaceAll(" ", "");
426 final String actualJson = withLockedWriterReturning(writer ->
427 writer.use(() -> writer.writeArray(items)));
428 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
429 }
430
431 @Test
432 void test_writeArray_null_Object() {
433 expectNull(writer -> writer.writeArray((Object[]) null));
434 }
435
436 @Test
437 void test_writeArray_Object() {
438 final String expectedJson = "[\"foo\",{\"bar\":\"buzz\"},null]";
439 final String actualJson = withLockedWriterReturning(writer ->
440 writer.use(() ->
441 writer.writeArray(new Object[]{
442 "foo",
443 Collections.singletonMap("bar", "buzz"),
444 null
445 })));
446 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
447 }
448
449 @Test
450 void test_writeString_null_emitter() {
451 Assertions
452 .assertThatThrownBy(() ->
453 withLockedWriter(writer ->
454 writer.use(() ->
455 writer.writeString(null, 0L))))
456 .isInstanceOf(NullPointerException.class)
457 .hasMessageContaining("emitter");
458 }
459
460 @Test
461 void test_writeString_emitter() {
462 final String state = "there-is-no-spoon";
463 final BiConsumer<StringBuilder, String> emitter = StringBuilder::append;
464 final String expectedJson = '"' + state + '"';
465 final String actualJson = withLockedWriterReturning(writer ->
466 writer.use(() -> writer.writeString(emitter, state)));
467 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
468 }
469
470 @Test
471 void test_writeString_emitter_excessive_string() {
472 withLockedWriter(writer -> {
473 final int maxStringLength = writer.getMaxStringLength();
474 final String excessiveString = Strings.repeat("x", maxStringLength) + 'y';
475 final String expectedJson = '"' +
476 excessiveString.substring(0, maxStringLength) +
477 writer.getTruncatedStringSuffix() +
478 '"';
479 final BiConsumer<StringBuilder, String> emitter = StringBuilder::append;
480 final String actualJson =
481 writer.use(() -> writer.writeString(emitter, excessiveString));
482 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
483 assertFormattableBufferReset(writer);
484 });
485 }
486
487 @Test
488 void test_writeString_emitter_excessive_string_ending_with_high_surrogate() {
489 withLockedWriter(writer -> {
490 final int maxStringLength = writer.getMaxStringLength();
491 @SuppressWarnings("StringBufferReplaceableByString")
492 final String excessiveString = new StringBuilder()
493 .append(Strings.repeat("x", maxStringLength - 1))
494 .append(HI_SURROGATE)
495 .append(LO_SURROGATE)
496 .toString();
497 final String expectedJson = "\"" +
498 Strings.repeat("x", maxStringLength - 1) +
499 writer.getTruncatedStringSuffix() +
500 '"';
501 final BiConsumer<StringBuilder, String> emitter = StringBuilder::append;
502 final String actualJson =
503 writer.use(() -> writer.writeString(emitter, excessiveString));
504 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
505 assertFormattableBufferReset(writer);
506 });
507 }
508
509 @Test
510 void test_writeString_null_formattable() {
511 expectNull(writer -> writer.writeString((StringBuilderFormattable) null));
512 }
513
514 @Test
515 void test_writeString_formattable() {
516 final String expectedJson = "\"foo\\tbar\\tbuzz\"";
517 final String actualJson = withLockedWriterReturning(writer ->
518 writer.use(() ->
519 writer.writeString(stringBuilder ->
520 stringBuilder.append("foo\tbar\tbuzz"))));
521 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
522 }
523
524 @Test
525 void test_writeString_formattable_excessive_string() {
526 withLockedWriter(writer -> {
527 final int maxStringLength = writer.getMaxStringLength();
528 final String excessiveString = Strings.repeat("x", maxStringLength) + 'y';
529 final String expectedJson = '"' +
530 excessiveString.substring(0, maxStringLength) +
531 writer.getTruncatedStringSuffix() +
532 '"';
533 final String actualJson = writer.use(() ->
534 writer.writeString(stringBuilder ->
535 stringBuilder.append(excessiveString)));
536 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
537 assertFormattableBufferReset(writer);
538 });
539 }
540
541 @Test
542 void test_writeString_formattable_excessive_string_ending_with_high_surrogate() {
543 withLockedWriter(writer -> {
544 final int maxStringLength = writer.getMaxStringLength();
545 @SuppressWarnings("StringBufferReplaceableByString")
546 final String excessiveString = new StringBuilder()
547 .append(Strings.repeat("x", maxStringLength - 1))
548 .append(HI_SURROGATE)
549 .append(LO_SURROGATE)
550 .toString();
551 final String expectedJson = "\"" +
552 Strings.repeat("x", maxStringLength - 1) +
553 writer.getTruncatedStringSuffix() +
554 '"';
555 final String actualJson = writer.use(() ->
556 writer.writeString(stringBuilder ->
557 stringBuilder.append(excessiveString)));
558 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
559 assertFormattableBufferReset(writer);
560 });
561 }
562
563 private static void assertFormattableBufferReset(final JsonWriter writer) {
564 final StringBuilder formattableBuffer = getFormattableBuffer(writer);
565 Assertions
566 .assertThat(formattableBuffer.capacity())
567 .isEqualTo(writer.getMaxStringLength());
568 Assertions
569 .assertThat(formattableBuffer.length())
570 .isEqualTo(0);
571 }
572
573 private static StringBuilder getFormattableBuffer(final JsonWriter writer) {
574 try {
575 final Field field = JsonWriter.class.getDeclaredField("formattableBuffer");
576 field.setAccessible(true);
577 return (StringBuilder) field.get(writer);
578 } catch (Exception error) {
579 throw new RuntimeException(error);
580 }
581 }
582
583 @Test
584 void test_writeString_null_seq_1() {
585 expectNull(writer -> writer.writeString((CharSequence) null));
586 }
587
588 @Test
589 void test_writeString_null_seq_2() {
590 expectNull(writer -> writer.writeString((CharSequence) null, 0, 4));
591 }
592
593 @Test
594 void test_writeString_seq_negative_offset() {
595 withLockedWriter(writer -> Assertions
596 .assertThatThrownBy(() ->
597 writer.use(() -> writer.writeString("a", -1, 0)))
598 .isInstanceOf(IllegalArgumentException.class)
599 .hasMessageContaining("offset"));
600 }
601
602 @Test
603 void test_writeString_seq_negative_length() {
604 withLockedWriter(writer -> Assertions
605 .assertThatThrownBy(() ->
606 writer.use(() -> writer.writeString("a", 0, -1)))
607 .isInstanceOf(IllegalArgumentException.class)
608 .hasMessageContaining("length"));
609 }
610
611 @Test
612 void test_writeString_excessive_seq() {
613 withLockedWriter(writer -> {
614 final CharSequence seq = Strings.repeat("x", writer.getMaxStringLength()) + 'y';
615 final String expectedJson = "\"" +
616 Strings.repeat("x", writer.getMaxStringLength()) +
617 writer.getTruncatedStringSuffix() +
618 '"';
619 final String actualJson = writer.use(() -> writer.writeString(seq));
620 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
621 });
622 }
623
624 @Test
625 void test_writeString_excessive_seq_ending_with_high_surrogate() {
626 withLockedWriter(writer -> {
627 final int maxStringLength = writer.getMaxStringLength();
628 @SuppressWarnings("StringBufferReplaceableByString")
629 final CharSequence seq = new StringBuilder()
630 .append(Strings.repeat("x", maxStringLength - 1))
631 .append(HI_SURROGATE)
632 .append(LO_SURROGATE)
633 .toString();
634 final String expectedJson = "\"" +
635 Strings.repeat("x", maxStringLength - 1) +
636 writer.getTruncatedStringSuffix() +
637 '"';
638 final String actualJson = writer.use(() -> writer.writeString(seq));
639 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
640 });
641 }
642
643 @Test
644 void test_writeString_seq() throws IOException {
645 final char[] surrogates = new char[2];
646 testQuoting((final Integer codePoint) -> {
647 // noinspection ResultOfMethodCallIgnored
648 Character.toChars(codePoint, surrogates, 0);
649 final String s = new String(surrogates);
650 return withLockedWriterReturning(writer ->
651 writer.use(() -> writer.writeString(s)));
652 });
653 }
654
655 @Test
656 void test_writeString_null_buffer_1() {
657 expectNull(writer -> writer.writeString((char[]) null));
658 }
659
660 @Test
661 void test_writeString_null_buffer_2() {
662 expectNull(writer -> writer.writeString((char[]) null, 0, 4));
663 }
664
665 @Test
666 void test_writeString_buffer_negative_offset() {
667 withLockedWriter(writer -> Assertions
668 .assertThatThrownBy(() ->
669 writer.use(() -> writer.writeString(new char[]{'a'}, -1, 0)))
670 .isInstanceOf(IllegalArgumentException.class)
671 .hasMessageContaining("offset"));
672 }
673
674 @Test
675 void test_writeString_buffer_negative_length() {
676 withLockedWriter(writer -> Assertions
677 .assertThatThrownBy(() ->
678 writer.use(() -> writer.writeString(new char[]{'a'}, 0, -1)))
679 .isInstanceOf(IllegalArgumentException.class)
680 .hasMessageContaining("length"));
681 }
682
683 @Test
684 void test_writeString_excessive_buffer() {
685 withLockedWriter(writer -> {
686 final char[] buffer =
687 (Strings.repeat("x", writer.getMaxStringLength()) + 'y')
688 .toCharArray();
689 final String expectedJson = "\"" +
690 Strings.repeat("x", writer.getMaxStringLength()) +
691 writer.getTruncatedStringSuffix() +
692 '"';
693 final String actualJson = writer.use(() -> writer.writeString(buffer));
694 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
695 });
696 }
697
698 @Test
699 void test_writerString_excessive_buffer_ending_with_high_surrogate() {
700 withLockedWriter(writer -> {
701 final int maxStringLength = writer.getMaxStringLength();
702 @SuppressWarnings("StringBufferReplaceableByString")
703 final char[] buffer = new StringBuilder()
704 .append(Strings.repeat("x", maxStringLength - 1))
705 .append(HI_SURROGATE)
706 .append(LO_SURROGATE)
707 .toString()
708 .toCharArray();
709 final String expectedJson = "\"" +
710 Strings.repeat("x", maxStringLength - 1) +
711 writer.getTruncatedStringSuffix() +
712 '"';
713 final String actualJson = writer.use(() -> writer.writeString(buffer));
714 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
715 });
716 }
717
718 @Test
719 void test_writeString_buffer() throws IOException {
720 final char[] buffer = new char[2];
721 testQuoting((final Integer codePoint) -> {
722 // noinspection ResultOfMethodCallIgnored
723 Character.toChars(codePoint, buffer, 0);
724 return withLockedWriterReturning(writer ->
725 writer.use(() -> writer.writeString(buffer)));
726 });
727 }
728
729 private static void testQuoting(
730 final Function<Integer, String> quoter) throws IOException {
731 final SoftAssertions assertions = new SoftAssertions();
732 final char[] surrogates = new char[2];
733 final Random random = new Random(0);
734 for (int codePoint = Character.MIN_CODE_POINT;
735 codePoint <= Character.MAX_CODE_POINT;
736 // Incrementing randomly, since incrementing by one takes almost
737 // two minutes for this test to finish.
738 codePoint += Math.abs(random.nextInt(100))) {
739 // noinspection ResultOfMethodCallIgnored
740 Character.toChars(codePoint, surrogates, 0);
741 final String s = new String(surrogates);
742 final String expectedJson = JacksonFixture
743 .getObjectMapper()
744 .writeValueAsString(s);
745 final String actualJson = quoter.apply(codePoint);
746 assertions
747 .assertThat(actualJson)
748 .as("codePoint='%s' (%d)", s, codePoint)
749 .isEqualTo(expectedJson);
750 }
751 assertions.assertAll();
752 }
753
754 @Test
755 void test_writeNumber_null_BigDecimal() {
756 expectNull(writer -> writer.writeNumber((BigDecimal) null));
757 }
758
759 @Test
760 void test_writeNumber_BigDecimal() {
761 for (final BigDecimal number : new BigDecimal[]{
762 BigDecimal.ZERO,
763 BigDecimal.ONE,
764 BigDecimal.TEN,
765 new BigDecimal("" + Long.MAX_VALUE +
766 "" + Long.MAX_VALUE +
767 '.' + Long.MAX_VALUE +
768 "" + Long.MAX_VALUE)}) {
769 final String expectedJson = String.valueOf(number);
770 final String actualJson = withLockedWriterReturning(writer ->
771 writer.use(() -> writer.writeNumber(number)));
772 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
773 }
774 }
775
776 @Test
777 void test_writeNumber_null_BigInteger() {
778 expectNull(writer -> writer.writeNumber((BigInteger) null));
779 }
780
781 @Test
782 void test_writeNumber_BigInteger() {
783 for (final BigInteger number : new BigInteger[]{
784 BigInteger.ZERO,
785 BigInteger.ONE,
786 BigInteger.TEN,
787 new BigInteger("" + Long.MAX_VALUE + "" + Long.MAX_VALUE)}) {
788 final String expectedJson = String.valueOf(number);
789 final String actualJson = withLockedWriterReturning(writer ->
790 writer.use(() -> writer.writeNumber(number)));
791 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
792 }
793 }
794
795 @Test
796 void test_writeNumber_float() {
797 for (final float number : new float[]{Float.MIN_VALUE, -1.0F, 0F, 1.0F, Float.MAX_VALUE}) {
798 final String expectedJson = String.valueOf(number);
799 final String actualJson = withLockedWriterReturning(writer ->
800 writer.use(() -> writer.writeNumber(number)));
801 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
802 }
803 }
804
805 @Test
806 void test_writeNumber_double() {
807 for (final double number : new double[]{Double.MIN_VALUE, -1.0D, 0D, 1.0D, Double.MAX_VALUE}) {
808 final String expectedJson = String.valueOf(number);
809 final String actualJson = withLockedWriterReturning(writer ->
810 writer.use(() -> writer.writeNumber(number)));
811 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
812 }
813 }
814
815 @Test
816 void test_writeNumber_short() {
817 for (final short number : new short[]{Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}) {
818 final String expectedJson = String.valueOf(number);
819 final String actualJson = withLockedWriterReturning(writer ->
820 writer.use(() -> writer.writeNumber(number)));
821 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
822 }
823 }
824
825 @Test
826 void test_writeNumber_int() {
827 for (final int number : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) {
828 final String expectedJson = String.valueOf(number);
829 final String actualJson = withLockedWriterReturning(writer ->
830 writer.use(() -> writer.writeNumber(number)));
831 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
832 }
833 }
834
835 @Test
836 void test_writeNumber_long() {
837 for (final long number : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) {
838 final String expectedJson = String.valueOf(number);
839 final String actualJson = withLockedWriterReturning(writer ->
840 writer.use(() -> writer.writeNumber(number)));
841 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
842 }
843 }
844
845 @Test
846 void test_writeNumber_integral_and_negative_fractional() {
847 Assertions
848 .assertThatThrownBy(() ->
849 withLockedWriter(writer ->
850 writer.use(() -> writer.writeNumber(0, -1))))
851 .isInstanceOf(IllegalArgumentException.class)
852 .hasMessage("was expecting a positive fraction: -1");
853 }
854
855 @Test
856 void test_writeNumber_integral_and_zero_fractional() {
857 final String expectedJson = "123";
858 final String actualJson = withLockedWriterReturning(writer ->
859 writer.use(() -> writer.writeNumber(123L, 0L)));
860 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
861 }
862
863 @Test
864 void test_writeNumber_integral_and_fractional() {
865 final String expectedJson = "123.456";
866 final String actualJson = withLockedWriterReturning(writer ->
867 writer.use(() -> writer.writeNumber(123L, 456L)));
868 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
869 }
870
871 @Test
872 void test_writeBoolean_true() {
873 final String expectedJson = "true";
874 final String actualJson = withLockedWriterReturning(writer ->
875 writer.use(() -> writer.writeBoolean(true)));
876 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
877 }
878
879 @Test
880 void test_writeBoolean_false() {
881 final String expectedJson = "false";
882 final String actualJson = withLockedWriterReturning(writer ->
883 writer.use(() -> writer.writeBoolean(false)));
884 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
885 }
886
887 @Test
888 void test_writeNull() {
889 expectNull(JsonWriter::writeNull);
890 }
891
892 private void expectNull(Consumer<JsonWriter> body) {
893 final String expectedJson = "null";
894 final String actualJson = withLockedWriterReturning(writer ->
895 writer.use(() -> body.accept(writer)));
896 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
897 }
898
899 @Test
900 void test_writeRawString_null_seq() {
901 withLockedWriter(writer -> Assertions
902 .assertThatThrownBy(() ->
903 writer.use(() ->
904 writer.writeRawString((String) null)))
905 .isInstanceOf(NullPointerException.class)
906 .hasMessage("seq"));
907 }
908
909 @Test
910 void test_writeRawString_seq_negative_offset() {
911 withLockedWriter(writer -> Assertions
912 .assertThatThrownBy(() ->
913 writer.use(() ->
914 writer.writeRawString("a", -1, 0)))
915 .isInstanceOf(IllegalArgumentException.class)
916 .hasMessageContaining("offset"));
917 }
918
919 @Test
920 void test_writeRawString_seq_negative_length() {
921 withLockedWriter(writer -> Assertions
922 .assertThatThrownBy(() ->
923 writer.use(() ->
924 writer.writeRawString("a", 0, -1)))
925 .isInstanceOf(IllegalArgumentException.class)
926 .hasMessageContaining("length"));
927 }
928
929 @Test
930 void test_writeRawString_seq() {
931 final String expectedJson = "this is not a valid JSON string";
932 final String actualJson = withLockedWriterReturning(writer ->
933 writer.use(() -> writer.writeRawString(expectedJson)));
934 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
935 }
936
937 @Test
938 void test_writeRawString_null_buffer() {
939 withLockedWriter(writer -> Assertions
940 .assertThatThrownBy(() ->
941 writer.use(() ->
942 writer.writeRawString((char[]) null)))
943 .isInstanceOf(NullPointerException.class)
944 .hasMessage("buffer"));
945 }
946
947 @Test
948 void test_writeRawString_buffer_negative_offset() {
949 withLockedWriter(writer -> Assertions
950 .assertThatThrownBy(() ->
951 writer.use(() ->
952 writer.writeRawString(new char[]{'a'}, -1, 0)))
953 .isInstanceOf(IllegalArgumentException.class)
954 .hasMessageContaining("offset"));
955 }
956
957 @Test
958 void test_writeRawString_buffer_negative_length() {
959 withLockedWriter(writer -> Assertions
960 .assertThatThrownBy(() ->
961 writer.use(() ->
962 writer.writeRawString(new char[]{'a'}, 0, -1)))
963 .isInstanceOf(IllegalArgumentException.class)
964 .hasMessageContaining("length"));
965 }
966
967 @Test
968 void test_writeRawString_buffer() {
969 final String expectedJson = "this is not a valid JSON string";
970 final String actualJson = withLockedWriterReturning(writer ->
971 writer.use(() ->
972 writer.writeRawString(expectedJson.toCharArray())));
973 Assertions.assertThat(actualJson).isEqualTo(expectedJson);
974 }
975
976 }
+0
-139
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.core.config.plugins.convert.TypeConverter;
19 import org.apache.logging.log4j.core.config.plugins.convert.TypeConverterRegistry;
20 import org.apache.logging.log4j.junit.LoggerContextSource;
21 import org.apache.logging.log4j.junit.Named;
22 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.assertj.core.api.Assertions;
25 import org.jctools.queues.MpmcArrayQueue;
26 import org.junit.jupiter.api.Test;
27
28 import java.lang.reflect.Field;
29 import java.util.ArrayDeque;
30 import java.util.concurrent.ArrayBlockingQueue;
31
32 class RecyclerFactoriesTest {
33
34 @Test
35 void test_RecyclerFactoryConverter() throws Exception {
36
37 // Check if the type converter is registered.
38 final TypeConverter<?> converter = TypeConverterRegistry
39 .getInstance()
40 .findCompatibleConverter(RecyclerFactory.class);
41 Assertions.assertThat(converter).isNotNull();
42
43 // Check dummy recycler factory.
44 {
45 final Object actualDummyRecyclerFactory = converter.convert("dummy");
46 Assertions
47 .assertThat(actualDummyRecyclerFactory)
48 .isSameAs(DummyRecyclerFactory.getInstance());
49 }
50
51 // Check thread-local recycler factory.
52 {
53 final Object actualThreadLocalRecyclerFactory = converter.convert("threadLocal");
54 Assertions
55 .assertThat(actualThreadLocalRecyclerFactory)
56 .isSameAs(ThreadLocalRecyclerFactory.getInstance());
57 }
58
59 // Check queueing recycler factory.
60 {
61 final Object actualQueueingRecyclerFactory = converter.convert("queue");
62 Assertions
63 .assertThat(actualQueueingRecyclerFactory)
64 .isInstanceOf(QueueingRecyclerFactory.class);
65 }
66
67 // Check queueing recycler factory with supplier.
68 {
69 final Object recyclerFactory = converter.convert(
70 "queue:supplier=java.util.ArrayDeque.new");
71 Assertions
72 .assertThat(recyclerFactory)
73 .isInstanceOf(QueueingRecyclerFactory.class);
74 final QueueingRecyclerFactory queueingRecyclerFactory =
75 (QueueingRecyclerFactory) recyclerFactory;
76 final Recycler<Object> recycler =
77 queueingRecyclerFactory.create(Object::new);
78 Assertions
79 .assertThat(recycler)
80 .isInstanceOf(QueueingRecycler.class);
81 final QueueingRecycler<Object> queueingRecycler =
82 (QueueingRecycler<Object>) recycler;
83 Assertions
84 .assertThat(queueingRecycler.getQueue())
85 .isInstanceOf(ArrayDeque.class);
86 }
87
88 // Check queueing recycler factory with capacity.
89 {
90 final Object actualQueueingRecyclerFactory = converter.convert(
91 "queue:capacity=100");
92 Assertions
93 .assertThat(actualQueueingRecyclerFactory)
94 .isInstanceOf(QueueingRecyclerFactory.class);
95 }
96
97 // Check queueing recycler factory with supplier and capacity.
98 {
99 final Object recyclerFactory = converter.convert(
100 "queue:" +
101 "supplier=java.util.concurrent.ArrayBlockingQueue.new," +
102 "capacity=100");
103 Assertions
104 .assertThat(recyclerFactory)
105 .isInstanceOf(QueueingRecyclerFactory.class);
106 final QueueingRecyclerFactory queueingRecyclerFactory =
107 (QueueingRecyclerFactory) recyclerFactory;
108 final Recycler<Object> recycler =
109 queueingRecyclerFactory.create(Object::new);
110 Assertions
111 .assertThat(recycler)
112 .isInstanceOf(QueueingRecycler.class);
113 final QueueingRecycler<Object> queueingRecycler =
114 (QueueingRecycler<Object>) recycler;
115 Assertions
116 .assertThat(queueingRecycler.getQueue())
117 .isInstanceOf(ArrayBlockingQueue.class);
118 final ArrayBlockingQueue<Object> queue =
119 (ArrayBlockingQueue<Object>) queueingRecycler.getQueue();
120 Assertions.assertThat(queue.remainingCapacity()).isEqualTo(100);
121 }
122
123 }
124
125 @Test
126 @LoggerContextSource("recyclerFactoryCustomizedJsonTemplateLayoutLogging.xml")
127 void test_RecyclerFactoryConverter_using_XML_config(
128 final @Named(value = "List") ListAppender appender)
129 throws Exception {
130 final JsonTemplateLayout layout = (JsonTemplateLayout) appender.getLayout();
131 final Field field = JsonTemplateLayout.class.getDeclaredField("contextRecycler");
132 field.setAccessible(true);
133 final QueueingRecycler<?> contextRecycler = (QueueingRecycler<?>) field.get(layout);
134 final MpmcArrayQueue<?> queue = (MpmcArrayQueue<?>) contextRecycler.getQueue();
135 Assertions.assertThat(queue.capacity()).isEqualTo(512);
136 }
137
138 }
+0
-410
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/StringParameterParserTest.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.layout.template.json.util.StringParameterParser.DoubleQuotedStringValue;
19 import org.apache.logging.log4j.layout.template.json.util.StringParameterParser.NullValue;
20 import org.apache.logging.log4j.layout.template.json.util.StringParameterParser.StringValue;
21 import org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Value;
22 import org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values;
23 import org.assertj.core.api.Assertions;
24 import org.junit.jupiter.api.Test;
25
26 import java.util.Collections;
27 import java.util.LinkedHashMap;
28 import java.util.LinkedHashSet;
29 import java.util.Map;
30 import java.util.Set;
31
32 @SuppressWarnings("DoubleBraceInitialization")
33 class StringParameterParserTest {
34
35 @Test
36 void test_empty_string() {
37 testSuccess(
38 "",
39 Collections.emptyMap());
40 }
41
42 @Test
43 void test_blank_string() {
44 testSuccess(
45 "\t",
46 Collections.emptyMap());
47 }
48
49 @Test
50 void test_simple_pair() {
51 testSuccess(
52 "a=b",
53 Collections.singletonMap("a", Values.stringValue("b")));
54 }
55
56 @Test
57 void test_simple_pair_with_whitespace_1() {
58 testSuccess(
59 " a=b",
60 Collections.singletonMap("a", Values.stringValue("b")));
61 }
62
63 @Test
64 void test_simple_pair_with_whitespace_2() {
65 testSuccess(
66 " a =b",
67 Collections.singletonMap("a", Values.stringValue("b")));
68 }
69
70 @Test
71 void test_simple_pair_with_whitespace_3() {
72 testSuccess(
73 " a = b",
74 Collections.singletonMap("a", Values.stringValue("b")));
75 }
76
77 @Test
78 void test_simple_pair_with_whitespace_4() {
79 testSuccess(
80 " a = b ",
81 Collections.singletonMap("a", Values.stringValue("b")));
82 }
83
84 @Test
85 void test_null_value_1() {
86 testSuccess(
87 "a",
88 Collections.singletonMap("a", Values.nullValue()));
89 }
90
91 @Test
92 void test_null_value_2() {
93 testSuccess(
94 "a,b=c,d=",
95 new LinkedHashMap<String, Value>() {{
96 put("a", Values.nullValue());
97 put("b", Values.stringValue("c"));
98 put("d", Values.nullValue());
99 }});
100 }
101
102 @Test
103 void test_null_value_3() {
104 testSuccess(
105 "a,b=c,d",
106 new LinkedHashMap<String, Value>() {{
107 put("a", Values.nullValue());
108 put("b", Values.stringValue("c"));
109 put("d", Values.nullValue());
110 }});
111 }
112
113 @Test
114 void test_null_value_4() {
115 testSuccess(
116 "a,b=\"c,=\\\"\",d=,e=f",
117 new LinkedHashMap<String, Value>() {{
118 put("a", Values.nullValue());
119 put("b", Values.doubleQuotedStringValue("c,=\""));
120 put("d", Values.nullValue());
121 put("e", Values.stringValue("f"));
122 }});
123 }
124
125 @Test
126 void test_two_pairs() {
127 testSuccess(
128 "a=b,c=d",
129 new LinkedHashMap<String, Value>() {{
130 put("a", Values.stringValue("b"));
131 put("c", Values.stringValue("d"));
132 }});
133 }
134
135 @Test
136 void test_quoted_string_01() {
137 testSuccess(
138 "a=\"b\"",
139 Collections.singletonMap("a", Values.doubleQuotedStringValue("b")));
140 }
141
142 @Test
143 void test_quoted_string_02() {
144 testSuccess(
145 "a=\"b\",c=d",
146 new LinkedHashMap<String, Value>() {{
147 put("a", Values.doubleQuotedStringValue("b"));
148 put("c", Values.stringValue("d"));
149 }});
150 }
151
152 @Test
153 void test_quoted_string_03() {
154 testSuccess(
155 "a=b,c=\"d\"",
156 new LinkedHashMap<String, Value>() {{
157 put("a", Values.stringValue("b"));
158 put("c", Values.doubleQuotedStringValue("d"));
159 }});
160 }
161
162 @Test
163 void test_quoted_string_04() {
164 testSuccess(
165 "a=\"b\",c=\"d\"",
166 new LinkedHashMap<String, Value>() {{
167 put("a", Values.doubleQuotedStringValue("b"));
168 put("c", Values.doubleQuotedStringValue("d"));
169 }});
170 }
171
172 @Test
173 void test_quoted_string_05() {
174 testSuccess(
175 "a=\"\\\"b\"",
176 Collections.singletonMap("a", Values.doubleQuotedStringValue("\"b")));
177 }
178
179 @Test
180 void test_quoted_string_06() {
181 testSuccess(
182 "a=\"\\\"b\\\"\"",
183 Collections.singletonMap("a", Values.doubleQuotedStringValue("\"b\"")));
184 }
185
186 @Test
187 void test_quoted_string_07() {
188 testSuccess(
189 "a=\"\\\"b\",c=d",
190 new LinkedHashMap<String, Value>() {{
191 put("a", Values.doubleQuotedStringValue("\"b"));
192 put("c", Values.stringValue("d"));
193 }});
194 }
195
196 @Test
197 void test_quoted_string_08() {
198 testSuccess(
199 "a=\"\\\"b\\\"\",c=d",
200 new LinkedHashMap<String, Value>() {{
201 put("a", Values.doubleQuotedStringValue("\"b\""));
202 put("c", Values.stringValue("d"));
203 }});
204 }
205
206 @Test
207 void test_quoted_string_09() {
208 testSuccess(
209 "a=\"\\\"b,\",c=d",
210 new LinkedHashMap<String, Value>() {{
211 put("a", Values.doubleQuotedStringValue("\"b,"));
212 put("c", Values.stringValue("d"));
213 }});
214 }
215
216 @Test
217 void test_quoted_string_10() {
218 testSuccess(
219 "a=\"\\\"b\\\",\",c=d",
220 new LinkedHashMap<String, Value>() {{
221 put("a", Values.doubleQuotedStringValue("\"b\","));
222 put("c", Values.stringValue("d"));
223 }});
224 }
225
226 @Test
227 void test_quoted_string_11() {
228 testSuccess(
229 "a=\"\\\"b\",c=\"d\"",
230 new LinkedHashMap<String, Value>() {{
231 put("a", Values.doubleQuotedStringValue("\"b"));
232 put("c", Values.doubleQuotedStringValue("d"));
233 }});
234 }
235
236 @Test
237 void test_quoted_string_12() {
238 testSuccess(
239 "a=\"\\\"b\\\"\",c=\"d\"",
240 new LinkedHashMap<String, Value>() {{
241 put("a", Values.doubleQuotedStringValue("\"b\""));
242 put("c", Values.doubleQuotedStringValue("d"));
243 }});
244 }
245
246 @Test
247 void test_quoted_string_13() {
248 testSuccess(
249 "a=\"\\\"b,\",c=\"\\\"d\"",
250 new LinkedHashMap<String, Value>() {{
251 put("a", Values.doubleQuotedStringValue("\"b,"));
252 put("c", Values.doubleQuotedStringValue("\"d"));
253 }});
254 }
255
256 @Test
257 void test_quoted_string_14() {
258 testSuccess(
259 "a=\"\\\"b\\\",\",c=\"\\\"d\\\"\"",
260 new LinkedHashMap<String, Value>() {{
261 put("a", Values.doubleQuotedStringValue("\"b\","));
262 put("c", Values.doubleQuotedStringValue("\"d\""));
263 }});
264 }
265
266 @Test
267 void test_quoted_string_15() {
268 testSuccess(
269 "a=\"\\\"b\",c=\",d\"",
270 new LinkedHashMap<String, Value>() {{
271 put("a", Values.doubleQuotedStringValue("\"b"));
272 put("c", Values.doubleQuotedStringValue(",d"));
273 }});
274 }
275
276 @Test
277 void test_quoted_string_16() {
278 testSuccess(
279 "a=\"\\\"b\\\"\",c=\",d\"",
280 new LinkedHashMap<String, Value>() {{
281 put("a", Values.doubleQuotedStringValue("\"b\""));
282 put("c", Values.doubleQuotedStringValue(",d"));
283 }});
284 }
285
286 @Test
287 void test_quoted_string_17() {
288 testSuccess(
289 "a=\"\\\"b,\",c=\"\\\"d,\"",
290 new LinkedHashMap<String, Value>() {{
291 put("a", Values.doubleQuotedStringValue("\"b,"));
292 put("c", Values.doubleQuotedStringValue("\"d,"));
293 }});
294 }
295
296 @Test
297 void test_quoted_string_18() {
298 testSuccess(
299 "a=\"\\\"b\\\",\",c=\"\\\"d\\\",\"",
300 new LinkedHashMap<String, Value>() {{
301 put("a", Values.doubleQuotedStringValue("\"b\","));
302 put("c", Values.doubleQuotedStringValue("\"d\","));
303 }});
304 }
305
306 private static void testSuccess(
307 final String input,
308 final Map<String, Value> expectedMap) {
309 final Map<String, Value> actualMap = StringParameterParser.parse(input);
310 Assertions
311 .assertThat(actualMap)
312 .as("input: %s", input)
313 .isEqualTo(expectedMap);
314 }
315
316 @Test
317 void test_missing_key() {
318 Assertions
319 .assertThatThrownBy(() -> {
320 final String input = ",a=b";
321 StringParameterParser.parse(input);
322 })
323 .hasMessageStartingWith("failed to locate key at index 0");
324 }
325
326 @Test
327 void test_conflicting_key() {
328 Assertions
329 .assertThatThrownBy(() -> {
330 final String input = "a,a";
331 StringParameterParser.parse(input);
332 })
333 .hasMessageStartingWith("conflicting key at index 2");
334 }
335
336 @Test
337 void test_prematurely_ending_quoted_string_01() {
338 Assertions
339 .assertThatThrownBy(() -> {
340 final String input = "a,b=\"";
341 StringParameterParser.parse(input);
342 })
343 .hasMessageStartingWith("failed to locate the end of double-quoted content starting at index 4");
344 }
345
346 @Test
347 void test_prematurely_ending_quoted_string_02() {
348 Assertions
349 .assertThatThrownBy(() -> {
350 final String input = "a,b=\"c";
351 StringParameterParser.parse(input);
352 })
353 .hasMessageStartingWith("failed to locate the end of double-quoted content starting at index 4");
354 }
355
356 @Test
357 void test_prematurely_ending_quoted_string_03() {
358 Assertions
359 .assertThatThrownBy(() -> {
360 final String input = "a,b=\",c";
361 StringParameterParser.parse(input);
362 })
363 .hasMessageStartingWith("failed to locate the end of double-quoted content starting at index 4");
364 }
365
366 @Test
367 void test_prematurely_ending_quoted_string_04() {
368 Assertions
369 .assertThatThrownBy(() -> {
370 final String input = "a,b=\",c\" x";
371 StringParameterParser.parse(input);
372 })
373 .hasMessageStartingWith("was expecting comma at index 9");
374 }
375
376 @Test
377 void test_NullValue_toString() {
378 final Map<String, Value> map = StringParameterParser.parse("a");
379 final NullValue value = (NullValue) map.get("a");
380 Assertions.assertThat(value.toString()).isEqualTo("null");
381 }
382
383 @Test
384 void test_StringValue_toString() {
385 final Map<String, Value> map = StringParameterParser.parse("a=b");
386 final StringValue value = (StringValue) map.get("a");
387 Assertions.assertThat(value.toString()).isEqualTo("b");
388 }
389
390 @Test
391 void test_DoubleQuotedStringValue_toString() {
392 final Map<String, Value> map = StringParameterParser.parse("a=\"\\\"b\"");
393 final DoubleQuotedStringValue value = (DoubleQuotedStringValue) map.get("a");
394 Assertions.assertThat(value.toString()).isEqualTo("\"b");
395 }
396
397 @Test
398 void test_allowedKeys() {
399 Assertions
400 .assertThatThrownBy(() -> {
401 final String input = "a,b";
402 final Set<String> allowedKeys =
403 new LinkedHashSet<>(Collections.singletonList("a"));
404 StringParameterParser.parse(input, allowedKeys);
405 })
406 .hasMessageStartingWith("unknown key \"b\" is found in input: a,b");
407 }
408
409 }
+0
-244
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/TruncatingBufferedWriterTest.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.logging.log4j.layout.template.json.util;
17
18 import org.assertj.core.api.Assertions;
19 import org.junit.jupiter.api.Test;
20
21 class TruncatingBufferedWriterTest {
22
23 @Test
24 void test_ctor_invalid_args() {
25 Assertions
26 .assertThatThrownBy(() -> new TruncatingBufferedWriter(-1))
27 .isInstanceOf(NegativeArraySizeException.class);
28 }
29
30 @Test
31 void test_okay_payloads() {
32
33 // Fill in the writer.
34 final int capacity = 1_000;
35 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(capacity);
36 writer.write(Character.MAX_VALUE);
37 writer.write(new char[]{Character.MIN_VALUE, Character.MAX_VALUE});
38 writer.write("foo");
39 writer.write("foobar", 3, 3);
40 writer.write(new char[]{'f', 'o', 'o', 'b', 'a', 'r', 'b', 'u', 'z', 'z'}, 6, 4);
41 writer.append('!');
42 writer.append("yo");
43 writer.append(null);
44 writer.append("yo dog", 3, 6);
45 writer.append(null, -1, -1);
46
47 // Verify accessors.
48 final char[] expectedBuffer = new char[capacity];
49 int expectedPosition = 0;
50 expectedBuffer[expectedPosition++] = Character.MAX_VALUE;
51 expectedBuffer[expectedPosition++] = Character.MIN_VALUE;
52 expectedBuffer[expectedPosition++] = Character.MAX_VALUE;
53 expectedBuffer[expectedPosition++] = 'f';
54 expectedBuffer[expectedPosition++] = 'o';
55 expectedBuffer[expectedPosition++] = 'o';
56 expectedBuffer[expectedPosition++] = 'b';
57 expectedBuffer[expectedPosition++] = 'a';
58 expectedBuffer[expectedPosition++] = 'r';
59 expectedBuffer[expectedPosition++] = 'b';
60 expectedBuffer[expectedPosition++] = 'u';
61 expectedBuffer[expectedPosition++] = 'z';
62 expectedBuffer[expectedPosition++] = 'z';
63 expectedBuffer[expectedPosition++] = '!';
64 expectedBuffer[expectedPosition++] = 'y';
65 expectedBuffer[expectedPosition++] = 'o';
66 expectedBuffer[expectedPosition++] = 'n';
67 expectedBuffer[expectedPosition++] = 'u';
68 expectedBuffer[expectedPosition++] = 'l';
69 expectedBuffer[expectedPosition++] = 'l';
70 expectedBuffer[expectedPosition++] = 'd';
71 expectedBuffer[expectedPosition++] = 'o';
72 expectedBuffer[expectedPosition++] = 'g';
73 expectedBuffer[expectedPosition++] = 'n';
74 expectedBuffer[expectedPosition++] = 'u';
75 expectedBuffer[expectedPosition++] = 'l';
76 expectedBuffer[expectedPosition++] = 'l';
77 Assertions.assertThat(writer.buffer()).isEqualTo(expectedBuffer);
78 Assertions.assertThat(writer.position()).isEqualTo(expectedPosition);
79 Assertions.assertThat(writer.capacity()).isEqualTo(capacity);
80 Assertions.assertThat(writer.truncated()).isFalse();
81 verifyClose(writer);
82
83 }
84
85 @Test
86 void test_write_int_truncation() {
87 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
88 writer.write('a');
89 writer.write('b');
90 verifyTruncation(writer, 'a');
91 }
92
93 @Test
94 void test_write_char_array_truncation() {
95 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
96 writer.write(new char[]{'a', 'b'});
97 verifyTruncation(writer, 'a');
98 }
99
100 @Test
101 void test_write_String_truncation() {
102 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
103 writer.write("ab");
104 verifyTruncation(writer, 'a');
105 }
106
107 @Test
108 void test_write_String_slice_invalid_args() {
109 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
110 final String string = "a";
111 Assertions
112 .assertThatThrownBy(() -> writer.write(string, -1, 1))
113 .isInstanceOf(IndexOutOfBoundsException.class)
114 .hasMessageStartingWith("invalid offset");
115 Assertions
116 .assertThatThrownBy(() -> writer.write(string, 1, 1))
117 .isInstanceOf(IndexOutOfBoundsException.class)
118 .hasMessageStartingWith("invalid offset");
119 Assertions
120 .assertThatThrownBy(() -> writer.write(string, 0, -1))
121 .isInstanceOf(IndexOutOfBoundsException.class)
122 .hasMessageStartingWith("invalid length");
123 Assertions
124 .assertThatThrownBy(() -> writer.write(string, 0, 2))
125 .isInstanceOf(IndexOutOfBoundsException.class)
126 .hasMessageStartingWith("invalid length");
127 }
128
129 @Test
130 void test_write_String_slice_truncation() {
131 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
132 writer.write("ab", 0, 2);
133 verifyTruncation(writer, 'a');
134 }
135
136 @Test
137 void test_write_char_array_slice_invalid_args() {
138 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
139 final char[] buffer = new char[]{'a'};
140 Assertions
141 .assertThatThrownBy(() -> writer.write(buffer, -1, 1))
142 .isInstanceOf(IndexOutOfBoundsException.class)
143 .hasMessageStartingWith("invalid offset");
144 Assertions
145 .assertThatThrownBy(() -> writer.write(buffer, 1, 1))
146 .isInstanceOf(IndexOutOfBoundsException.class)
147 .hasMessageStartingWith("invalid offset");
148 Assertions
149 .assertThatThrownBy(() -> writer.write(buffer, 0, -1))
150 .isInstanceOf(IndexOutOfBoundsException.class)
151 .hasMessageStartingWith("invalid length");
152 Assertions
153 .assertThatThrownBy(() -> writer.write(buffer, 0, 2))
154 .isInstanceOf(IndexOutOfBoundsException.class)
155 .hasMessageStartingWith("invalid length");
156 }
157
158 @Test
159 void test_write_char_array_slice_truncation() {
160 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
161 writer.write(new char[]{'a', 'b'}, 0, 2);
162 verifyTruncation(writer, 'a');
163 }
164
165 @Test
166 void test_append_char_truncation() {
167 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
168 writer.append('a');
169 writer.append('b');
170 verifyTruncation(writer, 'a');
171 }
172
173 @Test
174 void test_append_seq_truncation() {
175 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
176 writer.append("ab");
177 verifyTruncation(writer, 'a');
178 }
179
180 @Test
181 void test_append_seq_null_truncation() {
182 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
183 writer.append(null);
184 verifyTruncation(writer, 'n');
185 }
186
187 @Test
188 void test_append_seq_slice_invalid_args() {
189 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
190 final CharSequence seq = "ab";
191 Assertions
192 .assertThatThrownBy(() -> writer.append(seq, -1, 2))
193 .isInstanceOf(IndexOutOfBoundsException.class)
194 .hasMessageStartingWith("invalid start");
195 Assertions
196 .assertThatThrownBy(() -> writer.append(seq, 2, 2))
197 .isInstanceOf(IndexOutOfBoundsException.class)
198 .hasMessageStartingWith("invalid start");
199 Assertions
200 .assertThatThrownBy(() -> writer.append(seq, 0, -1))
201 .isInstanceOf(IndexOutOfBoundsException.class)
202 .hasMessageStartingWith("invalid end");
203 Assertions
204 .assertThatThrownBy(() -> writer.append(seq, 1, 0))
205 .isInstanceOf(IndexOutOfBoundsException.class)
206 .hasMessageStartingWith("invalid end");
207 Assertions
208 .assertThatThrownBy(() -> writer.append(seq, 0, 3))
209 .isInstanceOf(IndexOutOfBoundsException.class)
210 .hasMessageStartingWith("invalid end");
211 }
212
213 @Test
214 void test_append_seq_slice_truncation() {
215 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
216 writer.append("ab", 0, 1);
217 verifyTruncation(writer, 'a');
218 }
219
220 @Test
221 void test_append_seq_slice_null_truncation() {
222 final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
223 writer.append(null, -1, -1);
224 verifyTruncation(writer, 'n');
225 }
226
227 private void verifyTruncation(
228 final TruncatingBufferedWriter writer,
229 final char c) {
230 Assertions.assertThat(writer.buffer()).isEqualTo(new char[]{c});
231 Assertions.assertThat(writer.position()).isEqualTo(1);
232 Assertions.assertThat(writer.capacity()).isEqualTo(1);
233 Assertions.assertThat(writer.truncated()).isTrue();
234 verifyClose(writer);
235 }
236
237 private void verifyClose(final TruncatingBufferedWriter writer) {
238 writer.close();
239 Assertions.assertThat(writer.position()).isEqualTo(0);
240 Assertions.assertThat(writer.truncated()).isFalse();
241 }
242
243 }
+0
-63
log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/UrisTest.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.logging.log4j.layout.template.json.util;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.status.StatusLogger;
20 import org.assertj.core.api.Assertions;
21 import org.junit.jupiter.api.Test;
22
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.net.URI;
28 import java.nio.charset.StandardCharsets;
29 import java.nio.file.Files;
30
31 class UrisTest {
32
33 private static final Logger LOGGER = StatusLogger.getLogger();
34
35 @Test
36 void testClassPathResource() {
37 final String content = Uris.readUri(
38 "classpath:JsonLayout.json",
39 StandardCharsets.US_ASCII);
40 Assertions.assertThat(content).startsWith("{");
41 }
42
43 @Test
44 void testFilePathResource() throws IOException {
45 final String nonAsciiUtfText = "அஆஇฬ๘";
46 final File file = Files.createTempFile("log4j-UriUtilTest-", ".txt").toFile();
47 try {
48 try (final OutputStream outputStream = new FileOutputStream(file)) {
49 outputStream.write(nonAsciiUtfText.getBytes(StandardCharsets.UTF_8));
50 }
51 final URI uri = file.toURI();
52 final String content = Uris.readUri(uri, StandardCharsets.UTF_8);
53 Assertions.assertThat(content).isEqualTo(nonAsciiUtfText);
54 } finally {
55 final boolean deleted = file.delete();
56 if (!deleted) {
57 LOGGER.warn("could not delete temporary file: " + file);
58 }
59 }
60 }
61
62 }
+0
-42
log4j-layout-template-json/src/test/resources/additionalFieldEnrichedJsonTemplateLayoutLogging.json less more
0 {
1 "Configuration": {
2 "status": "OFF",
3 "appenders": {
4 "List": {
5 "name": "List",
6 "raw": "true",
7 "JsonTemplateLayout": {
8 "eventTemplateAdditionalField": [
9 {
10 "key": "stringField",
11 "value": "string"
12 },
13 {
14 "key": "numberField",
15 "value": "1",
16 "format": "JSON"
17 },
18 {
19 "key": "objectField",
20 "value": "{\"numberField\":1}",
21 "format": "JSON"
22 },
23 {
24 "key": "listField",
25 "value": "[1, \"two\"]",
26 "format": "JSON"
27 }
28 ]
29 }
30 }
31 },
32 "loggers": {
33 "root": {
34 "level": "trace",
35 "AppenderRef": {
36 "ref": "List"
37 }
38 }
39 }
40 }
41 }
+0
-37
log4j-layout-template-json/src/test/resources/additionalFieldEnrichedJsonTemplateLayoutLogging.properties 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 appender.list.name = List
16 appender.list.type = List
17 appender.list.raw = true
18 appender.list.layout.type = JsonTemplateLayout
19 appender.list.layout.eventTemplateAdditionalField[0].type = EventTemplateAdditionalField
20 appender.list.layout.eventTemplateAdditionalField[0].key = stringField
21 appender.list.layout.eventTemplateAdditionalField[0].value = string
22 appender.list.layout.eventTemplateAdditionalField[1].type = EventTemplateAdditionalField
23 appender.list.layout.eventTemplateAdditionalField[1].key = numberField
24 appender.list.layout.eventTemplateAdditionalField[1].value = 1
25 appender.list.layout.eventTemplateAdditionalField[1].format = JSON
26 appender.list.layout.eventTemplateAdditionalField[2].type = EventTemplateAdditionalField
27 appender.list.layout.eventTemplateAdditionalField[2].key = objectField
28 appender.list.layout.eventTemplateAdditionalField[2].value = {"numberField":1}
29 appender.list.layout.eventTemplateAdditionalField[2].format = JSON
30 appender.list.layout.eventTemplateAdditionalField[3].type = EventTemplateAdditionalField
31 appender.list.layout.eventTemplateAdditionalField[3].key = listField
32 appender.list.layout.eventTemplateAdditionalField[3].value = [1, "two"]
33 appender.list.layout.eventTemplateAdditionalField[3].format = JSON
34
35 rootLogger.level = info
36 rootLogger.appenderRef.stdout.ref = List
+0
-34
log4j-layout-template-json/src/test/resources/additionalFieldEnrichedJsonTemplateLayoutLogging.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <Configuration status="OFF">
18 <Appenders>
19 <List name="List" raw="true">
20 <JsonTemplateLayout>
21 <EventTemplateAdditionalField key="stringField" value="string"/>
22 <EventTemplateAdditionalField key="numberField" value="1" format="JSON"/>
23 <EventTemplateAdditionalField key="objectField" value='{"numberField":1}' format="JSON"/>
24 <EventTemplateAdditionalField key="listField" value='[1, "two"]' format="JSON"/>
25 </JsonTemplateLayout>
26 </List>
27 </Appenders>
28 <Loggers>
29 <Root level="TRACE">
30 <AppenderRef ref="List"/>
31 </Root>
32 </Loggers>
33 </Configuration>
+0
-39
log4j-layout-template-json/src/test/resources/additionalFieldEnrichedJsonTemplateLayoutLogging.yaml 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 Configuration:
16 status: "OFF"
17 appenders:
18 List:
19 name: "List"
20 raw: "true"
21 JsonTemplateLayout:
22 eventTemplateAdditionalField:
23 - key: "stringField"
24 value: "string"
25 - key: "numberField"
26 value: "1"
27 format: "JSON"
28 - key: "objectField"
29 value: '{"numberField":1}'
30 format: "JSON"
31 - key: "listField"
32 value: '[1, "two"]'
33 format: "JSON"
34 loggers:
35 root:
36 level: "trace"
37 AppenderRef:
38 ref: "List"
+0
-38
log4j-layout-template-json/src/test/resources/gcFreeJsonTemplateLayoutLogging.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <Configuration status="OFF">
18 <Appenders>
19 <Console name="Console" target="SYSTEM_OUT">
20 <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %X %m%ex%n"/>
21 </Console>
22 <File name="File"
23 fileName="target/gcFreeJsonTemplateLayoutLogging.log"
24 bufferedIO="false"
25 append="false">
26 <JsonTemplateLayout recyclerFactory="threadLocal"/>
27 </File>
28 </Appenders>
29 <Loggers>
30 <Root level="trace" includeLocation="false">
31 <Property name="prop1">value1</Property>
32 <Property name="prop2">value2</Property>
33 <appender-ref ref="Console" level="FATAL"/>
34 <appender-ref ref="File"/>
35 </Root>
36 </Loggers>
37 </Configuration>
+0
-36
log4j-layout-template-json/src/test/resources/messageFallbackKeyUsingJsonTemplateLayout.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <Configuration status="OFF">
18 <Appenders>
19 <List name="List" raw="true">
20 <JsonTemplateLayout eventTemplate=
21 '{
22 "message": {
23 "$resolver": "message",
24 "fallbackKey": "fallback"
25 }
26 }'
27 />
28 </List>
29 </Appenders>
30 <Loggers>
31 <Root level="TRACE">
32 <AppenderRef ref="List"/>
33 </Root>
34 </Loggers>
35 </Configuration>
+0
-38
log4j-layout-template-json/src/test/resources/nullEventDelimitedJsonTemplateLayoutLogging.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <Configuration status="OFF">
18 <Appenders>
19 <Socket name="Socket"
20 host="localhost"
21 port="${sys:serverPort}"
22 protocol="TCP"
23 ignoreExceptions="false"
24 reconnectionDelay="100"
25 immediateFlush="true">
26 <JsonTemplateLayout eventTemplate='{"$resolver": "message"}'
27 eventDelimiter=""
28 nullEventDelimiterEnabled="true"
29 charset="US-ASCII"/>
30 </Socket>
31 </Appenders>
32 <Loggers>
33 <Root level="TRACE">
34 <AppenderRef ref="Socket"/>
35 </Root>
36 </Loggers>
37 </Configuration>
+0
-30
log4j-layout-template-json/src/test/resources/recyclerFactoryCustomizedJsonTemplateLayoutLogging.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <Configuration status="OFF">
18 <Appenders>
19 <List name="List" raw="true">
20 <JsonTemplateLayout
21 recyclerFactory="queue:supplier=org.jctools.queues.MpmcArrayQueue.new,capacity=512"/>
22 </List>
23 </Appenders>
24 <Loggers>
25 <Root level="TRACE">
26 <AppenderRef ref="List"/>
27 </Root>
28 </Loggers>
29 </Configuration>
+0
-70
log4j-layout-template-json/src/test/resources/testJsonTemplateLayout.json less more
0 {
1 "exception_class": {
2 "$resolver": "exception",
3 "field": "className"
4 },
5 "exception_message": {
6 "$resolver": "exception",
7 "field": "message"
8 },
9 "stacktrace": {
10 "$resolver": "exception",
11 "field": "stackTrace",
12 "stackTrace": {
13 "stringified": true
14 }
15 },
16 "line_number": {
17 "$resolver": "source",
18 "field": "lineNumber"
19 },
20 "class": {
21 "$resolver": "source",
22 "field": "className"
23 },
24 "@version": 1,
25 "source_host": "${hostName}",
26 "message": {
27 "$resolver": "message",
28 "stringified": true
29 },
30 "thread_id": {
31 "$resolver": "thread",
32 "field": "id"
33 },
34 "thread_name": {
35 "$resolver": "thread",
36 "field": "name"
37 },
38 "thread_priority": {
39 "$resolver": "thread",
40 "field": "priority"
41 },
42 "@timestamp": {
43 "$resolver": "timestamp"
44 },
45 "level": {
46 "$resolver": "level",
47 "field": "name"
48 },
49 "file": {
50 "$resolver": "source",
51 "field": "fileName"
52 },
53 "method": {
54 "$resolver": "source",
55 "field": "methodName"
56 },
57 "logger_fqcn": {
58 "$resolver": "logger",
59 "field": "fqcn"
60 },
61 "logger_name": {
62 "$resolver": "logger",
63 "field": "name"
64 },
65 "end_of_batch": {
66 "$resolver": "endOfBatch"
67 },
68 "lookup_test_key": "${sys:lookup_test_key}"
69 }
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-liquibase</artifactId>
3030 <log4jParentDir>${basedir}/..</log4jParentDir>
3131 <docLabel>Liquibase Documentation</docLabel>
3232 <projectDir>/liquibase</projectDir>
33 <maven.doap.skip>true</maven.doap.skip>
3433 </properties>
3534 <dependencies>
3635 <dependency>
6463 <scope>test</scope>
6564 </dependency>
6665 <dependency>
67 <groupId>org.junit.vintage</groupId>
68 <artifactId>junit-vintage-engine</artifactId>
69 </dependency>
70 <dependency>
71 <groupId>org.junit.jupiter</groupId>
72 <artifactId>junit-jupiter-engine</artifactId>
66 <groupId>junit</groupId>
67 <artifactId>junit</artifactId>
68 <scope>test</scope>
7369 </dependency>
7470 </dependencies>
7571 <build>
220216 </reportSets>
221217 </plugin>
222218 <plugin>
223 <groupId>com.github.spotbugs</groupId>
224 <artifactId>spotbugs-maven-plugin</artifactId>
219 <groupId>org.codehaus.mojo</groupId>
220 <artifactId>findbugs-maven-plugin</artifactId>
221 <version>${findbugs.plugin.version}</version>
222 <configuration>
223 <fork>true</fork>
224 <jvmArgs>-Duser.language=en</jvmArgs>
225 <threshold>Normal</threshold>
226 <effort>Default</effort>
227 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
228 </configuration>
225229 </plugin>
226230 <plugin>
227231 <groupId>org.apache.maven.plugins</groupId>
2626
2727 ## Usage
2828
29 Including this module will automatically make Liquibase log via Log4j 2, due the plugin auto discovery mechanism of
29 Including this module will automatically make Liquibase log via Log4j 2, due the the plugin auto discovery mechanism of
3030 Liquibase.
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17
18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19 <parent>
20 <groupId>org.apache.logging.log4j</groupId>
21 <artifactId>log4j</artifactId>
22 <version>2.12.3</version>
23 </parent>
24 <modelVersion>4.0.0</modelVersion>
25
26 <artifactId>log4j-mongodb2</artifactId>
27 <name>Apache Log4j MongoDB 2</name>
28 <description>
29 MongoDB appender for Log4j using the MongoDB 2 driver API.
30 </description>
31 <properties>
32 <log4jParentDir>${basedir}/..</log4jParentDir>
33 <docLabel>MongoDB 2 Documentation</docLabel>
34 <projectDir>/log4j-mongodb2</projectDir>
35 <module.name>org.apache.logging.log4j.mongodb2</module.name>
36 </properties>
37
38 <dependencies>
39 <dependency>
40 <groupId>org.apache.logging.log4j</groupId>
41 <artifactId>log4j-core</artifactId>
42 </dependency>
43 <dependency>
44 <groupId>org.mongodb</groupId>
45 <artifactId>mongo-java-driver</artifactId>
46 </dependency>
47 <!-- Test Dependencies -->
48 <dependency>
49 <groupId>junit</groupId>
50 <artifactId>junit</artifactId>
51 </dependency>
52 <dependency>
53 <groupId>org.mockito</groupId>
54 <artifactId>mockito-core</artifactId>
55 <scope>test</scope>
56 </dependency>
57 <dependency>
58 <groupId>org.apache.logging.log4j</groupId>
59 <artifactId>log4j-api</artifactId>
60 <type>test-jar</type>
61 </dependency>
62 <dependency>
63 <groupId>org.apache.logging.log4j</groupId>
64 <artifactId>log4j-core</artifactId>
65 <type>test-jar</type>
66 </dependency>
67 <dependency>
68 <groupId>org.apache.logging.log4j</groupId>
69 <artifactId>log4j-slf4j-impl</artifactId>
70 <scope>test</scope>
71 </dependency>
72 <dependency>
73 <groupId>de.flapdoodle.embed</groupId>
74 <artifactId>de.flapdoodle.embed.mongo</artifactId>
75 <scope>test</scope>
76 </dependency>
77 </dependencies>
78
79 <build>
80 <plugins>
81 <plugin>
82 <groupId>org.apache.felix</groupId>
83 <artifactId>maven-bundle-plugin</artifactId>
84 <configuration>
85 <instructions>
86 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
87 <Export-Package>*</Export-Package>
88 </instructions>
89 </configuration>
90 </plugin>
91 <!-- workaround flaky "Operation not permitted" failures when running tests in parallel -->
92 <plugin>
93 <artifactId>maven-surefire-plugin</artifactId>
94 <configuration>
95 <forkCount>1</forkCount>
96 <reuseForks>false</reuseForks>
97 </configuration>
98 </plugin>
99 </plugins>
100 </build>
101 <reporting>
102 <plugins>
103 <plugin>
104 <groupId>org.apache.maven.plugins</groupId>
105 <artifactId>maven-changes-plugin</artifactId>
106 <version>${changes.plugin.version}</version>
107 <reportSets>
108 <reportSet>
109 <reports>
110 <report>changes-report</report>
111 </reports>
112 </reportSet>
113 </reportSets>
114 <configuration>
115 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
116 <useJql>true</useJql>
117 </configuration>
118 </plugin>
119 <plugin>
120 <groupId>org.apache.maven.plugins</groupId>
121 <artifactId>maven-checkstyle-plugin</artifactId>
122 <version>${checkstyle.plugin.version}</version>
123 <configuration>
124 <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
125 <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
126 <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
127 <enableRulesSummary>false</enableRulesSummary>
128 <propertyExpansion>basedir=${basedir}</propertyExpansion>
129 <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
130 </configuration>
131 </plugin>
132 <plugin>
133 <groupId>org.apache.maven.plugins</groupId>
134 <artifactId>maven-javadoc-plugin</artifactId>
135 <version>${javadoc.plugin.version}</version>
136 <configuration>
137 <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
138 Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
139 and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
140 <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating
141 project -->
142 <detectOfflineLinks>false</detectOfflineLinks>
143 <linksource>true</linksource>
144 </configuration>
145 <reportSets>
146 <reportSet>
147 <id>non-aggregate</id>
148 <reports>
149 <report>javadoc</report>
150 </reports>
151 </reportSet>
152 </reportSets>
153 </plugin>
154 <plugin>
155 <groupId>org.codehaus.mojo</groupId>
156 <artifactId>findbugs-maven-plugin</artifactId>
157 <version>${findbugs.plugin.version}</version>
158 <configuration>
159 <fork>true</fork>
160 <jvmArgs>-Duser.language=en</jvmArgs>
161 <threshold>Normal</threshold>
162 <effort>Default</effort>
163 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
164 </configuration>
165 </plugin>
166 <plugin>
167 <groupId>org.apache.maven.plugins</groupId>
168 <artifactId>maven-jxr-plugin</artifactId>
169 <version>${jxr.plugin.version}</version>
170 <reportSets>
171 <reportSet>
172 <id>non-aggregate</id>
173 <reports>
174 <report>jxr</report>
175 </reports>
176 </reportSet>
177 <reportSet>
178 <id>aggregate</id>
179 <reports>
180 <report>aggregate</report>
181 </reports>
182 </reportSet>
183 </reportSets>
184 </plugin>
185 <plugin>
186 <groupId>org.apache.maven.plugins</groupId>
187 <artifactId>maven-pmd-plugin</artifactId>
188 <version>${pmd.plugin.version}</version>
189 <configuration>
190 <targetJdk>${maven.compiler.target}</targetJdk>
191 </configuration>
192 </plugin>
193 </plugins>
194 </reporting>
195 </project>
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.mongodb2;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
21 import org.apache.logging.log4j.core.appender.nosql.AbstractNoSqlConnection;
22 import org.apache.logging.log4j.core.appender.nosql.NoSqlConnection;
23 import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
24 import org.apache.logging.log4j.status.StatusLogger;
25 import org.bson.BSON;
26 import org.bson.Transformer;
27
28 import com.mongodb.BasicDBObject;
29 import com.mongodb.DB;
30 import com.mongodb.DBCollection;
31 import com.mongodb.Mongo;
32 import com.mongodb.MongoException;
33 import com.mongodb.WriteConcern;
34
35 /**
36 * The MongoDB implementation of {@link NoSqlConnection}.
37 */
38 public final class MongoDbConnection extends AbstractNoSqlConnection<BasicDBObject, MongoDbObject> {
39
40 private static final Logger LOGGER = StatusLogger.getLogger();
41
42 static {
43 BSON.addEncodingHook(Level.class, new Transformer() {
44 @Override
45 public Object transform(final Object o) {
46 if (o instanceof Level) {
47 return ((Level) o).name();
48 }
49 return o;
50 }
51 });
52 }
53
54 private final DBCollection collection;
55 private final WriteConcern writeConcern;
56
57 public MongoDbConnection(final DB database, final WriteConcern writeConcern, final String collectionName,
58 final Boolean isCapped, final Integer collectionSize) {
59 if (database.collectionExists(collectionName)) {
60 LOGGER.debug("Gettting collection {}", collectionName);
61 collection = database.getCollection(collectionName);
62 } else {
63 final BasicDBObject options = new BasicDBObject();
64 options.put("capped", isCapped);
65 options.put("size", collectionSize);
66 LOGGER.debug("Creating collection {} (capped = {}, size = {})", collectionName, isCapped, collectionSize);
67 this.collection = database.createCollection(collectionName, options);
68 }
69 this.writeConcern = writeConcern;
70 }
71
72 @Override
73 public void closeImpl() {
74 // LOG4J2-1196
75 final Mongo mongo = this.collection.getDB().getMongo();
76 LOGGER.debug("Closing {} client {}", mongo.getClass().getSimpleName(), mongo);
77 mongo.close();
78 }
79
80 @Override
81 public MongoDbObject[] createList(final int length) {
82 return new MongoDbObject[length];
83 }
84
85 @Override
86 public MongoDbObject createObject() {
87 return new MongoDbObject();
88 }
89
90 @Override
91 public void insertObject(final NoSqlObject<BasicDBObject> object) {
92 try {
93 final BasicDBObject unwrapped = object.unwrap();
94 LOGGER.debug("Inserting object {}", unwrapped);
95 this.collection.insert(unwrapped, this.writeConcern);
96 } catch (final MongoException e) {
97 throw new AppenderLoggingException("Failed to write log event to MongoDB due to error: " + e.getMessage(),
98 e);
99 }
100 }
101
102 }
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.mongodb2;
17
18 import java.util.Collections;
19
20 import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
21
22 import com.mongodb.BasicDBList;
23 import com.mongodb.BasicDBObject;
24
25 /**
26 * The MongoDB implementation of {@link NoSqlObject}.
27 */
28 public final class MongoDbObject implements NoSqlObject<BasicDBObject> {
29 private final BasicDBObject mongoObject;
30
31 public MongoDbObject() {
32 this.mongoObject = new BasicDBObject();
33 }
34
35 @Override
36 public void set(final String field, final NoSqlObject<BasicDBObject> value) {
37 this.mongoObject.append(field, value.unwrap());
38 }
39
40 @Override
41 public void set(final String field, final NoSqlObject<BasicDBObject>[] values) {
42 final BasicDBList list = new BasicDBList();
43 for (final NoSqlObject<BasicDBObject> value : values) {
44 list.add(value.unwrap());
45 }
46 this.mongoObject.append(field, list);
47 }
48
49 @Override
50 public void set(final String field, final Object value) {
51 this.mongoObject.append(field, value);
52 }
53
54 @Override
55 public void set(final String field, final Object[] values) {
56 final BasicDBList list = new BasicDBList();
57 Collections.addAll(list, values);
58 this.mongoObject.append(field, list);
59 }
60
61 @Override
62 public BasicDBObject unwrap() {
63 return this.mongoObject;
64 }
65 }
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.mongodb2;
17
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Method;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.apache.logging.log4j.Logger;
24 import org.apache.logging.log4j.core.Core;
25 import org.apache.logging.log4j.core.appender.nosql.NoSqlProvider;
26 import org.apache.logging.log4j.core.config.plugins.Plugin;
27 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
28 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
29 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
30 import org.apache.logging.log4j.core.config.plugins.convert.TypeConverters;
31 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
32 import org.apache.logging.log4j.core.config.plugins.validation.constraints.ValidHost;
33 import org.apache.logging.log4j.core.config.plugins.validation.constraints.ValidPort;
34 import org.apache.logging.log4j.core.filter.AbstractFilterable;
35 import org.apache.logging.log4j.core.util.NameUtil;
36 import org.apache.logging.log4j.status.StatusLogger;
37 import org.apache.logging.log4j.util.LoaderUtil;
38 import org.apache.logging.log4j.util.Strings;
39
40 import com.mongodb.DB;
41 import com.mongodb.MongoClient;
42 import com.mongodb.MongoCredential;
43 import com.mongodb.ServerAddress;
44 import com.mongodb.WriteConcern;
45
46 /**
47 * The MongoDB implementation of {@link NoSqlProvider}.
48 */
49 @Plugin(name = "MongoDb2", category = Core.CATEGORY_NAME, printObject = true)
50 @PluginAliases("MongoDb") // Deprecated alias
51 public final class MongoDbProvider implements NoSqlProvider<MongoDbConnection> {
52
53 public static class Builder<B extends Builder<B>> extends AbstractFilterable.Builder<B>
54 implements org.apache.logging.log4j.core.util.Builder<MongoDbProvider> {
55
56 private static WriteConcern toWriteConcern(final String writeConcernConstant,
57 final String writeConcernConstantClassName) {
58 WriteConcern writeConcern;
59 if (Strings.isNotEmpty(writeConcernConstant)) {
60 if (Strings.isNotEmpty(writeConcernConstantClassName)) {
61 try {
62 final Class<?> writeConcernConstantClass = LoaderUtil.loadClass(writeConcernConstantClassName);
63 final Field field = writeConcernConstantClass.getField(writeConcernConstant);
64 writeConcern = (WriteConcern) field.get(null);
65 } catch (final Exception e) {
66 LOGGER.error("Write concern constant [{}.{}] not found, using default.",
67 writeConcernConstantClassName, writeConcernConstant);
68 writeConcern = DEFAULT_WRITE_CONCERN;
69 }
70 } else {
71 writeConcern = WriteConcern.valueOf(writeConcernConstant);
72 if (writeConcern == null) {
73 LOGGER.warn("Write concern constant [{}] not found, using default.", writeConcernConstant);
74 writeConcern = DEFAULT_WRITE_CONCERN;
75 }
76 }
77 } else {
78 writeConcern = DEFAULT_WRITE_CONCERN;
79 }
80 return writeConcern;
81 }
82
83 @PluginBuilderAttribute
84 @ValidHost
85 private String server = "localhost";
86
87 @PluginBuilderAttribute
88 @ValidPort
89 private String port = "" + DEFAULT_PORT;
90
91 @PluginBuilderAttribute
92 @Required(message = "No database name provided")
93 private String databaseName;
94
95 @PluginBuilderAttribute
96 @Required(message = "No collection name provided")
97 private String collectionName;
98
99 @PluginBuilderAttribute
100 private String userName;
101
102 @PluginBuilderAttribute(sensitive = true)
103 private String password;
104
105 @PluginBuilderAttribute("capped")
106 private boolean isCapped = false;
107
108 @PluginBuilderAttribute
109 private int collectionSize = DEFAULT_COLLECTION_SIZE;
110
111 @PluginBuilderAttribute
112 private String factoryClassName;
113
114 @PluginBuilderAttribute
115 private String factoryMethodName;
116
117 @PluginBuilderAttribute
118 private String writeConcernConstantClassName;
119
120 @PluginBuilderAttribute
121 private String writeConcernConstant;
122
123 @Override
124 public MongoDbProvider build() {
125 DB database;
126 String description;
127 if (Strings.isNotEmpty(factoryClassName) && Strings.isNotEmpty(factoryMethodName)) {
128 try {
129 final Class<?> factoryClass = LoaderUtil.loadClass(factoryClassName);
130 final Method method = factoryClass.getMethod(factoryMethodName);
131 final Object object = method.invoke(null);
132
133 if (object instanceof DB) {
134 database = (DB) object;
135 } else if (object instanceof MongoClient) {
136 if (Strings.isNotEmpty(databaseName)) {
137 database = ((MongoClient) object).getDB(databaseName);
138 } else {
139 LOGGER.error("The factory method [{}.{}()] returned a MongoClient so the database name is "
140 + "required.", factoryClassName, factoryMethodName);
141 return null;
142 }
143 } else if (object == null) {
144 LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName, factoryMethodName);
145 return null;
146 } else {
147 LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].", factoryClassName,
148 factoryMethodName, object.getClass().getName());
149 return null;
150 }
151
152 description = "database=" + database.getName();
153 final List<ServerAddress> addresses = database.getMongo().getAllAddress();
154 if (addresses.size() == 1) {
155 description += ", server=" + addresses.get(0).getHost() + ", port=" + addresses.get(0).getPort();
156 } else {
157 description += ", servers=[";
158 for (final ServerAddress address : addresses) {
159 description += " { " + address.getHost() + ", " + address.getPort() + " } ";
160 }
161 description += "]";
162 }
163 } catch (final ClassNotFoundException e) {
164 LOGGER.error("The factory class [{}] could not be loaded.", factoryClassName, e);
165 return null;
166 } catch (final NoSuchMethodException e) {
167 LOGGER.error("The factory class [{}] does not have a no-arg method named [{}].", factoryClassName,
168 factoryMethodName, e);
169 return null;
170 } catch (final Exception e) {
171 LOGGER.error("The factory method [{}.{}()] could not be invoked.", factoryClassName, factoryMethodName,
172 e);
173 return null;
174 }
175 } else if (Strings.isNotEmpty(databaseName)) {
176 final List<MongoCredential> credentials = new ArrayList<>();
177 description = "database=" + databaseName;
178 if (Strings.isNotEmpty(userName) && Strings.isNotEmpty(password)) {
179 description += ", username=" + userName + ", passwordHash="
180 + NameUtil.md5(password + MongoDbProvider.class.getName());
181 credentials.add(MongoCredential.createCredential(userName, databaseName, password.toCharArray()));
182 }
183 try {
184 final int portInt = TypeConverters.convert(port, int.class, DEFAULT_PORT);
185 description += ", server=" + server + ", port=" + portInt;
186 database = new MongoClient(new ServerAddress(server, portInt), credentials).getDB(databaseName);
187 } catch (final Exception e) {
188 LOGGER.error(
189 "Failed to obtain a database instance from the MongoClient at server [{}] and " + "port [{}].",
190 server, port);
191 return null;
192 }
193 } else {
194 LOGGER.error("No factory method was provided so the database name is required.");
195 return null;
196 }
197
198 try {
199 database.getCollectionNames(); // Check if the database actually requires authentication
200 } catch (final Exception e) {
201 LOGGER.error(
202 "The database is not up, or you are not authenticated, try supplying a username and password to the MongoDB provider.",
203 e);
204 return null;
205 }
206
207 final WriteConcern writeConcern = toWriteConcern(writeConcernConstant, writeConcernConstantClassName);
208
209 return new MongoDbProvider(database, writeConcern, collectionName, isCapped, collectionSize, description);
210 }
211
212 public B setCapped(final boolean isCapped) {
213 this.isCapped = isCapped;
214 return asBuilder();
215 }
216
217 public B setCollectionName(final String collectionName) {
218 this.collectionName = collectionName;
219 return asBuilder();
220 }
221
222 public B setCollectionSize(final int collectionSize) {
223 this.collectionSize = collectionSize;
224 return asBuilder();
225 }
226
227 public B setDatabaseName(final String databaseName) {
228 this.databaseName = databaseName;
229 return asBuilder();
230 }
231
232 public B setFactoryClassName(final String factoryClassName) {
233 this.factoryClassName = factoryClassName;
234 return asBuilder();
235 }
236
237 public B setFactoryMethodName(final String factoryMethodName) {
238 this.factoryMethodName = factoryMethodName;
239 return asBuilder();
240 }
241
242 public B setPassword(final String password) {
243 this.password = password;
244 return asBuilder();
245 }
246
247 public B setPort(final String port) {
248 this.port = port;
249 return asBuilder();
250 }
251
252 public B setServer(final String server) {
253 this.server = server;
254 return asBuilder();
255 }
256
257 public B setUserName(final String userName) {
258 this.userName = userName;
259 return asBuilder();
260 }
261
262 public B setWriteConcernConstant(final String writeConcernConstant) {
263 this.writeConcernConstant = writeConcernConstant;
264 return asBuilder();
265 }
266
267 public B setWriteConcernConstantClassName(final String writeConcernConstantClassName) {
268 this.writeConcernConstantClassName = writeConcernConstantClassName;
269 return asBuilder();
270 }
271 }
272 private static final WriteConcern DEFAULT_WRITE_CONCERN = WriteConcern.ACKNOWLEDGED;
273 private static final Logger LOGGER = StatusLogger.getLogger();
274 private static final int DEFAULT_PORT = 27017;
275
276 private static final int DEFAULT_COLLECTION_SIZE = 536870912;
277 /**
278 * Factory method for creating a MongoDB provider within the plugin manager.
279 *
280 * @param collectionName The name of the MongoDB collection to which log events should be written.
281 * @param writeConcernConstant The {@link WriteConcern} constant to control writing details, defaults to
282 * {@link WriteConcern#ACKNOWLEDGED}.
283 * @param writeConcernConstantClassName The name of a class containing the aforementioned static WriteConcern
284 * constant. Defaults to {@link WriteConcern}.
285 * @param databaseName The name of the MongoDB database containing the collection to which log events should be
286 * written. Mutually exclusive with {@code factoryClassName&factoryMethodName!=null}.
287 * @param server The host name of the MongoDB server, defaults to localhost and mutually exclusive with
288 * {@code factoryClassName&factoryMethodName!=null}.
289 * @param port The port the MongoDB server is listening on, defaults to the default MongoDB port and mutually
290 * exclusive with {@code factoryClassName&factoryMethodName!=null}.
291 * @param userName The username to authenticate against the MongoDB server with.
292 * @param password The password to authenticate against the MongoDB server with.
293 * @param factoryClassName A fully qualified class name containing a static factory method capable of returning a
294 * {@link DB} or a {@link MongoClient}.
295 * @param factoryMethodName The name of the public static factory method belonging to the aforementioned factory
296 * class.
297 * @return a new MongoDB provider.
298 * @deprecated in 2.8; use {@link #newBuilder()} instead.
299 */
300 @Deprecated
301 public static MongoDbProvider createNoSqlProvider(
302 final String collectionName,
303 final String writeConcernConstant,
304 final String writeConcernConstantClassName,
305 final String databaseName,
306 final String server,
307 final String port,
308 final String userName,
309 final String password,
310 final String factoryClassName,
311 final String factoryMethodName) {
312 LOGGER.info("createNoSqlProvider");
313 return newBuilder().setCollectionName(collectionName).setWriteConcernConstant(writeConcernConstantClassName)
314 .setWriteConcernConstant(writeConcernConstant).setDatabaseName(databaseName).setServer(server)
315 .setPort(port).setUserName(userName).setPassword(password).setFactoryClassName(factoryClassName)
316 .setFactoryMethodName(factoryMethodName).build();
317 }
318 @PluginBuilderFactory
319 public static <B extends Builder<B>> B newBuilder() {
320 return new Builder<B>().asBuilder();
321 }
322 private final String collectionName;
323 private final DB database;
324 private final String description;
325
326 private final WriteConcern writeConcern;
327
328 private final boolean isCapped;
329
330 private final Integer collectionSize;
331
332 private MongoDbProvider(final DB database, final WriteConcern writeConcern, final String collectionName,
333 final boolean isCapped, final Integer collectionSize, final String description) {
334 this.database = database;
335 this.writeConcern = writeConcern;
336 this.collectionName = collectionName;
337 this.isCapped = isCapped;
338 this.collectionSize = collectionSize;
339 this.description = "mongoDb{ " + description + " }";
340 }
341
342 @Override
343 public MongoDbConnection getConnection() {
344 return new MongoDbConnection(this.database, this.writeConcern, this.collectionName, this.isCapped, this.collectionSize);
345 }
346
347 @Override
348 public String toString() {
349 return this.description;
350 }
351 }
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 /**
17 * The classes in this package contain the MongoDB provider for the NoSQL Appender.
18 */
19 package org.apache.logging.log4j.mongodb2;
0 <!-- vim: set syn=markdown : -->
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 #set($h1='#')
18 #set($h2='##')
19 ## TODO: use properties for dynamic dependency versions
20
21 $h1 MongoDB appender
22
23 [MongoDB](http://www.mongodb.org/) is supported through the
24 [Java MongoDB Driver](http://docs.mongodb.org/ecosystem/drivers/java/).
25
26 ```
27 <dependencyManagement>
28 <dependencies>
29 <dependency>
30 <groupId>org.mongodb</groupId>
31 <artifactId>mongo-java-driver</artifactId>
32 <version>2.14.3</version>
33 </dependency>
34 </dependencies>
35 </dependencyManagement>
36 <dependencies>
37 <dependency>
38 <groupId>org.mongodb</groupId>
39 <artifactId>mongo-java-driver</artifactId>
40 </dependency>
41 </dependencies>
42 ```
43
44 $h2 Requirements
45
46 The MongoDB Appender is dependent on the Log4j 2 API and implementation.
47 For more information, see [Runtime Dependencies](../runtime-dependencies.html).
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 -->
17 <project name="Log4j MongoDB 2.x Appender"
18 xmlns="http://maven.apache.org/DECORATION/1.4.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
21 <body>
22 <links>
23 <item name="Apache" href="http://www.apache.org/" />
24 <item name="Logging Services" href="http://logging.apache.org/"/>
25 <item name="Log4j" href="../index.html"/>
26 </links>
27
28 <!-- Component-specific reports -->
29 <menu ref="reports"/>
30
31 <!-- Overall Project Info -->
32 <menu name="Log4j Project Information" img="icon-info-sign">
33 <item name="Dependencies" href="../dependencies.html" />
34 <item name="Dependency Convergence" href="../dependency-convergence.html" />
35 <item name="Dependency Management" href="../dependency-management.html" />
36 <item name="Project Team" href="../team-list.html" />
37 <item name="Mailing Lists" href="../mail-lists.html" />
38 <item name="Issue Tracking" href="../issue-tracking.html" />
39 <item name="Project License" href="../license.html" />
40 <item name="Source Repository" href="../source-repository.html" />
41 <item name="Project Summary" href="../project-summary.html" />
42 </menu>
43
44 <menu name="Log4j Project Reports" img="icon-cog">
45 <item name="Changes Report" href="../changes-report.html" />
46 <item name="JIRA Report" href="../jira-report.html" />
47 <item name="Surefire Report" href="../surefire-report.html" />
48 <item name="RAT Report" href="../rat-report.html" />
49 </menu>
50 </body>
51 </project>
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
17 package org.apache.logging.log4j.mongodb2;
18
19 import org.apache.commons.lang3.JavaVersion;
20 import org.apache.commons.lang3.SystemUtils;
21 import org.junit.Assume;
22 import org.junit.BeforeClass;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.junit.runners.Suite;
26
27 /**
28 * Runs all MongoDB only on Java 8.
29 * <p>
30 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
31 * </p>
32 */
33 @RunWith(Suite.class)
34 @Suite.SuiteClasses({ MongoDbTestTestRuleTestJava8.class, MongoDbAuthFailureTestJava8.class, MongoDbCappedTestJava8.class,
35 MongoDbMapMessageTestJava8.class, MongoDbTestJava8.class })
36 public class Java8Test {
37
38 @BeforeClass
39 public static void beforeClass() {
40 Assume.assumeTrue(SystemUtils.JAVA_VERSION, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
41 }
42
43 @Test
44 public void test() {
45 // noop
46 }
47 }
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.mongodb2;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb2.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.junit.Assert;
26 import org.junit.ClassRule;
27 import org.junit.Ignore;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.DB;
33 import com.mongodb.DBCollection;
34 import com.mongodb.MongoClient;
35
36 /**
37 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
38 *
39 * TODO Set up the log4j user in MongoDB.
40 */
41 @Ignore("TODO Set up the log4j user in MongoDB")
42 @Category(Appenders.MongoDb.class)
43 public class MongoDbAuthFailureTestJava8 {
44
45 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-auth-failure.xml");
46
47 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
48 .create(TestConstants.SYS_PROP_NAME_PORT);
49
50 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(), LoggingTarget.NULL);
51
52 @ClassRule
53 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
54 loggerContextTestRule);
55
56 @Test
57 public void test() {
58 final Logger logger = LogManager.getLogger();
59 logger.info("Hello log");
60 final MongoClient mongoClient = mongoDbTestRule.getMongoClient();
61 try {
62 final DB database = mongoClient.getDB("test");
63 Assert.assertNotNull(database);
64 final DBCollection collection = database.getCollection("applog");
65 Assert.assertNotNull(collection);
66 Assert.assertFalse(collection.find().hasNext());
67 } finally {
68 mongoClient.close();
69 }
70 }
71 }
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.mongodb2;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb2.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.junit.Assert;
26 import org.junit.ClassRule;
27 import org.junit.Test;
28 import org.junit.experimental.categories.Category;
29 import org.junit.rules.RuleChain;
30
31 import com.mongodb.DB;
32 import com.mongodb.DBCollection;
33 import com.mongodb.DBObject;
34 import com.mongodb.MongoClient;
35
36 /**
37 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDbCappedTestJava8 {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-capped.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(), LoggingTarget.NULL);
48
49 @ClassRule
50 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
51 loggerContextTestRule);
52
53 @Test
54 public void test() {
55 final Logger logger = LogManager.getLogger();
56 logger.info("Hello log");
57 final MongoClient mongoClient = mongoDbTestRule.getMongoClient();
58 try {
59 final DB database = mongoClient.getDB("test");
60 Assert.assertNotNull(database);
61 final DBCollection collection = database.getCollection("applog");
62 Assert.assertNotNull(collection);
63 Assert.assertTrue(collection.find().hasNext());
64 final DBObject first = collection.find().next();
65 Assert.assertNotNull(first);
66 Assert.assertEquals(first.toMap().toString(), "Hello log", first.get("message"));
67 } finally {
68 mongoClient.close();
69 }
70 }
71 }
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.mongodb2;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.message.MapMessage;
23 import org.apache.logging.log4j.mongodb2.MongoDbTestRule.LoggingTarget;
24 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
25 import org.apache.logging.log4j.test.RuleChainFactory;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.DB;
33 import com.mongodb.DBCollection;
34 import com.mongodb.DBObject;
35 import com.mongodb.MongoClient;
36
37 /**
38 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
39 */
40 @Category(Appenders.MongoDb.class)
41 public class MongoDbMapMessageTestJava8 {
42
43 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-map-message.xml");
44
45 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
46 .create(TestConstants.SYS_PROP_NAME_PORT);
47
48 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(), LoggingTarget.NULL);
49
50 @ClassRule
51 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
52 loggerContextTestRule);
53
54 @Test
55 public void test() {
56 final Logger logger = LogManager.getLogger();
57 final MapMessage mapMessage = new MapMessage();
58 mapMessage.with("SomeName", "SomeValue");
59 mapMessage.with("SomeInt", 1);
60 logger.info(mapMessage);
61 //
62 final MongoClient mongoClient = mongoDbTestRule.getMongoClient();
63 try {
64 final DB database = mongoClient.getDB("test");
65 Assert.assertNotNull(database);
66 final DBCollection collection = database.getCollection("applog");
67 Assert.assertNotNull(collection);
68 final DBObject first = collection.find().next();
69 Assert.assertNotNull(first);
70 final String firstMapString = first.toMap().toString();
71 Assert.assertEquals(firstMapString, "SomeValue", first.get("SomeName"));
72 Assert.assertEquals(firstMapString, Integer.valueOf(1), first.get("SomeInt"));
73 } finally {
74 mongoClient.close();
75 }
76 }
77 }
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.mongodb2;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb2.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.junit.Assert;
26 import org.junit.ClassRule;
27 import org.junit.Test;
28 import org.junit.experimental.categories.Category;
29 import org.junit.rules.RuleChain;
30
31 import com.mongodb.DB;
32 import com.mongodb.DBCollection;
33 import com.mongodb.DBObject;
34 import com.mongodb.MongoClient;
35
36 /**
37 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDbTestJava8 {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(), LoggingTarget.NULL);
48
49 @ClassRule
50 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
51 loggerContextTestRule);
52
53 @Test
54 public void test() {
55 final Logger logger = LogManager.getLogger();
56 logger.info("Hello log");
57 final MongoClient mongoClient = mongoDbTestRule.getMongoClient();
58 try {
59 final DB database = mongoClient.getDB("test");
60 Assert.assertNotNull(database);
61 final DBCollection collection = database.getCollection("applog");
62 Assert.assertNotNull(collection);
63 final DBObject first = collection.find().next();
64 Assert.assertNotNull(first);
65 Assert.assertEquals(first.toMap().toString(), "Hello log", first.get("message"));
66 } finally {
67 mongoClient.close();
68 }
69 }
70 }
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
17 package org.apache.logging.log4j.mongodb2;
18
19 import java.util.Objects;
20
21 import org.apache.commons.lang3.NotImplementedException;
22 import org.junit.rules.TestRule;
23 import org.junit.runner.Description;
24 import org.junit.runners.model.Statement;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import com.mongodb.MongoClient;
29
30 import de.flapdoodle.embed.mongo.Command;
31 import de.flapdoodle.embed.mongo.MongodExecutable;
32 import de.flapdoodle.embed.mongo.MongodProcess;
33 import de.flapdoodle.embed.mongo.MongodStarter;
34 import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
35 import de.flapdoodle.embed.mongo.config.Net;
36 import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
37 import de.flapdoodle.embed.mongo.config.Timeout;
38 import de.flapdoodle.embed.mongo.distribution.Version;
39 import de.flapdoodle.embed.process.config.IRuntimeConfig;
40 import de.flapdoodle.embed.process.config.io.ProcessOutput;
41 import de.flapdoodle.embed.process.runtime.Network;
42
43 /**
44 * A JUnit test rule to manage a MongoDB embedded instance.
45 *
46 * TODO Move this class to Apache Commons Testing.
47 */
48 public class MongoDbTestRule implements TestRule {
49
50 public enum LoggingTarget {
51 NULL, CONSOLE
52 }
53
54 private static final int BUILDER_TIMEOUT_MILLIS = 30000;
55
56 public static int getBuilderTimeoutMillis() {
57 return BUILDER_TIMEOUT_MILLIS;
58 }
59
60 /**
61 * Store {@link MongodStarter} (or RuntimeConfig) in a static final field if you want to use artifact store caching
62 * (or else disable caching).
63 * <p>
64 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
65 * </p>
66 */
67 protected final MongodStarter starter;
68
69 protected final String portSystemPropertyName;
70
71 protected MongoClient mongoClient;
72 protected MongodExecutable mongodExecutable;
73 protected MongodProcess mongodProcess;
74 protected final LoggingTarget loggingTarget;
75
76 /**
77 * Constructs a new test rule.
78 *
79 * @param portSystemPropertyName
80 * The system property name for the MongoDB port.
81 * @param loggingTarget
82 * The logging target
83 */
84 public MongoDbTestRule(final String portSystemPropertyName, final LoggingTarget loggingTarget) {
85 this.portSystemPropertyName = Objects.requireNonNull(portSystemPropertyName, "portSystemPropertyName");
86 this.loggingTarget = loggingTarget;
87 this.starter = getMongodStarter(loggingTarget);
88 }
89
90 private static MongodStarter getMongodStarter(final LoggingTarget loggingTarget) {
91 if (loggingTarget == null) {
92 return MongodStarter.getDefaultInstance();
93 }
94 switch (loggingTarget) {
95 case NULL:
96 final Logger logger = LoggerFactory.getLogger(MongoDbTestRule.class.getName());
97 final IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
98 // @formatter:off
99 .defaultsWithLogger(Command.MongoD, logger)
100 .processOutput(ProcessOutput.getDefaultInstanceSilent())
101 .build();
102 // @formatter:on
103
104 return MongodStarter.getInstance(runtimeConfig);
105 case CONSOLE:
106 return MongodStarter.getDefaultInstance();
107 default:
108 throw new NotImplementedException(loggingTarget.toString());
109 }
110 }
111
112 @Override
113 public Statement apply(final Statement base, final Description description) {
114 return new Statement() {
115
116 @Override
117 public void evaluate() throws Throwable {
118 final String value = Objects.requireNonNull(System.getProperty(portSystemPropertyName),
119 "System property '" + portSystemPropertyName + "' is null");
120 final int port = Integer.parseInt(value);
121 mongodExecutable = starter.prepare(
122 // @formatter:off
123 new MongodConfigBuilder()
124 .version(Version.Main.PRODUCTION)
125 .timeout(new Timeout(BUILDER_TIMEOUT_MILLIS))
126 .net(
127 new Net("localhost", port, Network.localhostIsIPv6()))
128 .build());
129 // @formatter:on
130 mongodProcess = mongodExecutable.start();
131 mongoClient = new MongoClient("localhost", port);
132 try {
133 base.evaluate();
134 } finally {
135 if (mongodProcess != null) {
136 mongodProcess.stop();
137 mongodProcess = null;
138 }
139 if (mongodExecutable != null) {
140 mongodExecutable.stop();
141 mongodExecutable = null;
142 }
143 }
144 }
145 };
146 }
147
148 public MongoClient getMongoClient() {
149 return mongoClient;
150 }
151
152 public MongodExecutable getMongodExecutable() {
153 return mongodExecutable;
154 }
155
156 public MongodProcess getMongodProcess() {
157 return mongodProcess;
158 }
159
160 public MongodStarter getStarter() {
161 return starter;
162 }
163
164 @Override
165 public String toString() {
166 final StringBuilder builder = new StringBuilder();
167 builder.append("MongoDbTestRule [starter=");
168 builder.append(starter);
169 builder.append(", portSystemPropertyName=");
170 builder.append(portSystemPropertyName);
171 builder.append(", mongoClient=");
172 builder.append(mongoClient);
173 builder.append(", mongodExecutable=");
174 builder.append(mongodExecutable);
175 builder.append(", mongodProcess=");
176 builder.append(mongodProcess);
177 builder.append(", loggingTarget=");
178 builder.append(loggingTarget);
179 builder.append("]");
180 return builder.toString();
181 }
182
183 }
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
17 package org.apache.logging.log4j.mongodb2;
18
19 import java.util.List;
20
21 import org.apache.commons.lang3.JavaVersion;
22 import org.apache.commons.lang3.SystemUtils;
23 import org.apache.logging.log4j.mongodb2.MongoDbTestRule.LoggingTarget;
24 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
25 import org.apache.logging.log4j.test.RuleChainFactory;
26 import org.junit.Assert;
27 import org.junit.Assume;
28 import org.junit.BeforeClass;
29 import org.junit.ClassRule;
30 import org.junit.Test;
31 import org.junit.rules.RuleChain;
32
33 /**
34 * Tests {@link MongoDbTestRule}. This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
35 * <p>
36 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
37 * </p>
38 */
39 public class MongoDbTestTestRuleTestJava8 {
40
41 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
42 .create(TestConstants.SYS_PROP_NAME_PORT);
43
44 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(), LoggingTarget.NULL);
45
46 @ClassRule
47 public static RuleChain mongoDbChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule);
48
49 @BeforeClass
50 public static void beforeClass() {
51 Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
52 }
53
54 @Test
55 public void testAccess() {
56 final List<String> databaseNames = mongoDbTestRule.getMongoClient().getDatabaseNames();
57 Assert.assertNotNull(databaseNames);
58 Assert.assertFalse(databaseNames.isEmpty());
59 Assert.assertNotNull(databaseNames.get(0));
60 }
61
62 @Test
63 public void testMongoDbTestRule() {
64 Assert.assertNotNull(mongoDbTestRule);
65 Assert.assertNotNull(mongoDbTestRule.getStarter());
66 Assert.assertNotNull(mongoDbTestRule.getMongoClient());
67 Assert.assertNotNull(mongoDbTestRule.getMongodExecutable());
68 Assert.assertNotNull(mongoDbTestRule.getMongodProcess());
69 }
70 }
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
17 package org.apache.logging.log4j.mongodb2;
18
19 public class TestConstants {
20
21 public static final String SYS_PROP_NAME_PORT = "MongoDBTestPort";
22
23 }
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb2 databaseName="test" collectionName="applog" server="localhost" userName="log4jUser" password="12345678"
22 port="${sys:MongoDBTestPort:-27017}" />
23 </NoSql>
24 </Appenders>
25 <Loggers>
26 <Root level="ALL">
27 <AppenderRef ref="MongoDbAppender" />
28 </Root>
29 </Loggers>
30 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb2 databaseName="test" collectionName="applog" server="localhost" capped="true" collectionSize="1073741824"
22 port="${sys:MongoDBTestPort:-27017}" />
23 </NoSql>
24 </Appenders>
25 <Loggers>
26 <Root level="ALL">
27 <AppenderRef ref="MongoDbAppender" />
28 </Root>
29 </Loggers>
30 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb2 databaseName="test" collectionName="applog" server="localhost"
22 port="${sys:MongoDBTestPort:-27017}" />
23 <MessageLayout />
24 </NoSql>
25 </Appenders>
26 <Loggers>
27 <Root level="ALL">
28 <AppenderRef ref="MongoDbAppender" />
29 </Root>
30 </Loggers>
31 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb2 databaseName="test" collectionName="applog" server="localhost"
22 port="${sys:MongoDBTestPort:-27017}" />
23 </NoSql>
24 </Appenders>
25 <Loggers>
26 <Root level="ALL">
27 <AppenderRef ref="MongoDbAppender" />
28 </Root>
29 </Loggers>
30 </Configuration>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
3333 <docLabel>MongoDB 3 Documentation</docLabel>
3434 <projectDir>/log4j-mongodb3</projectDir>
3535 <module.name>org.apache.logging.log4j.mongodb3</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
3736 </properties>
3837
3938 <dependencies>
4443 <dependency>
4544 <groupId>org.mongodb</groupId>
4645 <artifactId>mongodb-driver</artifactId>
47 <version>${mongodb3.version}</version>
4846 </dependency>
4947 <dependency>
5048 <groupId>org.mongodb</groupId>
5149 <artifactId>bson</artifactId>
52 <version>${mongodb3.version}</version>
5350 </dependency>
5451 <!-- Test Dependencies -->
5552 <dependency>
56 <groupId>org.junit.vintage</groupId>
57 <artifactId>junit-vintage-engine</artifactId>
58 </dependency>
59 <dependency>
60 <groupId>org.junit.jupiter</groupId>
61 <artifactId>junit-jupiter-engine</artifactId>
53 <groupId>junit</groupId>
54 <artifactId>junit</artifactId>
6255 </dependency>
6356 <dependency>
6457 <groupId>org.mockito</groupId>
6962 <groupId>org.apache.logging.log4j</groupId>
7063 <artifactId>log4j-api</artifactId>
7164 <type>test-jar</type>
72 <scope>test</scope>
7365 </dependency>
7466 <dependency>
7567 <groupId>org.apache.logging.log4j</groupId>
7668 <artifactId>log4j-core</artifactId>
7769 <type>test-jar</type>
70 </dependency>
71 <dependency>
72 <groupId>org.apache.logging.log4j</groupId>
73 <artifactId>log4j-slf4j-impl</artifactId>
7874 <scope>test</scope>
7975 </dependency>
8076 <dependency>
160156 </reportSets>
161157 </plugin>
162158 <plugin>
163 <groupId>com.github.spotbugs</groupId>
164 <artifactId>spotbugs-maven-plugin</artifactId>
159 <groupId>org.codehaus.mojo</groupId>
160 <artifactId>findbugs-maven-plugin</artifactId>
161 <version>${findbugs.plugin.version}</version>
162 <configuration>
163 <fork>true</fork>
164 <jvmArgs>-Duser.language=en</jvmArgs>
165 <threshold>Normal</threshold>
166 <effort>Default</effort>
167 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
168 </configuration>
165169 </plugin>
166170 <plugin>
167171 <groupId>org.apache.maven.plugins</groupId>
2828 */
2929 public class LevelCodec implements Codec<Level> {
3030
31 /**
32 * The singleton instance.
33 *
34 * @since 2.14.0
35 */
36 public static final LevelCodec INSTANCE = new LevelCodec();
37
3831 @Override
3932 public Level decode(final BsonReader reader, final DecoderContext decoderContext) {
4033 return Level.getLevel(reader.readString());
1515 */
1616 package org.apache.logging.log4j.mongodb3;
1717
18 import org.apache.logging.log4j.Level;
1819 import org.apache.logging.log4j.Logger;
1920 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
2021 import org.apache.logging.log4j.core.appender.nosql.AbstractNoSqlConnection;
2122 import org.apache.logging.log4j.core.appender.nosql.NoSqlConnection;
2223 import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
2324 import org.apache.logging.log4j.status.StatusLogger;
25 import org.bson.BSON;
2426 import org.bson.Document;
27 import org.bson.Transformer;
2528
2629 import com.mongodb.MongoClient;
2730 import com.mongodb.MongoException;
3538 public final class MongoDbConnection extends AbstractNoSqlConnection<Document, MongoDbDocumentObject> {
3639
3740 private static final Logger LOGGER = StatusLogger.getLogger();
41
42 static {
43 BSON.addEncodingHook(Level.class, new Transformer() {
44 @Override
45 public Object transform(final Object o) {
46 if (o instanceof Level) {
47 return ((Level) o).name();
48 }
49 return o;
50 }
51 });
52 }
3853
3954 private static MongoCollection<Document> getOrCreateMongoCollection(final MongoDatabase database,
4055 final String collectionName, final boolean isCapped, final Integer sizeInBytes) {
2929 import org.apache.logging.log4j.core.config.plugins.validation.constraints.ValidHost;
3030 import org.apache.logging.log4j.core.config.plugins.validation.constraints.ValidPort;
3131 import org.apache.logging.log4j.core.filter.AbstractFilterable;
32 import org.apache.logging.log4j.core.util.NameUtil;
3233 import org.apache.logging.log4j.status.StatusLogger;
3334 import org.apache.logging.log4j.util.LoaderUtil;
3435 import org.apache.logging.log4j.util.Strings;
3536 import org.bson.codecs.configuration.CodecRegistries;
36 import org.bson.codecs.configuration.CodecRegistry;
3737
3838 import com.mongodb.MongoClient;
3939 import com.mongodb.MongoClientOptions;
4343 import com.mongodb.client.MongoDatabase;
4444
4545 /**
46 * The MongoDB implementation of {@link NoSqlProvider}.using the MongoDB driver version 3 API.
46 * The MongoDB implementation of {@link NoSqlProvider}.
4747 */
4848 @Plugin(name = "MongoDb3", category = Core.CATEGORY_NAME, printObject = true)
4949 public final class MongoDbProvider implements NoSqlProvider<MongoDbConnection> {
5050
5151 public static class Builder<B extends Builder<B>> extends AbstractFilterable.Builder<B>
5252 implements org.apache.logging.log4j.core.util.Builder<MongoDbProvider> {
53
54 // @formatter:off
55 private static final CodecRegistry CODEC_REGISTRIES = CodecRegistries.fromRegistries(
56 CodecRegistries.fromCodecs(LevelCodec.INSTANCE),
57 MongoClient.getDefaultCodecRegistry());
58 // @formatter:on
5953
6054 private static WriteConcern toWriteConcern(final String writeConcernConstant,
6155 final String writeConcernConstantClassName) {
147141 + "required.", factoryClassName, factoryMethodName);
148142 return null;
149143 }
144 } else if (object == null) {
145 LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName,
146 factoryMethodName);
147 return null;
150148 } else {
151 if (object == null) {
152 LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName,
153 factoryMethodName);
154 } else {
155 LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].",
156 factoryClassName, factoryMethodName, object.getClass().getName());
157 }
149 LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].",
150 factoryClassName, factoryMethodName, object.getClass().getName());
158151 return null;
159152 }
160153
176169 MongoCredential mongoCredential = null;
177170 description = "database=" + databaseName;
178171 if (Strings.isNotEmpty(userName) && Strings.isNotEmpty(password)) {
179 description += ", username=" + userName;
172 description += ", username=" + userName + ", passwordHash="
173 + NameUtil.md5(password + MongoDbProvider.class.getName());
180174 mongoCredential = MongoCredential.createCredential(userName, databaseName, password.toCharArray());
181175 }
182176 try {
185179 final WriteConcern writeConcern = toWriteConcern(writeConcernConstant, writeConcernConstantClassName);
186180 // @formatter:off
187181 final MongoClientOptions options = MongoClientOptions.builder()
188 .codecRegistry(CODEC_REGISTRIES)
182 .codecRegistry(CodecRegistries.fromRegistries(
183 CodecRegistries.fromCodecs(new LevelCodec()),
184 MongoClient.getDefaultCodecRegistry()))
189185 .writeConcern(writeConcern)
190186 .build();
191187 // @formatter:on
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
17 package org.apache.logging.log4j.mongodb3;
18
19 import org.apache.commons.lang3.JavaVersion;
20 import org.apache.commons.lang3.SystemUtils;
21 import org.junit.Assume;
22 import org.junit.BeforeClass;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.junit.runners.Suite;
26
27 /**
28 * Runs all MongoDB only on Java 8.
29 * <p>
30 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
31 * </p>
32 */
33 @RunWith(Suite.class)
34 @Suite.SuiteClasses({ MongoDbTestTestRuleTestJava8.class, MongoDbAuthFailureTestJava8.class, MongoDbCappedTestJava8.class,
35 MongoDbMapMessageTestJava8.class, MongoDbTestJava8.class })
36 public class Java8Test {
37
38 @BeforeClass
39 public static void beforeClass() {
40 Assume.assumeTrue(SystemUtils.JAVA_VERSION, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
41 }
42
43 @Test
44 public void test() {
45 // noop
46 }
47 }
+0
-72
log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDbAuthFailureTest.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.logging.log4j.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Ignore;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import org.junit.rules.RuleChain;
32
33 import com.mongodb.MongoClient;
34 import com.mongodb.client.MongoCollection;
35 import com.mongodb.client.MongoDatabase;
36
37 /**
38 *
39 *
40 * TODO Set up the log4j user in MongoDB.
41 */
42 @Ignore("TODO Set up the log4j user in MongoDB")
43 @Category(Appenders.MongoDb.class)
44 public class MongoDbAuthFailureTest {
45
46 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-auth-failure.xml");
47
48 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
49 .create(TestConstants.SYS_PROP_NAME_PORT);
50
51 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
52 MongoDbAuthFailureTest.class, LoggingTarget.NULL);
53
54 @ClassRule
55 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
56 loggerContextTestRule);
57
58 @Test
59 public void test() {
60 final Logger logger = LogManager.getLogger();
61 logger.info("Hello log");
62 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
63 final MongoDatabase database = mongoClient.getDatabase("test");
64 Assert.assertNotNull(database);
65 final MongoCollection<Document> collection = database.getCollection("applog");
66 Assert.assertNotNull(collection);
67 final Document first = collection.find().first();
68 Assert.assertNull(first);
69 }
70 }
71 }
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.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Ignore;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import org.junit.rules.RuleChain;
32
33 import com.mongodb.MongoClient;
34 import com.mongodb.client.MongoCollection;
35 import com.mongodb.client.MongoDatabase;
36
37 /**
38 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
39 *
40 * TODO Set up the log4j user in MongoDB.
41 */
42 @Ignore("TODO Set up the log4j user in MongoDB")
43 @Category(Appenders.MongoDb.class)
44 public class MongoDbAuthFailureTestJava8 {
45
46 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-auth-failure.xml");
47
48 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
49 .create(TestConstants.SYS_PROP_NAME_PORT);
50
51 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
52 MongoDbAuthFailureTestJava8.class, LoggingTarget.NULL);
53
54 @ClassRule
55 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
56 loggerContextTestRule);
57
58 @Test
59 public void test() {
60 final Logger logger = LogManager.getLogger();
61 logger.info("Hello log");
62 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
63 final MongoDatabase database = mongoClient.getDatabase("test");
64 Assert.assertNotNull(database);
65 final MongoCollection<Document> collection = database.getCollection("applog");
66 Assert.assertNotNull(collection);
67 final Document first = collection.find().first();
68 Assert.assertNull(first);
69 }
70 }
71 }
+0
-69
log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDbCappedTest.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.logging.log4j.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.MongoClient;
33 import com.mongodb.client.MongoCollection;
34 import com.mongodb.client.MongoDatabase;
35
36 /**
37 *
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDbCappedTest {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-capped.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
48 MongoDbCappedTest.class, LoggingTarget.NULL);
49
50 @ClassRule
51 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
52 loggerContextTestRule);
53
54 @Test
55 public void test() {
56 final Logger logger = LogManager.getLogger();
57 logger.info("Hello log");
58 @SuppressWarnings("resource") // Mongo client is managed by the test rule.
59 final MongoClient mongoClient = mongoDbTestRule.getMongoClient();
60 final MongoDatabase database = mongoClient.getDatabase("test");
61 Assert.assertNotNull(database);
62 final MongoCollection<Document> collection = database.getCollection("applog");
63 Assert.assertNotNull(collection);
64 final Document first = collection.find().first();
65 Assert.assertNotNull(first);
66 Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
67 }
68 }
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.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.MongoClient;
33 import com.mongodb.client.MongoCollection;
34 import com.mongodb.client.MongoDatabase;
35
36 /**
37 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDbCappedTestJava8 {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-capped.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
48 MongoDbCappedTestJava8.class, LoggingTarget.NULL);
49
50 @ClassRule
51 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
52 loggerContextTestRule);
53
54 @Test
55 public void test() {
56 final Logger logger = LogManager.getLogger();
57 logger.info("Hello log");
58 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
59 final MongoDatabase database = mongoClient.getDatabase("test");
60 Assert.assertNotNull(database);
61 final MongoCollection<Document> collection = database.getCollection("applog");
62 Assert.assertNotNull(collection);
63 final Document first = collection.find().first();
64 Assert.assertNotNull(first);
65 Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
66 }
67 }
68 }
+0
-76
log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDbMapMessageTest.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.logging.log4j.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.message.MapMessage;
23 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
24 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
25 import org.apache.logging.log4j.test.RuleChainFactory;
26 import org.bson.Document;
27 import org.junit.Assert;
28 import org.junit.ClassRule;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import org.junit.rules.RuleChain;
32
33 import com.mongodb.MongoClient;
34 import com.mongodb.client.MongoCollection;
35 import com.mongodb.client.MongoDatabase;
36
37 /**
38 *
39 */
40 @Category(Appenders.MongoDb.class)
41 public class MongoDbMapMessageTest {
42
43 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-map-message.xml");
44
45 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
46 .create(TestConstants.SYS_PROP_NAME_PORT);
47
48 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
49 MongoDbMapMessageTest.class, LoggingTarget.NULL);
50
51 @ClassRule
52 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
53 loggerContextTestRule);
54
55 @Test
56 public void test() {
57 final Logger logger = LogManager.getLogger();
58 final MapMessage<?, Object> mapMessage = new MapMessage<>();
59 mapMessage.with("SomeName", "SomeValue");
60 mapMessage.with("SomeInt", 1);
61 logger.info(mapMessage);
62 //
63 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
64 final MongoDatabase database = mongoClient.getDatabase("test");
65 Assert.assertNotNull(database);
66 final MongoCollection<Document> collection = database.getCollection("applog");
67 Assert.assertNotNull(collection);
68 final Document first = collection.find().first();
69 Assert.assertNotNull(first);
70 final String firstJson = first.toJson();
71 Assert.assertEquals(firstJson, "SomeValue", first.getString("SomeName"));
72 Assert.assertEquals(firstJson, Integer.valueOf(1), first.getInteger("SomeInt"));
73 }
74 }
75 }
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.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.message.MapMessage;
23 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
24 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
25 import org.apache.logging.log4j.test.RuleChainFactory;
26 import org.bson.Document;
27 import org.junit.Assert;
28 import org.junit.ClassRule;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import org.junit.rules.RuleChain;
32
33 import com.mongodb.MongoClient;
34 import com.mongodb.client.MongoCollection;
35 import com.mongodb.client.MongoDatabase;
36
37 /**
38 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
39 */
40 @Category(Appenders.MongoDb.class)
41 public class MongoDbMapMessageTestJava8 {
42
43 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-map-message.xml");
44
45 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
46 .create(TestConstants.SYS_PROP_NAME_PORT);
47
48 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
49 MongoDbMapMessageTestJava8.class, LoggingTarget.NULL);
50
51 @ClassRule
52 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
53 loggerContextTestRule);
54
55 @Test
56 public void test() {
57 final Logger logger = LogManager.getLogger();
58 final MapMessage mapMessage = new MapMessage();
59 mapMessage.with("SomeName", "SomeValue");
60 mapMessage.with("SomeInt", 1);
61 logger.info(mapMessage);
62 //
63 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
64 final MongoDatabase database = mongoClient.getDatabase("test");
65 Assert.assertNotNull(database);
66 final MongoCollection<Document> collection = database.getCollection("applog");
67 Assert.assertNotNull(collection);
68 final Document first = collection.find().first();
69 Assert.assertNotNull(first);
70 final String firstJson = first.toJson();
71 Assert.assertEquals(firstJson, "SomeValue", first.getString("SomeName"));
72 Assert.assertEquals(firstJson, Integer.valueOf(1), first.getInteger("SomeInt"));
73 }
74 }
75 }
+0
-70
log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDbTest.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.logging.log4j.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.MongoClient;
33 import com.mongodb.client.MongoCollection;
34 import com.mongodb.client.MongoDatabase;
35
36 /**
37 *
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDbTest {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
48 MongoDbTest.class, LoggingTarget.NULL);
49
50 @ClassRule
51 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
52 loggerContextTestRule);
53
54 @Test
55 public void test() {
56 final Logger logger = LogManager.getLogger();
57 logger.info("Hello log");
58 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
59 final MongoDatabase database = mongoClient.getDatabase("test");
60 Assert.assertNotNull(database);
61 final MongoCollection<Document> collection = database.getCollection("applog");
62 Assert.assertNotNull(collection);
63 final Document first = collection.find().first();
64 Assert.assertNotNull(first);
65 Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
66 Assert.assertEquals(first.toJson(), "INFO", first.getString("level"));
67 }
68 }
69 }
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.mongodb3;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.MongoClient;
33 import com.mongodb.client.MongoCollection;
34 import com.mongodb.client.MongoDatabase;
35
36 /**
37 * This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDbTestJava8 {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
48 MongoDbTestJava8.class, LoggingTarget.NULL);
49
50 @ClassRule
51 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
52 loggerContextTestRule);
53
54 @Test
55 public void test() {
56 final Logger logger = LogManager.getLogger();
57 logger.info("Hello log");
58 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
59 final MongoDatabase database = mongoClient.getDatabase("test");
60 Assert.assertNotNull(database);
61 final MongoCollection<Document> collection = database.getCollection("applog");
62 Assert.assertNotNull(collection);
63 final Document first = collection.find().first();
64 Assert.assertNotNull(first);
65 Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
66 }
67 }
68 }
3131 import de.flapdoodle.embed.mongo.MongodExecutable;
3232 import de.flapdoodle.embed.mongo.MongodProcess;
3333 import de.flapdoodle.embed.mongo.MongodStarter;
34 import de.flapdoodle.embed.mongo.config.Defaults;
35 import de.flapdoodle.embed.mongo.config.MongodConfig;
34 import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
3635 import de.flapdoodle.embed.mongo.config.Net;
36 import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
3737 import de.flapdoodle.embed.mongo.config.Timeout;
3838 import de.flapdoodle.embed.mongo.distribution.Version;
39 import de.flapdoodle.embed.process.config.IRuntimeConfig;
3940 import de.flapdoodle.embed.process.config.io.ProcessOutput;
4041 import de.flapdoodle.embed.process.runtime.Network;
4142
6768 switch (loggingTarget) {
6869 case NULL:
6970 final Logger logger = LoggerFactory.getLogger(MongoDbTestRule.class.getName());
71 final IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
7072 // @formatter:off
71 return MongodStarter.getInstance(
72 Defaults
73 .runtimeConfigFor(Command.MongoD, logger)
74 .processOutput(ProcessOutput.getDefaultInstanceSilent()).build());
73 .defaultsWithLogger(Command.MongoD, logger)
74 .processOutput(ProcessOutput.getDefaultInstanceSilent())
75 .build();
7576 // @formatter:on
77
78 return MongodStarter.getInstance(runtimeConfig);
7679 case CONSOLE:
7780 return MongodStarter.getDefaultInstance();
7881 default:
125128 final int port = Integer.parseInt(value);
126129 mongodExecutable = starter.prepare(
127130 // @formatter:off
128 MongodConfig.builder()
131 new MongodConfigBuilder()
129132 .version(Version.Main.PRODUCTION)
130133 .timeout(new Timeout(BUILDER_TIMEOUT_MILLIS))
131 .net(new Net("localhost", port, Network.localhostIsIPv6()))
134 .net(
135 new Net("localhost", port, Network.localhostIsIPv6()))
132136 .build());
133137 // @formatter:on
134138 mongodProcess = mongodExecutable.start();
+0
-75
log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDbTestTestRuleTest.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
17 package org.apache.logging.log4j.mongodb3;
18
19 import org.apache.commons.lang3.JavaVersion;
20 import org.apache.commons.lang3.SystemUtils;
21 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
22 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
23 import org.apache.logging.log4j.test.RuleChainFactory;
24 import org.junit.Assert;
25 import org.junit.Assume;
26 import org.junit.BeforeClass;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.rules.RuleChain;
30
31 import com.mongodb.MongoClient;
32 import com.mongodb.client.MongoIterable;
33
34 /**
35 * Tests MongoDbRule.
36 * <p>
37 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
38 * </p>
39 */
40 public class MongoDbTestTestRuleTest {
41
42 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
43 .create(TestConstants.SYS_PROP_NAME_PORT);
44
45 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
46 MongoDbTestTestRuleTest.class, LoggingTarget.NULL);
47
48 @ClassRule
49 public static RuleChain mongoDbChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule);
50
51 @BeforeClass
52 public static void beforeClass() {
53 Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
54 }
55
56 @Test
57 public void testAccess() {
58 @SuppressWarnings("resource") // Mongo client is managed by the test rule.
59 final MongoIterable<String> databaseNames = mongoDbTestRule.getMongoClient().listDatabaseNames();
60 Assert.assertNotNull(databaseNames);
61 Assert.assertNotNull(databaseNames.first());
62 }
63
64 @Test
65 public void testMongoDbTestRule() {
66 Assert.assertNotNull(mongoDbTestRule);
67 Assert.assertNotNull(mongoDbTestRule.getStarter());
68 @SuppressWarnings("resource") // Mongo client is managed by the test rule.
69 final MongoClient mongoClient = mongoDbTestRule.getMongoClient();
70 Assert.assertNotNull(mongoClient);
71 Assert.assertNotNull(mongoDbTestRule.getMongodExecutable());
72 Assert.assertNotNull(mongoDbTestRule.getMongodProcess());
73 }
74 }
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
17 package org.apache.logging.log4j.mongodb3;
18
19 import org.apache.commons.lang3.JavaVersion;
20 import org.apache.commons.lang3.SystemUtils;
21 import org.apache.logging.log4j.mongodb3.MongoDbTestRule.LoggingTarget;
22 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
23 import org.apache.logging.log4j.test.RuleChainFactory;
24 import org.junit.Assert;
25 import org.junit.Assume;
26 import org.junit.BeforeClass;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.rules.RuleChain;
30
31 import com.mongodb.client.MongoIterable;
32
33 /**
34 * Tests MongoDbRule. This class name does NOT end in "Test" in order to only be picked up by {@link Java8Test}.
35 * <p>
36 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
37 * </p>
38 */
39 public class MongoDbTestTestRuleTestJava8 {
40
41 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
42 .create(TestConstants.SYS_PROP_NAME_PORT);
43
44 private static final MongoDbTestRule mongoDbTestRule = new MongoDbTestRule(mongoDbPortTestRule.getName(),
45 MongoDbTestTestRuleTestJava8.class, LoggingTarget.NULL);
46
47 @ClassRule
48 public static RuleChain mongoDbChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule);
49
50 @BeforeClass
51 public static void beforeClass() {
52 Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
53 }
54
55 @Test
56 public void testAccess() {
57 final MongoIterable<String> databaseNames = mongoDbTestRule.getMongoClient().listDatabaseNames();
58 Assert.assertNotNull(databaseNames);
59 Assert.assertNotNull(databaseNames.first());
60 }
61
62 @Test
63 public void testMongoDbTestRule() {
64 Assert.assertNotNull(mongoDbTestRule);
65 Assert.assertNotNull(mongoDbTestRule.getStarter());
66 Assert.assertNotNull(mongoDbTestRule.getMongoClient());
67 Assert.assertNotNull(mongoDbTestRule.getMongodExecutable());
68 Assert.assertNotNull(mongoDbTestRule.getMongodProcess());
69 }
70 }
+0
-196
log4j-mongodb4/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache License, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License.
16 -->
17
18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19 <parent>
20 <groupId>org.apache.logging.log4j</groupId>
21 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
23 </parent>
24 <modelVersion>4.0.0</modelVersion>
25
26 <artifactId>log4j-mongodb4</artifactId>
27 <name>Apache Log4j MongoDB 4</name>
28 <description>
29 MongoDB appender for Log4j using the MongoDB 4 driver API.
30 </description>
31 <properties>
32 <log4jParentDir>${basedir}/..</log4jParentDir>
33 <docLabel>MongoDB 4 Documentation</docLabel>
34 <projectDir>/log4j-mongodb4</projectDir>
35 <module.name>org.apache.logging.log4j.mongodb4</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
37 </properties>
38
39 <dependencies>
40 <dependency>
41 <groupId>org.apache.logging.log4j</groupId>
42 <artifactId>log4j-core</artifactId>
43 </dependency>
44 <dependency>
45 <groupId>org.mongodb</groupId>
46 <artifactId>mongodb-driver-sync</artifactId>
47 <version>${mongodb4.version}</version>
48 </dependency>
49 <dependency>
50 <groupId>org.mongodb</groupId>
51 <artifactId>bson</artifactId>
52 <version>${mongodb4.version}</version>
53 </dependency>
54 <!-- Test Dependencies -->
55 <dependency>
56 <groupId>org.junit.vintage</groupId>
57 <artifactId>junit-vintage-engine</artifactId>
58 </dependency>
59 <dependency>
60 <groupId>org.junit.jupiter</groupId>
61 <artifactId>junit-jupiter-engine</artifactId>
62 </dependency>
63 <dependency>
64 <groupId>org.mockito</groupId>
65 <artifactId>mockito-core</artifactId>
66 <scope>test</scope>
67 </dependency>
68 <dependency>
69 <groupId>org.apache.logging.log4j</groupId>
70 <artifactId>log4j-api</artifactId>
71 <type>test-jar</type>
72 <scope>test</scope>
73 </dependency>
74 <dependency>
75 <groupId>org.apache.logging.log4j</groupId>
76 <artifactId>log4j-core</artifactId>
77 <type>test-jar</type>
78 <scope>test</scope>
79 </dependency>
80 <dependency>
81 <groupId>de.flapdoodle.embed</groupId>
82 <artifactId>de.flapdoodle.embed.mongo</artifactId>
83 <scope>test</scope>
84 </dependency>
85 </dependencies>
86
87 <build>
88 <plugins>
89 <plugin>
90 <groupId>org.apache.felix</groupId>
91 <artifactId>maven-bundle-plugin</artifactId>
92 <configuration>
93 <instructions>
94 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
95 <Export-Package>*</Export-Package>
96 </instructions>
97 </configuration>
98 </plugin>
99 <!-- workaround flaky "Operation not permitted" failures when running tests in parallel -->
100 <plugin>
101 <artifactId>maven-surefire-plugin</artifactId>
102 <configuration>
103 <forkCount>1</forkCount>
104 <reuseForks>false</reuseForks>
105 </configuration>
106 </plugin>
107 </plugins>
108 </build>
109 <reporting>
110 <plugins>
111 <plugin>
112 <groupId>org.apache.maven.plugins</groupId>
113 <artifactId>maven-changes-plugin</artifactId>
114 <version>${changes.plugin.version}</version>
115 <reportSets>
116 <reportSet>
117 <reports>
118 <report>changes-report</report>
119 </reports>
120 </reportSet>
121 </reportSets>
122 <configuration>
123 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
124 <useJql>true</useJql>
125 </configuration>
126 </plugin>
127 <plugin>
128 <groupId>org.apache.maven.plugins</groupId>
129 <artifactId>maven-checkstyle-plugin</artifactId>
130 <version>${checkstyle.plugin.version}</version>
131 <configuration>
132 <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
133 <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
134 <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
135 <enableRulesSummary>false</enableRulesSummary>
136 <propertyExpansion>basedir=${basedir}</propertyExpansion>
137 <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
138 </configuration>
139 </plugin>
140 <plugin>
141 <groupId>org.apache.maven.plugins</groupId>
142 <artifactId>maven-javadoc-plugin</artifactId>
143 <version>${javadoc.plugin.version}</version>
144 <configuration>
145 <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
146 Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
147 and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
148 <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating
149 project -->
150 <detectOfflineLinks>false</detectOfflineLinks>
151 <linksource>true</linksource>
152 </configuration>
153 <reportSets>
154 <reportSet>
155 <id>non-aggregate</id>
156 <reports>
157 <report>javadoc</report>
158 </reports>
159 </reportSet>
160 </reportSets>
161 </plugin>
162 <plugin>
163 <groupId>com.github.spotbugs</groupId>
164 <artifactId>spotbugs-maven-plugin</artifactId>
165 </plugin>
166 <plugin>
167 <groupId>org.apache.maven.plugins</groupId>
168 <artifactId>maven-jxr-plugin</artifactId>
169 <version>${jxr.plugin.version}</version>
170 <reportSets>
171 <reportSet>
172 <id>non-aggregate</id>
173 <reports>
174 <report>jxr</report>
175 </reports>
176 </reportSet>
177 <reportSet>
178 <id>aggregate</id>
179 <reports>
180 <report>aggregate</report>
181 </reports>
182 </reportSet>
183 </reportSets>
184 </plugin>
185 <plugin>
186 <groupId>org.apache.maven.plugins</groupId>
187 <artifactId>maven-pmd-plugin</artifactId>
188 <version>${pmd.plugin.version}</version>
189 <configuration>
190 <targetJdk>${maven.compiler.target}</targetJdk>
191 </configuration>
192 </plugin>
193 </plugins>
194 </reporting>
195 </project>
+0
-111
log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Connection.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.logging.log4j.mongodb4;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
20 import org.apache.logging.log4j.core.appender.nosql.AbstractNoSqlConnection;
21 import org.apache.logging.log4j.core.appender.nosql.NoSqlConnection;
22 import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
23 import org.apache.logging.log4j.status.StatusLogger;
24 import org.bson.Document;
25
26 import com.mongodb.ConnectionString;
27 import com.mongodb.MongoException;
28 import com.mongodb.client.MongoClient;
29 import com.mongodb.client.MongoCollection;
30 import com.mongodb.client.MongoDatabase;
31 import com.mongodb.client.model.CreateCollectionOptions;
32 import com.mongodb.client.result.InsertOneResult;
33
34 /**
35 * The MongoDB implementation of {@link NoSqlConnection}.
36 */
37 public final class MongoDb4Connection extends AbstractNoSqlConnection<Document, MongoDb4DocumentObject> {
38
39 private static final Logger LOGGER = StatusLogger.getLogger();
40
41 private static MongoCollection<Document> getOrCreateMongoCollection(final MongoDatabase database,
42 final String collectionName, final boolean isCapped, final Integer sizeInBytes) {
43 try {
44 LOGGER.debug("Gettting collection '{}'...", collectionName);
45 // throws IllegalArgumentException if collectionName is invalid
46 final MongoCollection<Document> found = database.getCollection(collectionName);
47 LOGGER.debug("Got collection {}", found);
48 return found;
49 } catch (final IllegalStateException e) {
50 LOGGER.debug("Collection '{}' does not exist.", collectionName);
51 final CreateCollectionOptions options = new CreateCollectionOptions().capped(isCapped)
52 .sizeInBytes(sizeInBytes);
53 LOGGER.debug("Creating collection '{}' with options {}...", collectionName, options);
54 database.createCollection(collectionName, options);
55 LOGGER.debug("Created collection.");
56 final MongoCollection<Document> created = database.getCollection(collectionName);
57 LOGGER.debug("Got created collection {}", created);
58 return created;
59 }
60
61 }
62
63 private final ConnectionString connectionString;
64 private final MongoCollection<Document> collection;
65 private final MongoClient mongoClient;
66
67 public MongoDb4Connection(final ConnectionString connectionString, final MongoClient mongoClient,
68 final MongoDatabase mongoDatabase, final boolean isCapped, final Integer sizeInBytes) {
69 this.connectionString = connectionString;
70 this.mongoClient = mongoClient;
71 this.collection = getOrCreateMongoCollection(mongoDatabase, connectionString.getCollection(), isCapped,
72 sizeInBytes);
73 }
74
75 @Override
76 public void closeImpl() {
77 // LOG4J2-1196
78 mongoClient.close();
79 }
80
81 @Override
82 public MongoDb4DocumentObject[] createList(final int length) {
83 return new MongoDb4DocumentObject[length];
84 }
85
86 @Override
87 public MongoDb4DocumentObject createObject() {
88 return new MongoDb4DocumentObject();
89 }
90
91 @Override
92 public void insertObject(final NoSqlObject<Document> object) {
93 try {
94 final Document unwrapped = object.unwrap();
95 LOGGER.debug("Inserting BSON Document {}", unwrapped);
96 InsertOneResult insertOneResult = this.collection.insertOne(unwrapped);
97 LOGGER.debug("Insert MongoDb result {}", insertOneResult);
98 } catch (final MongoException e) {
99 throw new AppenderLoggingException("Failed to write log event to MongoDB due to error: " + e.getMessage(),
100 e);
101 }
102 }
103
104 @Override
105 public String toString() {
106 return String.format("Mongo4Connection [connectionString=%s, collection=%s, mongoClient=%s]", connectionString,
107 collection, mongoClient);
108 }
109
110 }
+0
-64
log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.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.logging.log4j.mongodb4;
17
18 import java.util.Arrays;
19
20 import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
21 import org.bson.Document;
22
23 /**
24 * The MongoDB implementation of {@link NoSqlObject} typed to a BSON
25 * {@link Document}.
26 */
27 public final class MongoDb4DocumentObject implements NoSqlObject<Document> {
28 private final Document document;
29
30 public MongoDb4DocumentObject() {
31 this.document = new Document();
32 }
33
34 @Override
35 public void set(final String field, final NoSqlObject<Document> value) {
36 this.document.append(field, value.unwrap());
37 }
38
39 @Override
40 public void set(final String field, final NoSqlObject<Document>[] values) {
41 this.document.append(field, Arrays.asList(values));
42 }
43
44 @Override
45 public void set(final String field, final Object value) {
46 this.document.append(field, value);
47 }
48
49 @Override
50 public void set(final String field, final Object[] values) {
51 this.document.append(field, Arrays.asList(values));
52 }
53
54 @Override
55 public String toString() {
56 return String.format("Mongo4DocumentObject [document=%s]", document);
57 }
58
59 @Override
60 public Document unwrap() {
61 return this.document;
62 }
63 }
+0
-52
log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4LevelCodec.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
17 package org.apache.logging.log4j.mongodb4;
18
19 import org.apache.logging.log4j.Level;
20 import org.bson.BsonReader;
21 import org.bson.BsonWriter;
22 import org.bson.codecs.Codec;
23 import org.bson.codecs.DecoderContext;
24 import org.bson.codecs.EncoderContext;
25
26 /**
27 * A BSON {@link Codec} for Log4j {@link Level}s.
28 */
29 public class MongoDb4LevelCodec implements Codec<Level> {
30
31 /**
32 * The singleton instance.
33 */
34 public static final MongoDb4LevelCodec INSTANCE = new MongoDb4LevelCodec();
35
36 @Override
37 public Level decode(final BsonReader reader, final DecoderContext decoderContext) {
38 return Level.getLevel(reader.readString());
39 }
40
41 @Override
42 public void encode(final BsonWriter writer, final Level level, final EncoderContext encoderContext) {
43 writer.writeString(level.name());
44 }
45
46 @Override
47 public Class<Level> getEncoderClass() {
48 return Level.class;
49 }
50
51 }
+0
-132
log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Provider.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.logging.log4j.mongodb4;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.Core;
20 import org.apache.logging.log4j.core.appender.nosql.NoSqlProvider;
21 import org.apache.logging.log4j.core.config.plugins.Plugin;
22 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
23 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
24 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
25 import org.apache.logging.log4j.core.filter.AbstractFilterable;
26 import org.apache.logging.log4j.status.StatusLogger;
27 import org.bson.codecs.configuration.CodecRegistries;
28 import org.bson.codecs.configuration.CodecRegistry;
29
30 import com.mongodb.ConnectionString;
31 import com.mongodb.MongoClientSettings;
32 import com.mongodb.client.MongoClient;
33 import com.mongodb.client.MongoClients;
34 import com.mongodb.client.MongoDatabase;
35
36 /**
37 * The MongoDB implementation of {@link NoSqlProvider} using the MongoDB driver
38 * version 4 API.
39 */
40 @Plugin(name = "MongoDb4", category = Core.CATEGORY_NAME, printObject = true)
41 public final class MongoDb4Provider implements NoSqlProvider<MongoDb4Connection> {
42
43 public static class Builder<B extends Builder<B>> extends AbstractFilterable.Builder<B>
44 implements org.apache.logging.log4j.core.util.Builder<MongoDb4Provider> {
45
46 @PluginBuilderAttribute(value = "connection")
47 @Required(message = "No connection string provided")
48 private String connectionStringSource;
49
50 @PluginBuilderAttribute
51 private int collectionSize = DEFAULT_COLLECTION_SIZE;
52
53 @PluginBuilderAttribute("capped")
54 private boolean capped = false;
55
56 @Override
57 public MongoDb4Provider build() {
58 return new MongoDb4Provider(connectionStringSource, capped, collectionSize);
59 }
60
61 public B setCapped(final boolean isCapped) {
62 this.capped = isCapped;
63 return asBuilder();
64 }
65
66 public B setCollectionSize(final int collectionSize) {
67 this.collectionSize = collectionSize;
68 return asBuilder();
69 }
70 }
71
72 private static final Logger LOGGER = StatusLogger.getLogger();
73
74 // @formatter:off
75 private static final CodecRegistry CODEC_REGISTRIES = CodecRegistries.fromRegistries(
76 MongoClientSettings.getDefaultCodecRegistry(),
77 CodecRegistries.fromCodecs(MongoDb4LevelCodec.INSTANCE));
78 // @formatter:on
79
80 // TODO Where does this number come from?
81 private static final int DEFAULT_COLLECTION_SIZE = 536_870_912;
82
83 @PluginBuilderFactory
84 public static <B extends Builder<B>> B newBuilder() {
85 return new Builder<B>().asBuilder();
86 }
87
88 private final Integer collectionSize;
89 private final boolean isCapped;
90 private final MongoClient mongoClient;
91 private final MongoDatabase mongoDatabase;
92 private final ConnectionString connectionString;
93
94 private MongoDb4Provider(final String connectionStringSource, final boolean isCapped,
95 final Integer collectionSize) {
96 LOGGER.debug("Creating ConnectionString {}...", connectionStringSource);
97 this.connectionString = new ConnectionString(connectionStringSource);
98 LOGGER.debug("Created ConnectionString {}", connectionString);
99 LOGGER.debug("Creating MongoClientSettings...");
100 // @formatter:off
101 final MongoClientSettings settings = MongoClientSettings.builder()
102 .applyConnectionString(this.connectionString)
103 .codecRegistry(CODEC_REGISTRIES)
104 .build();
105 // @formatter:on
106 LOGGER.debug("Created MongoClientSettings {}", settings);
107 LOGGER.debug("Creating MongoClient {}...", settings);
108 this.mongoClient = MongoClients.create(settings);
109 LOGGER.debug("Created MongoClient {}", mongoClient);
110 String databaseName = this.connectionString.getDatabase();
111 LOGGER.debug("Getting MongoDatabase {}...", databaseName);
112 this.mongoDatabase = this.mongoClient.getDatabase(databaseName);
113 LOGGER.debug("Got MongoDatabase {}", mongoDatabase);
114 this.isCapped = isCapped;
115 this.collectionSize = collectionSize;
116 }
117
118 @Override
119 public MongoDb4Connection getConnection() {
120 return new MongoDb4Connection(connectionString, mongoClient, mongoDatabase, isCapped, collectionSize);
121 }
122
123 @Override
124 public String toString() {
125 return String.format(
126 "%s [connectionString=%s, collectionSize=%s, isCapped=%s, mongoClient=%s, mongoDatabase=%s]",
127 MongoDb4Provider.class.getSimpleName(), connectionString, collectionSize, isCapped, mongoClient,
128 mongoDatabase);
129 }
130
131 }
+0
-21
log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/package-info.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 /**
17 * The classes in this package contain the MongoDB provider for the NoSQL
18 * Appender.
19 */
20 package org.apache.logging.log4j.mongodb4;
+0
-48
log4j-mongodb4/src/site/markdown/index.md.vm less more
0 <!-- vim: set syn=markdown : -->
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 #set($h1='#')
18 #set($h2='##')
19 ## TODO: use properties for dynamic dependency versions
20
21 $h1 MongoDB appender
22
23 [MongoDB](http://www.mongodb.org/) is supported through the
24 [Java MongoDB Driver](http://docs.mongodb.org/ecosystem/drivers/java/).
25
26 ```
27 <dependencyManagement>
28 <dependencies>
29 <dependency>
30 <groupId>org.mongodb</groupId>
31 <artifactId>mongo-java-driver</artifactId>
32 <version>2.12.3</version>
33 </dependency>
34 </dependencies>
35 </dependencyManagement>
36 <dependencies>
37 <dependency>
38 <groupId>org.mongodb</groupId>
39 <artifactId>mongo-java-driver</artifactId>
40 </dependency>
41 </dependencies>
42 ```
43
44 $h2 Requirements
45
46 The MongoDB Appender is dependent on the Log4j 2 API and implementation.
47 For more information, see [Runtime Dependencies](../runtime-dependencies.html).
+0
-52
log4j-mongodb4/src/site/site.xml 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 -->
17 <project name="Log4j MongoDB Appender"
18 xmlns="http://maven.apache.org/DECORATION/1.4.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
21 <body>
22 <links>
23 <item name="Apache" href="http://www.apache.org/" />
24 <item name="Logging Services" href="http://logging.apache.org/"/>
25 <item name="Log4j" href="../index.html"/>
26 </links>
27
28 <!-- Component-specific reports -->
29 <menu ref="reports"/>
30
31 <!-- Overall Project Info -->
32 <menu name="Log4j Project Information" img="icon-info-sign">
33 <item name="Dependencies" href="../dependencies.html" />
34 <item name="Dependency Convergence" href="../dependency-convergence.html" />
35 <item name="Dependency Management" href="../dependency-management.html" />
36 <item name="Project Team" href="../team-list.html" />
37 <item name="Mailing Lists" href="../mail-lists.html" />
38 <item name="Issue Tracking" href="../issue-tracking.html" />
39 <item name="Project License" href="../license.html" />
40 <item name="Source Repository" href="../source-repository.html" />
41 <item name="Project Summary" href="../project-summary.html" />
42 </menu>
43
44 <menu name="Log4j Project Reports" img="icon-cog">
45 <item name="Changes Report" href="../changes-report.html" />
46 <item name="JIRA Report" href="../jira-report.html" />
47 <item name="Surefire Report" href="../surefire-report.html" />
48 <item name="RAT Report" href="../rat-report.html" />
49 </menu>
50 </body>
51 </project>
+0
-72
log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AuthFailureTest.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.logging.log4j.mongodb4;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Ignore;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import org.junit.rules.RuleChain;
32
33 import com.mongodb.client.MongoClient;
34 import com.mongodb.client.MongoCollection;
35 import com.mongodb.client.MongoDatabase;
36
37 /**
38 *
39 *
40 * TODO Set up the log4j user in MongoDB.
41 */
42 @Ignore("TODO Set up the log4j user in MongoDB")
43 @Category(Appenders.MongoDb.class)
44 public class MongoDb4AuthFailureTest {
45
46 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-auth-failure.xml");
47
48 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
49 .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
50
51 private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
52 MongoDb4AuthFailureTest.class, LoggingTarget.NULL);
53
54 @ClassRule
55 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
56 loggerContextTestRule);
57
58 @Test
59 public void test() {
60 final Logger logger = LogManager.getLogger();
61 logger.info("Hello log");
62 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
63 final MongoDatabase database = mongoClient.getDatabase("testDb");
64 Assert.assertNotNull(database);
65 final MongoCollection<Document> collection = database.getCollection("testCollection");
66 Assert.assertNotNull(collection);
67 final Document first = collection.find().first();
68 Assert.assertNull(first);
69 }
70 }
71 }
+0
-69
log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4CappedTest.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.logging.log4j.mongodb4;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.client.MongoClient;
33 import com.mongodb.client.MongoCollection;
34 import com.mongodb.client.MongoDatabase;
35
36 /**
37 *
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDb4CappedTest {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-capped.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
48 MongoDb4CappedTest.class, LoggingTarget.NULL);
49
50 @ClassRule
51 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
52 loggerContextTestRule);
53
54 @Test
55 public void test() {
56 final Logger logger = LogManager.getLogger();
57 logger.info("Hello log");
58 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
59 final MongoDatabase database = mongoClient.getDatabase("testDb");
60 Assert.assertNotNull(database);
61 final MongoCollection<Document> collection = database.getCollection("testCollection");
62 Assert.assertNotNull(collection);
63 final Document first = collection.find().first();
64 Assert.assertNotNull(first);
65 Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
66 }
67 }
68 }
+0
-76
log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4MapMessageTest.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.logging.log4j.mongodb4;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.message.MapMessage;
23 import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
24 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
25 import org.apache.logging.log4j.test.RuleChainFactory;
26 import org.bson.Document;
27 import org.junit.Assert;
28 import org.junit.ClassRule;
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31 import org.junit.rules.RuleChain;
32
33 import com.mongodb.client.MongoClient;
34 import com.mongodb.client.MongoCollection;
35 import com.mongodb.client.MongoDatabase;
36
37 /**
38 *
39 */
40 @Category(Appenders.MongoDb.class)
41 public class MongoDb4MapMessageTest {
42
43 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-map-message.xml");
44
45 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
46 .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
47
48 private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
49 MongoDb4MapMessageTest.class, LoggingTarget.NULL);
50
51 @ClassRule
52 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
53 loggerContextTestRule);
54
55 @Test
56 public void test() {
57 final Logger logger = LogManager.getLogger();
58 final MapMessage<?, Object> mapMessage = new MapMessage<>();
59 mapMessage.with("SomeName", "SomeValue");
60 mapMessage.with("SomeInt", 1);
61 logger.info(mapMessage);
62 //
63 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
64 final MongoDatabase database = mongoClient.getDatabase("testDb");
65 Assert.assertNotNull(database);
66 final MongoCollection<Document> collection = database.getCollection("testCollection");
67 Assert.assertNotNull(collection);
68 final Document first = collection.find().first();
69 Assert.assertNotNull(first);
70 final String firstJson = first.toJson();
71 Assert.assertEquals(firstJson, "SomeValue", first.getString("SomeName"));
72 Assert.assertEquals(firstJson, Integer.valueOf(1), first.getInteger("SomeInt"));
73 }
74 }
75 }
+0
-70
log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4Test.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.logging.log4j.mongodb4;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.categories.Appenders;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
23 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
24 import org.apache.logging.log4j.test.RuleChainFactory;
25 import org.bson.Document;
26 import org.junit.Assert;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.experimental.categories.Category;
30 import org.junit.rules.RuleChain;
31
32 import com.mongodb.client.MongoClient;
33 import com.mongodb.client.MongoCollection;
34 import com.mongodb.client.MongoDatabase;
35
36 /**
37 *
38 */
39 @Category(Appenders.MongoDb.class)
40 public class MongoDb4Test {
41
42 private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb.xml");
43
44 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
45 .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
46
47 private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
48 MongoDb4Test.class, LoggingTarget.NULL);
49
50 @ClassRule
51 public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
52 loggerContextTestRule);
53
54 @Test
55 public void test() {
56 final Logger logger = LogManager.getLogger();
57 logger.info("Hello log");
58 try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
59 final MongoDatabase database = mongoClient.getDatabase("testDb");
60 Assert.assertNotNull(database);
61 final MongoCollection<Document> collection = database.getCollection("testCollection");
62 Assert.assertNotNull(collection);
63 final Document first = collection.find().first();
64 Assert.assertNotNull(first);
65 Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
66 Assert.assertEquals(first.toJson(), "INFO", first.getString("level"));
67 }
68 }
69 }
+0
-24
log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestConstants.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
17 package org.apache.logging.log4j.mongodb4;
18
19 public class MongoDb4TestConstants {
20
21 public static final String SYS_PROP_NAME_PORT = "MongoDBTestPort";
22
23 }
+0
-185
log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestRule.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
17 package org.apache.logging.log4j.mongodb4;
18
19 import java.util.Objects;
20
21 import org.apache.commons.lang3.NotImplementedException;
22 import org.junit.rules.TestRule;
23 import org.junit.runner.Description;
24 import org.junit.runners.model.Statement;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import com.mongodb.client.MongoClient;
29 import com.mongodb.client.MongoClients;
30
31 import de.flapdoodle.embed.mongo.Command;
32 import de.flapdoodle.embed.mongo.MongodExecutable;
33 import de.flapdoodle.embed.mongo.MongodProcess;
34 import de.flapdoodle.embed.mongo.MongodStarter;
35 import de.flapdoodle.embed.mongo.config.Defaults;
36 import de.flapdoodle.embed.mongo.config.MongodConfig;
37 import de.flapdoodle.embed.mongo.config.Net;
38 import de.flapdoodle.embed.mongo.config.Timeout;
39 import de.flapdoodle.embed.mongo.distribution.Version;
40 import de.flapdoodle.embed.process.config.io.ProcessOutput;
41 import de.flapdoodle.embed.process.runtime.Network;
42
43 /**
44 * A JUnit test rule to manage a MongoDB embedded instance.
45 *
46 * TODO Move this class to Apache Commons Testing.
47 */
48 public class MongoDb4TestRule implements TestRule {
49
50 public enum LoggingTarget {
51 CONSOLE, NULL;
52
53 public static LoggingTarget getLoggingTarget(final String sysPropertyName, final LoggingTarget defaultValue) {
54 return LoggingTarget.valueOf(System.getProperty(sysPropertyName, defaultValue.name()));
55 }
56 }
57
58 private static final int BUILDER_TIMEOUT_MILLIS = 30000;
59
60 public static int getBuilderTimeoutMillis() {
61 return BUILDER_TIMEOUT_MILLIS;
62 }
63
64 private static MongodStarter getMongodStarter(final LoggingTarget loggingTarget) {
65 if (loggingTarget == null) {
66 return MongodStarter.getDefaultInstance();
67 }
68 switch (loggingTarget) {
69 case NULL:
70 final Logger logger = LoggerFactory.getLogger(MongoDb4TestRule.class.getName());
71 // @formatter:off
72 return MongodStarter.getInstance(
73 Defaults
74 .runtimeConfigFor(Command.MongoD, logger)
75 .processOutput(ProcessOutput.getDefaultInstanceSilent()).build());
76 // @formatter:on
77 case CONSOLE:
78 return MongodStarter.getDefaultInstance();
79 default:
80 throw new NotImplementedException(loggingTarget.toString());
81 }
82 }
83
84 protected final LoggingTarget loggingTarget;
85
86 protected MongoClient mongoClient;
87 protected MongodExecutable mongodExecutable;
88 protected MongodProcess mongodProcess;
89 protected final String portSystemPropertyName;
90
91 /**
92 * Store {@link MongodStarter} (or RuntimeConfig) in a static final field if you
93 * want to use artifact store caching (or else disable caching).
94 * <p>
95 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
96 * </p>
97 */
98 protected final MongodStarter starter;
99
100 /**
101 * Constructs a new test rule.
102 *
103 * @param portSystemPropertyName The system property name for the MongoDB port.
104 * @param clazz The test case class.
105 * @param defaultLoggingTarget The logging target.
106 */
107 public MongoDb4TestRule(final String portSystemPropertyName, final Class<?> clazz,
108 final LoggingTarget defaultLoggingTarget) {
109 this.portSystemPropertyName = Objects.requireNonNull(portSystemPropertyName, "portSystemPropertyName");
110 this.loggingTarget = LoggingTarget.getLoggingTarget(clazz.getName() + "." + LoggingTarget.class.getSimpleName(),
111 defaultLoggingTarget);
112 this.starter = getMongodStarter(this.loggingTarget);
113 }
114
115 @Override
116 public Statement apply(final Statement base, final Description description) {
117 return new Statement() {
118
119 @Override
120 public void evaluate() throws Throwable {
121 final String value = Objects.requireNonNull(System.getProperty(portSystemPropertyName),
122 "System property '" + portSystemPropertyName + "' is null");
123 final int port = Integer.parseInt(value);
124 mongodExecutable = starter.prepare(
125 // @formatter:off
126 MongodConfig.builder()
127 .version(Version.Main.PRODUCTION)
128 .timeout(new Timeout(BUILDER_TIMEOUT_MILLIS))
129 .net(new Net("localhost", port, Network.localhostIsIPv6())).build());
130 // @formatter:on
131 mongodProcess = mongodExecutable.start();
132 mongoClient = MongoClients.create("mongodb://localhost:" + port);
133 try {
134 base.evaluate();
135 } finally {
136 if (mongodProcess != null) {
137 mongodProcess.stop();
138 mongodProcess = null;
139 }
140 if (mongodExecutable != null) {
141 mongodExecutable.stop();
142 mongodExecutable = null;
143 }
144 }
145 }
146 };
147 }
148
149 public MongoClient getMongoClient() {
150 return mongoClient;
151 }
152
153 public MongodExecutable getMongodExecutable() {
154 return mongodExecutable;
155 }
156
157 public MongodProcess getMongodProcess() {
158 return mongodProcess;
159 }
160
161 public MongodStarter getStarter() {
162 return starter;
163 }
164
165 @Override
166 public String toString() {
167 final StringBuilder builder = new StringBuilder();
168 builder.append("Mongo4TestRule [starter=");
169 builder.append(starter);
170 builder.append(", portSystemPropertyName=");
171 builder.append(portSystemPropertyName);
172 builder.append(", mongoClient=");
173 builder.append(mongoClient);
174 builder.append(", mongodExecutable=");
175 builder.append(mongodExecutable);
176 builder.append(", mongodProcess=");
177 builder.append(mongodProcess);
178 builder.append(", loggingTarget=");
179 builder.append(loggingTarget);
180 builder.append("]");
181 return builder.toString();
182 }
183
184 }
+0
-73
log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestTestRuleTest.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
17 package org.apache.logging.log4j.mongodb4;
18
19 import org.apache.commons.lang3.JavaVersion;
20 import org.apache.commons.lang3.SystemUtils;
21 import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
22 import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
23 import org.apache.logging.log4j.test.RuleChainFactory;
24 import org.junit.Assert;
25 import org.junit.Assume;
26 import org.junit.BeforeClass;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29 import org.junit.rules.RuleChain;
30
31 import com.mongodb.client.MongoIterable;
32
33 /**
34 * Tests MongoDbRule.
35 * <p>
36 * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
37 * </p>
38 */
39 public class MongoDb4TestTestRuleTest {
40
41 private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
42 .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
43
44 private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
45 MongoDb4TestTestRuleTest.class, LoggingTarget.NULL);
46
47 @ClassRule
48 public static RuleChain mongoDbChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule);
49
50 @BeforeClass
51 public static void beforeClass() {
52 Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
53 }
54
55 @Test
56 public void testAccess() {
57 @SuppressWarnings("resource")
58 final MongoIterable<String> databaseNames = mongoDbTestRule.getMongoClient().listDatabaseNames();
59 Assert.assertNotNull(databaseNames);
60 Assert.assertNotNull(databaseNames.first());
61 }
62
63 @SuppressWarnings("resource")
64 @Test
65 public void testMongoDbTestRule() {
66 Assert.assertNotNull(mongoDbTestRule);
67 Assert.assertNotNull(mongoDbTestRule.getStarter());
68 Assert.assertNotNull(mongoDbTestRule.getMongoClient());
69 Assert.assertNotNull(mongoDbTestRule.getMongodExecutable());
70 Assert.assertNotNull(mongoDbTestRule.getMongodProcess());
71 }
72 }
+0
-31
log4j-mongodb4/src/test/resources/log4j2-mongodb-auth-failure.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb4
22 connection="mongodb://log4jUser:12345678@localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" />
23 </NoSql>
24 </Appenders>
25 <Loggers>
26 <Root level="ALL">
27 <AppenderRef ref="MongoDbAppender" />
28 </Root>
29 </Loggers>
30 </Configuration>
+0
-33
log4j-mongodb4/src/test/resources/log4j2-mongodb-capped.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb4
22 connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection"
23 capped="true"
24 collectionSize="1073741824"/>
25 </NoSql>
26 </Appenders>
27 <Loggers>
28 <Root level="ALL">
29 <AppenderRef ref="MongoDbAppender" />
30 </Root>
31 </Loggers>
32 </Configuration>
+0
-31
log4j-mongodb4/src/test/resources/log4j2-mongodb-map-message.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb4 connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" />
22 <MessageLayout />
23 </NoSql>
24 </Appenders>
25 <Loggers>
26 <Root level="ALL">
27 <AppenderRef ref="MongoDbAppender" />
28 </Root>
29 </Loggers>
30 </Configuration>
+0
-30
log4j-mongodb4/src/test/resources/log4j2-mongodb.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="WARN">
19 <Appenders>
20 <NoSql name="MongoDbAppender">
21 <MongoDb4 connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" />
22 </NoSql>
23 </Appenders>
24 <Loggers>
25 <Root level="ALL">
26 <AppenderRef ref="MongoDbAppender" />
27 </Root>
28 </Loggers>
29 </Configuration>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-osgi</artifactId>
3131 <docLabel>OSGi Documentation</docLabel>
3232 <projectDir>/osgi</projectDir>
3333 <module.name>org.apache.logging.log4j.osgi</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
3534 </properties>
3635 <dependencies>
3736 <!-- Place Felix before Equinox because Felix is signed. / also place it before org.osgi.core so that its versions of the OSGi classes are used -->
4645 <scope>test</scope>
4746 </dependency>
4847 <dependency>
49 <groupId>org.junit.vintage</groupId>
50 <artifactId>junit-vintage-engine</artifactId>
51 </dependency>
52 <dependency>
53 <groupId>org.junit.jupiter</groupId>
54 <artifactId>junit-jupiter-engine</artifactId>
48 <groupId>junit</groupId>
49 <artifactId>junit</artifactId>
50 <scope>test</scope>
5551 </dependency>
5652 <dependency>
5753 <groupId>org.eclipse.tycho</groupId>
168164 </reportSets>
169165 </plugin>
170166 <plugin>
171 <groupId>com.github.spotbugs</groupId>
172 <artifactId>spotbugs-maven-plugin</artifactId>
167 <groupId>org.codehaus.mojo</groupId>
168 <artifactId>findbugs-maven-plugin</artifactId>
169 <version>${findbugs.plugin.version}</version>
170 <configuration>
171 <fork>true</fork>
172 <jvmArgs>-Duser.language=en</jvmArgs>
173 <threshold>Normal</threshold>
174 <effort>Default</effort>
175 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
176 </configuration>
173177 </plugin>
174178 <plugin>
175179 <groupId>org.apache.maven.plugins</groupId>
5050 * Constructs a test for a given bundle.
5151 */
5252 public AbstractLoadBundleTest() {
53 super();
5354 this.bundleTestInfo = new BundleTestInfo();
5455 }
5556
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525
3737 <log4jParentDir>${basedir}/..</log4jParentDir>
3838 <docLabel>Apache Log4J Performance Tests</docLabel>
3939 <projectDir>/log4j-perf</projectDir>
40 <jmh.version>1.21</jmh.version>
40 <jmh.version>1.19</jmh.version>
4141 <javac.target>1.7</javac.target>
4242 <uberjar.name>benchmarks</uberjar.name>
4343 <revapi.skip>true</revapi.skip>
44 <maven.doap.skip>true</maven.doap.skip>
4544 </properties>
4645
4746 <dependencies>
6766 <dependency>
6867 <groupId>org.apache.logging.log4j</groupId>
6968 <artifactId>log4j-jpa</artifactId>
70 <version>${project.version}</version>
71 </dependency>
72 <dependency>
73 <groupId>org.apache.logging.log4j</groupId>
74 <artifactId>log4j-layout-template-json</artifactId>
75 <version>${project.version}</version>
76 </dependency>
77 <dependency>
78 <groupId>org.apache.logging.log4j</groupId>
79 <artifactId>log4j-layout-template-json</artifactId>
80 <version>${project.version}</version>
81 <type>test-jar</type>
69 <version>2.12.3</version>
8270 </dependency>
8371 <dependency>
8472 <groupId>org.slf4j</groupId>
11098 <dependency>
11199 <groupId>com.conversantmedia</groupId>
112100 <artifactId>disruptor</artifactId>
101 <classifier>jdk7</classifier>
113102 </dependency>
114103 <dependency>
115104 <groupId>org.jctools</groupId>
154143 <artifactId>jackson-databind</artifactId>
155144 <optional>true</optional>
156145 </dependency>
157 <dependency>
158 <groupId>co.elastic.logging</groupId>
159 <artifactId>log4j2-ecs-layout</artifactId>
160 </dependency>
161146 </dependencies>
162147
163148 <build>
165150 <plugin>
166151 <groupId>org.apache.maven.plugins</groupId>
167152 <artifactId>maven-toolchains-plugin</artifactId>
168 <version>3.0.0</version>
153 <version>1.1</version>
169154 <executions>
170155 <execution>
171156 <goals>
176161 <configuration>
177162 <toolchains>
178163 <jdk>
179 <version>[11, )</version>
164 <version>9</version>
180165 </jdk>
181166 </toolchains>
182167 </configuration>
194179 <plugin>
195180 <groupId>org.apache.maven.plugins</groupId>
196181 <artifactId>maven-shade-plugin</artifactId>
197 <version>3.2.4</version>
182 <version>2.2</version>
198183 <executions>
199184 <execution>
200185 <phase>package</phase>
211196 <Multi-Release>true</Multi-Release>
212197 </manifestEntries>
213198 </transformer>
214 <transformer implementation="com.github.edwgiz.maven_shade_plugin.log4j2_cache_transformer.PluginsCacheFileTransformer" />
215199 </transformers>
216200 <filters>
217201 <filter>
230214 </configuration>
231215 </execution>
232216 </executions>
233 <dependencies>
234 <dependency>
235 <groupId>com.github.edwgiz</groupId>
236 <artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
237 <version>2.14.1</version>
238 </dependency>
239 </dependencies>
240217 </plugin>
241218
242219 <!-- Include the standard NOTICE and LICENSE -->
+0
-185
log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.core.Layout;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
21 import org.openjdk.jmh.annotations.Benchmark;
22
23 import java.nio.ByteBuffer;
24 import java.util.List;
25
26 /**
27 * Benchmark suite for various JSON layouts.
28 * <p>
29 * You can run this test as follows:
30 * <pre>
31 * java \
32 * -jar log4j-perf/target/benchmarks.jar \
33 * -f 2 \
34 * -wi 3 -w 20s \
35 * -i 5 -r 30s \
36 * -prof gc \
37 * -rf json -rff log4j-perf/target/JsonTemplateLayoutBenchmarkResult.json \
38 * ".*JsonTemplateLayoutBenchmark.*"
39 * </pre>
40 */
41 public class JsonTemplateLayoutBenchmark {
42
43 @Benchmark
44 public static int fullJsonTemplateLayout4JsonLayout(
45 final JsonTemplateLayoutBenchmarkState state) {
46 return benchmark(
47 state.getJsonTemplateLayout4JsonLayout(),
48 state.getFullLogEvents(),
49 state.getByteBufferDestination());
50 }
51
52 @Benchmark
53 public static int liteJsonTemplateLayout4JsonLayout(
54 final JsonTemplateLayoutBenchmarkState state) {
55 return benchmark(
56 state.getJsonTemplateLayout4JsonLayout(),
57 state.getLiteLogEvents(),
58 state.getByteBufferDestination());
59 }
60
61 @Benchmark
62 public static int fullJsonTemplateLayout4EcsLayout(
63 final JsonTemplateLayoutBenchmarkState state) {
64 return benchmark(
65 state.getJsonTemplateLayout4EcsLayout(),
66 state.getFullLogEvents(),
67 state.getByteBufferDestination());
68 }
69
70 @Benchmark
71 public static int liteJsonTemplateLayout4EcsLayout(
72 final JsonTemplateLayoutBenchmarkState state) {
73 return benchmark(
74 state.getJsonTemplateLayout4EcsLayout(),
75 state.getLiteLogEvents(),
76 state.getByteBufferDestination());
77 }
78
79 @Benchmark
80 public static int fullJsonTemplateLayout4GelfLayout(
81 final JsonTemplateLayoutBenchmarkState state) {
82 return benchmark(
83 state.getJsonTemplateLayout4GelfLayout(),
84 state.getFullLogEvents(),
85 state.getByteBufferDestination());
86 }
87
88 @Benchmark
89 public static int liteJsonTemplateLayout4GelfLayout(
90 final JsonTemplateLayoutBenchmarkState state) {
91 return benchmark(
92 state.getJsonTemplateLayout4GelfLayout(),
93 state.getLiteLogEvents(),
94 state.getByteBufferDestination());
95 }
96
97 @Benchmark
98 public static int fullDefaultJsonLayout(
99 final JsonTemplateLayoutBenchmarkState state) {
100 return benchmark(
101 state.getDefaultJsonLayout(),
102 state.getFullLogEvents(),
103 state.getByteBufferDestination());
104 }
105
106 @Benchmark
107 public static int liteDefaultJsonLayout(
108 final JsonTemplateLayoutBenchmarkState state) {
109 return benchmark(
110 state.getDefaultJsonLayout(),
111 state.getLiteLogEvents(),
112 state.getByteBufferDestination());
113 }
114
115 @Benchmark
116 public static int fullCustomJsonLayout(
117 final JsonTemplateLayoutBenchmarkState state) {
118 return benchmark(
119 state.getCustomJsonLayout(),
120 state.getFullLogEvents(),
121 state.getByteBufferDestination());
122 }
123
124 @Benchmark
125 public static int liteCustomJsonLayout(
126 final JsonTemplateLayoutBenchmarkState state) {
127 return benchmark(
128 state.getCustomJsonLayout(),
129 state.getLiteLogEvents(),
130 state.getByteBufferDestination());
131 }
132
133 @Benchmark
134 public static int fullEcsLayout(
135 final JsonTemplateLayoutBenchmarkState state) {
136 return benchmark(
137 state.getEcsLayout(),
138 state.getFullLogEvents(),
139 state.getByteBufferDestination());
140 }
141
142 @Benchmark
143 public static int liteEcsLayout(
144 final JsonTemplateLayoutBenchmarkState state) {
145 return benchmark(
146 state.getEcsLayout(),
147 state.getLiteLogEvents(),
148 state.getByteBufferDestination());
149 }
150
151 @Benchmark
152 public static int fullGelfLayout(
153 final JsonTemplateLayoutBenchmarkState state) {
154 return benchmark(
155 state.getGelfLayout(),
156 state.getFullLogEvents(),
157 state.getByteBufferDestination());
158 }
159
160 @Benchmark
161 public static int liteGelfLayout(
162 final JsonTemplateLayoutBenchmarkState state) {
163 return benchmark(
164 state.getGelfLayout(),
165 state.getLiteLogEvents(),
166 state.getByteBufferDestination());
167 }
168
169 private static int benchmark(
170 final Layout<String> layout,
171 final List<LogEvent> logEvents,
172 final ByteBufferDestination destination) {
173 // noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
174 for (int logEventIndex = 0; logEventIndex < logEvents.size(); logEventIndex++) {
175 LogEvent logEvent = logEvents.get(logEventIndex);
176 layout.encode(logEvent, destination);
177 }
178 final ByteBuffer byteBuffer = destination.getByteBuffer();
179 final int position = byteBuffer.position();
180 byteBuffer.clear();
181 return position;
182 }
183
184 }
+0
-375
log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkReport.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.logging.log4j.layout.template.json;
17
18 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
19 import org.apache.logging.log4j.util.Strings;
20
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.io.PrintStream;
26 import java.math.BigDecimal;
27 import java.math.BigInteger;
28 import java.math.RoundingMode;
29 import java.nio.charset.Charset;
30 import java.nio.charset.StandardCharsets;
31 import java.nio.file.Files;
32 import java.nio.file.Path;
33 import java.nio.file.attribute.FileTime;
34 import java.time.Instant;
35 import java.util.Arrays;
36 import java.util.Comparator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.stream.Collectors;
41
42 /**
43 * Utility class to summarize {@link JsonTemplateLayoutBenchmark} results in Asciidoctor.
44 * <p>
45 * Usage:
46 * <pre>
47 * java \
48 * -cp log4j-perf/target/benchmarks.jar \
49 * org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutBenchmarkReport \
50 * log4j-perf/target/JsonTemplateLayoutBenchmarkResult.json \
51 * log4j-perf/target/JsonTemplateLayoutBenchmarkReport.adoc
52 * </pre>
53 * @see JsonTemplateLayoutBenchmark on how to generate JMH result JSON file
54 */
55 public enum JsonTemplateLayoutBenchmarkReport {;
56
57 private static final Charset CHARSET = StandardCharsets.UTF_8;
58
59 public static void main(final String[] args) throws Exception {
60 final CliArgs cliArgs = CliArgs.parseArgs(args);
61 final JmhSetup jmhSetup = JmhSetup.ofJmhResult(cliArgs.jmhResultJsonFile);
62 final List<JmhSummary> jmhSummaries = JmhSummary.ofJmhResult(cliArgs.jmhResultJsonFile);
63 dumpReport(cliArgs.outputAdocFile, jmhSetup, jmhSummaries);
64 }
65
66 private static final class CliArgs {
67
68 private final File jmhResultJsonFile;
69
70 private final File outputAdocFile;
71
72 private CliArgs(final File jmhResultJsonFile, final File outputAdocFile) {
73 this.jmhResultJsonFile = jmhResultJsonFile;
74 this.outputAdocFile = outputAdocFile;
75 }
76
77 private static CliArgs parseArgs(final String[] args) {
78
79 // Check number of arguments.
80 if (args.length != 2) {
81 throw new IllegalArgumentException(
82 "usage: <jmhResultJsonFile> <outputAdocFile>");
83 }
84
85 // Parse the JMH result JSON file.
86 final File jmhResultJsonFile = new File(args[0]);
87 if (!jmhResultJsonFile.isFile()) {
88 throw new IllegalArgumentException(
89 "jmhResultJsonFile doesn't point to a regular file: " +
90 jmhResultJsonFile);
91 }
92 if (!jmhResultJsonFile.canRead()) {
93 throw new IllegalArgumentException(
94 "jmhResultJsonFile is not readable: " +
95 jmhResultJsonFile);
96 }
97
98 // Parse the output AsciiDoc file.
99 final File outputAdocFile = new File(args[1]);
100 touch(outputAdocFile);
101
102 // Looks okay.
103 return new CliArgs(jmhResultJsonFile, outputAdocFile);
104
105 }
106
107 public static void touch(final File file) {
108 Objects.requireNonNull(file, "file");
109 final Path path = file.toPath();
110 try {
111 if (Files.exists(path)) {
112 Files.setLastModifiedTime(path, FileTime.from(Instant.now()));
113 } else {
114 Files.createFile(path);
115 }
116 } catch (IOException error) {
117 throw new RuntimeException("failed to touch file: " + file, error);
118 }
119 }
120
121 }
122
123 private static final class JmhSetup {
124
125 private final String vmName;
126
127 private final String vmVersion;
128
129 private final List<String> vmArgs;
130
131 private final int forkCount;
132
133 private final int warmupIterationCount;
134
135 private final String warmupTime;
136
137 private final int measurementIterationCount;
138
139 private final String measurementTime;
140
141 private JmhSetup(
142 final String vmName,
143 final String vmVersion,
144 final List<String> vmArgs,
145 final int forkCount,
146 final int warmupIterationCount,
147 final String warmupTime,
148 final int measurementIterationCount,
149 final String measurementTime) {
150 this.vmName = vmName;
151 this.vmVersion = vmVersion;
152 this.vmArgs = vmArgs;
153 this.forkCount = forkCount;
154 this.warmupIterationCount = warmupIterationCount;
155 this.warmupTime = warmupTime;
156 this.measurementIterationCount = measurementIterationCount;
157 this.measurementTime = measurementTime;
158 }
159
160 private static JmhSetup ofJmhResult(final File jmhResultFile) throws IOException {
161 final List<Object> jmhResult = readObject(jmhResultFile);
162 return ofJmhResult(jmhResult);
163 }
164
165 private static JmhSetup ofJmhResult(final List<Object> jmhResult) {
166 final Object jmhResultEntry = jmhResult.stream().findFirst().get();
167 final String vmName = readObjectAtPath(jmhResultEntry, "vmName");
168 final String vmVersion = readObjectAtPath(jmhResultEntry, "vmVersion");
169 final List<String> vmArgs = readObjectAtPath(jmhResultEntry, "jvmArgs");
170 final int forkCount = readObjectAtPath(jmhResultEntry, "forks");
171 final int warmupIterationCount = readObjectAtPath(jmhResultEntry, "warmupIterations");
172 final String warmupTime = readObjectAtPath(jmhResultEntry, "warmupTime");
173 final int measurementIterationCount = readObjectAtPath(jmhResultEntry, "measurementIterations");
174 final String measurementTime = readObjectAtPath(jmhResultEntry, "measurementTime");
175 return new JmhSetup(
176 vmName,
177 vmVersion,
178 vmArgs,
179 forkCount,
180 warmupIterationCount,
181 warmupTime,
182 measurementIterationCount,
183 measurementTime);
184 }
185
186 }
187
188 private static final class JmhSummary {
189
190 private final String benchmark;
191
192 private final BigDecimal opRate;
193
194 private final BigDecimal gcRate;
195
196 private JmhSummary(
197 final String benchmark,
198 final BigDecimal opRate,
199 final BigDecimal gcRate) {
200 this.benchmark = benchmark;
201 this.opRate = opRate;
202 this.gcRate = gcRate;
203 }
204
205 private static List<JmhSummary> ofJmhResult(final File jmhResultFile) throws IOException {
206 final List<Object> jmhResult = readObject(jmhResultFile);
207 return ofJmhResult(jmhResult);
208 }
209
210 private static List<JmhSummary> ofJmhResult(final List<Object> jmhResult) {
211 final BigDecimal maxOpRate = jmhResult
212 .stream()
213 .map(jmhResultEntry -> readBigDecimalAtPath(jmhResultEntry, "primaryMetric", "scorePercentiles", "99.0"))
214 .max(BigDecimal::compareTo)
215 .get();
216 return jmhResult
217 .stream()
218 .map(jmhResultEntry -> {
219 final String benchmark = readObjectAtPath(jmhResultEntry, "benchmark");
220 final BigDecimal opRate = readBigDecimalAtPath(jmhResultEntry, "primaryMetric", "scorePercentiles", "99.0");
221 final BigDecimal gcRate = readBigDecimalAtPath(jmhResultEntry, "secondaryMetrics", "·gc.alloc.rate.norm", "scorePercentiles", "99.0");
222 return new JmhSummary(benchmark, opRate, gcRate);
223 })
224 .collect(Collectors.toList());
225 }
226
227 }
228
229 private static <V> V readObject(final File file) throws IOException {
230 final byte[] jsonBytes = Files.readAllBytes(file.toPath());
231 final String json = new String(jsonBytes, CHARSET);
232 @SuppressWarnings("unchecked")
233 final V object = (V) JsonReader.read(json);
234 return object;
235 }
236
237 private static <V> V readObjectAtPath(final Object object, String... path) {
238 Object lastObject = object;
239 for (final String key : path) {
240 @SuppressWarnings("unchecked")
241 Map<String, Object> lastMap = (Map<String, Object>) lastObject;
242 lastObject = lastMap.get(key);
243 }
244 @SuppressWarnings("unchecked")
245 final V typedLastObject = (V) lastObject;
246 return typedLastObject;
247 }
248
249 private static BigDecimal readBigDecimalAtPath(final Object object, String... path) {
250 final Number number = readObjectAtPath(object, path);
251 if (number instanceof BigDecimal) {
252 return (BigDecimal) number;
253 } else if (number instanceof Integer) {
254 final int intNumber = (int) number;
255 return BigDecimal.valueOf(intNumber);
256 } else if (number instanceof Long) {
257 final long longNumber = (long) number;
258 return BigDecimal.valueOf(longNumber);
259 } else if (number instanceof BigInteger) {
260 final BigInteger bigInteger = (BigInteger) number;
261 return new BigDecimal(bigInteger);
262 } else {
263 final String message = String.format(
264 "failed to convert the value to BigDecimal at path %s: %s",
265 Arrays.asList(path), number);
266 throw new IllegalArgumentException(message);
267 }
268 }
269
270 private static void dumpReport(
271 final File outputAdocFile,
272 final JmhSetup jmhSetup,
273 final List<JmhSummary> jmhSummaries) throws IOException {
274 try (final OutputStream outputStream = new FileOutputStream(outputAdocFile);
275 final PrintStream printStream = new PrintStream(outputStream, false, CHARSET.name())) {
276 dumpJmhSetup(printStream, jmhSetup);
277 dumpJmhSummaries(printStream, jmhSummaries, "lite");
278 dumpJmhSummaries(printStream, jmhSummaries, "full");
279 }
280 }
281
282 private static void dumpJmhSetup(
283 final PrintStream printStream,
284 final JmhSetup jmhSetup) {
285 printStream.println("[cols=\"1,4\", options=\"header\"]");
286 printStream.println(".JMH setup");
287 printStream.println("|===");
288 printStream.println("|Setting|Value");
289 printStream.format("|JVM name|%s%n", jmhSetup.vmName);
290 printStream.format("|JVM version|%s%n", jmhSetup.vmVersion);
291 printStream.format("|JVM args|%s%n", jmhSetup.vmArgs != null ? String.join(" ", jmhSetup.vmArgs) : "");
292 printStream.format("|Forks|%s%n", jmhSetup.forkCount);
293 printStream.format("|Warmup iterations|%d × %s%n", jmhSetup.warmupIterationCount, jmhSetup.warmupTime);
294 printStream.format("|Measurement iterations|%d × %s%n", jmhSetup.measurementIterationCount, jmhSetup.measurementTime);
295 printStream.println("|===");
296 }
297
298 private static void dumpJmhSummaries(
299 final PrintStream printStream,
300 final List<JmhSummary> jmhSummaries,
301 final String prefix) {
302
303 // Print header.
304 printStream.println("[cols=\"4,>2,4,>2\", options=\"header\"]");
305 printStream.format(".JMH result (99^th^ percentile) summary for \"%s\" log events%n", prefix);
306 printStream.println("|===");
307 printStream.println("^|Benchmark");
308 printStream.println("2+^|ops/sec");
309 printStream.println("^|B/op");
310
311 // Filter JMH summaries by prefix.
312 final String filterRegex = String.format("^.*\\.%s[A-Za-z0-9]+$", prefix);
313 final List<JmhSummary> filteredJmhSummaries = jmhSummaries
314 .stream()
315 .filter(jmhSummary -> jmhSummary.benchmark.matches(filterRegex))
316 .collect(Collectors.toList());
317
318 // Determine the max. op rate.
319 final BigDecimal maxOpRate = filteredJmhSummaries
320 .stream()
321 .map(jmhSummary -> jmhSummary.opRate)
322 .max(BigDecimal::compareTo)
323 .get();
324
325 // Print each summary.
326 final Comparator<JmhSummary> jmhSummaryComparator =
327 Comparator
328 .comparing((final JmhSummary jmhSummary) -> jmhSummary.opRate)
329 .reversed();
330 filteredJmhSummaries
331 .stream()
332 .sorted(jmhSummaryComparator)
333 .forEach((final JmhSummary jmhSummary) -> {
334 dumpJmhSummary(printStream, maxOpRate, jmhSummary);
335 });
336
337 // Print footer.
338 printStream.println("|===");
339
340 }
341
342 private static void dumpJmhSummary(
343 final PrintStream printStream,
344 final BigDecimal maxOpRate,
345 final JmhSummary jmhSummary) {
346 printStream.println();
347 final String benchmark = jmhSummary
348 .benchmark
349 .replaceAll("^.*\\.([^.]+)$", "$1");
350 printStream.format("|%s%n", benchmark);
351 final long opRatePerSec = jmhSummary
352 .opRate
353 .multiply(BigDecimal.valueOf(1_000L))
354 .toBigInteger()
355 .longValueExact();
356 printStream.format("|%,d%n", opRatePerSec);
357 final BigDecimal normalizedOpRate = jmhSummary
358 .opRate
359 .divide(maxOpRate, RoundingMode.CEILING);
360 final int opRateBarLength = normalizedOpRate
361 .multiply(BigDecimal.valueOf(19))
362 .toBigInteger()
363 .add(BigInteger.ONE)
364 .intValueExact();
365 final String opRateBar = Strings.repeat("▉", opRateBarLength);
366 final int opRatePercent = normalizedOpRate
367 .multiply(BigDecimal.valueOf(100))
368 .toBigInteger()
369 .intValueExact();
370 printStream.format("|%s (%d%%)%n", opRateBar, opRatePercent);
371 printStream.format("|%,.1f%n", jmhSummary.gcRate.doubleValue());
372 }
373
374 }
+0
-212
log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.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.logging.log4j.layout.template.json;
17
18 import co.elastic.logging.log4j2.EcsLayout;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.config.Configuration;
21 import org.apache.logging.log4j.core.config.DefaultConfiguration;
22 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
23 import org.apache.logging.log4j.core.layout.GelfLayout;
24 import org.apache.logging.log4j.core.layout.JsonLayout;
25 import org.apache.logging.log4j.core.util.KeyValuePair;
26 import org.apache.logging.log4j.core.util.NetUtils;
27 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
28 import org.apache.logging.log4j.layout.template.json.util.ThreadLocalRecyclerFactory;
29 import org.openjdk.jmh.annotations.Scope;
30 import org.openjdk.jmh.annotations.State;
31
32 import java.nio.charset.Charset;
33 import java.nio.charset.StandardCharsets;
34 import java.util.List;
35
36 @State(Scope.Benchmark)
37 public class JsonTemplateLayoutBenchmarkState {
38
39 private static final Configuration CONFIGURATION = new DefaultConfiguration();
40
41 private static final Charset CHARSET = StandardCharsets.UTF_8;
42
43 private final ByteBufferDestination byteBufferDestination;
44
45 private final JsonTemplateLayout jsonTemplateLayout4JsonLayout;
46
47 private final JsonTemplateLayout jsonTemplateLayout4EcsLayout;
48
49 private final JsonTemplateLayout jsonTemplateLayout4GelfLayout;
50
51 private final JsonLayout defaultJsonLayout;
52
53 private final JsonLayout customJsonLayout;
54
55 private final EcsLayout ecsLayout;
56
57 private final GelfLayout gelfLayout;
58
59 private final List<LogEvent> fullLogEvents;
60
61 private final List<LogEvent> liteLogEvents;
62
63 public JsonTemplateLayoutBenchmarkState() {
64 this.byteBufferDestination = new BlackHoleByteBufferDestination(1024 * 512);
65 this.jsonTemplateLayout4JsonLayout = createJsonTemplateLayout4JsonLayout();
66 this.jsonTemplateLayout4EcsLayout = createJsonTemplateLayout4EcsLayout();
67 this.jsonTemplateLayout4GelfLayout = createJsonTemplateLayout4GelfLayout();
68 this.defaultJsonLayout = createDefaultJsonLayout();
69 this.customJsonLayout = createCustomJsonLayout();
70 this.ecsLayout = createEcsLayout();
71 this.gelfLayout = createGelfLayout();
72 int logEventCount = 1_000;
73 this.fullLogEvents = LogEventFixture.createFullLogEvents(logEventCount);
74 this.liteLogEvents = LogEventFixture.createLiteLogEvents(logEventCount);
75 }
76
77 private static JsonTemplateLayout createJsonTemplateLayout4JsonLayout() {
78 return JsonTemplateLayout
79 .newBuilder()
80 .setConfiguration(CONFIGURATION)
81 .setCharset(CHARSET)
82 .setEventTemplateUri("classpath:JsonLayout.json")
83 .setRecyclerFactory(ThreadLocalRecyclerFactory.getInstance())
84 .build();
85 }
86
87 private static JsonTemplateLayout createJsonTemplateLayout4EcsLayout() {
88 final EventTemplateAdditionalField[] additionalFields =
89 new EventTemplateAdditionalField[]{
90 EventTemplateAdditionalField
91 .newBuilder()
92 .setKey("service.name")
93 .setValue("benchmark")
94 .build()
95 };
96 return JsonTemplateLayout
97 .newBuilder()
98 .setConfiguration(CONFIGURATION)
99 .setCharset(CHARSET)
100 .setEventTemplateUri("classpath:EcsLayout.json")
101 .setRecyclerFactory(ThreadLocalRecyclerFactory.getInstance())
102 .setEventTemplateAdditionalFields(additionalFields)
103 .build();
104 }
105
106 private static JsonTemplateLayout createJsonTemplateLayout4GelfLayout() {
107 return JsonTemplateLayout
108 .newBuilder()
109 .setConfiguration(CONFIGURATION)
110 .setCharset(CHARSET)
111 .setEventTemplateUri("classpath:GelfLayout.json")
112 .setRecyclerFactory(ThreadLocalRecyclerFactory.getInstance())
113 .setEventTemplateAdditionalFields(
114 new EventTemplateAdditionalField[]{
115 // Adding "host" as a constant rather than using
116 // the "hostName" property lookup at runtime, which
117 // is what GelfLayout does as well.
118 EventTemplateAdditionalField
119 .newBuilder()
120 .setKey("host")
121 .setValue(NetUtils.getLocalHostname())
122 .build()
123 })
124 .build();
125 }
126
127 private static JsonLayout createDefaultJsonLayout() {
128 return JsonLayout
129 .newBuilder()
130 .setConfiguration(CONFIGURATION)
131 .setCharset(CHARSET)
132 .build();
133 }
134
135 private static JsonLayout createCustomJsonLayout() {
136 return JsonLayout
137 .newBuilder()
138 .setConfiguration(CONFIGURATION)
139 .setCharset(CHARSET)
140 .setAdditionalFields(new KeyValuePair[]{
141 new KeyValuePair("@version", "\"1\"")
142 })
143 .build();
144 }
145
146 private static EcsLayout createEcsLayout() {
147 final EcsLayout layout = EcsLayout
148 .newBuilder()
149 .setConfiguration(CONFIGURATION)
150 .setServiceName("benchmark")
151 .build();
152 final Charset layoutCharset = layout.getCharset();
153 // Note that EcsLayout doesn't support charset configuration, though it
154 // uses UTF-8 internally.
155 if (!CHARSET.equals(layoutCharset)) {
156 throw new IllegalArgumentException(
157 "was expecting EcsLayout charset to be: " + CHARSET + ", found: " + layoutCharset);
158 }
159 return layout;
160 }
161
162 private static GelfLayout createGelfLayout() {
163 return GelfLayout
164 .newBuilder()
165 .setConfiguration(CONFIGURATION)
166 .setCharset(CHARSET)
167 .setCompressionType(GelfLayout.CompressionType.OFF)
168 .build();
169 }
170
171 ByteBufferDestination getByteBufferDestination() {
172 return byteBufferDestination;
173 }
174
175 JsonTemplateLayout getJsonTemplateLayout4JsonLayout() {
176 return jsonTemplateLayout4JsonLayout;
177 }
178
179 JsonTemplateLayout getJsonTemplateLayout4EcsLayout() {
180 return jsonTemplateLayout4EcsLayout;
181 }
182
183 JsonTemplateLayout getJsonTemplateLayout4GelfLayout() {
184 return jsonTemplateLayout4GelfLayout;
185 }
186
187 JsonLayout getDefaultJsonLayout() {
188 return defaultJsonLayout;
189 }
190
191 JsonLayout getCustomJsonLayout() {
192 return customJsonLayout;
193 }
194
195 EcsLayout getEcsLayout() {
196 return ecsLayout;
197 }
198
199 GelfLayout getGelfLayout() {
200 return gelfLayout;
201 }
202
203 List<LogEvent> getFullLogEvents() {
204 return fullLogEvents;
205 }
206
207 List<LogEvent> getLiteLogEvents() {
208 return liteLogEvents;
209 }
210
211 }
151151 private static volatile OldCachedClock instance;
152152 private static final Object INSTANCE_LOCK = new Object();
153153 private volatile long millis = System.currentTimeMillis();
154 private volatile short count;
154 private volatile short count = 0;
155155
156156 private OldCachedClock() {
157 final Thread updater = new Thread((Runnable) () -> {
158 while (true) {
159 final long time = System.currentTimeMillis();
160 millis = time;
157 final Thread updater = new Thread(new Runnable() {
158 @Override
159 public void run() {
160 while (true) {
161 final long time = System.currentTimeMillis();
162 millis = time;
161163
162 // avoid explicit dependency on sun.misc.Util
163 LockSupport.parkNanos(1000 * 1000);
164 // avoid explicit dependency on sun.misc.Util
165 LockSupport.parkNanos(1000 * 1000);
166 }
164167 }
165168 }, "Clock Updater Thread");
166169 updater.setDaemon(true);
+0
-122
log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/DateTimeFormatBenchmark.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.logging.log4j.perf.jmh;
17
18 import org.apache.logging.log4j.core.time.MutableInstant;
19 import org.apache.logging.log4j.core.util.datetime.FastDatePrinter;
20 import org.apache.logging.log4j.core.util.datetime.FixedDateFormat;
21 import org.openjdk.jmh.annotations.Benchmark;
22 import org.openjdk.jmh.annotations.Scope;
23 import org.openjdk.jmh.annotations.State;
24 import org.openjdk.jmh.infra.Blackhole;
25
26 import java.time.Instant;
27 import java.time.format.DateTimeFormatter;
28 import java.util.*;
29 import java.util.stream.IntStream;
30
31 /**
32 * Compares {@link MutableInstant} formatting efficiency of
33 * {@link FastDatePrinter}, {@link FixedDateFormat}, and {@link DateTimeFormatter}.
34 * <p>
35 * The major formatting efficiency is mostly provided by caching, i.e.,
36 * reusing the earlier formatter output if timestamps match. We deliberately
37 * exclude this optimization, since it is applicable to all formatters. This
38 * benchmark rather focuses on only and only the formatting efficiency.
39 */
40 @State(Scope.Thread)
41 public class DateTimeFormatBenchmark {
42
43 /**
44 * The pattern to be tested.
45 * <p>
46 * Note that neither {@link FastDatePrinter}, nor {@link FixedDateFormat}
47 * supports nanosecond precision.
48 */
49 private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS";
50
51 private static final Locale LOCALE = Locale.US;
52
53 private static final TimeZone TIME_ZONE = TimeZone.getTimeZone("UTC");
54
55 private static final Instant INIT_INSTANT = Instant.parse("2020-05-14T10:44:23.901Z");
56
57 private static final MutableInstant[] INSTANTS = IntStream
58 .range(0, 1_000)
59 .mapToObj((final int index) -> {
60 final MutableInstant instant = new MutableInstant();
61 instant.initFromEpochSecond(
62 Math.addExact(INIT_INSTANT.getEpochSecond(), index),
63 Math.addExact(INIT_INSTANT.getNano(), index));
64 return instant;
65 })
66 .toArray(MutableInstant[]::new);
67
68 private static final Calendar[] CALENDARS = Arrays
69 .stream(INSTANTS)
70 .map((final MutableInstant instant) -> {
71 final Calendar calendar = Calendar.getInstance(TIME_ZONE, LOCALE);
72 calendar.setTimeInMillis(instant.getEpochMillisecond());
73 return calendar;
74 })
75 .toArray(Calendar[]::new);
76
77 private static final FastDatePrinter FAST_DATE_PRINTER =
78 new FastDatePrinter(PATTERN, TIME_ZONE, LOCALE) {};
79
80 private static final FixedDateFormat FIXED_DATE_FORMAT =
81 Objects.requireNonNull(
82 FixedDateFormat.createIfSupported(PATTERN, TIME_ZONE.getID()),
83 "couldn't create FixedDateTime for pattern " + PATTERN + " and time zone " + TIME_ZONE.getID());
84
85 private static final DateTimeFormatter DATE_TIME_FORMATTER =
86 DateTimeFormatter
87 .ofPattern(PATTERN)
88 .withZone(TIME_ZONE.toZoneId())
89 .withLocale(LOCALE);
90
91 private final StringBuilder stringBuilder = new StringBuilder(PATTERN.length() * 2);
92
93 private final char[] charBuffer = new char[stringBuilder.capacity()];
94
95 @Benchmark
96 public void fastDatePrinter(final Blackhole blackhole) {
97 for (final Calendar calendar : CALENDARS) {
98 stringBuilder.setLength(0);
99 FAST_DATE_PRINTER.format(calendar, stringBuilder);
100 blackhole.consume(stringBuilder.length());
101 }
102 }
103
104 @Benchmark
105 public void fixedDateFormat(final Blackhole blackhole) {
106 for (final MutableInstant instant : INSTANTS) {
107 final int length = FIXED_DATE_FORMAT.formatInstant(instant, charBuffer, 0);
108 blackhole.consume(length);
109 }
110 }
111
112 @Benchmark
113 public void dateTimeFormatter(final Blackhole blackhole) {
114 for (final MutableInstant instant : INSTANTS) {
115 stringBuilder.setLength(0);
116 DATE_TIME_FORMATTER.formatTo(instant, stringBuilder);
117 blackhole.consume(stringBuilder.length());
118 }
119 }
120
121 }
152152 @BenchmarkMode(Mode.Throughput)
153153 @OutputTimeUnit(TimeUnit.SECONDS)
154154 @Benchmark
155 public void log4j2Builder() {
156 log4j2Logger.atDebug().withLocation().log(MESSAGE);
157 }
158
159 @BenchmarkMode(Mode.Throughput)
160 @OutputTimeUnit(TimeUnit.SECONDS)
161 @Benchmark
162155 public void logbackFile() {
163156 slf4jLogger.debug(MESSAGE);
164157 }
1818
1919 import org.apache.logging.log4j.LogManager;
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.async.AsyncLoggerContext;
22 import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
23 import org.apache.logging.log4j.core.util.Constants;
2421 import org.openjdk.jmh.annotations.Benchmark;
2522 import org.openjdk.jmh.annotations.BenchmarkMode;
2623 import org.openjdk.jmh.annotations.Fork;
2724 import org.openjdk.jmh.annotations.Measurement;
2825 import org.openjdk.jmh.annotations.Mode;
2926 import org.openjdk.jmh.annotations.OutputTimeUnit;
30 import org.openjdk.jmh.annotations.Param;
3127 import org.openjdk.jmh.annotations.Scope;
3228 import org.openjdk.jmh.annotations.Setup;
3329 import org.openjdk.jmh.annotations.State;
3935 import java.io.File;
4036 import java.lang.reflect.InvocationHandler;
4137 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Method;
4239 import java.lang.reflect.Proxy;
4340 import java.util.concurrent.TimeUnit;
4441 import java.util.logging.FileHandler;
5047 */
5148 // HOW TO RUN THIS TEST
5249 // java -jar target/benchmarks.jar ".*FileAppenderThrowableBenchmark.*" -f 1 -i 10 -wi 20 -bm sample -tu ns
53 @State(Scope.Benchmark)
50 @State(Scope.Thread)
5451 @Threads(1)
5552 @Fork(1)
5653 @Warmup(iterations = 3, time = 3)
5754 @Measurement(iterations = 3, time = 3)
5855 public class FileAppenderThrowableBenchmark {
59 static {
60 // log4j2
61 System.setProperty("log4j2.is.webapp", "false");
62 System.setProperty("log4j.configurationFile", "log4j2-perf-file-throwable.xml");
63 // log4j 1.2
64 System.setProperty("log4j.configuration", "log4j12-perf-file-throwable.xml");
65 // logback
66 System.setProperty("logback.configurationFile", "logback-perf-file-throwable.xml");
67 }
6856
6957 private static final Throwable THROWABLE = getSimpleThrowable();
7058 private static final Throwable COMPLEX_THROWABLE = getComplexThrowable();
71
72 @SuppressWarnings("unused") // Set by JMH
73 @Param
74 private LoggingConfiguration loggingConfiguration;
7559
7660 private static Throwable getSimpleThrowable() {
7761 return new IllegalStateException("Test Throwable");
117101 interface TestIface30 extends ThrowableHelper {}
118102
119103 private static Throwable getComplexThrowable() {
120 ThrowableHelper helper = () -> {
121 throw new IllegalStateException("Test Throwable");
104 ThrowableHelper helper = new ThrowableHelper() {
105 @Override
106 public void action() {
107 throw new IllegalStateException("Test Throwable");
108 }
122109 };
123110 try {
124111 for (int i = 0; i < 31; i++) {
126113 helper = (ThrowableHelper) Proxy.newProxyInstance(
127114 FileAppenderThrowableBenchmark.class.getClassLoader(),
128115 new Class<?>[]{Class.forName(FileAppenderThrowableBenchmark.class.getName() + "$TestIface" + (i % 31))},
129 (InvocationHandler) (proxy, method, args) -> {
130 try {
131 return method.invoke(delegate, args);
132 } catch (final InvocationTargetException e) {
133 throw e.getCause();
116 new InvocationHandler() {
117 @Override
118 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
119 try {
120 return method.invoke(delegate, args);
121 } catch (final InvocationTargetException e) {
122 throw e.getCause();
123 }
134124 }
135125 });
136126 }
145135 throw new IllegalStateException("Failed to create throwable");
146136 }
147137
138 private FileHandler julFileHandler;
139 Logger log4j2ExtendedThrowable;
140 Logger log4j2ExtendedThrowableAsync;
141 Logger log4j2SimpleThrowable;
142 Logger log4j2SimpleThrowableAsync;
143 org.slf4j.Logger slf4jLogger;
144 org.apache.log4j.Logger log4j1Logger;
145 java.util.logging.Logger julLogger;
148146
149147 @Setup
150148 public void setUp() throws Exception {
151149 deleteLogFiles();
152 loggingConfiguration.setUp();
150 System.setProperty("log4j2.is.webapp", "false");
151 System.setProperty("log4j.configurationFile", "log4j2-perf-file-throwable.xml");
152 System.setProperty("log4j.configuration", "log4j12-perf-file-throwable.xml");
153 System.setProperty("logback.configurationFile", "logback-perf-file-throwable.xml");
154
155 log4j2ExtendedThrowable = LogManager.getLogger("RAFExtendedException");
156 log4j2ExtendedThrowableAsync = LogManager.getLogger("async.RAFExtendedException");
157 log4j2SimpleThrowable = LogManager.getLogger("RAFSimpleException");
158 log4j2SimpleThrowableAsync = LogManager.getLogger("async.RAFSimpleException");
159 slf4jLogger = LoggerFactory.getLogger(getClass());
160 log4j1Logger = org.apache.log4j.Logger.getLogger(getClass());
161
162 julFileHandler = new FileHandler("target/testJulLog.log");
163 julLogger = java.util.logging.Logger.getLogger(getClass().getName());
164 julLogger.setUseParentHandlers(false);
165 julLogger.addHandler(julFileHandler);
166 julLogger.setLevel(Level.ALL);
153167 }
154168
155169 @TearDown
156 public void tearDown() throws Exception{
157 loggingConfiguration.tearDown();
170 public void tearDown() {
171 System.clearProperty("log4j2.is.webapp");
172 System.clearProperty("log4j.configurationFile");
173 System.clearProperty("log4j.configuration");
174 System.clearProperty("logback.configurationFile");
158175 deleteLogFiles();
159176 }
160177
171188 julFile.delete();
172189 }
173190
174 @SuppressWarnings("unused") // Used by JMH
175 public enum LoggingConfiguration {
176 LOG4J2_EXTENDED_THROWABLE() {
177 Logger logger;
178 @Override
179 void setUp() throws Exception {
180 logger = LogManager.getLogger("RAFExtendedException");
181 }
182
183 @Override
184 void tearDown() throws Exception {
185
186 }
187
188 @Override
189 void log(String message, Throwable throwable) {
190 logger.error(message, throwable);
191 }
192 },
193 LOG4J2_EXTENDED_THROWABLE_ASYNC() {
194 Logger logger;
195 @Override
196 void setUp() throws Exception {
197 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
198 AsyncLoggerContextSelector.class.getName());
199 logger = LogManager.getLogger("RAFExtendedException");
200 if (!AsyncLoggerContext.class.equals(LogManager.getContext(false).getClass())) {
201 throw new IllegalStateException("Expected an AsyncLoggerContext");
202 }
203 }
204
205 @Override
206 void tearDown() throws Exception {
207
208 }
209
210 @Override
211 void log(String message, Throwable throwable) {
212 logger.error(message, throwable);
213 }
214 },
215 LOG4J2_EXTENDED_THROWABLE_ASYNC_CONFIG() {
216 Logger logger;
217 @Override
218 void setUp() throws Exception {
219 logger = LogManager.getLogger("async.RAFExtendedException");
220 }
221
222 @Override
223 void tearDown() throws Exception {
224
225 }
226
227 @Override
228 void log(String message, Throwable throwable) {
229 logger.error(message, throwable);
230 }
231 },
232 LOG4J2_THROWABLE() {
233 Logger logger;
234 @Override
235 void setUp() throws Exception {
236 logger = LogManager.getLogger("RAFSimpleException");
237 }
238
239 @Override
240 void tearDown() throws Exception {
241
242 }
243
244 @Override
245 void log(String message, Throwable throwable) {
246 logger.error(message, throwable);
247 }
248 },
249 LOG4J2_THROWABLE_ASYNC() {
250 Logger logger;
251 @Override
252 void setUp() throws Exception {
253 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
254 AsyncLoggerContextSelector.class.getName());
255 logger = LogManager.getLogger("RAFSimpleException");
256 if (!AsyncLoggerContext.class.equals(LogManager.getContext(false).getClass())) {
257 throw new IllegalStateException("Expected an AsyncLoggerContext");
258 }
259 }
260
261 @Override
262 void tearDown() throws Exception {
263
264 }
265
266 @Override
267 void log(String message, Throwable throwable) {
268 logger.error(message, throwable);
269 }
270 },
271 LOG4J2_THROWABLE_ASYNC_CONFIG() {
272 Logger logger;
273 @Override
274 void setUp() throws Exception {
275 logger = LogManager.getLogger("async.RAFSimpleException");
276 }
277
278 @Override
279 void tearDown() throws Exception {
280
281 }
282
283 @Override
284 void log(String message, Throwable throwable) {
285 logger.error(message, throwable);
286 }
287 },
288 LOG4J1() {
289 org.apache.log4j.Logger logger;
290 @Override
291 void setUp() throws Exception {
292 logger = org.apache.log4j.Logger.getLogger(FileAppenderThrowableBenchmark.class);
293 }
294
295 @Override
296 void tearDown() throws Exception {
297
298 }
299
300 @Override
301 void log(String message, Throwable throwable) {
302 logger.error(message, throwable);
303 }
304 },
305 LOGBACK() {
306 org.slf4j.Logger logger;
307
308 @Override
309 void setUp() throws Exception {
310 logger = LoggerFactory.getLogger(FileAppenderThrowableBenchmark.class);
311 }
312
313 @Override
314 void tearDown() throws Exception {
315
316 }
317
318 @Override
319 void log(String message, Throwable throwable) {
320 logger.error(message, throwable);
321 }
322 },
323 JUL() {
324 private FileHandler julFileHandler;
325 private java.util.logging.Logger logger;
326
327 @Override
328 void setUp() throws Exception {
329 julFileHandler = new FileHandler("target/testJulLog.log");
330 logger = java.util.logging.Logger.getLogger(getClass().getName());
331 logger.setUseParentHandlers(false);
332 logger.addHandler(julFileHandler);
333 logger.setLevel(Level.ALL);
334 }
335
336 @Override
337 void tearDown() throws Exception {
338 julFileHandler.close();
339 }
340
341 @Override
342 void log(String message, Throwable throwable) {
343 // must specify sourceClass or JUL will look it up by walking the stack trace!
344 logger.logp(Level.SEVERE, FileAppenderThrowableBenchmark.class.getName(), "param1JulFile", message, throwable);
345 }
346 };
347
348 abstract void setUp() throws Exception;
349
350 abstract void tearDown() throws Exception;
351
352 abstract void log(String message, Throwable throwable);
353 }
354
355 @BenchmarkMode(Mode.Throughput)
356 @OutputTimeUnit(TimeUnit.SECONDS)
357 @Benchmark
358 public void simpleThrowable() {
359 loggingConfiguration.log("Caught an exception", THROWABLE);
360 }
361
362 @BenchmarkMode(Mode.Throughput)
363 @OutputTimeUnit(TimeUnit.SECONDS)
364 @Benchmark
365 public void complexThrowable() {
366 loggingConfiguration.log("Caught an exception", COMPLEX_THROWABLE);
191 @BenchmarkMode(Mode.Throughput)
192 @OutputTimeUnit(TimeUnit.SECONDS)
193 @Benchmark
194 public void log4j1() {
195 log4j1Logger.error("Caught an exception", THROWABLE);
196 }
197
198 @BenchmarkMode(Mode.Throughput)
199 @OutputTimeUnit(TimeUnit.SECONDS)
200 @Benchmark
201 public void complexLog4j1() {
202 log4j1Logger.error("Caught an exception", COMPLEX_THROWABLE);
203 }
204
205 @BenchmarkMode(Mode.Throughput)
206 @OutputTimeUnit(TimeUnit.SECONDS)
207 @Benchmark
208 public void log4j2Throwable() {
209 log4j2SimpleThrowable.error("Caught an exception", THROWABLE);
210 }
211
212 @BenchmarkMode(Mode.Throughput)
213 @OutputTimeUnit(TimeUnit.SECONDS)
214 @Benchmark
215 public void complexLog4j2Throwable() {
216 log4j2SimpleThrowable.error("Caught an exception", COMPLEX_THROWABLE);
217 }
218
219 @BenchmarkMode(Mode.Throughput)
220 @OutputTimeUnit(TimeUnit.SECONDS)
221 @Benchmark
222 public void complexLog4j2ThrowableAsync() {
223 log4j2SimpleThrowableAsync.error("Caught an exception", COMPLEX_THROWABLE);
224 }
225
226 @BenchmarkMode(Mode.Throughput)
227 @OutputTimeUnit(TimeUnit.SECONDS)
228 @Benchmark
229 public void log4j2ExtendedThrowable() {
230 log4j2ExtendedThrowable.error("Caught an exception", THROWABLE);
231 }
232
233 @BenchmarkMode(Mode.Throughput)
234 @OutputTimeUnit(TimeUnit.SECONDS)
235 @Benchmark
236 public void complexLog4j2ExtendedThrowable() {
237 log4j2ExtendedThrowable.error("Caught an exception", COMPLEX_THROWABLE);
238 }
239
240 @BenchmarkMode(Mode.Throughput)
241 @OutputTimeUnit(TimeUnit.SECONDS)
242 @Benchmark
243 public void complexLog4j2ExtendedThrowableAsync() {
244 log4j2ExtendedThrowableAsync.error("Caught an exception", COMPLEX_THROWABLE);
245 }
246
247 @BenchmarkMode(Mode.Throughput)
248 @OutputTimeUnit(TimeUnit.SECONDS)
249 @Benchmark
250 public void logbackFile() {
251 slf4jLogger.error("Caught an exception", THROWABLE);
252 }
253
254 @BenchmarkMode(Mode.Throughput)
255 @OutputTimeUnit(TimeUnit.SECONDS)
256 @Benchmark
257 public void complexLogbackFile() {
258 slf4jLogger.error("Caught an exception", COMPLEX_THROWABLE);
259 }
260
261 @BenchmarkMode(Mode.Throughput)
262 @OutputTimeUnit(TimeUnit.SECONDS)
263 @Benchmark
264 public void julFile() {
265 // must specify sourceClass or JUL will look it up by walking the stack trace!
266 julLogger.logp(Level.SEVERE, getClass().getName(), "param1JulFile", "Caught an exception", THROWABLE);
367267 }
368268 }
101101 @BenchmarkMode(Mode.Throughput)
102102 @OutputTimeUnit(TimeUnit.SECONDS)
103103 @Benchmark
104 public void log4j2FluentFile() {
105 log4j2Logger.atDebug().withLocation().log(MESSAGE);
106 }
107
108 @BenchmarkMode(Mode.Throughput)
109 @OutputTimeUnit(TimeUnit.SECONDS)
110 @Benchmark
111104 public void logbackFile() {
112105 slf4jLogger.debug(MESSAGE);
113106 }
4949 private static final CharSequence MESSAGE =
5050 "This is rather long and chatty log message with quite some interesting information and a bit of fun in it which is suitable here";
5151 private static final LogEvent EVENT = createLogEvent();
52 private static final KeyValuePair[] ADDITIONAL_FIELDS = KeyValuePair.EMPTY_ARRAY;
52 private static final KeyValuePair[] ADDITIONAL_FIELDS = new KeyValuePair[0];
5353
5454 private static LogEvent createLogEvent() {
5555 final Marker marker = null;
+0
-196
log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/InstantFormatBenchmark.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.logging.log4j.perf.jmh;
17
18 import org.apache.logging.log4j.core.time.MutableInstant;
19 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
20 import org.apache.logging.log4j.core.util.datetime.FixedDateFormat;
21 import org.openjdk.jmh.annotations.*;
22 import org.openjdk.jmh.infra.BenchmarkParams;
23 import org.openjdk.jmh.infra.Blackhole;
24
25 import java.time.Duration;
26 import java.time.Instant;
27 import java.time.format.DateTimeFormatter;
28 import java.time.temporal.ChronoUnit;
29 import java.util.*;
30 import java.util.stream.IntStream;
31 import java.util.stream.Stream;
32
33 /**
34 * Benchmarks certain {@link Instant} formatters with various patterns and instant collections.
35 */
36 @State(Scope.Thread)
37 public class InstantFormatBenchmark {
38
39 private static final TimeZone TIME_ZONE = TimeZone.getTimeZone("UTC");
40
41 /**
42 * Does (should?) have no effect, since {@link #pattern}s must be supported by {@link FixedDateFormat}, which doesn't have any locale support.
43 */
44 private static final Locale LOCALE = Locale.US;
45
46 private static final Instant[] INSTANTS = createInstants();
47
48 /**
49 * Date & time format patterns supported by all formatters and produce the same output.
50 */
51 @Param({
52 "HH:mm:ss.SSS",
53 "yyyy-MM-dd'T'HH:mm:ss.SSS"
54 })
55 public String pattern;
56
57 private Formatter log4jFdf;
58
59 private Formatter commonsFdf;
60
61 private Formatter javaDtf;
62
63 @Setup
64 public void setupFormatters(final BenchmarkParams params) {
65 final String pattern = params.getParam("pattern");
66 log4jFdf = new Log4jFixedDateFormat(pattern);
67 commonsFdf = new CommonsFastDateFormat(pattern);
68 javaDtf = new JavaDateTimeFormatter(pattern);
69 }
70
71 private static Instant[] createInstants() {
72 final Instant loInstant = Instant.EPOCH;
73 // Capping the max. offset to a day to avoid choking at `FixedDateTime#millisSinceMidnight(long)`, which is supposed to be executed once a day in practice.
74 final Instant hiInstant = loInstant.plus(Duration.ofDays(1));
75 final long maxOffsetNanos = Duration.between(loInstant, hiInstant).toNanos();
76 final Random random = new Random(0);
77 return IntStream
78 .range(0, 1_000)
79 .mapToObj(ignored -> {
80 final long offsetNanos = (long) Math.floor(random.nextDouble() * maxOffsetNanos);
81 return loInstant.plus(offsetNanos, ChronoUnit.NANOS);
82 })
83 .toArray(Instant[]::new);
84 }
85
86 @FunctionalInterface
87 interface Formatter {
88
89 void benchmark(Blackhole blackhole);
90
91 }
92
93 private static final class Log4jFixedDateFormat implements Formatter {
94
95 private final org.apache.logging.log4j.core.time.Instant[] log4jInstants;
96
97 private final char[] buffer;
98
99 private final FixedDateFormat formatter;
100
101 private Log4jFixedDateFormat(final String pattern) {
102 this.log4jInstants = Stream
103 .of(INSTANTS)
104 .map(instant -> {
105 final MutableInstant log4jInstant = new MutableInstant();
106 log4jInstant.initFromEpochSecond(instant.getEpochSecond(), instant.getNano());
107 return log4jInstant;
108 })
109 .toArray(org.apache.logging.log4j.core.time.Instant[]::new);
110 this.buffer = new char[pattern.length()];
111 this.formatter = Objects.requireNonNull(FixedDateFormat.createIfSupported(pattern, TIME_ZONE.getID()));
112 }
113
114 @Override
115 public void benchmark(final Blackhole blackhole) {
116 for (final org.apache.logging.log4j.core.time.Instant log4jInstant : log4jInstants) {
117 blackhole.consume(formatter.formatInstant(log4jInstant, buffer, 0));
118 }
119 }
120
121 }
122
123 private static final class CommonsFastDateFormat implements Formatter {
124
125 private final Calendar[] calendars;
126
127 private final StringBuilder stringBuilder = new StringBuilder();
128
129 private final FastDateFormat fastDateFormat;
130
131 private CommonsFastDateFormat(final String pattern) {
132 this.calendars = Arrays
133 .stream(INSTANTS)
134 .map(instant -> {
135 final Calendar calendar = Calendar.getInstance(TIME_ZONE, LOCALE);
136 calendar.setTimeInMillis(instant.toEpochMilli());
137 return calendar;
138 })
139 .toArray(Calendar[]::new);
140 this.fastDateFormat = FastDateFormat.getInstance(pattern, TIME_ZONE, LOCALE);
141 }
142
143 @Override
144 public void benchmark(final Blackhole blackhole) {
145 for (final Calendar calendar : calendars) {
146 stringBuilder.setLength(0);
147 fastDateFormat.format(calendar, stringBuilder);
148 blackhole.consume(stringBuilder.length());
149 }
150 }
151
152 }
153
154 private static final class JavaDateTimeFormatter implements Formatter {
155
156 private final Instant[] instants;
157
158 private final StringBuilder stringBuilder = new StringBuilder();
159
160 private final DateTimeFormatter dateTimeFormatter;
161
162 private JavaDateTimeFormatter(final String pattern) {
163 this.instants = INSTANTS;
164 this.dateTimeFormatter = DateTimeFormatter
165 .ofPattern(pattern, LOCALE)
166 .withZone(TIME_ZONE.toZoneId());
167 }
168
169 @Override
170 public void benchmark(final Blackhole blackhole) {
171 for (final Instant instant : instants) {
172 stringBuilder.setLength(0);
173 dateTimeFormatter.formatTo(instant, stringBuilder);
174 blackhole.consume(stringBuilder.length());
175 }
176 }
177
178 }
179
180 @Benchmark
181 public void log4jFdf(final Blackhole blackhole) {
182 log4jFdf.benchmark(blackhole);
183 }
184
185 @Benchmark
186 public void commonsFdf(final Blackhole blackhole) {
187 commonsFdf.benchmark(blackhole);
188 }
189
190 @Benchmark
191 public void javaDtf(final Blackhole blackhole) {
192 javaDtf.benchmark(blackhole);
193 }
194
195 }
5252 public class LoggerConfigBenchmark {
5353
5454 private final CopyOnWriteArraySet<AppenderControl> appenderSet = new CopyOnWriteArraySet<>();
55 private volatile Filter filter;
55 private volatile Filter filter = null;
5656 private final boolean additive = true;
5757 private final boolean includeLocation = true;
5858 private LoggerConfig parent;
+0
-140
log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/LoggingDisabledBenchmark.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.logging.log4j.perf.jmh;
17
18 import java.io.File;
19 import java.util.concurrent.TimeUnit;
20
21 import org.apache.logging.log4j.LogManager;
22 import org.apache.logging.log4j.Logger;
23 import org.openjdk.jmh.annotations.Benchmark;
24 import org.openjdk.jmh.annotations.BenchmarkMode;
25 import org.openjdk.jmh.annotations.Mode;
26 import org.openjdk.jmh.annotations.OutputTimeUnit;
27 import org.openjdk.jmh.annotations.Scope;
28 import org.openjdk.jmh.annotations.Setup;
29 import org.openjdk.jmh.annotations.State;
30 import org.openjdk.jmh.annotations.TearDown;
31 import org.slf4j.LoggerFactory;
32
33 //import com.newrelic.api.agent.Trace;
34
35 /**
36 * Benchmark logging with logging disabled.
37 * // ============================== HOW TO RUN THIS TEST: ====================================
38 * //
39 * // single thread:
40 * // java -jar log4j-perf/target/benchmarks.jar ".*LoggingDisabledBenchmark.*" -f 1 -wi 5 -i 10
41 * //
42 * // multiple threads (for example, 4 threads):
43 * // java -jar log4j-perf/target/benchmarks.jar ".*LoggingDisabledBenchmark.*" -f 1 -wi 5 -i 10 -t 4 -si true
44 * //
45 * // Usage help:
46 * // java -jar log4j-perf/target/benchmarks.jar -help
47 * //
48 */
49 @State(Scope.Thread)
50 public class LoggingDisabledBenchmark {
51
52 Logger log4j2Logger;
53 org.slf4j.Logger slf4jLogger;
54 org.apache.log4j.Logger log4j1Logger;
55
56 @Setup
57 public void setUp() throws Exception {
58 System.setProperty("log4j.configurationFile", "log4j2-perf2.xml");
59 System.setProperty("log4j.configuration", "log4j12-perf2.xml");
60 System.setProperty("logback.configurationFile", "logback-perf2.xml");
61
62 deleteLogFiles();
63
64 log4j2Logger = LogManager.getLogger(FileAppenderWithLocationBenchmark.class);
65 slf4jLogger = LoggerFactory.getLogger(FileAppenderWithLocationBenchmark.class);
66 log4j1Logger = org.apache.log4j.Logger.getLogger(FileAppenderWithLocationBenchmark.class);
67 }
68
69 @TearDown
70 public void tearDown() {
71 System.clearProperty("log4j.configurationFile");
72 System.clearProperty("log4j.configuration");
73 System.clearProperty("logback.configurationFile");
74
75 deleteLogFiles();
76 }
77
78 private void deleteLogFiles() {
79 final File logbackFile = new File("target/testlogback.log");
80 logbackFile.delete();
81 final File log4jFile = new File ("target/testlog4j.log");
82 log4jFile.delete();
83 final File log4j2File = new File ("target/testlog4j2.log");
84 log4j2File.delete();
85 }
86
87 @Benchmark
88 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
89 public void baseline() {
90 }
91
92 /*
93 This benchmark tests the overhead of NewRelic on method calls. It is commented out so
94 that we don't have to include the dependency during a "normal" build. Uncomment and add
95 the New Relic Agent client dependency if you would like to test this.
96 @Benchmark
97 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
98 @Trace(dispatcher = true)
99 public void log4j2NewRelic() {
100 log4j2Logger.debug("This won't be logged");
101 } */
102
103 @Benchmark
104 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
105 public void log4j2() {
106 log4j2Logger.debug("This won't be logged");
107 }
108
109 @Benchmark
110 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
111 public void slf4j() {
112 slf4jLogger.debug("This won't be logged");
113 }
114
115 @Benchmark
116 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
117 public void log4j2IsDebugEnabled() {
118 if (log4j2Logger.isDebugEnabled()) {
119 log4j2Logger.debug("This won't be logged");
120 }
121 }
122
123 @Benchmark
124 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
125 public void slf4jIsDebugEnabled() {
126 if (slf4jLogger.isDebugEnabled()) {
127 slf4jLogger.debug("This won't be logged");
128 }
129 }
130
131 @Benchmark
132 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
133 public void log4j1IsDebugEnabled() {
134 if (log4j1Logger.isDebugEnabled()) {
135 log4j1Logger.debug("This won't be logged");
136 }
137 }
138
139 }
+0
-106
log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/NamePatternConverterBenchmark.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.logging.log4j.perf.jmh;
17
18 import org.apache.logging.log4j.core.AbstractLogEvent;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.pattern.LoggerPatternConverter;
21 import org.openjdk.jmh.annotations.Benchmark;
22 import org.openjdk.jmh.annotations.BenchmarkMode;
23 import org.openjdk.jmh.annotations.Fork;
24 import org.openjdk.jmh.annotations.Measurement;
25 import org.openjdk.jmh.annotations.Mode;
26 import org.openjdk.jmh.annotations.OutputTimeUnit;
27 import org.openjdk.jmh.annotations.Param;
28 import org.openjdk.jmh.annotations.Scope;
29 import org.openjdk.jmh.annotations.Setup;
30 import org.openjdk.jmh.annotations.State;
31 import org.openjdk.jmh.annotations.Threads;
32 import org.openjdk.jmh.annotations.Warmup;
33
34 import java.util.concurrent.TimeUnit;
35
36 /**
37 * Tests Log4j2 NamePatternConverter's performance.<br>
38 *
39 * How to run these benchmarks:<br>
40 *
41 * Single thread:<br>
42 * <pre>java -jar log4j-perf/target/benchmarks.jar ".*NamePatternConverterBenchmark.*" -f 1 -wi 2 -i 3 -r 3s -jvmArgs '-server -XX:+AggressiveOpts'</pre>
43 *
44 * Multiple threads (for example, 4 threads):<br>
45 * <pre>java -jar log4j-perf/target/benchmarks.jar ".*NamePatternConverterBenchmark.*" -f 1 -wi 4 -i 20 -t 4 -si true</pre>
46 *
47 * Usage help:<br>
48 * <pre>java -jar log4j-perf/target/benchmarks.jar -help</pre>
49 */
50 @Fork(1)
51 @Threads(1)
52 @Warmup(iterations = 3, time = 3)
53 @Measurement(iterations = 4, time = 3)
54 public class NamePatternConverterBenchmark {
55
56 @State(Scope.Benchmark)
57 public static class ExecutionPlan {
58 @Param({
59 "org.bogus.hokus.pokus.org.bogus.hokus.pokus.org.bogus.hokus.pokus.RetroEncabulatorFactorySingleton",
60 "org.bogus.hokus.pokus.Clazz1",
61 "com.bogus.hokus.pokus.Clazz2",
62 "edu.bogus.hokus.pokus.a.Clazz3",
63 "de.bogus.hokus.b.Clazz4",
64 "jp.bogus.c.Clazz5",
65 "cn.d.Clazz6"
66 })
67 String className;
68 LogEvent event;
69 private final ThreadLocal<StringBuilder> destination = ThreadLocal.withInitial(StringBuilder::new);
70
71 final LoggerPatternConverter converter = LoggerPatternConverter.newInstance(new String[] {"1."});
72
73 @Setup
74 public void setup() {
75 event = new BenchmarkLogEvent(className);
76 }
77
78 StringBuilder destination() {
79 StringBuilder result = destination.get();
80 result.setLength(0);
81 return result;
82 }
83 }
84
85 @Benchmark
86 @BenchmarkMode(Mode.AverageTime)
87 @OutputTimeUnit(TimeUnit.NANOSECONDS)
88 public void benchNamePatternConverter(ExecutionPlan plan) {
89 plan.converter.format(plan.event, plan.destination());
90 }
91
92 private static class BenchmarkLogEvent extends AbstractLogEvent {
93 private final String loggerName;
94
95 BenchmarkLogEvent(String loggerName) {
96 this.loggerName = loggerName;
97 }
98
99 @Override
100 public String getLoggerName() {
101 return loggerName;
102 }
103 }
104
105 }
+0
-116
log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/OutputBenchmark.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
17 package org.apache.logging.log4j.perf.jmh;
18
19 import java.io.File;
20 import java.io.FileOutputStream;
21 import java.io.PrintStream;
22 import java.util.concurrent.TimeUnit;
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.openjdk.jmh.annotations.Benchmark;
26 import org.openjdk.jmh.annotations.BenchmarkMode;
27 import org.openjdk.jmh.annotations.Group;
28 import org.openjdk.jmh.annotations.Mode;
29 import org.openjdk.jmh.annotations.OutputTimeUnit;
30 import org.openjdk.jmh.annotations.Scope;
31 import org.openjdk.jmh.annotations.Setup;
32 import org.openjdk.jmh.annotations.State;
33 import org.openjdk.jmh.annotations.TearDown;
34
35 /**
36 * Benchmarks Log4j 2, Log4j 1, Logback and JUL using the DEBUG level which is enabled for this test. The configuration
37 * for each uses a FileAppender
38 */
39 // HOW TO RUN THIS TEST
40 // java -jar log4j-perf/target/benchmarks.jar ".*OutputBenchmark.*" -f 1 -wi 10 -i 20
41 //
42 // RUNNING THIS TEST WITH 4 THREADS:
43 // java -jar log4j-perf/target/benchmarks.jar ".*OutputBenchmark.*" -f 1 -wi 10 -i 20 -t 4
44 @State(Scope.Thread)
45 public class OutputBenchmark {
46 public static final String MESSAGE = "This is a debug message";
47
48 Logger log4j2Logger;
49
50
51 @State(Scope.Group)
52 public static class Redirect {
53 PrintStream defaultStream = System.out;
54
55 @Setup
56 public void setUp() throws Exception {
57 PrintStream ps = new PrintStream(new FileOutputStream("target/stdout.log"));
58 System.setOut(ps);
59 }
60
61 @TearDown
62 public void tearDown() {
63 PrintStream ps = System.out;
64 System.setOut(defaultStream);
65 ps.close();
66 }
67 }
68
69 @Setup
70 public void setUp() throws Exception {
71 System.setProperty("log4j.configurationFile", "log4j2-perf3.xml");
72
73 deleteLogFiles();
74
75 log4j2Logger = LogManager.getLogger(OutputBenchmark.class);
76 }
77
78 @TearDown
79 public void tearDown() {
80 System.clearProperty("log4j.configurationFile");
81
82 deleteLogFiles();
83 }
84
85 private void deleteLogFiles() {
86 final File outFile = new File("target/stdout.log");
87 final File log4j2File = new File ("target/testlog4j2.log");
88 log4j2File.delete();
89 outFile.delete();
90 }
91
92 @BenchmarkMode(Mode.Throughput)
93 @OutputTimeUnit(TimeUnit.SECONDS)
94 @Group("console")
95 @Benchmark
96 public void console() {
97 System.out.println(MESSAGE);
98 }
99
100 @BenchmarkMode(Mode.Throughput)
101 @OutputTimeUnit(TimeUnit.SECONDS)
102 @Group("file")
103 @Benchmark
104 public void log4j2File() {
105 log4j2Logger.debug(MESSAGE);
106 }
107
108 @BenchmarkMode(Mode.Throughput)
109 @OutputTimeUnit(TimeUnit.SECONDS)
110 @Group("redirect")
111 @Benchmark
112 public void redirect(Redirect redirect) {
113 System.out.println(MESSAGE);
114 }
115 }
6262 @State(Scope.Benchmark)
6363 public static class ClassContextManager extends SecurityManager {
6464 @Override
65 protected Class<?>[] getClassContext() {
65 protected Class[] getClassContext() {
6666 return super.getClassContext();
6767 }
6868 }
147147 private Class<?> findClass(final int depth) {
148148 if (depth == 1) {
149149 return locateCaller();
150 } else {
151 return findClass(depth - 1);
150152 }
151 return findClass(depth - 1);
152153 }
153154
154155 private Class<?> locateCaller() {
161162 private String findMethodName(final int depth) {
162163 if (depth == 1) {
163164 return locateMethodName();
165 } else {
166 return findMethodName(depth - 1);
164167 }
165 return findMethodName(depth - 1);
166168 }
167169
168170 private String locateMethodName() {
2323
2424 import org.apache.logging.log4j.perf.nogc.OpenHashStringMap;
2525 import org.apache.logging.log4j.util.SortedArrayStringMap;
26 import org.apache.logging.log4j.util.BiConsumer;
2627 import org.apache.logging.log4j.util.TriConsumer;
2728 import org.openjdk.jmh.annotations.Benchmark;
2829 import org.openjdk.jmh.annotations.BenchmarkMode;
143144 return new HashMap(populatedMap);
144145 }
145146
146 static TriConsumer<String, Object, int[]> COUNTER = (s, o, result) -> result[0] += s.hashCode() + o.hashCode();
147 static TriConsumer<String, Object, int[]> COUNTER = new TriConsumer<String, Object, int[]>() {
148 @Override
149 public void accept(final String s, final Object o, final int[] result) {
150 result[0] += s.hashCode() + o.hashCode();
151 }
152 };
147153
148154 @Benchmark
149155 public int iterateArrayContextDataTriConsumer() {
165171 public int iterateArrayContextDataBiConsumer() {
166172 final int[] result = {0};
167173
168 populatedSortedStringArrayMap.forEach((s, o) -> result[0] += s.hashCode() + o.hashCode());
174 populatedSortedStringArrayMap.forEach(new BiConsumer<String, Object>() {
175 @Override
176 public void accept(final String s, final Object o) {
177 result[0] += s.hashCode() + o.hashCode();
178 }
179 });
169180 return result[0];
170181 }
171182
173184 public int iterateHashContextDataBiConsumer() {
174185 final int[] result = {0};
175186
176 populatedOpenHashContextData.forEach((s, o) -> result[0] += s.hashCode() + o.hashCode());
187 populatedOpenHashContextData.forEach(new BiConsumer<String, Object>() {
188 @Override
189 public void accept(final String s, final Object o) {
190 result[0] += s.hashCode() + o.hashCode();
191 }
192 });
177193 return result[0];
178194 }
179195
+0
-133
log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/StackWalkBenchmark.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.logging.log4j.perf.jmh;
17
18 import java.util.concurrent.TimeUnit;
19 import java.util.function.Function;
20 import java.util.stream.Stream;
21
22 import org.apache.logging.log4j.perf.util.StackDriver;
23 import org.openjdk.jmh.annotations.Benchmark;
24 import org.openjdk.jmh.annotations.BenchmarkMode;
25 import org.openjdk.jmh.annotations.Mode;
26 import org.openjdk.jmh.annotations.OutputTimeUnit;
27 import org.openjdk.jmh.annotations.Param;
28 import org.openjdk.jmh.annotations.Scope;
29 import org.openjdk.jmh.annotations.State;
30 import org.openjdk.jmh.infra.Blackhole;
31
32 /**
33 * Benchmark logging with logging disabled.
34 * // ============================== HOW TO RUN THIS TEST: ====================================
35 * //
36 * // single thread:
37 * // java -jar log4j-perf/target/benchmarks.jar ".*StackWalkBenchmark.*" -f 1 -wi 5 -i 10
38 * //
39 * // multiple threads (for example, 4 threads):
40 * // java -jar log4j-perf/target/benchmarks.jar ".*StackWalkBenchmark.*" -f 1 -wi 5 -i 10 -t 4 -si true
41 * //
42 * // Usage help:
43 * // java -jar log4j-perf/target/benchmarks.jar -help
44 * //
45 */
46 @State(Scope.Benchmark)
47 @BenchmarkMode(Mode.AverageTime)
48 @OutputTimeUnit(TimeUnit.MICROSECONDS)
49 public class StackWalkBenchmark {
50
51 private static final StackDriver stackDriver = new StackDriver();
52 private final static ThreadLocal<String> FQCN = new ThreadLocal<>();
53 private final static FqcnCallerLocator LOCATOR = new FqcnCallerLocator();
54 private final static StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
55
56 @Param({"10", "20", "50"})
57 private int initialDepth;
58
59 @Param({"5", "10", "20"})
60 private int callDepth;
61
62 @Benchmark
63 public void throwableSearch(Blackhole bh) {
64
65 stackDriver.deepCall(initialDepth, callDepth, fqcn -> {
66 final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
67 boolean found = false;
68 for (int i = 0; i < stackTrace.length; i++) {
69 final String className = stackTrace[i].getClassName();
70 if (fqcn.equals(className)) {
71 found = true;
72 continue;
73 }
74 if (found && !fqcn.equals(className)) {
75 return stackTrace[i];
76 }
77 }
78 return null;
79 });
80 }
81
82 @Benchmark
83 public void stackWalkerWalk(Blackhole bh) {
84 stackDriver.deepCall(initialDepth, callDepth, fqcn -> walker.walk(
85 s -> s.dropWhile(f -> !f.getClassName().equals(fqcn)) // drop the top frames until we reach the logger
86 .dropWhile(f -> f.getClassName().equals(fqcn)) // drop the logger frames
87 .findFirst())
88 .get()
89 .toStackTraceElement());
90 }
91
92 @Benchmark
93 public void stackWalkerArray(Blackhole bh) {
94
95 stackDriver.deepCall(initialDepth, callDepth, fqcn -> {
96 FQCN.set(fqcn);
97 final StackWalker.StackFrame walk = walker.walk(LOCATOR);
98 final StackTraceElement element = walk == null ? null : walk.toStackTraceElement();
99 FQCN.set(null);
100 return element;
101 });
102 }
103
104 @Benchmark
105 public void baseline(Blackhole bh) {
106
107 stackDriver.deepCall(initialDepth, callDepth, fqcn -> null);
108 }
109
110 static final class FqcnCallerLocator implements Function<Stream<StackWalker.StackFrame>, StackWalker.StackFrame> {
111
112 @Override
113 public StackWalker.StackFrame apply(Stream<StackWalker.StackFrame> stackFrameStream) {
114 String fqcn = FQCN.get();
115 boolean foundFqcn = false;
116 Object[] frames = stackFrameStream.toArray();
117 for (int i = 0; i < frames.length ; ++i) {
118 final String className = ((StackWalker.StackFrame) frames[i]).getClassName();
119 if (!foundFqcn) {
120 // Skip frames until we find the FQCN
121 foundFqcn = className.equals(fqcn);
122 } else if (!className.equals(fqcn)) {
123 // The frame is no longer equal to the FQCN so it is the one we want.
124 return (StackWalker.StackFrame) frames[i];
125 } // Otherwise it is equal to the FQCN so we need to skip it.
126 }
127 // Should never happen
128 return null;
129 }
130 }
131
132 }
1616
1717 package org.apache.logging.log4j.perf.jmh;
1818
19 import java.nio.charset.Charset;
20 import java.util.Deque;
21 import java.util.List;
22 import java.util.concurrent.ConcurrentLinkedDeque;
23
1924 import org.apache.logging.log4j.Level;
25 import org.apache.logging.log4j.Marker;
26 import org.apache.logging.log4j.ThreadContext.ContextStack;
2027 import org.apache.logging.log4j.core.LogEvent;
2128 import org.apache.logging.log4j.core.config.Configuration;
2229 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2633 import org.apache.logging.log4j.core.pattern.PatternParser;
2734 import org.apache.logging.log4j.message.Message;
2835 import org.apache.logging.log4j.message.SimpleMessage;
29 import org.jctools.queues.MpmcArrayQueue;
36 import org.apache.logging.log4j.util.StringMap;
3037 import org.openjdk.jmh.annotations.Benchmark;
3138 import org.openjdk.jmh.annotations.Scope;
3239 import org.openjdk.jmh.annotations.State;
3340
34 import java.util.List;
35
3641 /**
37 * Checks {@link PatternFormatter} performance with various StringBuilder
38 * caching strategies: no-op, ThreadLocal, and JCTools MPMC queue.
42 * Checks PatternLayout performance when reusing the StringBuilder in a ThreadLocal, an ObjectPool or when creating a
43 * new instance for each log event.
3944 */
4045 // ============================== HOW TO RUN THIS TEST: ====================================
4146 // (Quick build: mvn -DskipTests=true clean package -pl log4j-perf -am )
5257 @State(Scope.Benchmark)
5358 public class ThreadLocalVsPoolBenchmark {
5459
55 private static final LogEvent LOG_EVENT = createLogEvent();
56
57 private static final List<PatternFormatter> FORMATTERS = createFormatters();
58
59 private static LogEvent createLogEvent() {
60 final String loggerName = "name(ignored)";
61 final String loggerFqcn = "com.mycom.myproject.mypackage.MyClass";
62 final Level level = Level.DEBUG;
63 final String messageString = "AB!(%087936DZYXQWEIOP$#^~-=/><nb"; // length=32
64 final Message message = new SimpleMessage(messageString);
65 final long timestamp = 12345678;
66 return Log4jLogEvent
67 .newBuilder()
68 .setLoggerName(loggerName)
69 .setLoggerFqcn(loggerFqcn)
70 .setLevel(level)
71 .setMessage(message)
72 .setTimeMillis(timestamp)
73 .build();
74 }
75
76 private static List<PatternFormatter> createFormatters() {
60 static final Charset CHARSET_DEFAULT = Charset.defaultCharset();
61 static final String LOG4JPATTERN = "%d %5p [%t] %c{1} %X{transactionId} - %m%n";
62 static final int DEFAULT_STRING_BUILDER_SIZE = 1024;
63
64 /**
65 * The LogEvent to serialize.
66 */
67 private final static LogEvent LOG4J2EVENT = createLog4j2Event();
68
69 /**
70 * Initial converter for pattern.
71 */
72 private final static PatternFormatter[] formatters = createFormatters();
73
74 private final StringBuilderPool pool = new StringBuilderPool(DEFAULT_STRING_BUILDER_SIZE);
75 private static ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>();
76
77 /**
78 */
79 private static PatternFormatter[] createFormatters() {
7780 final Configuration config = new DefaultConfiguration();
7881 final PatternParser parser = new PatternParser(config, "Converter", LogEventPatternConverter.class);
79 return parser.parse("%d %5p [%t] %c{1} %X{transactionId} - %m%n", false, true);
80 }
81
82 private static abstract class StringBuilderPool {
83
84 abstract StringBuilder acquire();
85
86 abstract void release(StringBuilder stringBuilder);
87
88 StringBuilder createStringBuilder() {
89 return new StringBuilder(1024 * 32);
82 final List<PatternFormatter> result = parser.parse(LOG4JPATTERN, false, true);
83 return result.toArray(new PatternFormatter[result.size()]);
84 }
85
86 @Benchmark
87 public byte[] newInstance() {
88 return serializeWithNewInstance(LOG4J2EVENT).getBytes(CHARSET_DEFAULT);
89 }
90
91 @Benchmark
92 public byte[] threadLocal() {
93 return serializeWithThreadLocal(LOG4J2EVENT).getBytes(CHARSET_DEFAULT);
94 }
95
96 @Benchmark
97 public byte[] objectPool() {
98 return serializeWithPool(LOG4J2EVENT).getBytes(CHARSET_DEFAULT);
99 }
100
101 @Benchmark
102 public String _stringNewInstance() {
103 return serializeWithNewInstance(LOG4J2EVENT);
104 }
105
106 @Benchmark
107 public String _stringThreadLocal() {
108 return serializeWithThreadLocal(LOG4J2EVENT);
109 }
110
111 @Benchmark
112 public String _stringObjectPool() {
113 return serializeWithPool(LOG4J2EVENT);
114 }
115
116 private String serializeWithNewInstance(final LogEvent event) {
117 final StringBuilder buf = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
118 return serialize(event, buf);
119 }
120
121 private String serializeWithThreadLocal(final LogEvent event) {
122 StringBuilder buf = threadLocal.get();
123 if (buf == null) {
124 buf = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
125 threadLocal.set(buf);
90126 }
91
92 }
93
94 private static final class AllocatePool extends StringBuilderPool {
95
96 private static final AllocatePool INSTANCE = new AllocatePool();
97
98 @Override
99 public StringBuilder acquire() {
100 return createStringBuilder();
127 buf.setLength(0);
128 return serialize(event, buf);
129 }
130
131 private String serializeWithPool(final LogEvent event) {
132 final StringBuilder buf = pool.borrowObject();
133 try {
134 buf.setLength(0);
135 return serialize(event, buf);
136 } finally {
137 pool.returnObject(buf);
101138 }
102
103 @Override
104 public void release(final StringBuilder stringBuilder) {}
105
106 }
107
108 private static final class ThreadLocalPool extends StringBuilderPool {
109
110 private static final ThreadLocalPool INSTANCE = new ThreadLocalPool();
111
112 private final ThreadLocal<StringBuilder> stringBuilderRef =
113 ThreadLocal.withInitial(this::createStringBuilder);
114
115 @Override
116 public StringBuilder acquire() {
117 return stringBuilderRef.get();
139 }
140
141 private String serialize(final LogEvent event, final StringBuilder buf) {
142 final int len = formatters.length;
143 for (int i = 0; i < len; i++) {
144 formatters[i].format(event, buf);
118145 }
119
120 @Override
121 public void release(final StringBuilder stringBuilder) {
122 stringBuilder.setLength(0);
123 }
124
125 }
126
127 private static final class JcPool extends StringBuilderPool {
128
129 private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
130
131 private static final int MPMC_REQUIRED_MIN_CAPACITY = 2;
132
133 // Putting the under-provisioned instance to a wrapper class to prevent
134 // the initialization of JcPool itself when there are insufficient CPU
135 // cores.
136 private enum UnderProvisionedInstanceHolder {;
137
138 private static final JcPool INSTANCE = createInstance();
139
140 private static JcPool createInstance() {
141 if (CPU_COUNT <= MPMC_REQUIRED_MIN_CAPACITY) {
142 throw new IllegalArgumentException("insufficient CPU cores");
143 }
144 return new JcPool(MPMC_REQUIRED_MIN_CAPACITY);
145 }
146
147 }
148
149 private static final JcPool RIGHT_PROVISIONED_INSTANCE =
150 new JcPool(Math.max(MPMC_REQUIRED_MIN_CAPACITY, CPU_COUNT));
151
152 private final MpmcArrayQueue<StringBuilder> stringBuilders;
153
154 private JcPool(final int capacity) {
155 this.stringBuilders = new MpmcArrayQueue<>(capacity);
156 }
157
158 @Override
159 public StringBuilder acquire() {
160 final StringBuilder stringBuilder = stringBuilders.poll();
161 return stringBuilder != null
162 ? stringBuilder
163 : createStringBuilder();
164 }
165
166 @Override
167 public void release(final StringBuilder stringBuilder) {
168 stringBuilder.setLength(0);
169 stringBuilders.offer(stringBuilder);
170 }
171
172 }
173
174 @Benchmark
175 public int allocate() {
176 return findSerializedLength(AllocatePool.INSTANCE);
177 }
178
179 @Benchmark
180 public int threadLocal() {
181 return findSerializedLength(ThreadLocalPool.INSTANCE);
182 }
183
184 @Benchmark
185 public int rightProvedJc() {
186 return findSerializedLength(JcPool.RIGHT_PROVISIONED_INSTANCE);
187 }
188
189 @Benchmark
190 public int underProvedJc() {
191 return findSerializedLength(JcPool.UnderProvisionedInstanceHolder.INSTANCE);
192 }
193
194 private int findSerializedLength(final StringBuilderPool pool) {
195 final StringBuilder stringBuilder = pool.acquire();
196 serialize(stringBuilder);
197 final int length = stringBuilder.length();
198 pool.release(stringBuilder);
199 return length;
200 }
201
202 private void serialize(final StringBuilder stringBuilder) {
203 // noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
204 for (int formatterIndex = 0; formatterIndex < FORMATTERS.size(); formatterIndex++) {
205 PatternFormatter formatter = FORMATTERS.get(formatterIndex);
206 formatter.format(LOG_EVENT, stringBuilder);
207 }
208 }
209
146 return buf.toString();
147 }
148
149 private static LogEvent createLog4j2Event() {
150 final Marker marker = null;
151 final String fqcn = "com.mycom.myproject.mypackage.MyClass";
152 final Level level = Level.DEBUG;
153 final String STR = "AB!(%087936DZYXQWEIOP$#^~-=/><nb"; // length=32
154 final Message message = new SimpleMessage(STR);
155 final Throwable t = null;
156 final StringMap mdc = null;
157 final ContextStack ndc = null;
158 final String threadName = null;
159 final StackTraceElement location = null;
160 final long timestamp = 12345678;
161
162 return Log4jLogEvent.newBuilder() //
163 .setLoggerName("name(ignored)") //
164 .setMarker(marker) //
165 .setLoggerFqcn(fqcn) //
166 .setLevel(level) //
167 .setMessage(message) //
168 .setThrown(t) //
169 .setContextData(mdc) //
170 .setContextStack(ndc) //
171 .setThreadName(threadName) //
172 .setSource(location) //
173 .setTimeMillis(timestamp) //
174 .build();
175 }
210176 }
177
178 /**
179 *
180 */
181 abstract class ObjectPool<T> {
182 private final Deque<T> pool = new ConcurrentLinkedDeque<>();
183
184 public T borrowObject() {
185 final T object = pool.poll();
186 return object == null ? createObject() : object;
187 }
188
189 public void returnObject(final T object) {
190 pool.add(object);
191 }
192
193 protected abstract T createObject();
194 }
195
196 /**
197 *
198 */
199 class StringBuilderPool extends ObjectPool<StringBuilder> {
200 private final int initialSize;
201
202 public StringBuilderPool(final int stringBuilderSize) {
203 this.initialSize = stringBuilderSize;
204 }
205
206 @Override
207 public void returnObject(final StringBuilder stringBuilder) {
208 stringBuilder.setLength(0);
209 super.returnObject(stringBuilder);
210 }
211
212 @Override
213 protected StringBuilder createObject() {
214 return new StringBuilder(initialSize);
215 }
216 }
1717 package org.apache.logging.log4j.perf.jmh;
1818
1919 import java.text.SimpleDateFormat;
20 import java.time.LocalDateTime;
21 import java.time.format.DateTimeFormatter;
2220 import java.util.Date;
2321 import java.util.concurrent.TimeUnit;
2422 import java.util.concurrent.atomic.AtomicReference;
5048 public class ThreadsafeDateFormatBenchmark {
5149
5250 private final Date date = new Date();
53 private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
5451 private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
55 private final ThreadLocal<SimpleDateFormat> threadLocalSDFormat = new ThreadLocal<>() {
52 private final ThreadLocal<SimpleDateFormat> threadLocalSDFormat = new ThreadLocal<SimpleDateFormat>() {
5653 @Override
5754 protected SimpleDateFormat initialValue() {
5855 return new SimpleDateFormat("HH:mm:ss.SSS");
5956 }
6057 };
6158
62 private final ThreadLocal<FormatterSimple> threadLocalCachedSDFormat = new ThreadLocal<>() {
59 private final ThreadLocal<FormatterSimple> threadLocalCachedSDFormat = new ThreadLocal<FormatterSimple>() {
6360 @Override
6461 protected FormatterSimple initialValue() {
6562 return new FormatterSimple();
112109 private final FixedDateFormat customFormat = FixedDateFormat.createIfSupported("HH:mm:ss.SSS");
113110 private long timestamp;
114111 private String formatted;
115 private final ThreadLocal<char[]> reusableBuffer = new ThreadLocal<>() {
112 private final ThreadLocal<char[]> reusableBuffer = new ThreadLocal<char[]>() {
116113 @Override
117114 protected char[] initialValue() {
118115 return new char[255];
165162 @Benchmark
166163 @BenchmarkMode(Mode.SampleTime)
167164 @OutputTimeUnit(TimeUnit.NANOSECONDS)
168 public String dateTimeFormatter() {
169 final LocalDateTime now = LocalDateTime.now();
170 return dateTimeFormatter.format(now);
171 }
172
173 @Benchmark
174 @BenchmarkMode(Mode.SampleTime)
175 @OutputTimeUnit(TimeUnit.NANOSECONDS)
176165 public String threadLocalSimpleDateFmt() {
177166 final long timestamp = System.currentTimeMillis();
178167 return threadLocalSDFormat.get().format(timestamp);
4848 @State(Scope.Benchmark)
4949 public class TimeFormatBenchmark {
5050
51 ThreadLocal<SimpleDateFormat> threadLocalSimpleDateFormat = new ThreadLocal<>() {
51 ThreadLocal<SimpleDateFormat> threadLocalSimpleDateFormat = new ThreadLocal<SimpleDateFormat>() {
5252 @Override
5353 protected SimpleDateFormat initialValue() {
5454 return new SimpleDateFormat("HH:mm:ss.SSS");
5555 }
5656 };
5757 FastDateFormat fastDateFormat = FastDateFormat.getInstance("HH:mm:ss.SSS");
58 FixedDateFormat fixedDateFormat = FixedDateFormat.createIfSupported("ABSOLUTE");
59 volatile long midnightToday;
60 volatile long midnightTomorrow;
58 FixedDateFormat fixedDateFormat = FixedDateFormat.createIfSupported(new String[]{"ABSOLUTE"});
59 volatile long midnightToday = 0;
60 volatile long midnightTomorrow = 0;
6161
6262 @State(Scope.Thread)
6363 public static class BufferState {
3838 private long id = 0L;
3939
4040 public TestBasicEntity() {
41 super();
4142 }
4243
4344 public TestBasicEntity(final LogEvent wrapped) {
3535 * For this demo we cannot
3636 * </p>
3737 */
38 public class NoGcLayout implements Layout<Serializable> {
39
40 private static final byte[] EMPTY_BYTE_ARRAY = {};
41
38 public class NoGcLayout implements Layout<Serializable>, Encoder<LogEvent> {
4239 private final StringBuilder cachedStringBuilder = new StringBuilder(2048);
4340 private final PatternSerializer2 serializer = new PatternSerializer2();
4441 private final StringBuilderEncoder cachedHelper;
8683 }
8784
8885 private PatternSerializer2(final PatternFormatter[] formatters) {
86 super();
8987 this.formatters = formatters;
9088 }
9189
105103
106104 @Override
107105 public byte[] getFooter() {
108 return EMPTY_BYTE_ARRAY;
106 return new byte[0];
109107 }
110108
111109 @Override
112110 public byte[] getHeader() {
113 return EMPTY_BYTE_ARRAY;
111 return new byte[0];
114112 }
115113
116114 @Override
188188 }
189189 }
190190 private static final TriConsumer<String, Object, StringMap> PUT_ALL =
191 (key, value, contextData) -> contextData.putValue(key, value);
191 new TriConsumer<String, Object, StringMap>() {
192 @Override
193 public void accept(final String key, final Object value, final StringMap contextData) {
194 contextData.putValue(key, value);
195 }
196 };
192197
193198 private void assertNotFrozen() {
194199 if (immutable) {
241246 }
242247
243248 private static final TriConsumer<String, Object, Map<String, String>> COPY_INTO_MAP =
244 (k, v, map) -> map.put(k, v == null ? null : v.toString());
249 new TriConsumer<String, Object, Map<String, String>>() {
250 @Override
251 public void accept(final String k, final Object v, final Map<String, String> map) {
252 map.put(k, v == null ? null : v.toString());
253 }
254 };
245255
246256 /*
247257 * Removes all elements from this map.
476486 assertNotFrozen();
477487 assertNoConcurrentModification();
478488
479 if (isEmpty() && source instanceof OpenHashStringMap) {
489 if (size() == 0 && source instanceof OpenHashStringMap) {
480490 initFrom0((OpenHashStringMap) source);
481491 } else if (source != null) {
482492 source.forEach(PUT_ALL, this);
759769 }
760770
761771 private static final TriConsumer<String, Object, ObjectOutputStream> SERIALIZER =
762 (k, v, objectOutputStream) -> {
763 try {
764 objectOutputStream.writeObject(k);
765 objectOutputStream.writeObject(v);
766 } catch (final IOException ioex) {
767 throw new IllegalStateException(ioex);
768 }
769 };
772 new TriConsumer<String, Object, ObjectOutputStream>() {
773 @Override
774 public void accept(final String k, final Object v, final ObjectOutputStream objectOutputStream) {
775 try {
776 objectOutputStream.writeObject(k);
777 objectOutputStream.writeObject(v);
778 } catch (final IOException ioex) {
779 throw new IllegalStateException(ioex);
780 }
781 }
782 };
770783
771784 @Override
772785 public String toString() {
+0
-45
log4j-perf/src/main/java/org/apache/logging/log4j/perf/util/StackDriver.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.logging.log4j.perf.util;
17
18 import java.util.function.BiFunction;
19 import java.util.function.Function;
20
21 /**
22 * Facilitates creating a Call Stack for testing the performance of walkign it.
23 */
24 public class StackDriver {
25 public StackTraceElement deepCall(int initialDepth, Integer targetDepth, Function<String, StackTraceElement> supplier) {
26 if (--initialDepth == 0) {
27 Processor processor = new Processor();
28 return processor.apply(targetDepth, supplier);
29 }
30 return deepCall(initialDepth, targetDepth, supplier);
31 }
32
33 public static class Processor implements BiFunction<Integer, Function<String, StackTraceElement>, StackTraceElement> {
34 private static final String FQCN = Processor.class.getName();
35
36 @Override
37 public StackTraceElement apply(Integer depth, Function<String, StackTraceElement> function) {
38 if (--depth == 0) {
39 return function.apply(FQCN);
40 }
41 return apply(depth, function);
42 }
43 }
44 }
3232 <Logger name="RAFExtendedException" level="debug" additivity="false">
3333 <AppenderRef ref="RAFExtendedException"/>
3434 </Logger>
35 <AsyncLogger name="async.RAFExtendedException" level="debug" additivity="false">
35 <Logger name="async.RAFExtendedException" level="debug" additivity="false">
3636 <AppenderRef ref="RAFExtendedException"/>
37 </AsyncLogger>
37 </Logger>
3838 <Logger name="RAFSimpleException" level="debug" additivity="false">
3939 <AppenderRef ref="RAFSimpleException"/>
4040 </Logger>
+0
-32
log4j-perf/src/main/resources/log4j2-perf3.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration name="XMLPerfTest" status="OFF">
19 <Appenders>
20 <File name="TestLogfile" fileName="target/testlog4j2.log" immediateFlush="false">
21 <PatternLayout>
22 <Pattern>%d %5p [%t] %c{1} %X{transactionId} - %m%n</Pattern>
23 </PatternLayout>
24 </File>
25 </Appenders>
26 <Loggers>
27 <Root level="debug">
28 <AppenderRef ref="TestLogfile"/>
29 </Root>
30 </Loggers>
31 </Configuration>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <artifactId>log4j-samples-configuration</artifactId>
2525 <packaging>jar</packaging>
2727 <url>http://maven.apache.org</url>
2828 <properties>
2929 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
30 <log4jParentDir>${basedir}/../..</log4jParentDir>
3130 </properties>
3231 <dependencies>
3332 <dependency>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-common</artifactId>
2525 <packaging>jar</packaging>
2727 <url>http://maven.apache.org</url>
2828 <properties>
2929 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
30 <log4jParentDir>${basedir}/../..</log4jParentDir>
3130 </properties>
3231 <dependencies>
3332 <dependency>
4444 */
4545 private static Logger logger = LogManager.getLogger(LoggingController.class);
4646
47 private volatile boolean generateLog;
47 private volatile boolean generateLog = false;
4848 private final Random ran = new Random();
4949
5050 private List<AuditEvent> events;
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-embedded</artifactId>
2525 <packaging>war</packaging>
2828 <properties>
2929 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3030 <deploy.plugin.version>2.8.2</deploy.plugin.version>
31 <log4jParentDir>${basedir}/../..</log4jParentDir>
3231 </properties>
3332 <dependencies>
3433 <dependency>
139138 <groupId>org.apache.felix</groupId>
140139 <artifactId>maven-bundle-plugin</artifactId>
141140 </plugin>
141 <plugin>
142 <groupId>org.apache.maven.plugins</groupId>
143 <artifactId>maven-deploy-plugin</artifactId>
144 <version>${deploy.plugin.version}</version>
145 <configuration>
146 <skip>true</skip>
147 </configuration>
148 </plugin>
142149 </plugins>
143150 </build>
144151 </project>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-remote</artifactId>
2525 <packaging>war</packaging>
2828 <properties>
2929 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3030 <deploy.plugin.version>2.8.2</deploy.plugin.version>
31 <log4jParentDir>${basedir}/../..</log4jParentDir>
3231 </properties>
3332 <dependencies>
3433 <dependency>
127126 <groupId>org.apache.felix</groupId>
128127 <artifactId>maven-bundle-plugin</artifactId>
129128 </plugin>
129 <plugin>
130 <groupId>org.apache.maven.plugins</groupId>
131 <artifactId>maven-deploy-plugin</artifactId>
132 <version>${deploy.plugin.version}</version>
133 <configuration>
134 <skip>true</skip>
135 </configuration>
136 </plugin>
130137 </plugins>
131138 </build>
132139 </project>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <artifactId>log4j-samples-loggerProperties</artifactId>
2525 <packaging>jar</packaging>
2727 <url>http://maven.apache.org</url>
2828 <properties>
2929 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
30 <log4jParentDir>${basedir}/../..</log4jParentDir>
3130 </properties>
3231 <dependencies>
3332 <dependency>
2323 import org.apache.logging.log4j.core.lookup.AbstractLookup;
2424 import org.apache.logging.log4j.core.lookup.StrLookup;
2525 import org.apache.logging.log4j.message.MapMessage;
26 import org.apache.logging.log4j.message.StringMapMessage;
2627 import org.apache.logging.log4j.message.Message;
2728 import org.apache.logging.log4j.status.StatusLogger;
2829
6364 return mapMessage.get(key);
6465 } catch (final Exception ex) {
6566 LOGGER.warn(LOOKUP, "Error while getting property [{}].", key, ex);
67 return null;
6668 }
6769 }
6870 return null;
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <groupId>org.apache.logging.log4j.samples</groupId>
7272 <dependency>
7373 <groupId>junit</groupId>
7474 <artifactId>junit</artifactId>
75 <version>${junitVersion}</version>
75 <version>4.12</version>
7676 <scope>test</scope>
7777 </dependency>
7878 </dependencies>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-slf4j-impl</artifactId>
3030 <log4jParentDir>${basedir}/..</log4jParentDir>
3131 <docLabel>SLF4J Documentation</docLabel>
3232 <projectDir>/slf4j-impl</projectDir>
33 <!-- Do not upgrade the SLF4J version. 1.7.26 broke backward compatibility. Users can update the version if
34 they do not require support for SLF4J's EventData -->
3533 <slf4j.version>1.7.25</slf4j.version>
36 <module.name>org.apache.logging.log4j.slf4j</module.name>
37 <maven.doap.skip>true</maven.doap.skip>
3834 </properties>
3935 <dependencies>
4036 <dependency>
8682 <version>${project.version}</version>
8783 </dependency>
8884 <dependency>
89 <groupId>org.junit.vintage</groupId>
90 <artifactId>junit-vintage-engine</artifactId>
91 </dependency>
92 <dependency>
93 <groupId>org.junit.jupiter</groupId>
94 <artifactId>junit-jupiter-engine</artifactId>
85 <groupId>junit</groupId>
86 <artifactId>junit</artifactId>
87 <scope>test</scope>
9588 </dependency>
9689 </dependencies>
9790 <build>
133126 <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
134127 <X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
135128 <X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
136 <Automatic-Module-Name>${module.name}</Automatic-Module-Name>
137129 </manifestEntries>
138130 </archive>
139131 </configuration>
266258 </reportSets>
267259 </plugin>
268260 <plugin>
269 <groupId>com.github.spotbugs</groupId>
270 <artifactId>spotbugs-maven-plugin</artifactId>
261 <groupId>org.codehaus.mojo</groupId>
262 <artifactId>findbugs-maven-plugin</artifactId>
263 <version>${findbugs.plugin.version}</version>
264 <configuration>
265 <fork>true</fork>
266 <jvmArgs>-Duser.language=en</jvmArgs>
267 <threshold>Normal</threshold>
268 <effort>Default</effort>
269 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
270 </configuration>
271271 </plugin>
272272 <plugin>
273273 <groupId>org.apache.maven.plugins</groupId>
4141
4242 private static final long serialVersionUID = 7869000638091304316L;
4343 private static final Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT");
44 private static final EventDataConverter CONVERTER = createConverter();
45
4644 private final boolean eventLogger;
4745 private transient ExtendedLogger logger;
4846 private final String name;
47 private transient EventDataConverter converter;
4948
5049 public Log4jLogger(final ExtendedLogger logger, final String name) {
5150 this.logger = logger;
5251 this.eventLogger = "EventLogger".equals(name);
5352 this.name = name;
53 this.converter = createConverter();
5454 }
5555
5656 @Override
362362 return;
363363 }
364364 final Message msg;
365 if (CONVERTER != null && eventLogger && marker != null && marker.contains(EVENT_MARKER)) {
366 msg = CONVERTER.convertEvent(message, params, throwable);
365 if (eventLogger && marker != null && marker.contains(EVENT_MARKER) && converter != null) {
366 msg = converter.convertEvent(message, params, throwable);
367367 } else if (params == null) {
368368 msg = new SimpleMessage(message);
369369 } else {
399399 // always perform the default de-serialization first
400400 aInputStream.defaultReadObject();
401401 logger = LogManager.getContext().getLogger(name);
402 converter = createConverter();
402403 }
403404
404405 /**
1919 import org.apache.logging.log4j.LoggingException;
2020 import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
2121 import org.apache.logging.log4j.spi.LoggerContext;
22 import org.apache.logging.log4j.status.StatusLogger;
2322 import org.apache.logging.log4j.util.StackLocatorUtil;
2423 import org.slf4j.ILoggerFactory;
2524 import org.slf4j.Logger;
26
27 import java.util.function.Predicate;
2825
2926 /**
3027 * Log4j implementation of SLF4J ILoggerFactory interface.
3128 */
3229 public class Log4jLoggerFactory extends AbstractLoggerAdapter<Logger> implements ILoggerFactory {
3330
34 private static final StatusLogger LOGGER = StatusLogger.getLogger();
35 private static final String SLF4J_PACKAGE = "org.slf4j";
31 private static final String FQCN = Log4jLoggerFactory.class.getName();
32 private static final String PACKAGE = "org.slf4j";
3633 private static final String TO_SLF4J_CONTEXT = "org.apache.logging.slf4j.SLF4JLoggerContext";
37 private static final Predicate<Class<?>> CALLER_PREDICATE = clazz ->
38 !AbstractLoggerAdapter.class.equals(clazz) && !clazz.getName().startsWith(SLF4J_PACKAGE);
3934
4035 @Override
4136 protected Logger newLogger(final String name, final LoggerContext context) {
4540
4641 @Override
4742 protected LoggerContext getContext() {
48 final Class<?> anchor = LogManager.getFactory().isClassLoaderDependent()
49 ? StackLocatorUtil.getCallerClass(Log4jLoggerFactory.class, CALLER_PREDICATE)
50 : null;
51 LOGGER.trace("Log4jLoggerFactory.getContext() found anchor {}", anchor);
52 return anchor == null
53 ? LogManager.getContext(false)
54 : getContext(anchor);
43 final Class<?> anchor = StackLocatorUtil.getCallerClass(FQCN, PACKAGE);
44 return anchor == null ? LogManager.getContext() : getContext(StackLocatorUtil.getCallerClass(anchor));
5545 }
56
5746 private LoggerContext validateContext(final LoggerContext context) {
5847 if (TO_SLF4J_CONTEXT.equals(context.getClass().getName())) {
5948 throw new LoggingException("log4j-slf4j-impl cannot be present with log4j-to-slf4j");
5454 @SuppressWarnings("unchecked") // nothing we can do about this, restricted by SLF4J API
5555 public void setContextMap(@SuppressWarnings("rawtypes") final Map map) {
5656 ThreadContext.clearMap();
57 ThreadContext.putAll(map);
57 for (final Map.Entry<String, String> entry : ((Map<String, String>) map).entrySet()) {
58 ThreadContext.put(entry.getKey(), entry.getValue());
59 }
5860 }
5961 }
1818 import java.util.ArrayList;
1919 import java.util.Iterator;
2020 import java.util.List;
21 import java.util.Objects;
2221
2322 import org.apache.logging.log4j.MarkerManager;
2423 import org.slf4j.IMarkerFactory;
7877 return false;
7978 }
8079 final Log4jMarker other = (Log4jMarker) obj;
81 if (!Objects.equals(marker, other.marker)) {
80 if (marker == null) {
81 if (other.marker != null) {
82 return false;
83 }
84 } else if (!marker.equals(other.marker)) {
8285 return false;
8386 }
8487 return true;
100103
101104 @Override
102105 public int hashCode() {
103 return 31 + Objects.hashCode(marker);
106 final int prime = 31;
107 int result = 1;
108 result = prime * result + ((marker == null) ? 0 : marker.hashCode());
109 return result;
104110 }
105111
106112 @Override
3232 }
3333
3434 /**
35 * Returns the {@link #SINGLETON} {@link StaticMDCBinder}.
36 * Added to slf4j-api 1.7.14 via https://github.com/qos-ch/slf4j/commit/ea3cca72cd5a9329a06b788317a17e806ee8acd0
37 * @return the singleton instance
38 */
39 public static StaticMDCBinder getSingleton() {
40 return SINGLETON;
41 }
42
43 /**
4435 * Currently this method always returns an instance of {@link StaticMDCBinder}.
4536 * @return an MDC adapter
4637 */
3232
3333 private final IMarkerFactory markerFactory = new Log4jMarkerFactory();
3434
35 /**
36 * Returns the {@link #SINGLETON} {@link StaticMarkerBinder}.
37 * Added to slf4j-api 1.7.14 via https://github.com/qos-ch/slf4j/commit/ea3cca72cd5a9329a06b788317a17e806ee8acd0
38 * @return the singleton instance
39 */
40 public static StaticMarkerBinder getSingleton() {
41 return SINGLETON;
42 }
43
4435 @Override
4536 public IMarkerFactory getMarkerFactory() {
4637 return markerFactory;
+0
-91
log4j-slf4j-impl/src/test/java/org/apache/logging/other/pkg/LoggerContextAnchorTest.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.logging.other.pkg;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.status.StatusData;
20 import org.apache.logging.log4j.status.StatusListener;
21 import org.apache.logging.log4j.status.StatusLogger;
22 import org.junit.Test;
23 import org.slf4j.LoggerFactory;
24
25 import java.util.List;
26 import java.util.concurrent.CopyOnWriteArrayList;
27
28 import static org.junit.Assert.assertEquals;
29
30 /**
31 * Test LoggerContext lookups by verifying the anchor class representing calling code.
32 */
33 public class LoggerContextAnchorTest {
34 private static final String PREFIX = "Log4jLoggerFactory.getContext() found anchor class ";
35
36 @Test
37 public void testLoggerFactoryLookupClass() {
38 String fqcn = getAnchorFqcn(() -> LoggerFactory.getLogger(LoggerContextAnchorTest.class));
39 assertEquals(getClass().getName(), fqcn);
40 }
41
42 @Test
43 public void testLoggerFactoryLookupString() {
44 String fqcn = getAnchorFqcn(() -> LoggerFactory.getLogger("custom.logger"));
45 assertEquals(getClass().getName(), fqcn);
46 }
47
48 @Test
49 public void testLoggerFactoryGetILoggerFactoryLookup() {
50 String fqcn = getAnchorFqcn(() -> LoggerFactory.getILoggerFactory().getLogger("custom.logger"));
51 assertEquals(getClass().getName(), fqcn);
52 }
53
54 private static String getAnchorFqcn(Runnable runnable) {
55 List<String> results = new CopyOnWriteArrayList<>();
56 StatusListener listener = new StatusListener() {
57 @Override
58 public void log(StatusData data) {
59 String formattedMessage = data.getMessage().getFormattedMessage();
60 if (formattedMessage.startsWith(PREFIX)) {
61 results.add(formattedMessage.substring(PREFIX.length()));
62 }
63 }
64
65 @Override
66 public Level getStatusLevel() {
67 return Level.TRACE;
68 }
69
70 @Override
71 public void close() {
72 // nop
73 }
74 };
75 StatusLogger statusLogger = StatusLogger.getLogger();
76 statusLogger.registerListener(listener);
77 try {
78 runnable.run();
79 if (results.isEmpty()) {
80 throw new AssertionError("Failed to locate an anchor lookup status message");
81 }
82 if (results.size() > 1) {
83 throw new AssertionError("Found multiple anchor lines: " + results);
84 }
85 return results.get(0);
86 } finally {
87 statusLogger.removeListener(listener);
88 }
89 }
90 }
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-slf4j18-impl</artifactId>
3030 <log4jParentDir>${basedir}/..</log4jParentDir>
3131 <docLabel>SLF4J Documentation</docLabel>
3232 <projectDir>/slf4j18</projectDir>
33 <slf4j.version>1.8.0-beta4</slf4j.version>
33 <slf4j.version>1.8.0-alpha2</slf4j.version>
3434 <module.name>org.apache.logging.log4j.slf4j</module.name>
35 <maven.doap.skip>true</maven.doap.skip>
3635 </properties>
3736 <dependencies>
3837 <dependency>
8483 <version>${project.version}</version>
8584 </dependency>
8685 <dependency>
87 <groupId>org.junit.vintage</groupId>
88 <artifactId>junit-vintage-engine</artifactId>
89 </dependency>
90 <dependency>
91 <groupId>org.junit.jupiter</groupId>
92 <artifactId>junit-jupiter-engine</artifactId>
86 <groupId>junit</groupId>
87 <artifactId>junit</artifactId>
88 <scope>test</scope>
9389 </dependency>
9490 </dependencies>
9591 <build>
219215 </reportSets>
220216 </plugin>
221217 <plugin>
222 <groupId>com.github.spotbugs</groupId>
223 <artifactId>spotbugs-maven-plugin</artifactId>
218 <groupId>org.codehaus.mojo</groupId>
219 <artifactId>findbugs-maven-plugin</artifactId>
220 <version>${findbugs.plugin.version}</version>
221 <configuration>
222 <fork>true</fork>
223 <jvmArgs>-Duser.language=en</jvmArgs>
224 <threshold>Normal</threshold>
225 <effort>Default</effort>
226 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
227 </configuration>
224228 </plugin>
225229 <plugin>
226230 <groupId>org.apache.maven.plugins</groupId>
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.slf4j;
17
18 import java.util.Map;
19
20 import org.apache.logging.log4j.message.Message;
21 import org.apache.logging.log4j.message.ParameterizedMessage;
22 import org.apache.logging.log4j.message.StructuredDataMessage;
23 import org.slf4j.ext.EventData;
24
25 /**
26 *
27 */
28 public class EventDataConverter {
29
30 public Message convertEvent(final String message, final Object[] objects, final Throwable throwable) {
31 try {
32 final EventData data = objects != null && objects[0] instanceof EventData ?
33 (EventData) objects[0] : new EventData(message);
34 final StructuredDataMessage msg =
35 new StructuredDataMessage(data.getEventId(), data.getMessage(), data.getEventType());
36 for (final Map.Entry<String, Object> entry : data.getEventMap().entrySet()) {
37 final String key = entry.getKey();
38 if (EventData.EVENT_TYPE.equals(key) || EventData.EVENT_ID.equals(key)
39 || EventData.EVENT_MESSAGE.equals(key)) {
40 continue;
41 }
42 msg.put(key, String.valueOf(entry.getValue()));
43 }
44 return msg;
45 } catch (final Exception ex) {
46 return new ParameterizedMessage(message, objects, throwable);
47 }
48 }
49 }
2626 import org.apache.logging.log4j.message.ParameterizedMessage;
2727 import org.apache.logging.log4j.message.SimpleMessage;
2828 import org.apache.logging.log4j.spi.ExtendedLogger;
29 import org.apache.logging.log4j.util.LoaderUtil;
2930 import org.slf4j.Marker;
31 import org.slf4j.MarkerFactory;
3032 import org.slf4j.spi.LocationAwareLogger;
3133
3234 /**
3739 public static final String FQCN = Log4jLogger.class.getName();
3840
3941 private static final long serialVersionUID = 7869000638091304316L;
42 private static final Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT");
43 private final boolean eventLogger;
4044 private transient ExtendedLogger logger;
4145 private final String name;
46 private transient EventDataConverter converter;
4247 private transient Log4jMarkerFactory markerFactory;
4348
4449 public Log4jLogger(final Log4jMarkerFactory markerFactory, final ExtendedLogger logger, final String name) {
4550 this.markerFactory = markerFactory;
4651 this.logger = logger;
52 this.eventLogger = "EventLogger".equals(name);
4753 this.name = name;
54 this.converter = createConverter();
4855 }
4956
5057 @Override
356363 return;
357364 }
358365 final Message msg;
359 if (params == null) {
366 if (eventLogger && marker != null && marker.contains(EVENT_MARKER) && converter != null) {
367 msg = converter.convertEvent(message, params, throwable);
368 } else if (params == null) {
360369 msg = new SimpleMessage(message);
361370 } else {
362371 msg = new ParameterizedMessage(message, params, throwable);
390399 // always perform the default de-serialization first
391400 aInputStream.defaultReadObject();
392401 logger = LogManager.getContext().getLogger(name);
402 converter = createConverter();
393403 markerFactory = ((Log4jLoggerFactory) org.slf4j.LoggerFactory.getILoggerFactory()).getMarkerFactory();
394404 }
395405
399409 private void writeObject(final ObjectOutputStream aOutputStream) throws IOException {
400410 // perform the default serialization for all non-transient, non-static fields
401411 aOutputStream.defaultWriteObject();
412 }
413
414 private static EventDataConverter createConverter() {
415 try {
416 LoaderUtil.loadClass("org.slf4j.ext.EventData");
417 return new EventDataConverter();
418 } catch (final ClassNotFoundException cnfe) {
419 return null;
420 }
402421 }
403422
404423 private static Level getLevel(final int i) {
1919 import org.apache.logging.log4j.LoggingException;
2020 import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
2121 import org.apache.logging.log4j.spi.LoggerContext;
22 import org.apache.logging.log4j.status.StatusLogger;
2322 import org.apache.logging.log4j.util.StackLocatorUtil;
2423 import org.slf4j.ILoggerFactory;
2524 import org.slf4j.Logger;
26
27 import java.util.function.Predicate;
2825
2926 /**
3027 * Log4j implementation of SLF4J ILoggerFactory interface.
3128 */
3229 public class Log4jLoggerFactory extends AbstractLoggerAdapter<Logger> implements ILoggerFactory {
3330
34 private static final StatusLogger LOGGER = StatusLogger.getLogger();
35 private static final String SLF4J_PACKAGE = "org.slf4j";
36 private static final Predicate<Class<?>> CALLER_PREDICATE = clazz ->
37 !AbstractLoggerAdapter.class.equals(clazz) && !clazz.getName().startsWith(SLF4J_PACKAGE);
31 private static final String FQCN = Log4jLoggerFactory.class.getName();
32 private static final String PACKAGE = "org.slf4j";
33 private final Log4jMarkerFactory markerFactory;
3834 private static final String TO_SLF4J_CONTEXT = "org.apache.logging.slf4j.SLF4JLoggerContext";
39
40 private final Log4jMarkerFactory markerFactory;
4135
4236 public Log4jLoggerFactory(final Log4jMarkerFactory markerFactory) {
4337 this.markerFactory = markerFactory;
5246
5347 @Override
5448 protected LoggerContext getContext() {
55 final Class<?> anchor = LogManager.getFactory().isClassLoaderDependent()
56 ? StackLocatorUtil.getCallerClass(Log4jLoggerFactory.class, CALLER_PREDICATE)
57 : null;
58 LOGGER.trace("Log4jLoggerFactory.getContext() found anchor {}", anchor);
59 return anchor == null
60 ? LogManager.getContext(false)
61 : getContext(anchor);
49 final Class<?> anchor = StackLocatorUtil.getCallerClass(FQCN, PACKAGE);
50 return anchor == null ? LogManager.getContext() : getContext(StackLocatorUtil.getCallerClass(anchor));
6251 }
6352
6453 Log4jMarkerFactory getMarkerFactory() {
5454 @SuppressWarnings("unchecked") // nothing we can do about this, restricted by SLF4J API
5555 public void setContextMap(@SuppressWarnings("rawtypes") final Map map) {
5656 ThreadContext.clearMap();
57 ThreadContext.putAll(map);
57 for (final Map.Entry<String, String> entry : ((Map<String, String>) map).entrySet()) {
58 ThreadContext.put(entry.getKey(), entry.getValue());
59 }
5860 }
5961 }
1818 import java.util.ArrayList;
1919 import java.util.Iterator;
2020 import java.util.List;
21 import java.util.Objects;
2221
2322 import org.apache.logging.log4j.MarkerManager;
2423 import org.slf4j.IMarkerFactory;
7877 return false;
7978 }
8079 final Log4jMarker other = (Log4jMarker) obj;
81 if (!Objects.equals(marker, other.marker)) {
80 if (marker == null) {
81 if (other.marker != null) {
82 return false;
83 }
84 } else if (!marker.equals(other.marker)) {
8285 return false;
8386 }
8487 return true;
100103
101104 @Override
102105 public int hashCode() {
103 return 31 + Objects.hashCode(marker);
106 final int prime = 31;
107 int result = 1;
108 result = prime * result + ((marker == null) ? 0 : marker.hashCode());
109 return result;
104110 }
105111
106112 @Override
+0
-91
log4j-slf4j18-impl/src/test/java/org/apache/logging/other/pkg/LoggerContextAnchorTest.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.logging.other.pkg;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.status.StatusData;
20 import org.apache.logging.log4j.status.StatusListener;
21 import org.apache.logging.log4j.status.StatusLogger;
22 import org.junit.Test;
23 import org.slf4j.LoggerFactory;
24
25 import java.util.List;
26 import java.util.concurrent.CopyOnWriteArrayList;
27
28 import static org.junit.Assert.assertEquals;
29
30 /**
31 * Test LoggerContext lookups by verifying the anchor class representing calling code.
32 */
33 public class LoggerContextAnchorTest {
34 private static final String PREFIX = "Log4jLoggerFactory.getContext() found anchor class ";
35
36 @Test
37 public void testLoggerFactoryLookupClass() {
38 String fqcn = getAnchorFqcn(() -> LoggerFactory.getLogger(LoggerContextAnchorTest.class));
39 assertEquals(getClass().getName(), fqcn);
40 }
41
42 @Test
43 public void testLoggerFactoryLookupString() {
44 String fqcn = getAnchorFqcn(() -> LoggerFactory.getLogger("custom.logger"));
45 assertEquals(getClass().getName(), fqcn);
46 }
47
48 @Test
49 public void testLoggerFactoryGetILoggerFactoryLookup() {
50 String fqcn = getAnchorFqcn(() -> LoggerFactory.getILoggerFactory().getLogger("custom.logger"));
51 assertEquals(getClass().getName(), fqcn);
52 }
53
54 private static String getAnchorFqcn(Runnable runnable) {
55 List<String> results = new CopyOnWriteArrayList<>();
56 StatusListener listener = new StatusListener() {
57 @Override
58 public void log(StatusData data) {
59 String formattedMessage = data.getMessage().getFormattedMessage();
60 if (formattedMessage.startsWith(PREFIX)) {
61 results.add(formattedMessage.substring(PREFIX.length()));
62 }
63 }
64
65 @Override
66 public Level getStatusLevel() {
67 return Level.TRACE;
68 }
69
70 @Override
71 public void close() {
72 // nop
73 }
74 };
75 StatusLogger statusLogger = StatusLogger.getLogger();
76 statusLogger.registerListener(listener);
77 try {
78 runnable.run();
79 if (results.isEmpty()) {
80 throw new AssertionError("Failed to locate an anchor lookup status message");
81 }
82 if (results.size() > 1) {
83 throw new AssertionError("Found multiple anchor lines: " + results);
84 }
85 return results.get(0);
86 } finally {
87 statusLogger.removeListener(listener);
88 }
89 }
90 }
2020 import static org.junit.Assert.assertTrue;
2121
2222 import java.util.List;
23 import java.util.Locale;
2324
2425 import org.apache.logging.log4j.junit.LoggerContextRule;
2526 import org.apache.logging.log4j.test.appender.ListAppender;
3233 import org.slf4j.LoggerFactory;
3334 import org.slf4j.MDC;
3435 import org.slf4j.Marker;
36 import org.slf4j.ext.EventData;
37 import org.slf4j.ext.EventLogger;
3538 import org.slf4j.ext.XLogger;
3639 import org.slf4j.ext.XLoggerFactory;
3740 import org.slf4j.spi.LocationAwareLogger;
141144 verify("List", "o.a.l.s.LoggerTest Hello, Log4j Log4j {} MDC{}" + Strings.LINE_SEPARATOR);
142145 }
143146
147 @Test
148 public void testEventLogger() {
149 MDC.put("loginId", "JohnDoe");
150 MDC.put("ipAddress", "192.168.0.120");
151 MDC.put("locale", Locale.US.getDisplayName());
152 final EventData data = new EventData();
153 data.setEventType("Transfer");
154 data.setEventId("Audit@18060");
155 data.setMessage("Transfer Complete");
156 data.put("ToAccount", "123456");
157 data.put("FromAccount", "123457");
158 data.put("Amount", "200.00");
159 EventLogger.logEvent(data);
160 MDC.clear();
161 verify("EventLogger", "o.a.l.s.LoggerTest Transfer [Audit@18060 Amount=\"200.00\" FromAccount=\"123457\" ToAccount=\"123456\"] Transfer Complete" + Strings.LINE_SEPARATOR);
162 }
163
144164 private void verify(final String name, final String expected) {
145165 final ListAppender listApp = ctx.getListAppender(name);
146166 assertNotNull("Missing Appender", listApp);
156176 public void cleanup() {
157177 MDC.clear();
158178 ctx.getListAppender("List").clear();
179 ctx.getListAppender("EventLogger").clear();
159180 }
160181 }
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.slf4j;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.junit.LoggerContextRule;
21 import org.apache.logging.log4j.test.appender.ListAppender;
22 import org.apache.logging.log4j.util.Strings;
23 import org.junit.Before;
24 import org.junit.ClassRule;
25 import org.junit.Test;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.slf4j.MDC;
29 import org.slf4j.Marker;
30 import org.slf4j.MarkerFactory;
31
32 import static org.junit.Assert.*;
33
34 /**
35 *
36 */
37 public class OptionalTest {
38
39 private static final String CONFIG = "log4j-test1.xml";
40
41 @ClassRule
42 public static final LoggerContextRule CTX = new LoggerContextRule(CONFIG);
43
44 Logger logger = LoggerFactory.getLogger("EventLogger");
45 Marker marker = MarkerFactory.getMarker("EVENT");
46
47 @Test
48 public void testEventLogger() {
49 logger.info(marker, "This is a test");
50 MDC.clear();
51 verify("EventLogger", "o.a.l.s.OptionalTest This is a test" + Strings.LINE_SEPARATOR);
52 }
53
54 private void verify(final String name, final String expected) {
55 final ListAppender listApp = CTX.getListAppender(name);
56 final List<String> events = listApp.getMessages();
57 assertTrue("Incorrect number of messages. Expected 1 Actual " + events.size(), events.size()== 1);
58 final String actual = events.get(0);
59 assertEquals("Incorrect message. Expected " + expected + ". Actual " + actual, expected, actual);
60 listApp.clear();
61 }
62
63 @Before
64 public void cleanup() {
65 CTX.getListAppender("List").clear();
66 CTX.getListAppender("EventLogger").clear();
67 }
68 }
55 <ThresholdFilter level="trace"/>
66
77 <Appenders>
8 <List name="EventLogger">
9 <PatternLayout pattern="%C{1.} %m%n"/>
10 </List>
811 <Console name="STDOUT">
912 <PatternLayout pattern="%C{1.} %m MDC%X%n"/>
1013 </Console>
2023 </Appenders>
2124
2225 <Loggers>
26 <Logger name="EventLogger" level="info" additivity="false">
27 <AppenderRef ref="EventLogger"/>
28 </Logger>>
29
2330 <Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
2431 <AppenderRef ref="File"/>
2532 </Logger>
+0
-274
log4j-spring-boot/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
18 <modelVersion>4.0.0</modelVersion>
19 <parent>
20 <groupId>org.apache.logging.log4j</groupId>
21 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
23 <relativePath>../</relativePath>
24 </parent>
25 <artifactId>log4j-spring-boot</artifactId>
26 <packaging>jar</packaging>
27 <name>Apache Log4j Spring Boot Support</name>
28 <description>Apache Log4j Spring Boot Support</description>
29 <properties>
30 <log4jParentDir>${basedir}/..</log4jParentDir>
31 <docLabel>Log4j Spring Boot Documentation</docLabel>
32 <projectDir>/log4j-spring-boot</projectDir>
33 <module.name>org.apache.logging.log4j.spring.boot</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
35 </properties>
36 <dependencyManagement>
37 <dependencies>
38 <dependency>
39 <groupId>org.springframework</groupId>
40 <artifactId>spring-framework-bom</artifactId>
41 <version>${springVersion}</version>
42 <type>pom</type>
43 <scope>import</scope>
44 </dependency>
45 <dependency>
46 <groupId>org.springframework.boot</groupId>
47 <artifactId>spring-boot-dependencies</artifactId>
48 <version>${spring-boot.version}</version>
49 <type>pom</type>
50 <scope>import</scope>
51 </dependency>
52 </dependencies>
53 </dependencyManagement>
54 <dependencies>
55 <dependency>
56 <groupId>org.junit.vintage</groupId>
57 <artifactId>junit-vintage-engine</artifactId>
58 </dependency>
59 <dependency>
60 <groupId>org.junit.jupiter</groupId>
61 <artifactId>junit-jupiter-engine</artifactId>
62 </dependency>
63 <dependency>
64 <groupId>org.apache.logging.log4j</groupId>
65 <artifactId>log4j-api</artifactId>
66 <type>test-jar</type>
67 </dependency>
68 <dependency>
69 <groupId>org.springframework.boot</groupId>
70 <artifactId>spring-boot</artifactId>
71 </dependency>
72 <dependency>
73 <groupId>org.springframework</groupId>
74 <artifactId>spring-context</artifactId>
75 </dependency>
76 <dependency>
77 <groupId>org.springframework</groupId>
78 <artifactId>spring-context-support</artifactId>
79 </dependency>
80 <dependency>
81 <groupId>org.hamcrest</groupId>
82 <artifactId>hamcrest</artifactId>
83 <scope>test</scope>
84 </dependency>
85 <dependency>
86 <groupId>commons-logging</groupId>
87 <artifactId>commons-logging</artifactId>
88 </dependency>
89 <dependency>
90 <groupId>org.apache.logging.log4j</groupId>
91 <artifactId>log4j-api</artifactId>
92 </dependency>
93 <dependency>
94 <groupId>org.apache.logging.log4j</groupId>
95 <artifactId>log4j-core</artifactId>
96 </dependency>
97 <dependency>
98 <groupId>org.apache.logging.log4j</groupId>
99 <artifactId>log4j-core</artifactId>
100 <type>test-jar</type>
101 <scope>test</scope>
102 </dependency>
103 <dependency>
104 <groupId>org.springframework.boot</groupId>
105 <artifactId>spring-boot-starter-test</artifactId>
106 <version>${spring-boot.version}</version>
107 <scope>test</scope>
108 <exclusions>
109 <exclusion>
110 <groupId>org.springframework.boot</groupId>
111 <artifactId>spring-boot-starter-logging</artifactId>
112 </exclusion>
113 </exclusions>
114 </dependency>
115 </dependencies>
116 <build>
117 <plugins>
118 <!-- Include the standard NOTICE and LICENSE -->
119 <plugin>
120 <groupId>org.apache.maven.plugins</groupId>
121 <artifactId>maven-remote-resources-plugin</artifactId>
122 <executions>
123 <execution>
124 <goals>
125 <goal>process</goal>
126 </goals>
127 <configuration>
128 <skip>false</skip>
129 </configuration>
130 </execution>
131 </executions>
132 </plugin>
133 <plugin>
134 <groupId>org.apache.felix</groupId>
135 <artifactId>maven-bundle-plugin</artifactId>
136 <configuration>
137 <instructions>
138 <Export-Package>org.apache.logging.log4j.spring.cloud.config.controller</Export-Package>
139 </instructions>
140 </configuration>
141 </plugin>
142 <plugin>
143 <groupId>org.apache.maven.plugins</groupId>
144 <artifactId>maven-compiler-plugin</artifactId>
145 <executions>
146 <execution>
147 <id>default-compile</id>
148 <phase>compile</phase>
149 <goals>
150 <goal>compile</goal>
151 </goals>
152 </execution>
153 <execution>
154 <id>default-test-compile</id>
155 <phase>test-compile</phase>
156 <goals>
157 <goal>testCompile</goal>
158 </goals>
159 </execution>
160 </executions>
161 <configuration>
162 <source>1.8</source>
163 <target>1.8</target>
164 </configuration>
165 </plugin>
166 <plugin>
167 <groupId>org.apache.maven.plugins</groupId>
168 <artifactId>maven-toolchains-plugin</artifactId>
169 <version>3.0.0</version>
170 <executions>
171 <execution>
172 <goals>
173 <goal>toolchain</goal>
174 </goals>
175 </execution>
176 </executions>
177 <configuration>
178 <toolchains>
179 <jdk>
180 <version>[8, )</version>
181 </jdk>
182 </toolchains>
183 </configuration>
184 </plugin>
185 </plugins>
186 </build>
187 <reporting>
188 <plugins>
189 <plugin>
190 <groupId>org.apache.maven.plugins</groupId>
191 <artifactId>maven-changes-plugin</artifactId>
192 <version>${changes.plugin.version}</version>
193 <reportSets>
194 <reportSet>
195 <reports>
196 <report>changes-report</report>
197 </reports>
198 </reportSet>
199 </reportSets>
200 <configuration>
201 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
202 <useJql>true</useJql>
203 </configuration>
204 </plugin>
205 <plugin>
206 <groupId>org.apache.maven.plugins</groupId>
207 <artifactId>maven-checkstyle-plugin</artifactId>
208 <version>${checkstyle.plugin.version}</version>
209 <configuration>
210 <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
211 <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
212 <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
213 <enableRulesSummary>false</enableRulesSummary>
214 <propertyExpansion>basedir=${basedir}</propertyExpansion>
215 <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
216 </configuration>
217 </plugin>
218 <plugin>
219 <groupId>org.apache.maven.plugins</groupId>
220 <artifactId>maven-javadoc-plugin</artifactId>
221 <version>${javadoc.plugin.version}</version>
222 <configuration>
223 <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
224 Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
225 and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
226 <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating
227 project -->
228 <detectOfflineLinks>false</detectOfflineLinks>
229 <linksource>true</linksource>
230 </configuration>
231 <reportSets>
232 <reportSet>
233 <id>non-aggregate</id>
234 <reports>
235 <report>javadoc</report>
236 </reports>
237 </reportSet>
238 </reportSets>
239 </plugin>
240 <plugin>
241 <groupId>com.github.spotbugs</groupId>
242 <artifactId>spotbugs-maven-plugin</artifactId>
243 </plugin>
244 <plugin>
245 <groupId>org.apache.maven.plugins</groupId>
246 <artifactId>maven-jxr-plugin</artifactId>
247 <version>${jxr.plugin.version}</version>
248 <reportSets>
249 <reportSet>
250 <id>non-aggregate</id>
251 <reports>
252 <report>jxr</report>
253 </reports>
254 </reportSet>
255 <reportSet>
256 <id>aggregate</id>
257 <reports>
258 <report>aggregate</report>
259 </reports>
260 </reportSet>
261 </reportSets>
262 </plugin>
263 <plugin>
264 <groupId>org.apache.maven.plugins</groupId>
265 <artifactId>maven-pmd-plugin</artifactId>
266 <version>${pmd.plugin.version}</version>
267 <configuration>
268 <targetJdk>${maven.compiler.target}</targetJdk>
269 </configuration>
270 </plugin>
271 </plugins>
272 </reporting>
273 </project>
+0
-214
log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystem.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.logging.log4j.spring.boot;
17
18 import java.io.File;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.io.UnsupportedEncodingException;
22 import java.net.MalformedURLException;
23 import java.net.URISyntaxException;
24 import java.net.URL;
25 import java.net.URLConnection;
26 import java.net.URLDecoder;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Properties;
31 import javax.net.ssl.HttpsURLConnection;
32
33 import org.apache.logging.log4j.LogManager;
34 import org.apache.logging.log4j.Logger;
35 import org.apache.logging.log4j.core.LoggerContext;
36 import org.apache.logging.log4j.core.config.AbstractConfiguration;
37 import org.apache.logging.log4j.core.config.Configuration;
38 import org.apache.logging.log4j.core.config.ConfigurationFactory;
39 import org.apache.logging.log4j.core.config.ConfigurationSource;
40 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
41 import org.apache.logging.log4j.core.net.ssl.LaxHostnameVerifier;
42 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
43 import org.apache.logging.log4j.core.net.ssl.SslConfigurationFactory;
44 import org.apache.logging.log4j.core.util.AuthorizationProvider;
45 import org.apache.logging.log4j.core.util.FileUtils;
46 import org.apache.logging.log4j.status.StatusLogger;
47 import org.apache.logging.log4j.util.PropertiesUtil;
48 import org.apache.logging.log4j.util.Strings;
49 import org.springframework.boot.logging.LogFile;
50 import org.springframework.boot.logging.LoggingInitializationContext;
51 import org.springframework.boot.logging.log4j2.Log4J2LoggingSystem;
52 import org.springframework.util.Assert;
53 import org.springframework.util.ClassUtils;
54 import org.springframework.util.ResourceUtils;
55
56 /**
57 * Override Spring's implementation of the Log4j 2 Logging System to properly support Spring Cloud Config.
58 */
59 public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem {
60 private static final String HTTPS = "https";
61 public static final String ENVIRONMENT_KEY = "SpringEnvironment";
62 private static final String OVERRIDE_PARAM = "override";
63 private static Logger LOGGER = StatusLogger.getLogger();
64
65 public Log4j2CloudConfigLoggingSystem(ClassLoader loader) {
66 super(loader);
67 }
68
69 /**
70 * Set the environment into the ExternalContext field so that it can be obtained by SpringLookup when it
71 * is constructed. Spring will replace the ExternalContext field with a String once initialization is
72 * complete.
73 * @param initializationContext The initialization context.
74 * @param configLocation The configuration location.
75 * @param logFile the log file.
76 */
77 @Override
78 public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
79 getLoggerContext().putObjectIfAbsent(ENVIRONMENT_KEY, initializationContext.getEnvironment());
80 super.initialize(initializationContext, configLocation, logFile);
81 }
82
83 @Override
84 protected String[] getStandardConfigLocations() {
85 String[] locations = super.getStandardConfigLocations();
86 PropertiesUtil props = new PropertiesUtil(new Properties());
87 String location = props.getStringProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
88 if (location != null) {
89 List<String> list = new ArrayList<>(Arrays.asList(super.getStandardConfigLocations()));
90 list.add(location);
91 locations = list.toArray(Strings.EMPTY_ARRAY);
92 }
93 return locations;
94 }
95
96 @Override
97 protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) {
98 if (logFile != null) {
99 this.loadConfiguration(this.getBootPackagedConfigFile("log4j2-file.xml"), logFile);
100 } else {
101 this.loadConfiguration(this.getBootPackagedConfigFile("log4j2.xml"), logFile);
102 }
103 }
104
105 private String getBootPackagedConfigFile(String fileName) {
106 String defaultPath = ClassUtils.getPackageName(Log4J2LoggingSystem.class);
107 defaultPath = defaultPath.replace('.', '/');
108 defaultPath = defaultPath + "/" + fileName;
109 defaultPath = "classpath:" + defaultPath;
110 return defaultPath;
111 }
112
113 @Override
114 protected void loadConfiguration(String location, LogFile logFile) {
115 Assert.notNull(location, "Location must not be null");
116 try {
117 LoggerContext ctx = getLoggerContext();
118 String[] locations = parseConfigLocations(location);
119 if (locations.length == 1) {
120 final URL url = ResourceUtils.getURL(location);
121 final ConfigurationSource source = getConfigurationSource(url);
122 if (source != null) {
123 ctx.start(ConfigurationFactory.getInstance().getConfiguration(ctx, source));
124 }
125 } else {
126 final List<AbstractConfiguration> configs = new ArrayList<>();
127 for (final String sourceLocation : locations) {
128 final ConfigurationSource source = getConfigurationSource(ResourceUtils.getURL(sourceLocation));
129 if (source != null) {
130 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(ctx, source);
131 if (config instanceof AbstractConfiguration) {
132 configs.add((AbstractConfiguration) config);
133 } else {
134 LOGGER.warn("Configuration at {} cannot be combined in a CompositeConfiguration", sourceLocation);
135 return;
136 }
137 }
138 }
139 if (configs.size() > 1) {
140 ctx.start(new CompositeConfiguration(configs));
141 } else {
142 ctx.start(configs.get(0));
143 }
144 }
145 }
146 catch (Exception ex) {
147 throw new IllegalStateException(
148 "Could not initialize Log4J2 logging from " + location, ex);
149 }
150 }
151
152 @Override
153 public void cleanUp() {
154 getLoggerContext().removeObject(ENVIRONMENT_KEY);
155 super.cleanUp();
156 }
157
158 private String[] parseConfigLocations(String configLocations) {
159 final String[] uris = configLocations.split("\\?");
160 final List<String> locations = new ArrayList<>();
161 if (uris.length > 1) {
162 locations.add(uris[0]);
163 try {
164 final URL url = new URL(configLocations);
165 final String[] pairs = url.getQuery().split("&");
166 for (String pair : pairs) {
167 final int idx = pair.indexOf("=");
168 try {
169 final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
170 if (key.equalsIgnoreCase(OVERRIDE_PARAM)) {
171 locations.add(URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
172 }
173 } catch (UnsupportedEncodingException ex) {
174 LOGGER.warn("Bad data in configuration string: {}", pair);
175 }
176 }
177 return locations.toArray(Strings.EMPTY_ARRAY);
178 } catch (MalformedURLException ex) {
179 LOGGER.warn("Unable to parse configuration URL {}", configLocations);
180 }
181 }
182 return new String[] {uris[0]};
183 }
184
185 private ConfigurationSource getConfigurationSource(URL url) throws IOException, URISyntaxException {
186 URLConnection urlConnection = url.openConnection();
187 AuthorizationProvider provider = ConfigurationFactory.authorizationProvider(PropertiesUtil.getProperties());
188 provider.addAuthorization(urlConnection);
189 if (url.getProtocol().equals(HTTPS)) {
190 SslConfiguration sslConfiguration = SslConfigurationFactory.getSslConfiguration();
191 if (sslConfiguration != null) {
192 ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslConfiguration.getSslSocketFactory());
193 if (!sslConfiguration.isVerifyHostName()) {
194 ((HttpsURLConnection) urlConnection).setHostnameVerifier(LaxHostnameVerifier.INSTANCE);
195 }
196 }
197 }
198 File file = FileUtils.fileFromUri(url.toURI());
199 try {
200 if (file != null) {
201 return new ConfigurationSource(urlConnection.getInputStream(), FileUtils.fileFromUri(url.toURI()));
202 }
203 return new ConfigurationSource(urlConnection.getInputStream(), url, urlConnection.getLastModified());
204 } catch (FileNotFoundException ex) {
205 LOGGER.info("Unable to locate file {}, ignoring.", url.toString());
206 return null;
207 }
208 }
209
210 private LoggerContext getLoggerContext() {
211 return (LoggerContext) LogManager.getContext(false);
212 }
213 }
+0
-50
log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/SpringEnvironmentHolder.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.logging.log4j.spring.boot;
17
18 import java.util.concurrent.locks.Lock;
19 import java.util.concurrent.locks.ReentrantLock;
20
21 import org.apache.logging.log4j.LogManager;
22 import org.apache.logging.log4j.internal.LogManagerStatus;
23 import org.springframework.core.env.Environment;
24
25 /**
26 * Provides access to the Spring Environment.
27 */
28 public class SpringEnvironmentHolder {
29
30 private volatile Environment environment;
31 private Lock lock = new ReentrantLock();
32
33
34 protected Environment getEnvironment() {
35 if (environment == null && LogManagerStatus.isInitialized() && LogManager.getFactory() != null &&
36 LogManager.getFactory().hasContext(SpringEnvironmentHolder.class.getName(), null, false)) {
37 lock.lock();
38 try {
39 if (environment == null) {
40 Object obj = LogManager.getContext(false).getObject(Log4j2CloudConfigLoggingSystem.ENVIRONMENT_KEY);
41 environment = obj instanceof Environment ? (Environment) obj : null;
42 }
43 } finally {
44 lock.unlock();
45 }
46 }
47 return environment;
48 }
49 }
+0
-117
log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/SpringLookup.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.logging.log4j.spring.boot;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.core.lookup.StrLookup;
22 import org.apache.logging.log4j.status.StatusLogger;
23 import org.springframework.core.env.Environment;
24
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28 /**
29 * Lookup for Spring properties.
30 */
31 @Plugin(name = "spring", category = StrLookup.CATEGORY)
32 public class SpringLookup extends SpringEnvironmentHolder implements StrLookup {
33
34 private static final Logger LOGGER = StatusLogger.getLogger();
35 private static final String ACTIVE = "profiles.active";
36 private static final String DEFAULT = "profiles.default";
37 private static final String PATTERN = "\\[(\\d+?)\\]";
38 private static final Pattern ACTIVE_PATTERN = Pattern.compile(ACTIVE + PATTERN);
39 private static final Pattern DEFAULT_PATTERN = Pattern.compile(DEFAULT + PATTERN);
40
41 public SpringLookup() {
42 getEnvironment();
43 }
44
45 @Override
46 public String lookup(String key) {
47 Environment env = getEnvironment();
48 if (env != null) {
49 String lowerKey = key.toLowerCase();
50 if (lowerKey.startsWith(ACTIVE)) {
51 switch (env.getActiveProfiles().length) {
52 case 0: {
53 return null;
54 }
55 case 1: {
56 return env.getActiveProfiles()[0];
57 }
58 default: {
59 Matcher matcher = ACTIVE_PATTERN.matcher(key);
60 if (matcher.matches()) {
61 try {
62 int index = Integer.parseInt(matcher.group(1));
63 if (index < env.getActiveProfiles().length) {
64 return env.getActiveProfiles()[index];
65 }
66 LOGGER.warn("Index out of bounds for Spring active profiles: {}", index);
67 return null;
68 } catch (Exception ex) {
69 LOGGER.warn("Unable to parse {} as integer value", matcher.group(1));
70 return null;
71 }
72
73 }
74 return String.join(",", env.getActiveProfiles());
75 }
76 }
77 } else if (lowerKey.startsWith(DEFAULT)) {
78 switch (env.getDefaultProfiles().length) {
79 case 0: {
80 return null;
81 }
82 case 1: {
83 return env.getDefaultProfiles()[0];
84 }
85 default: {
86 Matcher matcher = DEFAULT_PATTERN.matcher(key);
87 if (matcher.matches()) {
88 try {
89 int index = Integer.parseInt(matcher.group(1));
90 if (index < env.getDefaultProfiles().length) {
91 return env.getDefaultProfiles()[index];
92 }
93 LOGGER.warn("Index out of bounds for Spring default profiles: {}", index);
94 return null;
95 } catch (Exception ex) {
96 LOGGER.warn("Unable to parse {} as integer value", matcher.group(1));
97 return null;
98 }
99
100 }
101 return String.join(",", env.getDefaultProfiles());
102 }
103 }
104 }
105
106 return env.getProperty(key);
107
108 }
109 return null;
110 }
111
112 @Override
113 public String lookup(LogEvent event, String key) {
114 return lookup((key));
115 }
116 }
+0
-97
log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/SpringProfileArbiter.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.logging.log4j.spring.boot;
17
18 import org.apache.logging.log4j.core.config.Configuration;
19 import org.apache.logging.log4j.core.config.Node;
20 import org.apache.logging.log4j.core.config.arbiters.Arbiter;
21 import org.apache.logging.log4j.core.config.plugins.Plugin;
22 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
23 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
24 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
25 import org.springframework.core.env.Environment;
26 import org.springframework.core.env.Profiles;
27 import org.springframework.util.StringUtils;
28
29 /**
30 * An Aribter that uses the active Spring profile to determine if configuration should be included.
31 */
32 @Plugin(name = "SpringProfile", category = Node.CATEGORY, elementType = Arbiter.ELEMENT_TYPE,
33 deferChildren = true, printObject = true)
34 public class SpringProfileArbiter extends SpringEnvironmentHolder implements Arbiter {
35
36 private final String[] profileNames;
37
38 private SpringProfileArbiter(final String[] profiles) {
39 this.profileNames = profiles;
40
41 }
42
43 @Override
44 public boolean isCondition() {
45 Environment environment = getEnvironment();
46 if (environment == null) {
47 return false;
48 }
49
50 if (profileNames.length == 0) {
51 return false;
52 }
53 return environment.acceptsProfiles(Profiles.of(profileNames));
54 }
55
56 @PluginBuilderFactory
57 public static Builder newBuilder() {
58 return new Builder();
59 }
60
61 public static class Builder implements org.apache.logging.log4j.core.util.Builder<SpringProfileArbiter> {
62
63 public static final String ATTR_NAME = "name";
64
65 @PluginBuilderAttribute(ATTR_NAME)
66 private String name;
67
68 @PluginConfiguration
69 private Configuration configuration;;
70
71 /**
72 * Sets the Profile Name or Names.
73 * @param name the profile name(s).
74 * @return this
75 */
76 public Builder setName(final String name) {
77 this.name = name;
78 return asBuilder();
79 }
80
81 public Builder setConfiguration(final Configuration configuration) {
82 this.configuration = configuration;
83 return asBuilder();
84 }
85
86 private SpringProfileArbiter.Builder asBuilder() {
87 return this;
88 }
89
90 public SpringProfileArbiter build() {
91 String[] profileNames = StringUtils.trimArrayElements(
92 StringUtils.commaDelimitedListToStringArray(configuration.getStrSubstitutor().replace(name)));
93 return new SpringProfileArbiter(profileNames);
94 }
95 }
96 }
+0
-54
log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/SpringPropertySource.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.logging.log4j.spring.boot;
17
18 import org.apache.logging.log4j.util.PropertySource;
19 import org.springframework.core.env.Environment;
20
21 /**
22 * Returns properties from Spring.
23 */
24 public class SpringPropertySource extends SpringEnvironmentHolder implements PropertySource {
25
26 /**
27 * System properties take precendence followed by properties in Log4j properties files. Spring properties
28 * follow.
29 * @return This PropertySource's priority.
30 */
31 @Override
32 public int getPriority() {
33 return -50;
34 }
35
36 @Override
37 public String getProperty(String key) {
38 Environment environment = getEnvironment();
39 if (environment != null) {
40 return environment.getProperty(key);
41 }
42 return null;
43 }
44
45 @Override
46 public boolean containsProperty(String key) {
47 Environment environment = getEnvironment();
48 if (environment != null) {
49 return environment.containsProperty(key);
50 }
51 return false;
52 }
53 }
+0
-15
log4j-spring-boot/src/main/resources/META-INF/services/org.apache.logging.log4j.util.PropertySource 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 org.apache.logging.log4j.spring.boot.SpringPropertySource
+0
-17
log4j-spring-boot/src/main/resources/log4j2.system.properties 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 org.springframework.boot.logging.LoggingSystem=org.apache.logging.log4j.spring.boot.Log4j2CloudConfigLoggingSystem
+0
-91
log4j-spring-boot/src/site/markdown/index.md less more
0 <!-- vim: set syn=markdown : -->
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 -->
17
18 # Log4j Spring Boot Support
19
20 This module provides enhanced support for Spring Boot beyond what Spring Boot itself provides.
21
22 ## Overview
23
24 The components in this module require a Spring Environment to have been created. Spring Boot
25 applications initialize logging multiple times. The first initialization occurs before
26 any initialization work is performed by Spring, thus no Environment will have been created
27 and the components implemented in this module will not produce the desired results. Subsequent
28 initializations of logging will have a Spring Environment.
29
30
31 ## Usage
32
33 ### Spring Lookup
34
35 The Spring Lookup allows configuration files to reference properties defined in Spring
36 configuration files from a Log4j configuration file. For example:
37
38 <property name="applicationName">${spring:spring.application.name}</property>
39
40 would set the Log4j applicationName property to the value of spring.application.name set in the
41 Spring configuration.
42
43 ### Spring Property Source
44
45 Log4j uses property sources when resolving properties it uses internally. This support allows
46 most of Log4j's [System Properties](http://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties)
47 to be specified in the Spring Configuration. However, some properties that are only referenced
48 during the first Log4j initialization, such as the property Log4j uses to allow the default
49 Log4j implementation to be chosen, would not be available.
50
51 ### Spring Profile Arbiter
52
53 New with Log4j 2.15.0 are "Arbiters" which are conditionals that can cause a portion of the Log4j configuration to
54 be included or excluded. log4j-spring-boot provides an Arbiter that allows a Spring profile value to be used for
55 this purpose. Below is an example:
56 ```
57 <Configuration name="ConfigTest" status="ERROR" monitorInterval="5">
58 <Appenders>
59
60 <SpringProfile name="dev | staging">
61 <Console name="Out">
62 <PatternLayout pattern="%m%n"/>
63 </Console>
64 </SpringProfile>
65 <SpringProfile name="prod">
66 <List name="Out">
67 </List>
68 </SpringProfile>
69
70 </Appenders>
71 <Loggers>
72 <Logger name="org.apache.test" level="trace" additivity="false">
73 <AppenderRef ref="Out"/>
74 </Logger>
75 <Root level="error">
76 <AppenderRef ref="Out"/>
77 </Root>
78 </Loggers>
79 </Configuration>
80 ```
81
82 ## Requirements
83
84 The Log4j 2 Spring Cloud Configuration integration has a dependency on Log4j 2 API, Log4j 2 Core, and
85 Spring Boot versions 2.0.3.RELEASE or 2.1.1.RELEASE or later versions it either release series.
86 For more information, see [Runtime Dependencies](../../runtime-dependencies.html).
87
88
89
90
+0
-52
log4j-spring-boot/src/site/site.xml 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 -->
17 <project name="Log4j Spring Boot Integration"
18 xmlns="http://maven.apache.org/DECORATION/1.4.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
21 <body>
22 <links>
23 <item name="Apache" href="http://www.apache.org/" />
24 <item name="Logging Services" href="http://logging.apache.org/"/>
25 <item name="Log4j" href="../index.html"/>
26 </links>
27
28 <!-- Component-specific reports -->
29 <menu ref="reports"/>
30
31 <!-- Overall Project Info -->
32 <menu name="Log4j Project Information" img="icon-info-sign">
33 <item name="Dependencies" href="../dependencies.html" />
34 <item name="Dependency Convergence" href="../dependency-convergence.html" />
35 <item name="Dependency Management" href="../dependency-management.html" />
36 <item name="Project Team" href="../team-list.html" />
37 <item name="Mailing Lists" href="../mail-lists.html" />
38 <item name="Issue Tracking" href="../issue-tracking.html" />
39 <item name="Project License" href="../license.html" />
40 <item name="Source Repository" href="../source-repository.html" />
41 <item name="Project Summary" href="../project-summary.html" />
42 </menu>
43
44 <menu name="Log4j Project Reports" img="icon-cog">
45 <item name="Changes Report" href="../changes-report.html" />
46 <item name="JIRA Report" href="../jira-report.html" />
47 <item name="Surefire Report" href="../surefire-report.html" />
48 <item name="RAT Report" href="../rat-report.html" />
49 </menu>
50 </body>
51 </project>
+0
-41
log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystemTest.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.logging.log4j.spring.boot;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.core.config.ConfigurationFactory;
20 import org.apache.logging.log4j.spi.LoggerContext;
21 import org.junit.Test;
22
23 import java.util.Arrays;
24 import java.util.List;
25
26 import static org.junit.Assert.assertTrue;
27
28 public class Log4j2CloudConfigLoggingSystemTest {
29
30 @Test
31 public void getStandardConfigLocations() {
32 String customLog4j2Location = "classpath:my_custom_log4j2.properties";
33 LoggerContext lc = LogManager.getContext(); // Initialize LogManager to here to prevent a failure trying to initialize it from StatusLogger.
34 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, customLog4j2Location);
35 Log4j2CloudConfigLoggingSystem cloudLoggingSystem = new Log4j2CloudConfigLoggingSystem(this.getClass().getClassLoader());
36 List<String> standardConfigLocations = Arrays.asList(cloudLoggingSystem.getStandardConfigLocations());
37 assertTrue(standardConfigLocations.contains(customLog4j2Location));
38
39 }
40 }
+0
-60
log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/SpringLookupTest.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.logging.log4j.spring.boot;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.core.LoggerContext;
20 import org.junit.Test;
21 import org.springframework.mock.env.MockEnvironment;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNull;
26
27 /**
28 * Test SpringLookup.
29 */
30 public class SpringLookupTest {
31
32 @Test
33 public void testLookup() {
34 MockEnvironment env = new MockEnvironment();
35 env.setActiveProfiles("test");
36 env.setDefaultProfiles("one", "two");
37 env.setProperty("app.property", "test");
38 LoggerContext context = (LoggerContext) LogManager.getContext(false);
39 context.putObject(Log4j2CloudConfigLoggingSystem.ENVIRONMENT_KEY, env);
40 SpringLookup lookup = new SpringLookup();
41 String result = lookup.lookup("profiles.active");
42 assertNotNull("No active profiles", result);
43 assertEquals("Incorrect active profile", "test", result);
44 result = lookup.lookup("profiles.active[0]");
45 assertNotNull("No active profiles", result);
46 assertEquals("Incorrect active profile", "test", result);
47 result = lookup.lookup("profiles.default");
48 assertNotNull("No default profiles", result);
49 assertEquals("Incorrect default profiles", "one,two", result);
50 result = lookup.lookup("profiles.default[0]");
51 assertNotNull("No default profiles", result);
52 assertEquals("Incorrect default profiles", "one", result);
53 result = lookup.lookup("profiles.default[2]");
54 assertNull("Did not get index out of bounds", result);
55 result = lookup.lookup("app.property");
56 assertNotNull("Did not find property", result);
57 assertEquals("Incorrect property value", "test", result);
58 }
59 }
+0
-69
log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/SpringProfileTest.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.logging.log4j.spring.boot;
17
18 import java.io.File;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.core.Appender;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.appender.ConsoleAppender;
24 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.BeforeClass;
26 import org.junit.Test;
27 import org.springframework.mock.env.MockEnvironment;
28
29 import static org.junit.jupiter.api.Assertions.assertNotNull;
30 import static org.junit.jupiter.api.Assertions.assertTrue;
31
32 /**
33 * Tests basic condition processing.
34 */
35 public class SpringProfileTest {
36
37 static final String CONFIG = "target/test-classes/log4j2-springProfile.xml";
38 static LoggerContext loggerContext;
39 static MockEnvironment env;
40
41 @BeforeClass
42 public static void before() {
43 loggerContext = (LoggerContext) LogManager.getContext(false);
44 env = new MockEnvironment();
45 loggerContext.putObject(Log4j2CloudConfigLoggingSystem.ENVIRONMENT_KEY, env);
46 }
47
48
49 @Test
50 public void prodTest() {
51 env.setActiveProfiles("prod");
52 loggerContext.setConfigLocation(new File(CONFIG).toURI());
53 assertNotNull(loggerContext);
54 Appender app = loggerContext.getConfiguration().getAppender("Out");
55 assertNotNull(app);
56 assertTrue(app instanceof ListAppender);
57 }
58
59 @Test
60 public void devTest() {
61 env.setActiveProfiles("dev");
62 loggerContext.setConfigLocation(new File(CONFIG).toURI());
63 assertNotNull(loggerContext);
64 Appender app = loggerContext.getConfiguration().getAppender("Out");
65 assertNotNull(app);
66 assertTrue(app instanceof ConsoleAppender);
67 }
68 }
+0
-41
log4j-spring-boot/src/test/resources/log4j2-springProfile.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration name="ConfigTest" status="ERROR" monitorInterval="5">
19 <Appenders>
20
21 <SpringProfile name="dev | staging">
22 <Console name="Out">
23 <PatternLayout pattern="%m%n"/>
24 </Console>
25 </SpringProfile>
26 <SpringProfile name="prod">
27 <List name="Out">
28 </List>
29 </SpringProfile>
30
31 </Appenders>
32 <Loggers>
33 <Logger name="org.apache.test" level="trace" additivity="false">
34 <AppenderRef ref="Out"/>
35 </Logger>
36 <Root level="error">
37 <AppenderRef ref="Out"/>
38 </Root>
39 </Loggers>
40 </Configuration>
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.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-spring-cloud-config-client</artifactId>
3434 </properties>
3535 <dependencies>
3636 <dependency>
37 <groupId>org.junit.vintage</groupId>
38 <artifactId>junit-vintage-engine</artifactId>
39 </dependency>
40 <dependency>
41 <groupId>org.junit.jupiter</groupId>
42 <artifactId>junit-jupiter-engine</artifactId>
43 </dependency>
44 <dependency>
45 <groupId>org.apache.logging.log4j</groupId>
46 <artifactId>log4j-spring-boot</artifactId>
47 <version>${project.version}</version>
48 </dependency>
49 <dependency>
50 <groupId>org.springframework.cloud</groupId>
51 <artifactId>spring-cloud-starter-bootstrap</artifactId>
37 <groupId>junit</groupId>
38 <artifactId>junit</artifactId>
39 <scope>test</scope>
5240 </dependency>
5341 <dependency>
5442 <groupId>org.springframework.cloud</groupId>
5947 <artifactId>spring-cloud-bus</artifactId>
6048 </dependency>
6149 <dependency>
50 <groupId>org.springframework.boot</groupId>
51 <artifactId>spring-boot</artifactId>
52 </dependency>
53 <dependency>
54 <groupId>org.springframework</groupId>
55 <artifactId>spring-context</artifactId>
56 </dependency>
57 <dependency>
58 <groupId>org.springframework</groupId>
59 <artifactId>spring-context-support</artifactId>
60 </dependency>
61 <dependency>
6262 <groupId>org.hamcrest</groupId>
63 <artifactId>hamcrest</artifactId>
63 <artifactId>hamcrest-all</artifactId>
6464 <scope>test</scope>
6565 </dependency>
6666 <dependency>
8181 <type>test-jar</type>
8282 <scope>test</scope>
8383 </dependency>
84 <dependency>
85 <groupId>org.springframework.boot</groupId>
86 <artifactId>spring-boot-starter-test</artifactId>
87 <version>${spring-boot.version}</version>
88 <scope>test</scope>
89 <exclusions>
90 <exclusion>
91 <groupId>org.springframework.boot</groupId>
92 <artifactId>spring-boot-starter-logging</artifactId>
93 </exclusion>
94 </exclusions>
95 </dependency>
9684 </dependencies>
9785 <build>
9886 <plugins>
142130 <configuration>
143131 <source>1.8</source>
144132 <target>1.8</target>
133 <proc>none</proc>
145134 </configuration>
146135 </plugin>
147136 <plugin>
148137 <groupId>org.apache.maven.plugins</groupId>
149138 <artifactId>maven-toolchains-plugin</artifactId>
150 <version>3.0.0</version>
139 <version>1.1</version>
151140 <executions>
152141 <execution>
153142 <goals>
219208 </reportSets>
220209 </plugin>
221210 <plugin>
222 <groupId>com.github.spotbugs</groupId>
223 <artifactId>spotbugs-maven-plugin</artifactId>
211 <groupId>org.codehaus.mojo</groupId>
212 <artifactId>findbugs-maven-plugin</artifactId>
213 <version>${findbugs.plugin.version}</version>
214 <configuration>
215 <fork>true</fork>
216 <jvmArgs>-Duser.language=en</jvmArgs>
217 <threshold>Normal</threshold>
218 <effort>Default</effort>
219 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
220 </configuration>
224221 </plugin>
225222 <plugin>
226223 <groupId>org.apache.maven.plugins</groupId>
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.spring.cloud.config.client;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.net.URISyntaxException;
21 import java.net.URL;
22 import java.net.URLConnection;
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.Properties;
26 import javax.net.ssl.HttpsURLConnection;
27
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.apache.logging.log4j.core.LoggerContext;
31 import org.apache.logging.log4j.core.config.ConfigurationFactory;
32 import org.apache.logging.log4j.core.config.ConfigurationSource;
33 import org.apache.logging.log4j.core.net.ssl.LaxHostnameVerifier;
34 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
35 import org.apache.logging.log4j.core.net.ssl.SslConfigurationFactory;
36 import org.apache.logging.log4j.core.util.AuthorizationProvider;
37 import org.apache.logging.log4j.core.util.FileUtils;
38 import org.apache.logging.log4j.status.StatusLogger;
39 import org.apache.logging.log4j.util.PropertiesUtil;
40 import org.springframework.boot.logging.LogFile;
41 import org.springframework.boot.logging.LoggingInitializationContext;
42 import org.springframework.boot.logging.log4j2.Log4J2LoggingSystem;
43 import org.springframework.core.io.ClassPathResource;
44 import org.springframework.util.Assert;
45 import org.springframework.util.ClassUtils;
46 import org.springframework.util.ResourceUtils;
47
48 /**
49 *
50 */
51 public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem {
52 private static final String FILE_PROTOCOL = "file";
53 private static final String HTTPS = "https";
54 private Logger LOGGER = StatusLogger.getLogger();
55
56 public Log4j2CloudConfigLoggingSystem(ClassLoader loader) {
57 super(loader);
58 }
59
60 @Override
61 protected String[] getStandardConfigLocations() {
62 String[] locations = super.getStandardConfigLocations();
63 PropertiesUtil props = new PropertiesUtil(new Properties());
64 String location = props.getStringProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
65 if (location != null) {
66 List<String> list = Arrays.asList(super.getStandardConfigLocations());
67 list.add(location);
68 locations = list.toArray(new String[list.size()]);
69 }
70 return locations;
71 }
72
73 @Override
74 protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) {
75 if (logFile != null) {
76 this.loadConfiguration(this.getBootPackagedConfigFile("log4j2-file.xml"), logFile);
77 } else {
78 this.loadConfiguration(this.getBootPackagedConfigFile("log4j2.xml"), logFile);
79 }
80 }
81
82 private String getBootPackagedConfigFile(String fileName) {
83 String defaultPath = ClassUtils.getPackageName(Log4J2LoggingSystem.class);
84 defaultPath = defaultPath.replace('.', '/');
85 defaultPath = defaultPath + "/" + fileName;
86 defaultPath = "classpath:" + defaultPath;
87 return defaultPath;
88 }
89
90 @Override
91 protected void loadConfiguration(String location, LogFile logFile) {
92 Assert.notNull(location, "Location must not be null");
93 try {
94 LoggerContext ctx = getLoggerContext();
95 URL url = ResourceUtils.getURL(location);
96 ConfigurationSource source = getConfigurationSource(url);
97 ctx.start(ConfigurationFactory.getInstance().getConfiguration(ctx, source));
98 }
99 catch (Exception ex) {
100 throw new IllegalStateException(
101 "Could not initialize Log4J2 logging from " + location, ex);
102 }
103 }
104
105 private ConfigurationSource getConfigurationSource(URL url) throws IOException, URISyntaxException {
106 URLConnection urlConnection = url.openConnection();
107 AuthorizationProvider provider = ConfigurationFactory.getAuthorizationProvider();
108 if (provider != null) {
109 provider.addAuthorization(urlConnection);
110 }
111 if (url.getProtocol().equals(HTTPS)) {
112 SslConfiguration sslConfiguration = SslConfigurationFactory.getSslConfiguration();
113 if (sslConfiguration != null) {
114 ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslConfiguration.getSslSocketFactory());
115 if (!sslConfiguration.isVerifyHostName()) {
116 ((HttpsURLConnection) urlConnection).setHostnameVerifier(LaxHostnameVerifier.INSTANCE);
117 }
118 }
119 }
120 File file = FileUtils.fileFromUri(url.toURI());
121 if (file != null) {
122 return new ConfigurationSource(urlConnection.getInputStream(), FileUtils.fileFromUri(url.toURI()));
123 } else {
124 return new ConfigurationSource(urlConnection.getInputStream(), url, urlConnection.getLastModified());
125 }
126 }
127
128 private LoggerContext getLoggerContext() {
129 return (LoggerContext) LogManager.getContext(false);
130 }
131 }
1818 import org.apache.logging.log4j.LogManager;
1919 import org.apache.logging.log4j.Logger;
2020 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
21 import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
22 import org.springframework.context.ApplicationListener;
21
22 import org.springframework.cloud.bus.ConditionalOnBusEnabled;
23 import org.springframework.cloud.bus.SpringCloudBusClient;
24 import org.springframework.cloud.bus.event.RemoteApplicationEvent;
25 import org.springframework.cloud.stream.annotation.EnableBinding;
26 import org.springframework.cloud.stream.annotation.StreamListener;
27 import org.springframework.context.event.EventListener;
2328 import org.springframework.stereotype.Component;
2429
2530 @Component
31 @ConditionalOnBusEnabled
32 @EnableBinding(SpringCloudBusClient.class)
2633 @ConditionalOnProperty(value = "spring.cloud.config.watch.enabled")
27 public class Log4j2EventListener implements ApplicationListener<EnvironmentChangeEvent> {
34 public class Log4j2EventListener {
2835 private static Logger LOGGER = LogManager.getLogger(Log4j2EventListener.class);
2936
30 @Override
31 public void onApplicationEvent(EnvironmentChangeEvent environmentChangeEvent) {
32 LOGGER.debug("Application change event triggered");
37 @EventListener(classes = RemoteApplicationEvent.class)
38 public void acceptLocal(RemoteApplicationEvent event) {
39 LOGGER.debug("Refresh application event triggered");
40 WatchEventManager.publishEvent();
41 }
42
43 @StreamListener(SpringCloudBusClient.INPUT)
44 public void acceptRemote(RemoteApplicationEvent event) {
45 LOGGER.debug("Refresh application event triggered");
3346 WatchEventManager.publishEvent();
3447 }
3548 }
1313 # See the license for the specific language governing permissions and
1414 # limitations under the license.
1515 #
16 org.springframework.context.ApplicationListener=org.apache.logging.log4j.spring.cloud.config.client.Log4j2EventListener
16 org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.apache.logging.log4j.spring.cloud.config.client.Log4j2EventListener
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 #
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 org.springframework.boot.logging.LoggingSystem=org.apache.logging.log4j.spring.cloud.config.client.Log4j2CloudConfigLoggingSystem
4040 ```
4141 log4j.configurationFile=http://host.docker.internal:8888/ConfigService/sampleapp/default/master/log4j2.xml
4242 ```
43
44 Log4j also supports Composite Configurations. The standard way to do that is to concatentate the paths to the files in
45 a comma separated string. Unfortunately, Spring validates the URL being provided and commas are not allowed.
46 Therefore, additional configurations must be supplied as "override" query parametes.
47
48 ```
49 log4j.configurationFile=http://host.docker.internal:8888/ConfigService/sampleapp/default/master/log4j2.xml
50 ?override=http://host.docker.internal:8888/ConfigService/sampleapp/default/master/log4j2-sampleapp.xml
51 ```
52 Note that the location within the directory structure and how configuration files are located is completely
53 dependent on the searchPaths setting in the Spring Cloud Config server.
54
5543 When running in a docker container host.docker.internal may be used as the domain name to access an application
5644 running on the same hose outside of the docker container. Note that in accordance with Spring Cloud Config
5745 practices but the application, profile, and label should be specified in the url.
5846
5947 The Spring Cloud Config support also allows connections using TLS and/or basic authentication. When using basic
60 authentication the userid and password may be specified as system properties, log4j2.component.properties or Spring
61 Boot's bootstrap.yml. The table below shows the alternate names that may be used to specify the properties. Any of
62 the alternatives may be used in any configuration location.
63
64 | Property | Alias | Spring-like alias | Purpose |
65 |----------|---------|---------|---------|
66 | log4j2.configurationUserName | log4j2.config.username | logging.auth.username | User name for basic authentication |
67 | log4j2.configurationPassword | log4j2.config.password | logging.auth.password | Password for basic authentication |
68 | log4j2.authorizationProvider | log4j2.config.authorizationProvider | logging.auth.authorizationProvider | Class used to create HTTP Authorization header |
48 authentication the userid and password may be specified as system properties or in log4j2.component.properties as
6949
7050 ```
7151 log4j2.configurationUserName=guest
7252 log4j2.configurationPassword=guest
7353 ```
74 As noted above, Log4j supports accessing logging configuration from bootstrap.yml. As an example, to configure reading
75 from a Spring Cloud Configuration service using basic authoriztion you can do:
76 ```
77 spring:
78 application:
79 name: myApp
80 cloud:
81 config:
82 uri: https://spring-configuration-server.mycorp.com
83 username: appuser
84 password: changeme
54 Note that Log4j currently does not support encrypting the password.
8555
86 logging:
87 config: classpath:log4j2.xml
88 label: ${spring.cloud.config.label}
89
90 ---
91 spring:
92 profiles: dev
93
94 logging:
95 config: https://spring-configuration-server.mycorp.com/myApp/default/${logging.label}/log4j2-dev.xml
96 auth:
97 username: appuser
98 password: changeme
99 ```
100
101 Note that Log4j currently does not directly support encrypting the password. However, Log4j does use Spring's
102 standard APIs to access properties in the Spring configuration so any customizations made to Spring's property
103 handling would apply to the properties Log4j uses as well.
104
105 If more extensive authentication is required an ```AuthorizationProvider``` can be implemented and the fully
106 qualified class name in
107 the ```log4j2.authorizationProvider``` system property, in log4j2.component.properties or in Spring's bootstrap.yml
108 using either the ```log4j2.authorizationProvider``` key or with the key ```logging.auth.authorizationProvider```.
56 If more extensive authentication is required an ```AuthorizationProvider``` can be implemented and defined in
57 the log4j2.authorizationProvider system property or in log4j2.component.properties.
10958
11059 TLS can be enabled by adding the following system properties or defining them in log4j2.component.properties
11160
11362 | ------------- |-------|:-------------|
11463 | log4j2.trustStoreLocation | Optional | The location of the trust store. If not provided the default trust store will be used.|
11564 | log4j2.trustStorePassword | Optional | Password needed to access the trust store. |
116 | log4j2.trustStorePasswordFile | Optional | The location of a file that contains the password for the trust store. |
65 | log4j2.trustStorePasswordFile | Optinoal | The location of a file that contains the password for the trust store. |
11766 | log4j2.trustStorePasswordEnvironmentVariable | Optional | The name of the environment variable that contains the trust store password. |
11867 | log4j2.trustStoreKeyStoreType | Required if keystore location provided | The type of key store. |
11968 | log4j2.trustStoreKeyManagerFactoryAlgorithm | Optional | Java cryptographic algorithm. |
+0
-113
log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/test/java/org/apache/logging/log4j/spring/cloud/config/client/Log4j2EventListenerTest.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.logging.log4j.spring.cloud.config.client;
17
18 import java.io.File;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.concurrent.atomic.AtomicInteger;
22
23 import org.apache.logging.log4j.core.config.ConfigurationListener;
24 import org.apache.logging.log4j.core.config.Reconfigurable;
25 import org.apache.logging.log4j.core.util.Source;
26 import org.apache.logging.log4j.core.util.Watcher;
27 import org.apache.logging.log4j.junit.LoggerContextRule;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.rules.RuleChain;
31 import org.junit.runner.RunWith;
32 import org.springframework.beans.factory.annotation.Autowired;
33 import org.springframework.boot.test.context.SpringBootTest;
34 import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
35 import org.springframework.context.ApplicationEventPublisher;
36 import org.springframework.test.context.junit4.SpringRunner;
37
38 import static org.junit.Assert.assertTrue;
39
40 /**
41 * Class Description goes here.
42 */
43 @RunWith(SpringRunner.class)
44 @SpringBootTest(classes = {SpringConfiguration.class})
45 public class Log4j2EventListenerTest {
46
47 private static final String CONFIG = "log4j-console.xml";
48 private static final String DIR = "target/logs";
49
50 public static LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
51
52 @Rule
53 public RuleChain chain = loggerContextRule.withCleanFilesRule(DIR);
54
55 @Autowired
56 private ApplicationEventPublisher publisher;
57
58 @Test
59 public void test() throws Exception {
60 AtomicInteger count = new AtomicInteger(0);
61 Source source = new Source(new File("test.java"));
62 loggerContextRule.getLoggerContext().getConfiguration().getWatchManager()
63 .watch(source, new TestWatcher(count));
64 publisher.publishEvent(new EnvironmentChangeEvent(new HashSet<>()));
65 assertTrue(count.get() > 0);
66 }
67
68 private static class TestWatcher implements Watcher {
69
70 private final AtomicInteger count;
71
72 public TestWatcher(AtomicInteger count) {
73 this.count = count;
74 }
75
76 @Override
77 public List<ConfigurationListener> getListeners() {
78 return null;
79 }
80
81 @Override
82 public void modified() {
83
84 }
85
86 @Override
87 public boolean isModified() {
88 count.incrementAndGet();
89 return false;
90 }
91
92 @Override
93 public long getLastModified() {
94 return 0;
95 }
96
97 @Override
98 public void watching(Source source) {
99
100 }
101
102 @Override
103 public Source getSource() {
104 return null;
105 }
106
107 @Override
108 public Watcher newWatcher(Reconfigurable reconfigurable, List<ConfigurationListener> listeners, long lastModifiedMillis) {
109 return this;
110 }
111 }
112 }
+0
-26
log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/test/java/org/apache/logging/log4j/spring/cloud/config/client/SpringConfiguration.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.logging.log4j.spring.cloud.config.client;
17
18 import org.springframework.context.annotation.Configuration;
19
20 /**
21 * Needed to make Spring happy.
22 */
23 @Configuration
24 public class SpringConfiguration {
25 }
+0
-31
log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/test/resources/log4j2-console.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="OFF">
19 <Appenders>
20 <Console name="Console" target="SYSTEM_OUT">
21 <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable" />
22 </Console>
23 </Appenders>
24 <Loggers>
25 <Logger name="org.foo" level="DEBUG" />
26 <Root level="TRACE">
27 <AppenderRef ref="Console" />
28 </Root>
29 </Loggers>
30 </Configuration>
2828 EXPOSE 8080
2929
3030 #CMD java "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" -jar sampleapp.jar
31 ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar -Xmx1G sampleapp.jar"]
31 CMD java -jar -Xmx2G sampleapp.jar
0 # Log4j Spring Cloud Sample Application
0 ##Log4j Spring Cloud Sample Application
11
22 This application uses Spring Boot and reads the logging configuration from the companion Spring Cloud Config Server
33 project. The log4j2.xml file is located in the config-repo directory in that project.
44
5 ## Running With Docker
65 This sample packages the application in a docker container that is packaged with rabbit-mq (to allow dynamic updates
76 from Spring Cloud Config), fluent-bit (to test as a log forwarder), Apache Flume (to test as a log forwarder), and
87 Apache Kafka also as a log forwarder. It also installs Socat, a proxy to allow access to the Docker REST API.
1918 zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties & kafka-server-start /usr/local/etc/kafka/server.properties
2019 ```
2120
22 ### Starting the Application
21 ###Starting the Application
2322 * Start the companion rabbit-mq, fluent-bit and flume images `./docker/up.sh`
2423 * Compile and start local application image `./docker/restartApp.sh`
2524 * The application exposes two endpoints.
2827 1. http://localhost:8080/sample/exception This endpoint generates an exception that can be used to verify whether
2928 multiline logging works with the chosen set of components.
3029
31 ### Viewing the logs
30 ###Viewing the logs
3231
3332 Accessing the log files varies depending on the appending being used. When logging to the console "docker logs" may
3433 be used. As configured, Flume will write to files in /var/log/flume, fluent-bit to the standard output of its container.
35 Kafka output may be viewed using a tool like [Kafka Tool](http://www.kafkatool.com/).
36
37 ## Running with Kubernetes
38
39 This sample has been verified to run in a Docker Desktop for Mac environment with Kubernetes enabled and may run in
40 other Kubernetes environments.
41
42 ### Prerequisites
43 Note: This guide assumes you already have Docker and Kubernetes installed. Since the same container is used for
44 Kubernetes as with Docker, Java 11 is also required. This implmentation uses an ELK stack which is expected to
45 be installed. They can be downloaded individually and started as local applications on the development
46 machine for testing. Logstash should be configured as shown in
47 [Logging in the Cloud](http://logging.apache.org/log4j/2.x/manual/cloud.html).
48
49 ### Starting the Application
50 Run the ```docker/deploy.sh``` command from the base directory of the log4j-spring-cloud-config-sample-application
51 project. This will build the application and then deploy it to Kubernetes. You should see the start-up logs in Kibana.
52 To stop, run the ```docker/undeploy.sh``` script, then run ```docker images``` and perform
53 ```docker rmi --force {image id}``` where image id is the id of the image for the sample application.
34 Kafka output may be viewed using a tool like [Kafka Tool](http://www.kafkatool.com/).
5435
77 SERVICE_PARAMS: --spring.config.location=classpath:/,classpath:/application-local-docker.yml
88 ports:
99 - "5005:5005"
10 - "8080:8080"
10 - "8080:4567"
1111 networks:
1212 sample_network:
1313 aliases:
+0
-86
log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/docker/combined-compose.yml less more
0 version: "3"
1 services:
2 socat:
3 container_name: socat
4 image: bobrik/socat
5 command: TCP-LISTEN:1234,fork UNIX-CONNECT:/var/run/docker.sock
6 expose:
7 - "1234"
8 volumes:
9 - /var/run/docker.sock:/var/run/docker.sock
10 networks:
11 sample_network:
12 aliases:
13 - socat
14
15 rabbitmq:
16 container_name: rabbit
17 image: rabbitmq:3-management-alpine
18 expose:
19 - "5672"
20 - "15672"
21 ports:
22 - "5672:5672"
23 - "15672:15672"
24 volumes:
25 - ./init/rabbit/rabbitmq.config:/etc/rabbitmq/rabbitmq.config:ro
26 - ./init/rabbit/definitions.json:/etc/rabbitmq/definitions.json:ro
27 networks:
28 sample_network:
29 aliases:
30 - rabbitmq
31
32 fluent-bit:
33 container_name: fluent-bit
34 image: fluent/fluent-bit:latest
35 expose:
36 - "2020"
37 - "24221"
38 - "24224"
39 ports:
40 - "24224:24224"
41 volumes:
42 - ./init/fluent-bit/fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf
43 - ./target/logs:/var/logs
44 networks:
45 sample_network:
46 aliases:
47 - fluent-bit
48
49 flume:
50 container_name: flume
51 image: probablyfine/flume:latest
52 expose:
53 - "5050"
54 environment:
55 FLUME_AGENT_NAME: forwarder
56 FLUME_JAVA_OPTS: -Dlog4j.configuration=file:///opt/flume-config/log4j.properties
57 volumes:
58 - ./init/flume/start-flume.sh:/opt/flume/bin/start-flume
59 - ./init/flume/flume.conf:/opt/flume-config/flume.conf
60 - ./init/flume/flume-env.sh:/opt/flume-config/flume-env.sh
61 - ./init/flume/log4j.properties:/opt/flume-config/log4j.properties
62 - ~/flume-logs:/var/log/flume
63 networks:
64 sample_network:
65 aliases:
66 - flume
67
68 sampleapp:
69 container_name: sampleapp
70 image: sampleapp
71 environment:
72 DOCKER_URI: http://socat:1234
73 SERVICE_PARAMS: --spring.config.location=classpath:/,classpath:/application-local-docker.yml
74 ports:
75 - "5005:5005"
76 - "8080:8080"
77 networks:
78 sample_network:
79 aliases:
80 - sampleapp
81 networks:
82 sample_network:
83
84 volumes:
85 pgdata:
2222 networkName=docker_sample_network
2323 debug_port=5005
2424 #debug_expose="-p $debug_port:$debug_port"
25 exposed_ports="-p 8080:8080 $debug_expose"
25 exposed_ports="-p 8080:4567 $debug_expose"
2626
2727 mvn clean package -DskipTests=true
2828
+0
-36
log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/k8s/deploy.sh less more
0 #!/usr/bin/env bash
1 #
2 #
3 # Licensed to the Apache Software Foundation (ASF) under one
4 # or more contributor license agreements. See the NOTICE file
5 # distributed with this work for additional information
6 # regarding copyright ownership. The ASF licenses this file
7 # to you under the Apache License, Version 2.0 (the
8 # "License"); you may not use this file except in compliance
9 # with the License. You may obtain a copy of the License at
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing,
14 # software distributed under the License is distributed on an
15 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 # KIND, either express or implied. See the License for the
17 # specific language governing permissions and limitations
18 # under the License.
19 #
20
21 echo "Building, (re)creating, starting, and attaching to containers for a service."
22
23 imageName=sampleapp
24 containerName=sampleapp-container
25 networkName=docker_sampleapp
26 debug_port=5005
27 #debug_expose="-p $debug_port:$debug_port"
28 exposed_ports="-p 8080:8090 $debug_expose"
29
30 mvn clean package -DskipTests=true
31 docker build --no-cache -t $imageName -f Dockerfile .
32
33 docker tag $imageName localhost:5000/$imageName
34 docker push localhost:5000/$imageName
35 kubectl apply -f k8s/sampleapp-deployment.yaml
+0
-53
log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/k8s/sampleapp-deployment.yaml less more
0 apiVersion: apps/v1
1 kind: Deployment
2 metadata:
3 name: sampleapp
4 labels:
5 app: sampleapp
6 spec:
7 replicas: 1
8 selector:
9 matchLabels:
10 app: sampleapp
11 template:
12 metadata:
13 labels:
14 app: sampleapp
15 spec:
16 containers:
17 - name: sampleapp
18 image: localhost:5000/sampleapp:latest
19 imagePullPolicy: Always
20 ports:
21 - containerPort: 8080
22 - containerPort: 5005
23 env:
24 - name: JAVA_OPTS
25 value: "-Delastic.search.host=host.docker.internal"
26 - name: key-value-store
27 image: redis
28 ports:
29 - containerPort: 6379
30
31
32 ---
33 apiVersion: v1
34 kind: Service
35 metadata:
36 name: sampleapp
37 spec:
38 selector:
39 app: sampleapp
40 ports:
41 - protocol: TCP
42 port: 8080
43 targetPort: 8080
44 name: http
45 - protocol: TCP
46 port: 6379
47 targetPort: 6379
48 name: redis
49 - protocol: TCP
50 port: 5005
51 targetPort: 5005
52 name: debug
+0
-29
log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/k8s/undeploy.sh less more
0 #!/usr/bin/env bash
1 #
2 #
3 # Licensed to the Apache Software Foundation (ASF) under one
4 # or more contributor license agreements. See the NOTICE file
5 # distributed with this work for additional information
6 # regarding copyright ownership. The ASF licenses this file
7 # to you under the Apache License, Version 2.0 (the
8 # "License"); you may not use this file except in compliance
9 # with the License. You may obtain a copy of the License at
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing,
14 # software distributed under the License is distributed on an
15 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 # KIND, either express or implied. See the License for the
17 # specific language governing permissions and limitations
18 # under the License.
19 #
20
21 echo "Building, (re)creating, starting, and attaching to containers for a service."
22
23 imageName=sampleapp
24 containerName=sampleapp-container
25 networkName=docker_sampleapp
26
27 kubectl delete deploy/$imageName svc/$imageName
28
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.12.3</version>
2424 <relativePath>..</relativePath>
2525 </parent>
2626
2727 <artifactId>sample-app</artifactId>
2828 <packaging>jar</packaging>
2929
30 <name>Apache Log4j Spring Cloud Config Sample Application</name>
30 <name>Spring Cloud Config Sample Application</name>
3131 <url>http://maven.apache.org</url>
3232 <properties>
3333 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3434 <maven.compiler.source>1.8</maven.compiler.source>
3535 <maven.compiler.target>1.8</maven.compiler.target>
36 <log4jParentDir>${basedir}/../../..</log4jParentDir>
3736 <!--<manifestfile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestfile>-->
3837 </properties>
3938
106105 <artifactId>log4j-docker</artifactId>
107106 <version>${project.version}</version>
108107 </dependency>
109 <dependency>
110 <groupId>org.apache.logging.log4j</groupId>
111 <artifactId>log4j-kubernetes</artifactId>
112 <version>${project.version}</version>
113 </dependency>
114108 <!-- Required for Async Loggers -->
115109 <dependency>
116110 <groupId>com.lmax</groupId>
167161 <plugin>
168162 <groupId>org.apache.maven.plugins</groupId>
169163 <artifactId>maven-toolchains-plugin</artifactId>
170 <version>3.0.0</version>
164 <version>1.1</version>
171165 <executions>
172166 <execution>
173167 <goals>
292286 <profiles>
293287
294288 </profiles>
295 </project>
289 </project>
2121 import org.springframework.context.annotation.Bean;
2222 import org.springframework.context.annotation.Configuration;
2323 import org.springframework.web.client.RestTemplate;
24 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
24 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
2525
2626 @Configuration
27 public class WebMvcConfig implements WebMvcConfigurer {
27 public class WebMvcConfig extends WebMvcConfigurerAdapter {
2828 private Logger LOGGER = LogManager.getLogger(WebMvcConfig.class);
2929
3030 @Bean
+0
-83
log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application/src/main/java/org/apache/logging/log4j/spring/cloud/config/sample/controller/K8SController.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
17 package org.apache.logging.log4j.spring.cloud.config.sample.controller;
18
19 import java.nio.file.Paths;
20
21 import org.apache.logging.log4j.LogManager;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.kubernetes.KubernetesClientBuilder;
24 import org.apache.logging.log4j.util.Strings;
25 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.http.HttpStatus;
27 import org.springframework.http.ResponseEntity;
28 import org.springframework.web.bind.annotation.GetMapping;
29 import org.springframework.web.bind.annotation.RestController;
30
31 import com.fasterxml.jackson.databind.ObjectMapper;
32
33 import io.fabric8.kubernetes.api.model.Pod;
34 import io.fabric8.kubernetes.client.Config;
35 import io.fabric8.kubernetes.client.KubernetesClient;
36
37 /**
38 * Test class
39 */
40 @RestController
41 public class K8SController {
42
43 private static final Logger LOGGER = LogManager.getLogger(K8SController.class);
44 private static final String HOSTNAME = "HOSTNAME";
45 @Autowired
46 private ObjectMapper objectMapper;
47
48 @GetMapping("/k8s/pod")
49 public ResponseEntity<Pod> getPod() {
50 try {
51 KubernetesClient client = new KubernetesClientBuilder().createClient();
52 if (client != null) {
53 Pod pod = getCurrentPod(client);
54 if (pod != null) {
55 LOGGER.info("Pod: {}", objectMapper.writeValueAsString(pod));
56 return new ResponseEntity<>(pod, HttpStatus.OK);
57 }
58 }
59 } catch (Exception ex) {
60 LOGGER.error("Unable to obtain or print Pod information", ex);
61 }
62 return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
63 }
64
65 private Pod getCurrentPod(KubernetesClient kubernetesClient) {
66 String hostName = System.getenv(HOSTNAME);
67 try {
68 if (isServiceAccount() && Strings.isNotBlank(hostName)) {
69 return kubernetesClient.pods().withName(hostName).get();
70 }
71 } catch (Throwable t) {
72 LOGGER.debug("Unable to locate pod with name {}.", hostName);
73 }
74 return null;
75 }
76
77 private boolean isServiceAccount() {
78 return Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH).toFile().exists()
79 && Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile().exists();
80 }
81
82 }
1717
1818 import java.io.IOException;
1919 import org.springframework.http.client.ClientHttpResponse;
20 import org.springframework.web.client.ResponseErrorHandler;
2021
2122 /**
2223 * Custom http client error handler which doesn't throw exception in case http code is not 2xx.
00 server:
1 port: 8080
1 port: 4567
22 servlet:
33 context-path: /sample
44
2626 addresses: rabbit
2727 port: 5672
2828 username: guest
29 password: guest
30
31 log4j2:
32 debug: true
29 password: guest
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>
24
25 <name>Apache Log4j Sample Configuration Service</name>
23 <version>2.12.3</version>
24
25 <name>Log4j Sample Configuration Service</name>
2626 <description>Sample Cloud Config Server</description>
2727
2828 <parent>
2929 <groupId>org.springframework.boot</groupId>
3030 <artifactId>spring-boot-starter-parent</artifactId>
31 <version>2.3.6.RELEASE</version>
31 <version>2.1.2.RELEASE</version>
3232 <relativePath /> <!-- lookup parent from repository -->
3333 </parent>
3434
3535 <properties>
3636 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3737 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
38 <log4jParentDir>${basedir}/../../..</log4jParentDir>
3938 <java.version>1.8</java.version>
40 <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
39 <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
4140 <deploy.plugin.version>2.8.2</deploy.plugin.version>
4241
4342 <!-- paths -->
4948 <maven.findbugs.version>3.0.5</maven.findbugs.version>
5049 <maven.google.code.findbugs.version>3.0.2</maven.google.code.findbugs.version>
5150 <maven.google.code.findbugs.findbugs.version>3.0.1</maven.google.code.findbugs.findbugs.version>
52 <maven.jacoco.version>0.8.6</maven.jacoco.version>
51 <maven.jacoco.version>0.8.1</maven.jacoco.version>
5352 <maven.pmd.version>3.9.0</maven.pmd.version>
5453 <site.plugin.version>3.4</site.plugin.version>
5554 <!-- maven plugin config -->
5655 <pmd.failurePriority>2</pmd.failurePriority>
5756 <deploy.plugin.version>2.8.2</deploy.plugin.version>
5857 <rat.plugin.version>0.12</rat.plugin.version>
59 <maven.doap.skip>true</maven.doap.skip>
6058 </properties>
6159
6260 <dependencyManagement>
138136 <plugins>
139137 <plugin>
140138 <groupId>org.apache.maven.plugins</groupId>
139 <artifactId>maven-doap-plugin</artifactId>
140 <version>1.2</version>
141 <configuration>
142 <doapOptions>
143 <programmingLanguage>Java</programmingLanguage>
144 <category>library</category>
145 </doapOptions>
146 <asfExtOptions>
147 <charter>
148 The Apache Logging Services Project creates and maintains open-source software related to the logging of
149 application behavior and released at no charge to the public.
150 </charter>
151 <pmc>https://logging.apache.org</pmc>
152 </asfExtOptions>
153 <skip>true</skip>
154 </configuration>
155 <executions>
156 <execution>
157 <id>site</id>
158 <phase>site</phase>
159 <goals>
160 <goal>generate</goal>
161 </goals>
162 </execution>
163 </executions>
164 </plugin>
165 <plugin>
166 <groupId>org.apache.maven.plugins</groupId>
141167 <artifactId>maven-site-plugin</artifactId>
142168 <version>${site.plugin.version}</version>
143169 <configuration>
241267 </distributionManagement>
242268
243269 <repositories>
244 <repository>
245 <id>apache</id>
246 <url>https://repository.apache.org/content/repositories/releases/</url>
247 <snapshots>
248 <enabled>false</enabled>
249 </snapshots>
250 </repository>
251 <repository>
252 <id>apache.snapshots</id>
253 <name>Apache snapshots repository</name>
254 <url>http://repository.apache.org/content/groups/snapshots</url>
255 <snapshots>
256 <enabled>true</enabled>
257 </snapshots>
258 </repository>
259270 <repository>
260271 <id>spring-snapshots</id>
261272 <name>Spring Snapshots</name>
303314 </profile>
304315 </profiles>
305316
317
306318 <scm>
307 <tag>log4j-2.17.0-rc1</tag>
319 <tag>log4j-2.12.3-rc1</tag>
308320 </scm>
309321 </project>
1515 limitations under the License.
1616
1717 -->
18 <Configuration status="DEBUG" monitorInterval="0">
19 <Properties>
20 <Property name="spring.application.name">sampleapp</Property>
21 </Properties>
18 <Configuration status="ERROR" monitorInterval="0">
2219 <Appenders>
23 <!--<Flume name="flume" ignoreExceptions="false" type="Embedded" compress="false">
20 <Console name="console" target="SYSTEM_OUT">
21 <JsonLayout properties="true" compact="true" eventEol="true" stackTraceAsString="true">
22 </JsonLayout>
23 </Console>
24 <Flume name="flume" ignoreExceptions="false" type="Embedded" compress="false">
2425 <Property name="channel.type">memory</Property>
2526 <Property name="channel.capacity">100000</Property>
2627 <Property name="channel.transactionCapacity">5000</Property>
3435 <KeyValuePair key="containerId" value="\${docker:containerId}"/>
3536 <KeyValuePair key="containerName" value="\${docker:containerName}"/>
3637 <KeyValuePair key="imageName" value="\${docker:imageName}"/>
37 <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
3838 </JsonLayout>
3939 </Flume>
4040 <Flume name="avro" ignoreExceptions="false" batchSize="1" compress="false">
4343 <KeyValuePair key="containerId" value="\${docker:containerId}"/>
4444 <KeyValuePair key="containerName" value="\${docker:containerName}"/>
4545 <KeyValuePair key="imageName" value="\${docker:imageName}"/>
46 <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
4746 </JsonLayout>
4847 </Flume>
4948 <Flume name="avroSyslog" ignoreExceptions="false" batchSize="100" compress="false">
5453 <KeyValuePair key="containerId" value="\${docker:containerId}"/>
5554 <KeyValuePair key="containerName" value="\${docker:containerName}"/>
5655 <KeyValuePair key="imageName" value="\${docker:imageName}"/>
57 <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
5856 </LoggerFields>
5957 </RFC5424Layout>
6058 </Flume>
6361 <KeyValuePair key="containerId" value="\${docker:containerId}"/>
6462 <KeyValuePair key="containerName" value="\${docker:containerName}"/>
6563 <KeyValuePair key="imageName" value="\${docker:imageName}"/>
66 <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
6764 </JsonLayout>
6865 <Property name="bootstrap.servers">host.docker.internal:9092</Property>
6966 </Kafka>
7269 <KeyValuePair key="containerId" value="\${docker:containerId}"/>
7370 <KeyValuePair key="containerName" value="\${docker:containerName}"/>
7471 <KeyValuePair key="imageName" value="\${docker:imageName}"/>
75 <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
7672 </JsonLayout>
7773 </Socket>
7874 <RollingFile name="RollingFile" fileName="/var/log/sampleapp/app.log"
8177 <KeyValuePair key="containerId" value="\${docker:containerId}"/>
8278 <KeyValuePair key="containerName" value="\${docker:containerName}"/>
8379 <KeyValuePair key="imageName" value="\${docker:imageName}"/>
84 <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
8580 </JsonLayout>
8681 <SizeBasedTriggeringPolicy size="10MB" />
8782 <DefaultRolloverStrategy max="5"/>
9489 <KeyValuePair key="containerId" value="\${docker:containerId}"/>
9590 <KeyValuePair key="containerName" value="\${docker:containerName}"/>
9691 <KeyValuePair key="imageName" value="\${docker:imageName}"/>
97 <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
9892 </LoggerFields>
9993 </RFC5424Layout>
10094 <SizeBasedTriggeringPolicy size="10MB" />
10195 <DefaultRolloverStrategy max="5"/>
102 </RollingFile>-->
103 <Socket name="Elastic"
104 host="\${sys:logstash.search.host}"
105 port="12222"
106 protocol="tcp"
107 bufferedIo="true">
108 <GelfLayout includeStackTrace="true" host="${hostName}" includeThreadContext="true" includeNullDelimiter="true"
109 compressionType="OFF">
110 <ThreadContextIncludes>requestId,sessionId,loginId,userId,ipAddress,corpAcctNumber,callingHost,ohBehalfOf,onBehalfOfAccount</ThreadContextIncludes>
111 <MessagePattern>%d [%t] %-5p %X{requestId, sessionId, loginId, userId, ipAddress, corpAcctNumber} %C{1.}.%M:%L - %m%n</MessagePattern>
112 <KeyValuePair key="docker.containerId" value="\${docker:containerId:-}"/>
113 <KeyValuePair key="application" value="$\${lower:\${spring:spring.application.name}}"/>
114 <KeyValuePair key="kubernetes.serviceAccountName" value="\${k8s:accountName:-}"/>
115 <KeyValuePair key="kubernetes.containerId" value="\${k8s:containerId:-}"/>
116 <KeyValuePair key="kubernetes.containerName" value="\${k8s:containerName:-}"/>
117 <KeyValuePair key="kubernetes.host" value="\${k8s:host:-}"/>
118 <KeyValuePair key="kubernetes.labels.app" value="\${k8s:labels.app:-}"/>
119 <KeyValuePair key="kubernetes.labels.pod-template-hash" value="\${k8s:labels.podTemplateHash:-}"/>
120 <KeyValuePair key="kubernetes.master_url" value="\${k8s:masterUrl:-}"/>
121 <KeyValuePair key="kubernetes.namespaceId" value="\${k8s:namespaceId:-}"/>
122 <KeyValuePair key="kubernetes.namespaceName" value="\${k8s:namespaceName:-}"/>
123 <KeyValuePair key="kubernetes.podID" value="\${k8s:podId:-}"/>
124 <KeyValuePair key="kubernetes.podIP" value="\${k8s:podIp:-}"/>
125 <KeyValuePair key="kubernetes.podName" value="\${k8s:podName:-}"/>
126 <KeyValuePair key="kubernetes.imageId" value="\${k8s:imageId:-}"/>
127 <KeyValuePair key="kubernetes.imageName" value="\${k8s:imageName:-}"/>
128 </GelfLayout>
129 </Socket>
130 <Console name="Console" target="SYSTEM_OUT">
131 <RFC5424Layout enterpriseNumber="50177" includeMDC="true" mdcId="RequestContext" appName="SalesforceGateway"
132 mdcPrefix="" newLine="true" mdcIncludes="requestId,sessionId,loginId,userId,ipAddress,corpAcctNumber"/>
133 </Console>
134 <Failover name="log4j" primary="Elastic">
135 <Failovers>
136 <AppenderRef ref="Console"/>
137 </Failovers>
138 </Failover>
96 </RollingFile>
13997 </Appenders>
140
14198 <Loggers>
14299 <Logger name="org.apache.kafka" level="warn" additivity="false">
143 <AppenderRef ref="log4j"/>
100 <AppenderRef ref="console"/>
144101 </Logger>
145102 <Logger name="org.apache.flume" level="warn" additivity="false">
146 <AppenderRef ref="log4j"/>
103 <AppenderRef ref="console"/>
147104 </Logger>
148105 <Logger name="org.apache.avro" level="warn" additivity="false">
149 <AppenderRef ref="log4j"/>
106 <AppenderRef ref="console"/>
150107 </Logger>
151108 <Root level="DEBUG">
152 <AppenderRef ref="log4j"/>
109 <AppenderRef ref="console"/>
153110 </Root>
154111 </Loggers>
155112 </Configuration>
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.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <groupId>org.apache.logging.log4j.samples</groupId>
3030 <properties>
3131 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3232 <revapi.skip>true</revapi.skip>
33 <log4jParentDir>${basedir}/../..</log4jParentDir>
3433 </properties>
3534 <dependencyManagement>
3635 <dependencies>
6059 <dependency>
6160 <groupId>junit</groupId>
6261 <artifactId>junit</artifactId>
62 <version>4.12</version>
6363 <scope>test</scope>
6464 </dependency>
6565 </dependencies>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <groupId>org.apache.logging.log4j</groupId>
3030 <properties>
3131 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3232 <revapi.skip>true</revapi.skip>
33 <spring-cloud-version>2020.0.4</spring-cloud-version>
33 <spring-cloud-version>Greenwich.SR1</spring-cloud-version>
34 <spring-boot.version>2.1.6.RELEASE</spring-boot.version>
35 <springVersion>5.1.8.RELEASE</springVersion>
3436 <log4jParentDir>${basedir}/..</log4jParentDir>
35 <maven.doap.skip>true</maven.doap.skip>
3637 </properties>
3738 <dependencyManagement>
3839 <dependencies>
4546 </dependency>
4647 <dependency>
4748 <groupId>org.springframework.boot</groupId>
48 <artifactId>spring-boot-starter-parent</artifactId>
49 <artifactId>spring-boot</artifactId>
4950 <version>${spring-boot.version}</version>
5051 <type>pom</type>
5152 <scope>import</scope>
5657 <version>${spring-cloud-version}</version>
5758 <type>pom</type>
5859 <scope>import</scope>
60 </dependency>
61 <dependency>
62 <groupId>junit</groupId>
63 <artifactId>junit</artifactId>
64 <version>4.12</version>
65 <scope>test</scope>
5966 </dependency>
6067 </dependencies>
6168 </dependencyManagement>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-taglib</artifactId>
3131 <docLabel>Log4j Tag Library Documentation</docLabel>
3232 <projectDir>/taglib</projectDir>
3333 <module.name>org.apache.logging.log4j.taglib</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
3534 </properties>
3635 <dependencies>
3736 <dependency>
6766 <scope>test</scope>
6867 </dependency>
6968 <dependency>
70 <groupId>org.junit.vintage</groupId>
71 <artifactId>junit-vintage-engine</artifactId>
72 </dependency>
73 <dependency>
74 <groupId>org.junit.jupiter</groupId>
75 <artifactId>junit-jupiter-engine</artifactId>
69 <groupId>junit</groupId>
70 <artifactId>junit</artifactId>
71 <scope>test</scope>
7672 </dependency>
7773 <dependency>
7874 <groupId>org.springframework</groupId>
164160 </reportSets>
165161 </plugin>
166162 <plugin>
167 <groupId>com.github.spotbugs</groupId>
168 <artifactId>spotbugs-maven-plugin</artifactId>
163 <groupId>org.codehaus.mojo</groupId>
164 <artifactId>findbugs-maven-plugin</artifactId>
165 <version>${findbugs.plugin.version}</version>
166 <configuration>
167 <fork>true</fork>
168 <jvmArgs>-Duser.language=en</jvmArgs>
169 <threshold>Normal</threshold>
170 <effort>Default</effort>
171 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
172 </configuration>
169173 </plugin>
170174 <plugin>
171175 <groupId>org.apache.maven.plugins</groupId>
3434 private int scope;
3535
3636 public DumpTag() {
37 super();
3738 init();
3839 }
3940
5656 final Log4jTaglibLogger logger = this.getLogger();
5757
5858 if (TagUtils.isEnabled(logger, Level.TRACE, null)) {
59 if (this.attributes.isEmpty()) {
59 if (this.attributes.size() == 0) {
6060 logger.entry(FQCN);
6161 } else {
6262 logger.entry(FQCN, this.attributes.toArray());
4141 private int scope;
4242
4343 public SetLoggerTag() {
44 super();
4445 init();
4546 }
4647
1919 xmlns="http://maven.apache.org/DECORATION/1.4.0"
2020 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2121 xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
22 <bannerLeft>
23 <name>Logging Services</name>
24 <src>../images/ls-logo.jpg</src>
25 <href>../index.html</href>
26 </bannerLeft>
27 <bannerRight>
28 <src>../images/logo.jpg</src>
29 </bannerRight>
2230 <body>
2331 <links>
2432 <item name="Apache" href="http://www.apache.org/" />
4856 <item name="Surefire Report" href="../surefire-report.html" />
4957 <item name="RAT Report" href="../rat-report.html" />
5058 </menu>
59 <footer><div class="row span16">Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, and the
60 Apache Logging project logo are trademarks of The Apache Software Foundation.</div>
61 </footer>
5162 </body>
5263 </project>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-to-slf4j</artifactId>
3131 <docLabel>SLF4J Documentation</docLabel>
3232 <projectDir>/log4j-to-slf4j</projectDir>
3333 <module.name>org.apache.logging.slf4j</module.name>
34 <maven.doap.skip>true</maven.doap.skip>
3534 </properties>
3635 <dependencies>
3736 <dependency>
5958 <scope>test</scope>
6059 </dependency>
6160 <dependency>
62 <groupId>org.junit.vintage</groupId>
63 <artifactId>junit-vintage-engine</artifactId>
64 </dependency>
65 <dependency>
66 <groupId>org.junit.jupiter</groupId>
67 <artifactId>junit-jupiter-engine</artifactId>
61 <groupId>junit</groupId>
62 <artifactId>junit</artifactId>
63 <scope>test</scope>
6864 </dependency>
6965 <dependency>
7066 <groupId>org.hamcrest</groupId>
71 <artifactId>hamcrest</artifactId>
67 <artifactId>hamcrest-all</artifactId>
7268 <scope>test</scope>
7369 </dependency>
7470 </dependencies>
154150 </reportSets>
155151 </plugin>
156152 <plugin>
157 <groupId>com.github.spotbugs</groupId>
158 <artifactId>spotbugs-maven-plugin</artifactId>
153 <groupId>org.codehaus.mojo</groupId>
154 <artifactId>findbugs-maven-plugin</artifactId>
155 <version>${findbugs.plugin.version}</version>
156 <configuration>
157 <fork>true</fork>
158 <jvmArgs>-Duser.language=en</jvmArgs>
159 <threshold>Normal</threshold>
160 <effort>Default</effort>
161 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
162 </configuration>
159163 </plugin>
160164 <plugin>
161165 <groupId>org.apache.maven.plugins</groupId>
7070
7171 @Override
7272 public boolean containsKey(final String key) {
73 Map<String, String> map = MDC.getCopyOfContextMap();
74 return map != null && map.containsKey(key);
73 return MDC.getCopyOfContextMap().containsKey(key);
7574 }
7675
7776 @Override
8887
8988 @Override
9089 public boolean isEmpty() {
91 Map<String, String> map = MDC.getCopyOfContextMap();
92 return map == null || map.isEmpty();
90 return MDC.getCopyOfContextMap().isEmpty();
9391 }
9492
9593 @Override
2727 */
2828 public class SLF4JLoggerContextFactory implements LoggerContextFactory {
2929 private static final StatusLogger LOGGER = StatusLogger.getLogger();
30 private static final LoggerContext context = new SLF4JLoggerContext();
30 private static LoggerContext context = new SLF4JLoggerContext();
3131
3232 public SLF4JLoggerContextFactory() {
3333 // LOG4J2-230, LOG4J2-204 (improve error reporting when misconfigured)
5959 @Override
6060 public void removeContext(final LoggerContext ignored) {
6161 }
62
63 @Override
64 public boolean isClassLoaderDependent() {
65 // context is always used
66 return false;
67 }
6862 }
3232 import org.junit.Before;
3333 import org.junit.ClassRule;
3434 import org.junit.Test;
35 import org.slf4j.MDC;
3635
3736 import static org.hamcrest.Matchers.*;
3837 import static org.junit.Assert.*;
183182 assertThat(list.strList, hasSize(2));
184183 assertTrue("Incorrect year", list.strList.get(0).startsWith("2010"));
185184 }
185 }
186186
187 @Test
188 public void mdcNullBackedIsEmpty() {
189 assertNull("Setup wrong", MDC.getCopyOfContextMap());
190 assertTrue(ThreadContext.isEmpty());
191 }
192
193 @Test
194 public void mdcNullBackedContainsKey() {
195 assertNull("Setup wrong", MDC.getCopyOfContextMap());
196 assertFalse(ThreadContext.containsKey("something"));
197 }
198
199 @Test
200 public void mdcNullBackedContainsNullKey() {
201 assertNull("Setup wrong", MDC.getCopyOfContextMap());
202 assertFalse(ThreadContext.containsKey(null));
203 }
204
205 @Test
206 public void mdcContainsNullKey() {
207 try {
208 ThreadContext.put("some", "thing");
209 assertNotNull("Setup wrong", MDC.getCopyOfContextMap());
210 assertFalse(ThreadContext.containsKey(null));
211 } finally {
212 ThreadContext.clearMap();
213 }
214 }
215
216 @Test
217 public void mdcCannotContainNullKey() {
218 try {
219 ThreadContext.put(null, "something");
220 fail("should throw");
221 } catch (IllegalArgumentException | NullPointerException e) {
222 // expected
223 }
224 }
225 }
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
3333 <docLabel>Web Documentation</docLabel>
3434 <projectDir>/log4j-web</projectDir>
3535 <module.name>org.apache.logging.log4j.web</module.name>
36 <maven.doap.skip>true</maven.doap.skip>
3736 </properties>
3837
3938 <dependencies>
6059 <scope>test</scope>
6160 </dependency>
6261 <dependency>
63 <groupId>org.hamcrest</groupId>
64 <artifactId>hamcrest</artifactId>
62 <groupId>junit</groupId>
63 <artifactId>junit</artifactId>
64 <scope>test</scope>
6565 </dependency>
66 <dependency>
67 <groupId>org.junit.jupiter</groupId>
68 <artifactId>junit-jupiter-engine</artifactId>
69 </dependency>
70 <dependency>
71 <groupId>org.mockito</groupId>
72 <artifactId>mockito-junit-jupiter</artifactId>
73 </dependency>
7466 <dependency>
7567 <groupId>org.springframework</groupId>
7668 <artifactId>spring-test</artifactId>
156148 </reportSets>
157149 </plugin>
158150 <plugin>
159 <groupId>com.github.spotbugs</groupId>
160 <artifactId>spotbugs-maven-plugin</artifactId>
151 <groupId>org.codehaus.mojo</groupId>
152 <artifactId>findbugs-maven-plugin</artifactId>
153 <version>${findbugs.plugin.version}</version>
154 <configuration>
155 <fork>true</fork>
156 <jvmArgs>-Duser.language=en</jvmArgs>
157 <threshold>Normal</threshold>
158 <effort>Default</effort>
159 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
160 </configuration>
161161 </plugin>
162162 <plugin>
163163 <groupId>org.apache.maven.plugins</groupId>
3333 */
3434 public class Log4jServletContainerInitializer implements ServletContainerInitializer {
3535
36 private static final Logger LOGGER = StatusLogger.getLogger();
37
3638 @Override
3739 public void onStartup(final Set<Class<?>> classes, final ServletContext servletContext) throws ServletException {
3840 if (servletContext.getMajorVersion() > 2 && servletContext.getEffectiveMajorVersion() > 2 &&
3941 !"true".equalsIgnoreCase(servletContext.getInitParameter(
4042 Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED
4143 ))) {
42 final Logger LOGGER = StatusLogger.getLogger();
43
4444 LOGGER.debug("Log4jServletContainerInitializer starting up Log4j in Servlet 3.0+ environment.");
4545
4646 final FilterRegistration.Dynamic filter =
5656 initializer.start();
5757 initializer.setLoggerContext(); // the application is just now starting to start up
5858
59 if (!"true".equalsIgnoreCase(servletContext.getInitParameter(
60 Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED))) {
61 servletContext.addListener(new Log4jServletContextListener());
62 }
59 servletContext.addListener(new Log4jServletContextListener());
6360
6461 filter.setAsyncSupported(true); // supporting async when the user isn't using async has no downsides
6562 filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
4949 public void contextInitialized(final ServletContextEvent event) {
5050 this.servletContext = event.getServletContext();
5151 LOGGER.debug("Log4jServletContextListener ensuring that Log4j starts up properly.");
52
53 if ("true".equalsIgnoreCase(servletContext.getInitParameter(
54 Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED))) {
55 throw new IllegalStateException("Do not use " + getClass().getSimpleName() + " when "
56 + Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED + " is true. Please use "
57 + Log4jShutdownOnContextDestroyedListener.class.getSimpleName() + " instead of "
58 + getClass().getSimpleName() + ".");
59 }
6052
6153 this.initializer = WebLoggerContextUtils.getWebLifeCycle(this.servletContext);
6254 try {
+0
-80
log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListener.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.logging.log4j.web;
17
18 import java.util.Locale;
19 import java.util.concurrent.TimeUnit;
20
21 import javax.servlet.ServletContext;
22 import javax.servlet.ServletContextEvent;
23 import javax.servlet.ServletContextListener;
24
25 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.LifeCycle2;
27 import org.apache.logging.log4j.status.StatusLogger;
28 import org.apache.logging.log4j.util.Strings;
29
30 public class Log4jShutdownOnContextDestroyedListener implements ServletContextListener {
31
32 private static final int DEFAULT_STOP_TIMEOUT = 30;
33 private static final TimeUnit DEFAULT_STOP_TIMEOUT_TIMEUNIT = TimeUnit.SECONDS;
34
35 private static final String KEY_STOP_TIMEOUT = "log4j.stop.timeout";
36 private static final String KEY_STOP_TIMEOUT_TIMEUNIT = "log4j.stop.timeout.timeunit";
37
38 private static final Logger LOGGER = StatusLogger.getLogger();
39
40 private ServletContext servletContext;
41 private Log4jWebLifeCycle initializer;
42
43 @Override
44 public void contextInitialized(final ServletContextEvent event) {
45 LOGGER.debug(Log4jShutdownOnContextDestroyedListener.class.getSimpleName() +
46 " ensuring that Log4j started up properly.");
47 servletContext = event.getServletContext();
48 if (null == servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)) {
49 throw new IllegalStateException(
50 "Context did not contain required Log4jWebLifeCycle in the "
51 + Log4jWebSupport.SUPPORT_ATTRIBUTE + " attribute.");
52 }
53 this.initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
54 }
55
56 @Override
57 public void contextDestroyed(final ServletContextEvent event) {
58 if (this.servletContext == null || this.initializer == null) {
59 LOGGER.warn("Context destroyed before it was initialized.");
60 return;
61 }
62 LOGGER.debug(Log4jShutdownOnContextDestroyedListener.class.getSimpleName() +
63 " ensuring that Log4j shuts down properly.");
64
65 this.initializer.clearLoggerContext(); // the application is finished
66 // shutting down now
67 if (initializer instanceof LifeCycle2) {
68 final String stopTimeoutStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT);
69 final long stopTimeout = Strings.isEmpty(stopTimeoutStr) ? DEFAULT_STOP_TIMEOUT
70 : Long.parseLong(stopTimeoutStr);
71 final String timeoutTimeUnitStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT_TIMEUNIT);
72 final TimeUnit timeoutTimeUnit = Strings.isEmpty(timeoutTimeUnitStr) ? DEFAULT_STOP_TIMEOUT_TIMEUNIT
73 : TimeUnit.valueOf(timeoutTimeUnitStr.toUpperCase(Locale.ROOT));
74 ((LifeCycle2) this.initializer).stop(stopTimeout, timeoutTimeUnit);
75 } else {
76 this.initializer.stop();
77 }
78 }
79 }
1515 */
1616 package org.apache.logging.log4j.web;
1717
18 import java.net.URI;
19 import java.net.URL;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Date;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.TimeUnit;
28
29 import javax.servlet.ServletContext;
30
1831 import org.apache.logging.log4j.LogManager;
1932 import org.apache.logging.log4j.core.AbstractLifeCycle;
2033 import org.apache.logging.log4j.core.LoggerContext;
2942 import org.apache.logging.log4j.core.selector.NamedContextSelector;
3043 import org.apache.logging.log4j.core.util.Loader;
3144 import org.apache.logging.log4j.core.util.NetUtils;
45 import org.apache.logging.log4j.core.util.SetUtils;
3246 import org.apache.logging.log4j.spi.LoggerContextFactory;
3347 import org.apache.logging.log4j.util.LoaderUtil;
34 import org.apache.logging.log4j.util.Strings;
35
36 import javax.servlet.ServletContext;
37 import java.net.URI;
38 import java.net.URL;
39 import java.text.SimpleDateFormat;
40 import java.util.*;
41 import java.util.concurrent.ConcurrentHashMap;
42 import java.util.concurrent.TimeUnit;
4348
4449 /**
4550 * This class initializes and deinitializes Log4j no matter how the initialization occurs.
128133 final ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
129134 if (selector instanceof NamedContextSelector) {
130135 this.namedContextSelector = (NamedContextSelector) selector;
131 context = this.namedContextSelector.locateContext(this.name,
132 WebLoggerContextUtils.createExternalEntry(this.servletContext), configLocation);
136 context = this.namedContextSelector.locateContext(this.name, this.servletContext, configLocation);
133137 ContextAnchor.THREAD_CONTEXT.set(context);
134138 if (context.isInitialized()) {
135139 context.start();
162166 }
163167 if (location != null && location.contains(",")) {
164168 final List<URI> uris = getConfigURIs(location);
165 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uris,
166 WebLoggerContextUtils.createExternalEntry(this.servletContext));
169 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uris, this.servletContext);
167170 return;
168171 }
169172
170173 final URI uri = getConfigURI(location);
171 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uri,
172 WebLoggerContextUtils.createExternalEntry(this.servletContext));
174 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uri, this.servletContext);
173175 }
174176
175177 private List<URI> getConfigURIs(final String location) {
188190 try {
189191 String configLocation = location;
190192 if (configLocation == null) {
191 final String[] paths = prefixSet(servletContext.getResourcePaths(WEB_INF), WEB_INF + "log4j2");
193 final String[] paths = SetUtils.prefixSet(servletContext.getResourcePaths(WEB_INF), WEB_INF + "log4j2");
192194 LOGGER.debug("getConfigURI found resource paths {} in servletContext at [{}]", Arrays.toString(paths), WEB_INF);
193195 if (paths.length == 1) {
194196 configLocation = paths[0];
230232 return null;
231233 }
232234
233 /**
234 * Collects strings starting with the given {@code prefix} from the given {@code set}.
235 *
236 * @param set a (nullable) set of strings
237 * @param prefix a prefix to look for in the string set
238 * @return an array of the matching strings from the given set
239 */
240 @SuppressWarnings("SameParameterValue")
241 private static String[] prefixSet(final Set<String> set, final String prefix) {
242 if (set == null) {
243 return Strings.EMPTY_ARRAY;
244 }
245 return set
246 .stream()
247 .filter(string -> string.startsWith(prefix))
248 .toArray(String[]::new);
249 }
250
251235 @Override
252236 public synchronized boolean stop(final long timeout, final TimeUnit timeUnit) {
253237 if (!this.isStarted() && !this.isStopped()) {
5555 String IS_LOG4J_AUTO_INITIALIZATION_DISABLED = "isLog4jAutoInitializationDisabled";
5656
5757 /**
58 * The {@link javax.servlet.ServletContext} parameter name for the flag that disables Log4j's auto-shutdown
59 * in Servlet 3.0+ web applications. Set a context parameter with this name to "true" to disable
60 * auto-shutdown.
61 */
62 String IS_LOG4J_AUTO_SHUTDOWN_DISABLED = "isLog4jAutoShutdownDisabled";
63
64 /**
6558 * The attribute key for the {@link javax.servlet.ServletContext} attribute that the singleton support instance
6659 * is stored in.
6760 */
1515 */
1616 package org.apache.logging.log4j.web;
1717
18 import java.util.AbstractMap;
19 import java.util.Map;
2018 import java.util.concurrent.locks.Lock;
2119 import java.util.concurrent.locks.ReentrantLock;
2220 import javax.servlet.ServletContext;
3836 }
3937
4038 private static final Lock WEB_SUPPORT_LOOKUP = new ReentrantLock();
41 private static final String SERVLET_CONTEXT = "__SERVLET_CONTEXT__";
4239
4340 /**
4441 * Finds the main {@link org.apache.logging.log4j.core.LoggerContext} configured for the given ServletContext.
10097 * @since 2.0.1
10198 */
10299 public static Runnable wrapExecutionContext(final ServletContext servletContext, final Runnable runnable) {
103 return () -> {
104 final Log4jWebSupport webSupport = getWebLifeCycle(servletContext);
105 webSupport.setLoggerContext();
106 try {
107 runnable.run();
108 } finally {
109 webSupport.clearLoggerContext();
100 return new Runnable() {
101 @Override
102 public void run() {
103 final Log4jWebSupport webSupport = getWebLifeCycle(servletContext);
104 webSupport.setLoggerContext();
105 try {
106 runnable.run();
107 } finally {
108 webSupport.clearLoggerContext();
109 }
110110 }
111111 };
112 }
113
114 public static Map.Entry<String, Object> createExternalEntry(ServletContext servletContext) {
115 return new AbstractMap.SimpleEntry<>(SERVLET_CONTEXT, servletContext);
116 }
117
118 public static void setServletContext(LoggerContext lc, ServletContext servletContext) {
119 if (lc != null) {
120 lc.putObject(SERVLET_CONTEXT, servletContext);
121 }
122112 }
123113
124114 /**
132122 if (lc == null) {
133123 lc = LogManager.getContext(false);
134124 }
135
136 Object obj = lc != null ? lc.getObject(SERVLET_CONTEXT) : null;
137 if (obj instanceof ServletContext) {
138 return (ServletContext) obj;
139 }
140 return null;
125 return lc == null ? null :
126 lc.getExternalContext() instanceof ServletContext ? (ServletContext) lc.getExternalContext() : null;
141127 }
142128 }
5858 return root;
5959 }
6060
61 if ("contextPathName".equals(key)) {
62 String path = ctx.getContextPath();
63 if (path.trim().contains("/")) {
64 String[] fields = path.split("/");
65 for (String field : fields) {
66 if (field.length() > 0) {
67 return field;
68 }
69 }
70 return null;
71 }
72 return ctx.getContextPath();
73 }
74
7561 if ("contextPath".equals(key)) {
7662 return ctx.getContextPath();
7763 }
2323 import javax.servlet.ServletContext;
2424
2525 import org.apache.logging.log4j.util.Strings;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
2929 import org.mockito.ArgumentCaptor;
3030 import org.mockito.Captor;
3131 import org.mockito.Mock;
32 import org.mockito.junit.jupiter.MockitoExtension;
32 import org.mockito.runners.MockitoJUnitRunner;
3333
34 import static org.junit.jupiter.api.Assertions.*;
34 import static org.junit.Assert.*;
3535 import static org.mockito.ArgumentMatchers.eq;
36 import static org.mockito.BDDMockito.any;
3736 import static org.mockito.BDDMockito.given;
38 import static org.mockito.BDDMockito.never;
3937 import static org.mockito.BDDMockito.then;
4038 import static org.mockito.BDDMockito.willThrow;
4139 import static org.mockito.Mockito.mock;
4240
43 @ExtendWith(MockitoExtension.class)
41 @RunWith(MockitoJUnitRunner.class)
4442 public class Log4jServletContainerInitializerTest {
4543 @Mock
4644 private ServletContext servletContext;
5351
5452 private Log4jServletContainerInitializer containerInitializer;
5553
56 @BeforeEach
54 @Before
5755 public void setUp() {
5856 this.containerInitializer = new Log4jServletContainerInitializer();
5957 }
8482 }
8583
8684 @Test
87 public void testOnStartupWithServletVersion3_xEffectiveVersion3_xShutdownDisabled() throws Exception {
88 final FilterRegistration.Dynamic registration = mock(FilterRegistration.Dynamic.class);
89 given(servletContext.getMajorVersion()).willReturn(3);
90 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
91 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
92 .willReturn("true");
93 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
94 null);
95 given(servletContext.addFilter(eq("log4jServletFilter"), filterCaptor.capture())).willReturn(registration);
96 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
97
98 this.containerInitializer.onStartup(null, this.servletContext);
99
100 then(initializer).should().start();
101 then(initializer).should().setLoggerContext();
102 then(registration).should().setAsyncSupported(eq(true));
103 then(registration).should().addMappingForUrlPatterns(eq(EnumSet.allOf(DispatcherType.class)), eq(false), eq("/*"));
104
105 // initParam IS_LOG4J_AUTO_SHUTDOWN_DISABLED is "true" so addListener shouldn't be called.
106 then(servletContext).should(never()).addListener(any(Log4jServletContextListener.class));
107 }
108
109 @Test
11085 public void testOnStartupWithServletVersion3_xEffectiveVersion3_xDisabledTRUE() throws Exception {
11186 given(servletContext.getMajorVersion()).willReturn(3);
11287 given(servletContext.getEffectiveMajorVersion()).willReturn(3);
134109 then(registration).should().setAsyncSupported(eq(true));
135110 then(registration).should().addMappingForUrlPatterns(eq(EnumSet.allOf(DispatcherType.class)), eq(false), eq("/*"));
136111
137 assertNotNull(listenerCaptor.getValue(), "The listener should not be null.");
138 assertSame(Log4jServletContextListener.class,
139 listenerCaptor.getValue().getClass(),
140 "The listener is not correct.");
112 assertNotNull("The listener should not be null.", listenerCaptor.getValue());
113 assertSame("The listener is not correct.", Log4jServletContextListener.class,
114 listenerCaptor.getValue().getClass());
141115
142 assertNotNull(filterCaptor.getValue(), "The filter should not be null.");
143 assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The filter is not correct.");
116 assertNotNull("The filter should not be null.", filterCaptor.getValue());
117 assertSame("The filter is not correct.", Log4jServletFilter.class, filterCaptor.getValue());
144118 }
145119
146120 @Test
153127
154128 this.containerInitializer.onStartup(null, this.servletContext);
155129
156 assertNotNull(filterCaptor.getValue(), "The filter should not be null.");
157 assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The filter is not correct.");
130 assertNotNull("The filter should not be null.", filterCaptor.getValue());
131 assertSame("The filter is not correct.", Log4jServletFilter.class, filterCaptor.getValue());
158132 }
159133
160134 @Test
173147 this.containerInitializer.onStartup(null, this.servletContext);
174148 fail("Expected the exception thrown by the initializer; got no exception.");
175149 } catch (final IllegalStateException e) {
176 assertSame(exception, e, "The exception is not correct.");
150 assertSame("The exception is not correct.", exception, e);
177151 }
178152
179153 then(initializer).should().start();
180 assertNotNull(filterCaptor.getValue(), "The filter should not be null.");
181 assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The filter is not correct.");
154 assertNotNull("The filter should not be null.", filterCaptor.getValue());
155 assertSame("The filter is not correct.", Log4jServletFilter.class, filterCaptor.getValue());
182156 }
183157 }
1919 import javax.servlet.ServletContextEvent;
2020
2121 import org.apache.logging.log4j.util.Strings;
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.api.extension.ExtendWith;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
2525 import org.mockito.Mock;
26 import org.mockito.junit.jupiter.MockitoExtension;
26 import org.mockito.runners.MockitoJUnitRunner;
2727
28 import static org.junit.jupiter.api.Assertions.*;
29 import static org.mockito.BDDMockito.eq;
28 import static org.junit.Assert.*;
3029 import static org.mockito.BDDMockito.given;
3130 import static org.mockito.BDDMockito.then;
3231 import static org.mockito.BDDMockito.willThrow;
3332
34 @ExtendWith(MockitoExtension.class)
33 @RunWith(MockitoJUnitRunner.class)
3534 public class Log4jServletContextListenerTest {
36 /* event and servletContext are marked lenient because they aren't used in the
37 * testDestroyWithNoInit but are only accessed during initialization
38 */
39 @Mock(lenient = true)
40 private ServletContextEvent event;
41 @Mock(lenient = true)
35 @Mock
36 private ServletContextEvent event;
37 @Mock
4238 private ServletContext servletContext;
4339 @Mock
4440 private Log4jWebLifeCycle initializer;
4541
4642 private Log4jServletContextListener listener;
4743
48 @BeforeEach
44 @Before
4945 public void setUp() {
5046 this.listener = new Log4jServletContextListener();
5147 given(event.getServletContext()).willReturn(servletContext);
7369 this.listener.contextInitialized(this.event);
7470 fail("Expected a RuntimeException.");
7571 } catch (final RuntimeException e) {
76 assertEquals("Failed to initialize Log4j properly.", e.getMessage(), "The message is not correct.");
72 assertEquals("The message is not correct.", "Failed to initialize Log4j properly.", e.getMessage());
7773 }
7874 }
7975
80 @Test
81 public void initializingLog4jServletContextListenerShouldFaileWhenAutoShutdownIsTrue() throws Exception {
82 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
83 .willReturn("true");
84 ensureInitializingFailsWhenAuthShutdownIsEnabled();
85 }
86
87 @Test
88 public void initializingLog4jServletContextListenerShouldFaileWhenAutoShutdownIsTRUE() throws Exception {
89 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
90 .willReturn("TRUE");
91 ensureInitializingFailsWhenAuthShutdownIsEnabled();
92 }
93
94 private void ensureInitializingFailsWhenAuthShutdownIsEnabled() {
95 try {
96 this.listener.contextInitialized(this.event);
97 fail("Expected a RuntimeException.");
98 } catch (final RuntimeException e) {
99 String expectedMessage =
100 "Do not use " + Log4jServletContextListener.class.getSimpleName() + " when "
101 + Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED + " is true. Please use "
102 + Log4jShutdownOnContextDestroyedListener.class.getSimpleName() + " instead of "
103 + Log4jServletContextListener.class.getSimpleName() + ".";
104
105 assertEquals(expectedMessage, e.getMessage(), "The message is not correct");
106 }
107 }
10876 }
2121 import javax.servlet.ServletRequest;
2222 import javax.servlet.ServletResponse;
2323
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
2727 import org.mockito.Mock;
28 import org.mockito.junit.jupiter.MockitoExtension;
28 import org.mockito.runners.MockitoJUnitRunner;
2929
30 import static org.junit.jupiter.api.Assertions.*;
3130 import static org.mockito.ArgumentMatchers.eq;
3231 import static org.mockito.ArgumentMatchers.same;
3332 import static org.mockito.BDDMockito.given;
3433 import static org.mockito.BDDMockito.then;
3534 import static org.mockito.Mockito.reset;
3635
37 @ExtendWith(MockitoExtension.class)
36 @RunWith(MockitoJUnitRunner.class)
3837 public class Log4jServletFilterTest {
39 @Mock(lenient = true) // because filterConfig is not used in testDestroy
38 @Mock
4039 private FilterConfig filterConfig;
41 @Mock(lenient = true) // because filterConfig is not used in testDestroy
40 @Mock
4241 private ServletContext servletContext;
4342 @Mock
4443 private Log4jWebLifeCycle initializer;
5150
5251 private Log4jServletFilter filter;
5352
54 @BeforeEach
53 @Before
5554 public void setUp() {
5655 given(filterConfig.getServletContext()).willReturn(servletContext);
5756 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
6968 then(initializer).should().setLoggerContext();
7069 }
7170
72 @Test
71 @Test(expected = IllegalStateException.class)
7372 public void testDestroy() {
74 assertThrows(IllegalStateException.class, () -> {
75 this.filter.destroy();
76 });
73 this.filter.destroy();
7774 }
7875
7976 @Test
+0
-83
log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListenerTest.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.logging.log4j.web;
17
18 import static org.junit.jupiter.api.Assertions.*;
19 import static org.mockito.BDDMockito.given;
20 import static org.mockito.BDDMockito.then;
21 import static org.mockito.Mockito.never;
22
23 import javax.servlet.ServletContext;
24 import javax.servlet.ServletContextEvent;
25
26 import org.junit.jupiter.api.Test;
27 import org.junit.jupiter.api.extension.ExtendWith;
28 import org.mockito.Mock;
29 import org.mockito.junit.jupiter.MockitoExtension;
30
31 @ExtendWith(MockitoExtension.class)
32 public class Log4jShutdownOnContextDestroyedListenerTest {
33 @Mock(lenient = true)
34 private ServletContextEvent event;
35 @Mock(lenient = true)
36 private ServletContext servletContext;
37 @Mock
38 private Log4jWebLifeCycle initializer;
39
40 private Log4jShutdownOnContextDestroyedListener listener;
41
42 public void setUp(boolean mockInitializer) {
43 this.listener = new Log4jShutdownOnContextDestroyedListener();
44 given(event.getServletContext()).willReturn(servletContext);
45 if (mockInitializer) {
46 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE))
47 .willReturn(initializer);
48 }
49 }
50
51 @Test
52 public void testInitAndDestroy() throws Exception {
53 setUp(true);
54 this.listener.contextInitialized(this.event);
55
56 then(initializer).should(never()).start();
57 then(initializer).should(never()).setLoggerContext();
58
59 this.listener.contextDestroyed(this.event);
60
61 then(initializer).should().clearLoggerContext();
62 then(initializer).should().stop();
63 }
64
65 @Test
66 public void testDestroy() throws Exception {
67 setUp(true);
68 this.listener.contextDestroyed(this.event);
69
70 then(initializer).should(never()).clearLoggerContext();
71 then(initializer).should(never()).stop();
72 }
73
74 @Test
75 public void whenNoInitializerInContextTheContextInitializedShouldThrowAnException() {
76 setUp(false);
77
78 assertThrows(IllegalStateException.class, () -> {
79 this.listener.contextInitialized(this.event);
80 });
81 }
82 }
2323 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2424 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
2525 import org.apache.logging.log4j.core.impl.ContextAnchor;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.ExpectedException;
30 import org.junit.runner.RunWith;
2931 import org.mockito.ArgumentCaptor;
3032 import org.mockito.Captor;
3133 import org.mockito.Mock;
32 import org.mockito.junit.jupiter.MockitoExtension;
34 import org.mockito.runners.MockitoJUnitRunner;
3335
3436 import static java.util.Arrays.asList;
3537 import static java.util.Collections.singletonList;
3638 import static org.hamcrest.CoreMatchers.instanceOf;
3739 import static org.hamcrest.CoreMatchers.is;
3840 import static org.hamcrest.CoreMatchers.nullValue;
39 import static org.hamcrest.MatcherAssert.assertThat;
40 import static org.junit.jupiter.api.Assertions.*;
41 import static org.junit.Assert.assertNotNull;
42 import static org.junit.Assert.assertNull;
43 import static org.junit.Assert.assertSame;
44 import static org.junit.Assert.assertThat;
45 import static org.junit.Assert.assertTrue;
4146 import static org.mockito.ArgumentMatchers.eq;
4247 import static org.mockito.BDDMockito.given;
4348 import static org.mockito.BDDMockito.then;
4449
45 @ExtendWith(MockitoExtension.class)
50 @RunWith(MockitoJUnitRunner.class)
4651 public class Log4jWebInitializerImplTest {
47 /* Marking servletContext lenient because otherwise testCompositeLocationParameterWithEmptyUriListSetsDefaultConfiguration fails
48 * when null is passed in as the initial param because Mockito deciced null isn't a String rather than the absence of a string.
49 */
50 @Mock(lenient = true)
51 private ServletContext servletContext;
52 @Mock
53 private ServletContext servletContext;
5254 @Captor
5355 private ArgumentCaptor<Log4jWebLifeCycle> initializerCaptor;
5456 @Captor
5557 private ArgumentCaptor<LoggerContext> loggerContextCaptor;
58 @Rule
59 public ExpectedException expectedException = ExpectedException.none();
5660
5761 private Log4jWebInitializerImpl initializerImpl;
5862
59 @BeforeEach
63 @Before
6064 public void setUp() {
6165 given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(null);
6266
6367 final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(this.servletContext);
6468
6569 then(servletContext).should().setAttribute(eq(Log4jWebSupport.SUPPORT_ATTRIBUTE), initializerCaptor.capture());
66 assertNotNull(initializer, "The initializer should not be null.");
67 assertSame(initializer, initializerCaptor.getValue(), "The capture is not correct.");
68 assertTrue(initializer instanceof Log4jWebInitializerImpl, "The initializer is not correct.");
70 assertNotNull("The initializer should not be null.", initializer);
71 assertSame("The capture is not correct.", initializer, initializerCaptor.getValue());
72 assertTrue("The initializer is not correct.", initializer instanceof Log4jWebInitializerImpl);
6973
7074 this.initializerImpl = (Log4jWebInitializerImpl) initializer;
7175 }
7276
7377 @Test
7478 public void testDeinitializeBeforeInitialize() {
75 assertThrows(IllegalStateException.class, () -> {
76 this.initializerImpl.stop();
77 });
79 expectedException.expect(IllegalStateException.class);
80 this.initializerImpl.stop();
7881 }
7982
8083 @Test
8184 public void testSetLoggerContextBeforeInitialize() {
82 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
83
84 this.initializerImpl.setLoggerContext();
85
86 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
85 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
86
87 this.initializerImpl.setLoggerContext();
88
89 assertNull("The context should still be null.", ContextAnchor.THREAD_CONTEXT.get());
8790 }
8891
8992 @Test
9093 public void testClearLoggerContextBeforeInitialize() {
91 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
94 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
9295
9396 this.initializerImpl.clearLoggerContext();
9497
95 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
96 }
97
98 @Test
99 public void testInitializeWithNoParametersThenSetLoggerContextThenDeinitialize() {
98 assertNull("The context should still be null.", ContextAnchor.THREAD_CONTEXT.get());
99 }
100
101 @Test
102 public void testInitializeWithNoParametersThenSetLoggerContextThenDeinitialize() throws Exception {
100103 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
101104 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
102105 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
106109 this.initializerImpl.start();
107110
108111 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
109 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
112 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
110113 final org.apache.logging.log4j.spi.LoggerContext loggerContext = loggerContextCaptor.getValue();
111114
112 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
115 assertNull("The context should still be null.", ContextAnchor.THREAD_CONTEXT.get());
113116
114117 this.initializerImpl.setLoggerContext();
115118
116119 final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
117 assertNotNull(context, "The context should not be null.");
118 assertSame(loggerContext, context, "The context is not correct.");
120 assertNotNull("The context should not be null.", context);
121 assertSame("The context is not correct.", loggerContext, context);
119122
120123 this.initializerImpl.clearLoggerContext();
121124
122 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
123
124 this.initializerImpl.stop();
125
126 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
127
128 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
129
130 this.initializerImpl.setLoggerContext();
131
132 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
133 }
134
135 @Test
136 public void testInitializeWithClassLoaderNoParametersThenSetLoggerContextThenDeinitialize() {
125 assertNull("The context should be null again.", ContextAnchor.THREAD_CONTEXT.get());
126
127 this.initializerImpl.stop();
128
129 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
130
131 assertNull("The context should again still be null.", ContextAnchor.THREAD_CONTEXT.get());
132
133 this.initializerImpl.setLoggerContext();
134
135 assertNull("The context should finally still be null.", ContextAnchor.THREAD_CONTEXT.get());
136 }
137
138 @Test
139 public void testInitializeWithClassLoaderNoParametersThenSetLoggerContextThenDeinitialize() throws Exception {
137140 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
138141 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
139142 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("false");
140143 given(servletContext.getServletContextName()).willReturn("helloWorld02");
141144 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
142145 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
143 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
144
145 this.initializerImpl.start();
146
147 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
148 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
146 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
147
148 this.initializerImpl.start();
149
150 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
151 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
149152 final org.apache.logging.log4j.spi.LoggerContext loggerContext = loggerContextCaptor.getValue();
150153
151 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
154 assertNull("The context should still be null.", ContextAnchor.THREAD_CONTEXT.get());
152155
153156 this.initializerImpl.setLoggerContext();
154157
155158 final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
156 assertNotNull(context, "The context should not be null.");
157 assertSame(loggerContext, context, "The context is not correct.");
159 assertNotNull("The context should not be null.", context);
160 assertSame("The context is not correct.", loggerContext, context);
158161
159162 this.initializerImpl.clearLoggerContext();
160163
161 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
162
163 this.initializerImpl.stop();
164
165 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
166
167 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
168
169 this.initializerImpl.setLoggerContext();
170
171 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
172 }
173
174 @Test
175 public void testInitializeIsIdempotent() {
164 assertNull("The context should be null again.", ContextAnchor.THREAD_CONTEXT.get());
165
166 this.initializerImpl.stop();
167
168 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
169
170 assertNull("The context should again still be null.", ContextAnchor.THREAD_CONTEXT.get());
171
172 this.initializerImpl.setLoggerContext();
173
174 assertNull("The context should finally still be null.", ContextAnchor.THREAD_CONTEXT.get());
175 }
176
177 @Test
178 public void testInitializeIsIdempotent() throws Exception {
176179 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
177180 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
178181 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("nothing");
179182 given(servletContext.getServletContextName()).willReturn("helloWorld03");
180183 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
181184 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
182 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
183
184 this.initializerImpl.start();
185
186 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
187 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
188
189 this.initializerImpl.start();
190 this.initializerImpl.start();
191 this.initializerImpl.start();
192 this.initializerImpl.stop();
193
194 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
195 }
196
197 @Test
198 public void testInitializeFailsAfterDeinitialize() {
185 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
186
187 this.initializerImpl.start();
188
189 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
190 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
191
192 this.initializerImpl.start();
193 this.initializerImpl.start();
194 this.initializerImpl.start();
195 this.initializerImpl.stop();
196
197 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
198 }
199
200 @Test
201 public void testInitializeFailsAfterDeinitialize() throws Exception {
199202 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
200203 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
201204 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
202205 given(servletContext.getServletContextName()).willReturn("helloWorld04");
203206 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
204207 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
205 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
206
207 this.initializerImpl.start();
208
209 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
210 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
211
212 this.initializerImpl.stop();
213
214 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
215
216 assertThrows(IllegalStateException.class, () -> {
217 this.initializerImpl.start();
218 });
219 }
220
221 @Test
222 public void testDeinitializeIsIdempotent() {
208 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
209
210 this.initializerImpl.start();
211
212 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
213 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
214
215 this.initializerImpl.stop();
216
217 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
218
219 expectedException.expect(IllegalStateException.class);
220 this.initializerImpl.start();
221 }
222
223 @Test
224 public void testDeinitializeIsIdempotent() throws Exception {
223225 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
224226 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
225227 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
226228 given(servletContext.getServletContextName()).willReturn("helloWorld05");
227229 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
228230 given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
229 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
230
231 this.initializerImpl.start();
232
233 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
234 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
235
236 this.initializerImpl.stop();
237 this.initializerImpl.stop();
238 this.initializerImpl.stop();
239 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
240 }
241
242 @Test
243 public void testInitializeUsingJndiSelectorFails() {
231 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
232
233 this.initializerImpl.start();
234
235 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
236 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
237
238 this.initializerImpl.stop();
239 this.initializerImpl.stop();
240 this.initializerImpl.stop();
241 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
242 }
243
244 @Test
245 public void testInitializeUsingJndiSelectorFails() throws Exception {
244246 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
245247 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
246248 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("true");
247249 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
248 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
249
250 assertThrows(IllegalStateException.class, () -> {
251 this.initializerImpl.start();
252 });
253 }
254
255 @Test
256 public void testInitializeUsingJndiSelector() {
250 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
251
252 expectedException.expect(IllegalStateException.class);
253 this.initializerImpl.start();
254 }
255
256 @Test
257 public void testInitializeUsingJndiSelector() throws Exception {
257258 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn("helloWorld06");
258259 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
259260 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("true");
260261 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
261 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
262
263 this.initializerImpl.start();
264
265 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
266 assertNull(loggerContextCaptor.getValue(), "The context attribute should be null.");
267
268 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
269
270 this.initializerImpl.setLoggerContext();
271
272 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null because no named selector.");
262 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
263
264 this.initializerImpl.start();
265
266 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
267 assertNull("The context attribute should be null.", loggerContextCaptor.getValue());
268
269 assertNull("The context should still be null.", ContextAnchor.THREAD_CONTEXT.get());
270
271 this.initializerImpl.setLoggerContext();
272
273 assertNull("The context should still be null because no named selector.", ContextAnchor.THREAD_CONTEXT.get());
273274
274275 this.initializerImpl.clearLoggerContext();
275276
276 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
277
278 this.initializerImpl.stop();
279
280 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
281
282 this.initializerImpl.setLoggerContext();
283
284 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
285 }
286
287 @Test
288 public void testWrapExecutionWithNoParameters() {
277 assertNull("The context should be null again.", ContextAnchor.THREAD_CONTEXT.get());
278
279 this.initializerImpl.stop();
280
281 assertNull("The context should again still be null.", ContextAnchor.THREAD_CONTEXT.get());
282
283 this.initializerImpl.setLoggerContext();
284
285 assertNull("The context should finally still be null.", ContextAnchor.THREAD_CONTEXT.get());
286 }
287
288 @Test
289 public void testWrapExecutionWithNoParameters() throws Exception {
289290 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn(null);
290291 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
291292 given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
292293 given(servletContext.getServletContextName()).willReturn("helloWorld07");
293294 given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
294 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null.");
295
296 this.initializerImpl.start();
297
298 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
299 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
295 assertNull("The context should be null.", ContextAnchor.THREAD_CONTEXT.get());
296
297 this.initializerImpl.start();
298
299 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
300 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
300301 final org.apache.logging.log4j.spi.LoggerContext loggerContext = loggerContextCaptor.getValue();
301302
302 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should still be null.");
303
304 final Runnable runnable = () -> {
305 final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
306 assertNotNull(context, "The context should not be null.");
307 assertSame(loggerContext, context, "The context is not correct.");
303 assertNull("The context should still be null.", ContextAnchor.THREAD_CONTEXT.get());
304
305 final Runnable runnable = new Runnable() {
306 @Override
307 public void run() {
308 final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
309 assertNotNull("The context should not be null.", context);
310 assertSame("The context is not correct.", loggerContext, context);
311 }
308312 };
309313
310314 this.initializerImpl.wrapExecution(runnable);
311315
312 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be null again.");
313
314 this.initializerImpl.stop();
315
316 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
317
318 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should again still be null.");
319
320 this.initializerImpl.setLoggerContext();
321
322 assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should finally still be null.");
316 assertNull("The context should be null again.", ContextAnchor.THREAD_CONTEXT.get());
317
318 this.initializerImpl.stop();
319
320 then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
321
322 assertNull("The context should again still be null.", ContextAnchor.THREAD_CONTEXT.get());
323
324 this.initializerImpl.setLoggerContext();
325
326 assertNull("The context should finally still be null.", ContextAnchor.THREAD_CONTEXT.get());
323327 }
324328
325329 @Test
329333 this.initializerImpl.start();
330334
331335 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
332 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
336 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
333337
334338 assertThat(loggerContextCaptor.getValue().getConfigLocation(), is(nullValue()));
335339
344348 this.initializerImpl.start();
345349
346350 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
347 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
351 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
348352
349353 assertThat(loggerContextCaptor.getValue().getConfigLocation(), is(URI.create("file:/a/b/c/WEB-INF/log4j2.xml")));
350354
362366 this.initializerImpl.start();
363367
364368 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
365 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
369 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
366370
367371 assertThat(loggerContextCaptor.getValue().getConfigLocation(),
368372 is(URI.create("file:/a/b/c/WEB-INF/log4j2-mycontext.xml")));
377381 this.initializerImpl.start();
378382
379383 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
380 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
384 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
381385
382386 assertThat(loggerContextCaptor.getValue().getConfiguration(), is(instanceOf(DefaultConfiguration.class)));
383387
388392 public void testCompositeLocationParameterSetsCompositeConfiguration() {
389393 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONTEXT_NAME))).willReturn("mycontext");
390394 given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(
391 "log4j2-combined.xml,log4j2-override.xml");
392
393 this.initializerImpl.start();
394
395 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
396 assertNotNull(loggerContextCaptor.getValue(), "The context attribute should not be null.");
395 "/a.txt,,/WEB-INF/log4j2-mycontext.xml");
396
397 this.initializerImpl.start();
398
399 then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
400 assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());
397401
398402 assertThat(loggerContextCaptor.getValue().getConfiguration(), is(instanceOf(CompositeConfiguration.class)));
399403
1818 import org.apache.logging.log4j.LogManager;
1919 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
2020 import org.apache.logging.log4j.util.Constants;
21 import org.junit.jupiter.api.Test;
21 import org.junit.Test;
2222
23 import static org.junit.jupiter.api.Assertions.*;
23 import static org.junit.Assert.*;
2424
2525 /**
2626 *
3030 @Test
3131 public void testShutdownHookDisabled() {
3232 assertFalse(
33 ((Log4jContextFactory) LogManager.getFactory()).isShutdownHookEnabled(),
34 "Shutdown hook should be disabled by default in web applications");
33 "Shutdown hook should be disabled by default in web applications",
34 ((Log4jContextFactory) LogManager.getFactory()).isShutdownHookEnabled());
3535 }
3636
3737 @Test
3838 public void testIsWebApp() {
39 assertTrue(Constants.IS_WEB_APP, "When servlet classes are available IS_WEB_APP should default to true");
39 assertTrue("When servlet classes are available IS_WEB_APP should default to true", Constants.IS_WEB_APP);
4040 }
4141 }
2323 import org.apache.logging.log4j.core.LoggerContext;
2424 import org.apache.logging.log4j.core.config.Configuration;
2525 import org.apache.logging.log4j.core.impl.ContextAnchor;
26 import org.junit.jupiter.api.Test;
26 import org.junit.Test;
2727 import org.springframework.mock.web.MockServletContext;
2828
29 import static org.junit.jupiter.api.Assertions.*;
29 import static org.junit.Assert.*;
3030
3131 /**
3232 *
4949 initializer.start();
5050 initializer.setLoggerContext();
5151 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
52 assertNotNull(ctx, "No LoggerContext");
53 assertNotNull(WebLoggerContextUtils.getServletContext(), "No ServletContext");
52 assertNotNull("No LoggerContext", ctx);
53 assertNotNull("No ServletContext", ctx.getExternalContext());
5454 final Configuration configuration = ctx.getConfiguration();
55 assertNotNull(configuration, "No configuration");
55 assertNotNull("No configuration", configuration);
5656 final Appender appender = configuration.getAppender("Servlet");
57 assertNotNull(appender, "No ServletAppender");
57 assertNotNull("No ServletAppender", appender);
5858 final Logger logger = LogManager.getLogger("Test");
5959 logger.info("This is a test");
6060 logger.error("This is a test 2", new IllegalStateException().fillInStackTrace());
3333 @Override
3434 protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
3535 final AsyncContext asyncContext = req.startAsync();
36 asyncContext.start(WebLoggerContextUtils.wrapExecutionContext(this.getServletContext(), () -> {
37 final Logger logger = LogManager.getLogger(TestAsyncServlet.class);
38 logger.info("Hello, servlet!");
36 asyncContext.start(WebLoggerContextUtils.wrapExecutionContext(this.getServletContext(), new Runnable() {
37 @Override
38 public void run() {
39 final Logger logger = LogManager.getLogger(TestAsyncServlet.class);
40 logger.info("Hello, servlet!");
41 }
3942 }));
4043 }
4144
4245 @Override
4346 protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
4447 final AsyncContext asyncContext = req.startAsync();
45 asyncContext.start(() -> {
46 final Log4jWebSupport webSupport =
47 WebLoggerContextUtils.getWebLifeCycle(TestAsyncServlet.this.getServletContext());
48 webSupport.setLoggerContext();
49 // do stuff
50 webSupport.clearLoggerContext();
48 asyncContext.start(new Runnable() {
49 @Override
50 public void run() {
51 final Log4jWebSupport webSupport =
52 WebLoggerContextUtils.getWebLifeCycle(TestAsyncServlet.this.getServletContext());
53 webSupport.setLoggerContext();
54 // do stuff
55 webSupport.clearLoggerContext();
56 }
5157 });
5258 }
5359 }
2525 import org.apache.logging.log4j.core.config.Configuration;
2626 import org.apache.logging.log4j.core.impl.ContextAnchor;
2727 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
28 import org.junit.jupiter.api.Test;
28 import org.junit.Test;
2929 import org.springframework.mock.web.MockServletContext;
3030
31 import static org.junit.jupiter.api.Assertions.*;
31 import static org.junit.Assert.*;
3232
3333 public class WebLookupTest {
3434
3636 public void testLookup() throws Exception {
3737 ContextAnchor.THREAD_CONTEXT.remove();
3838 final ServletContext servletContext = new MockServletContext();
39 ((MockServletContext) servletContext).setContextPath("/WebApp");
4039 servletContext.setAttribute("TestAttr", "AttrValue");
4140 servletContext.setInitParameter("TestParam", "ParamValue");
4241 servletContext.setAttribute("Name1", "Ben");
4645 initializer.start();
4746 initializer.setLoggerContext();
4847 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
49 assertNotNull(ctx, "No LoggerContext");
50 assertNotNull(WebLoggerContextUtils.getServletContext(), "No ServletContext");
48 assertNotNull("No LoggerContext", ctx);
49 assertNotNull("No ServletContext", ctx.getExternalContext());
5150 final Configuration config = ctx.getConfiguration();
52 assertNotNull(config, "No Configuration");
51 assertNotNull("No Configuration", config);
5352 final StrSubstitutor substitutor = config.getStrSubstitutor();
54 assertNotNull(substitutor, "No Interpolator");
53 assertNotNull("No Interpolator", substitutor);
5554 String value = substitutor.replace("${web:initParam.TestParam}");
56 assertNotNull(value, "No value for TestParam");
57 assertEquals("ParamValue", value, "Incorrect value for TestParam: " + value);
55 assertNotNull("No value for TestParam", value);
56 assertEquals("Incorrect value for TestParam: " + value, "ParamValue", value);
5857 value = substitutor.replace("${web:attr.TestAttr}");
59 assertNotNull(value, "No value for TestAttr");
60 assertEquals("AttrValue", value, "Incorrect value for TestAttr: " + value);
58 assertNotNull("No value for TestAttr", value);
59 assertEquals("Incorrect value for TestAttr: " + value, "AttrValue", value);
6160 value = substitutor.replace("${web:Name1}");
62 assertNotNull(value, "No value for Name1");
63 assertEquals("Ben", value, "Incorrect value for Name1: " + value);
61 assertNotNull("No value for Name1", value);
62 assertEquals("Incorrect value for Name1: " + value, "Ben", value);
6463 value = substitutor.replace("${web:Name2}");
65 assertNotNull(value, "No value for Name2");
66 assertEquals("Jerry", value, "Incorrect value for Name2: " + value);
67 value = substitutor.replace("${web:contextPathName}");
68 assertNotNull(value, "No value for context name");
69 assertEquals("WebApp", value, "Incorrect value for context name");
64 assertNotNull("No value for Name2", value);
65 assertEquals("Incorrect value for Name2: " + value, "Jerry", value);
7066 } catch (final IllegalStateException e) {
7167 fail("Failed to initialize Log4j properly." + e.getMessage());
7268 }
7874 public void testLookup2() throws Exception {
7975 ContextAnchor.THREAD_CONTEXT.remove();
8076 final ServletContext servletContext = new MockServletContext();
81 ((MockServletContext) servletContext).setContextPath("/");
8277 servletContext.setAttribute("TestAttr", "AttrValue");
8378 servletContext.setInitParameter("myapp.logdir", "target");
8479 servletContext.setAttribute("Name1", "Ben");
8883 initializer.start();
8984 initializer.setLoggerContext();
9085 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
91 assertNotNull(ctx, "No LoggerContext");
92 assertNotNull(WebLoggerContextUtils.getServletContext(), "No ServletContext");
86 assertNotNull("No LoggerContext", ctx);
87 assertNotNull("No ServletContext", ctx.getExternalContext());
9388 final Configuration config = ctx.getConfiguration();
94 assertNotNull(config, "No Configuration");
89 assertNotNull("No Configuration", config);
9590 final Map<String, Appender> appenders = config.getAppenders();
9691 for (final Map.Entry<String, Appender> entry : appenders.entrySet()) {
9792 if (entry.getKey().equals("file")) {
9994 assertEquals("target/myapp.log", fa.getFileName());
10095 }
10196 }
102 final StrSubstitutor substitutor = config.getStrSubstitutor();
103 String value = substitutor.replace("${web:contextPathName:-default}");
104 assertEquals("default", value, "Incorrect value for context name");
105 assertNotNull(value, "No value for context name");
10697 initializer.stop();
10798 ContextAnchor.THREAD_CONTEXT.remove();
10899 }
+0
-31
log4j-web/src/test/resources/log4j2-combined.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration status="OFF">
19 <Appenders>
20 <Console name="Console" target="SYSTEM_OUT">
21 <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable" />
22 </Console>
23 </Appenders>
24 <Loggers>
25 <Logger name="org.foo" level="DEBUG" />
26 <Root level="TRACE">
27 <AppenderRef ref="Console" />
28 </Root>
29 </Loggers>
30 </Configuration>
+0
-23
log4j-web/src/test/resources/log4j2-override.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 -->
18 <Configuration>
19 <Loggers>
20 <Logger name="org.foo" level="ERROR" />
21 </Loggers>
22 </Configuration>
+164
-286
pom.xml less more
1919 <artifactId>log4j</artifactId>
2020 <packaging>pom</packaging>
2121 <name>Apache Log4j 2</name>
22 <version>2.17.0</version>
22 <version>2.12.3</version>
2323 <parent>
24 <groupId>org.apache.logging</groupId>
25 <artifactId>logging-parent</artifactId>
26 <version>3</version>
27 <relativePath />
24 <groupId>org.apache</groupId>
25 <artifactId>apache</artifactId>
26 <version>21</version>
2827 </parent>
28 <prerequisites>
29 <maven>3.0.5</maven>
30 </prerequisites>
2931 <description>Apache Log4j 2</description>
3032 <url>https://logging.apache.org/log4j/2.x/</url>
3133 <issueManagement>
3436 </issueManagement>
3537 <ciManagement>
3638 <system>Jenkins</system>
37 <url>https://ci-builds.apache.org/job/Logging/job/log4j/</url>
39 <url>https://builds.apache.org/job/Log4j%202.x/</url>
3840 </ciManagement>
3941 <inceptionYear>1999</inceptionYear>
4042 <developers>
126128 </roles>
127129 <timezone>America/New York</timezone>
128130 </developer>
129 <developer>
130 <id>vy</id>
131 <name>Volkan Yazıcı</name>
132 <email>vy@apache.org</email>
133 <roles>
134 <role>PMC Member</role>
135 </roles>
136 <timezone>Europe/Amsterdam</timezone>
137 </developer>
138131 </developers>
139132 <!-- Contributors -->
140133 <contributors>
179172 </mailingList>
180173 </mailingLists>
181174 <scm>
182 <connection>scm:git:https://gitbox.apache.org/repos/asf/logging-log4j2.git</connection>
183 <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/logging-log4j2.git</developerConnection>
184 <url>https://gitbox.apache.org/repos/asf?p=logging-log4j2.git</url>
185 <tag>log4j-2.17.0-rc1</tag>
175 <connection>scm:git:https://git-wip-us.apache.org/repos/asf/logging-log4j2.git</connection>
176 <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/logging-log4j2.git</developerConnection>
177 <url>https://git-wip-us.apache.org/repos/asf?p=logging-log4j2.git;a=summary</url>
178 <tag>log4j-2.12.3-rc1</tag>
186179 </scm>
187180 <properties>
188181 <!-- make sure to update these for each release! -->
189182 <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-->
183 <Log4jReleaseVersion>2.12.3</Log4jReleaseVersion>
195184 <Log4jReleaseManager>Ralph Goers</Log4jReleaseManager>
196185 <Log4jReleaseKey>B3D8E1BA</Log4jReleaseKey>
186 <Log4jSigningUserName>rgoers@apache.org</Log4jSigningUserName>
187 <!--<Log4jReleaseManager>Matt Sicker</Log4jReleaseManager> -->
188 <!--<Log4jReleaseKey>748F15B2CF9BA8F024155E6ED7C92B70FA1C814D</Log4jReleaseKey> -->
197189 <!-- note that any properties you want available in velocity templates must not use periods! -->
198190 <slf4jVersion>1.7.25</slf4jVersion>
199191 <logbackVersion>1.2.3</logbackVersion>
200192 <jackson1Version>1.9.13</jackson1Version>
201 <jackson2Version>2.12.4</jackson2Version>
202 <spring-boot.version>2.5.7</spring-boot.version>
203 <springVersion>5.3.13</springVersion>
204 <kubernetes-client.version>4.6.1</kubernetes-client.version>
205 <flumeVersion>1.9.0</flumeVersion>
206 <disruptorVersion>3.4.4</disruptorVersion>
207 <conversantDisruptorVersion>1.2.15</conversantDisruptorVersion> <!-- Version 1.2.16 requires Java 9 -->
208 <elastic.version>7.6.2</elastic.version>
209 <mongodb3.version>3.12.7</mongodb3.version>
210 <mongodb4.version>4.2.2</mongodb4.version>
211 <!-- POM for jackson-dataformat-xml 2.12.4 depends on woodstox-core 6.2.4 -->
212 <woodstox.version>6.2.6</woodstox.version>
213 <groovy.version>3.0.8</groovy.version>
193 <jackson2Version>2.9.9</jackson2Version>
194 <springVersion>3.2.18.RELEASE</springVersion>
195 <flumeVersion>1.7.0</flumeVersion> <!-- Version 1.8.0 requires Java 8 -->
196 <disruptorVersion>3.4.2</disruptorVersion>
197 <conversantDisruptorVersion>1.2.10</conversantDisruptorVersion> <!-- Version 1.2.11 requires Java 8 -->
198 <mongodb2.version>2.14.3</mongodb2.version>
199 <mongodb3.version>3.10.2</mongodb3.version>
200 <groovy.version>2.5.6</groovy.version>
214201 <compiler.plugin.version>3.8.1</compiler.plugin.version>
215202 <pmd.plugin.version>3.10.0</pmd.plugin.version>
203 <findbugs.plugin.version>3.0.5</findbugs.plugin.version>
216204 <changes.plugin.version>2.12.1</changes.plugin.version>
217 <javadoc.plugin.version>3.3.1</javadoc.plugin.version>
205 <javadoc.plugin.version>3.0.1</javadoc.plugin.version>
218206 <!-- surefire.plugin.version 2.18 yields http://jira.codehaus.org/browse/SUREFIRE-1121, which is fixed in 2.18.1 -->
219207 <!-- surefire.plugin.version 2.19 yields https://issues.apache.org/jira/browse/SUREFIRE-1193. -->
220208 <!-- all versions after 2.13 yield https://issues.apache.org/jira/browse/SUREFIRE-720 -->
221 <surefire.plugin.version>3.0.0-M5</surefire.plugin.version>
222 <failsafe.plugin.version>3.0.0-M5</failsafe.plugin.version>
209 <surefire.plugin.version>2.22.2</surefire.plugin.version>
210 <failsafe.plugin.version>2.22.2</failsafe.plugin.version>
223211 <checkstyle.plugin.version>3.0.0</checkstyle.plugin.version>
224212 <deploy.plugin.version>2.8.2</deploy.plugin.version>
225 <rat.plugin.version>0.13</rat.plugin.version>
213 <rat.plugin.version>0.12</rat.plugin.version>
226214 <pdf.plugin.version>1.2</pdf.plugin.version>
227215 <cobertura.plugin.version>2.7</cobertura.plugin.version>
228 <jacoco.plugin.version>0.8.6</jacoco.plugin.version>
216 <jacoco.plugin.version>0.8.3</jacoco.plugin.version>
229217 <release.plugin.version>2.5.3</release.plugin.version>
230218 <scm.plugin.version>1.9.5</scm.plugin.version>
231219 <jxr.plugin.version>2.5</jxr.plugin.version>
232 <revapi.plugin.version>0.11.1</revapi.plugin.version>
220 <revapi.plugin.version>0.10.5</revapi.plugin.version>
233221 <revapi.skip>false</revapi.skip>
234222 <clirr.plugin.version>2.8</clirr.plugin.version>
235 <site.plugin.version>3.8.2</site.plugin.version>
223 <!-- Maven site 3.7 uses the wrong stylesheet? -->
224 <site.plugin.version>3.4</site.plugin.version>
236225 <!-- Maven site depends on Velocity and the escaping rules are different in newer versions. -->
237226 <!-- See https://maven.apache.org/plugins/maven-site-plugin/migrate.html -->
238227 <velocity.plugin.version>1.5</velocity.plugin.version>
239 <asciidoc.plugin.version>1.5.6</asciidoc.plugin.version>
240228 <remote.resources.plugin.version>1.5</remote.resources.plugin.version>
241229 <manifestfile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestfile>
242 <maven.compiler.source>1.8</maven.compiler.source>
243 <maven.compiler.target>1.8</maven.compiler.target>
244 <maven.doap.skip>false</maven.doap.skip>
245 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
230 <maven.compiler.source>1.7</maven.compiler.source>
231 <maven.compiler.target>1.7</maven.compiler.target>
246232 <docLabel>Site Documentation</docLabel>
247233 <projectDir />
248234 <commonsLoggingVersion>1.2</commonsLoggingVersion>
249 <javax.persistence>2.2.1</javax.persistence>
235 <javax.persistence>2.1.1</javax.persistence>
250236 <!-- The OSGi API version MUST always be the MINIMUM version Log4j supports -->
251237 <osgi.api.version>4.3.1</osgi.api.version>
252 <activemq.version>5.16.3</activemq.version>
238 <!-- Version 5.15.0 requires Java 8 -->
239 <activemq.version>5.14.5</activemq.version>
253240 <!-- Allow Clirr severity to be overriden by the command-line option -DminSeverity=level -->
254241 <minSeverity>info</minSeverity>
255242 <jctoolsVersion>1.2.1</jctoolsVersion>
256 <junitVersion>4.13.2</junitVersion>
257 <junitJupiterVersion>5.7.2</junitJupiterVersion>
258 <mockitoVersion>3.11.2</mockitoVersion>
259 <xmlunitVersion>2.8.3</xmlunitVersion>
243 <mockitoVersion>2.25.1</mockitoVersion>
260244 <argLine>-Xms256m -Xmx1024m</argLine>
261 <javaTargetVersion>1.8</javaTargetVersion>
245 <javaTargetVersion>1.7</javaTargetVersion>
262246 <module.name />
263247 </properties>
264248 <pluginRepositories>
303287 <dependency>
304288 <groupId>org.eclipse.tycho</groupId>
305289 <artifactId>org.eclipse.osgi</artifactId>
306 <version>3.13.0.v20180226-1711</version>
290 <version>3.12.1.v20170821-1548</version>
307291 </dependency>
308292 <dependency>
309293 <groupId>org.apache.felix</groupId>
310294 <artifactId>org.apache.felix.framework</artifactId>
311 <version>5.6.12</version>
295 <version>5.6.10</version>
312296 </dependency>
313297 <dependency>
314298 <groupId>org.apache.maven</groupId>
315299 <artifactId>maven-core</artifactId>
316 <version>3.6.3</version>
300 <version>3.6.0</version>
317301 </dependency>
318302 <dependency>
319303 <groupId>commons-codec</groupId>
320304 <artifactId>commons-codec</artifactId>
321 <version>1.15</version>
305 <version>1.12</version>
322306 </dependency>
323307 <dependency>
324308 <groupId>org.apache.commons</groupId>
325309 <artifactId>commons-lang3</artifactId>
326 <version>3.12.0</version>
327 </dependency>
328 <dependency>
329 <groupId>org.apache.commons</groupId>
330 <artifactId>commons-pool2</artifactId>
331 <version>2.11.1</version>
332 </dependency>
333 <dependency>
334 <groupId>org.apache.commons</groupId>
335 <artifactId>commons-dbcp2</artifactId>
336 <version>2.9.0</version>
310 <version>3.7</version>
337311 </dependency>
338312 <dependency>
339313 <groupId>ch.qos.logback</groupId>
386360 </dependency>
387361 <dependency>
388362 <groupId>org.apache.logging.log4j</groupId>
389 <artifactId>log4j-layout-template-json</artifactId>
390 <version>${project.version}</version>
391 <type>test-jar</type>
392 </dependency>
393 <dependency>
394 <groupId>org.apache.logging.log4j</groupId>
395363 <artifactId>log4j-slf4j-impl</artifactId>
396364 <version>${project.version}</version>
397365 </dependency>
438406 </dependency>
439407 <dependency>
440408 <groupId>org.apache.logging.log4j</groupId>
441 <artifactId>log4j-jpl</artifactId>
442 <version>${project.version}</version>
443 </dependency>
444 <dependency>
445 <groupId>org.apache.logging.log4j</groupId>
446409 <artifactId>log4j-taglib</artifactId>
447410 <version>${project.version}</version>
448411 </dependency>
449412 <dependency>
450413 <groupId>org.apache.logging.log4j</groupId>
451414 <artifactId>log4j-web</artifactId>
452 <version>${project.version}</version>
453 </dependency>
454 <dependency>
455 <groupId>org.apache.logging.log4j</groupId>
456 <artifactId>log4j-jakarta-web</artifactId>
457415 <version>${project.version}</version>
458416 </dependency>
459417 <dependency>
470428 <dependency>
471429 <groupId>org.fusesource.jansi</groupId>
472430 <artifactId>jansi</artifactId>
473 <version>2.3.4</version>
431 <version>1.17.1</version>
474432 <optional>true</optional>
475433 </dependency>
476434 <dependency>
692650 <groupId>com.conversantmedia</groupId>
693651 <artifactId>disruptor</artifactId>
694652 <version>${conversantDisruptorVersion}</version>
653 <!-- TODO: this can be switched based on a profile -->
654 <classifier>jdk7</classifier>
695655 </dependency>
696656 <dependency>
697657 <groupId>org.jctools</groupId>
698658 <artifactId>jctools-core</artifactId>
699659 <version>${jctoolsVersion}</version>
700660 </dependency>
701 <!-- JUnit 5 engine -->
702 <dependency>
703 <groupId>org.junit.jupiter</groupId>
704 <artifactId>junit-jupiter-engine</artifactId>
705 <version>${junitJupiterVersion}</version>
706 <scope>test</scope>
707 </dependency>
708 <!-- JUnit 4 to 5 migration support -->
709 <dependency>
710 <groupId>org.junit.jupiter</groupId>
711 <artifactId>junit-jupiter-migrationsupport</artifactId>
712 <version>${junitJupiterVersion}</version>
713 <scope>test</scope>
714 </dependency>
715 <!-- JUnit 5 parameterized test support -->
716 <dependency>
717 <groupId>org.junit.jupiter</groupId>
718 <artifactId>junit-jupiter-params</artifactId>
719 <version>${junitJupiterVersion}</version>
720 <scope>test</scope>
721 </dependency>
722 <!-- JUnit 4 API dependency -->
723661 <dependency>
724662 <groupId>junit</groupId>
725663 <artifactId>junit</artifactId>
726 <version>${junitVersion}</version>
664 <version>4.12</version>
727665 <scope>test</scope>
728666 </dependency>
729 <!-- JUnit 4 engine -->
730 <dependency>
731 <groupId>org.junit.vintage</groupId>
732 <artifactId>junit-vintage-engine</artifactId>
733 <version>${junitJupiterVersion}</version>
734 <scope>test</scope>
735 </dependency>
736 <dependency>
737 <groupId>org.assertj</groupId>
738 <artifactId>assertj-core</artifactId>
739 <version>3.20.2</version>
740 <scope>test</scope>
741 </dependency>
742667 <dependency>
743668 <groupId>org.hamcrest</groupId>
744 <artifactId>hamcrest</artifactId>
745 <version>2.2</version>
746 <scope>test</scope>
747 </dependency>
748 <dependency>
749 <groupId>org.awaitility</groupId>
750 <artifactId>awaitility</artifactId>
751 <version>4.0.3</version>
669 <artifactId>hamcrest-all</artifactId>
670 <version>1.3</version>
752671 <scope>test</scope>
753672 </dependency>
754673 <dependency>
755674 <groupId>org.codehaus.plexus</groupId>
756675 <artifactId>plexus-utils</artifactId>
757 <version>3.4.0</version>
676 <version>3.1.0</version>
758677 <scope>test</scope>
759678 </dependency>
760679 <dependency>
764683 <scope>test</scope>
765684 </dependency>
766685 <dependency>
767 <groupId>org.mockito</groupId>
768 <artifactId>mockito-junit-jupiter</artifactId>
769 <version>${mockitoVersion}</version>
770 <scope>test</scope>
771 </dependency>
772 <dependency>
773686 <groupId>org.springframework</groupId>
774687 <artifactId>spring-aop</artifactId>
775688 <version>${springVersion}</version>
815728 <version>${springVersion}</version>
816729 </dependency>
817730 <dependency>
818 <groupId>org.springframework</groupId>
819 <artifactId>spring-context-support</artifactId>
820 <version>${springVersion}</version>
821 </dependency>
822 <dependency>
823 <groupId>io.fabric8</groupId>
824 <artifactId>kubernetes-client</artifactId>
825 <version>${kubernetes-client.version}</version>
826 </dependency>
827 <dependency>
828731 <groupId>org.hsqldb</groupId>
829732 <artifactId>hsqldb</artifactId>
830 <version>2.5.2</version>
733 <version>2.3.5</version>
734 <!-- version 2.4.0 requires Java 8 -->
831735 </dependency>
832736 <dependency>
833737 <groupId>com.h2database</groupId>
834738 <artifactId>h2</artifactId>
835 <version>1.4.200</version>
739 <version>1.4.199</version>
836740 </dependency>
837741 <dependency>
838742 <groupId>org.eclipse.persistence</groupId>
839743 <artifactId>org.eclipse.persistence.jpa</artifactId>
840 <version>2.7.9</version>
744 <version>2.6.5</version>
841745 </dependency>
842746 <dependency>
843747 <groupId>org.eclipse.persistence</groupId>
846750 <scope>provided</scope>
847751 </dependency>
848752 <dependency>
753 <groupId>org.mongodb</groupId>
754 <artifactId>mongo-java-driver</artifactId>
755 <version>${mongodb2.version}</version>
756 </dependency>
757 <dependency>
758 <groupId>org.mongodb</groupId>
759 <artifactId>mongodb-driver</artifactId>
760 <version>${mongodb3.version}</version>
761 </dependency>
762 <dependency>
763 <groupId>org.mongodb</groupId>
764 <artifactId>bson</artifactId>
765 <version>${mongodb3.version}</version>
766 </dependency>
767 <dependency>
849768 <groupId>org.lightcouch</groupId>
850769 <artifactId>lightcouch</artifactId>
851770 <version>0.0.6</version>
858777 <dependency>
859778 <groupId>org.liquibase</groupId>
860779 <artifactId>liquibase-core</artifactId>
861 <!-- 3.6.0 to 4.3.2 break binary compatibility. -->
862 <version>3.5.5</version>
780 <version>3.5.3</version>
863781 </dependency>
864782 <dependency>
865783 <groupId>net.javacrumbs.json-unit</groupId>
866784 <artifactId>json-unit</artifactId>
867 <version>2.27.0</version>
785 <version>1.31.1</version>
868786 <scope>test</scope>
869787 </dependency>
870788 <dependency>
871789 <groupId>org.xmlunit</groupId>
872790 <artifactId>xmlunit-core</artifactId>
873 <version>${xmlunitVersion}</version>
791 <version>2.5.1</version>
874792 <scope>test</scope>
875793 </dependency>
876794 <dependency>
877795 <groupId>org.xmlunit</groupId>
878796 <artifactId>xmlunit-matchers</artifactId>
879 <version>${xmlunitVersion}</version>
797 <version>2.5.1</version>
880798 <scope>test</scope>
881799 </dependency>
882800 <dependency>
883801 <groupId>commons-io</groupId>
884802 <artifactId>commons-io</artifactId>
885 <version>2.11.0</version>
803 <version>2.6</version>
886804 <scope>test</scope>
887 </dependency>
888 <!-- Used for testing JsonTemplateLayout -->
889 <dependency>
890 <groupId>co.elastic.logging</groupId>
891 <artifactId>log4j2-ecs-layout</artifactId>
892 <version>1.0.1</version>
893 </dependency>
894 <dependency>
895 <groupId>org.elasticsearch.client</groupId>
896 <artifactId>elasticsearch-rest-high-level-client</artifactId>
897 <version>${elastic.version}</version>
898805 </dependency>
899806 <!-- Used for testing HttpAppender -->
900807 <dependency>
901808 <groupId>com.github.tomakehurst</groupId>
902809 <artifactId>wiremock</artifactId>
903810 <scope>test</scope>
904 <!-- 2.27.2 causes WatchHttpTest to fail. -->
905 <version>2.26.3</version>
811 <version>2.19.0</version>
906812 </dependency>
907813 <!-- Used for compressing to formats other than zip and gz -->
908814 <dependency>
909815 <groupId>org.apache.commons</groupId>
910816 <artifactId>commons-compress</artifactId>
911 <version>1.21</version>
817 <version>1.18</version>
912818 </dependency>
913819 <dependency>
914820 <groupId>org.tukaani</groupId>
915821 <artifactId>xz</artifactId>
916 <version>1.9</version>
822 <version>1.8</version>
917823 <scope>test</scope>
918824 </dependency>
919825 <!-- Used for the CSV layout -->
920826 <dependency>
921827 <groupId>org.apache.commons</groupId>
922828 <artifactId>commons-csv</artifactId>
923 <version>1.9.0</version>
829 <version>1.6</version>
924830 </dependency>
925831 <!-- GC-free -->
926832 <dependency>
952858 <!-- Testing MongoDB -->
953859 <groupId>de.flapdoodle.embed</groupId>
954860 <artifactId>de.flapdoodle.embed.mongo</artifactId>
955 <version>3.0.0</version>
956 <scope>test</scope>
957 </dependency>
958 <!-- Testing LDAP -->
959 <dependency>
960 <groupId>org.zapodot</groupId>
961 <artifactId>embedded-ldap-junit</artifactId>
962 <version>0.8.1</version>
861 <version>2.2.0</version>
963862 <scope>test</scope>
964863 </dependency>
965864 </dependencies>
1026925 <configuration>
1027926 <source>${maven.compiler.source}</source>
1028927 <target>${maven.compiler.target}</target>
1029 <parameters>true</parameters>
1030928 <showDeprecation>true</showDeprecation>
1031929 <showWarnings>true</showWarnings>
1032930 <encoding>UTF-8</encoding>
1048946 <groupId>org.apache.maven.plugins</groupId>
1049947 <artifactId>maven-failsafe-plugin</artifactId>
1050948 <version>${failsafe.plugin.version}</version>
1051 </plugin>
1052 <plugin>
1053 <groupId>com.github.spotbugs</groupId>
1054 <artifactId>spotbugs-maven-plugin</artifactId>
1055 <version>4.0.4</version>
1056 <configuration>
1057 <plugins>
1058 <plugin>
1059 <groupId>com.h3xstream.findsecbugs</groupId>
1060 <artifactId>findsecbugs-plugin</artifactId>
1061 <version>1.10.1</version>
1062 </plugin>
1063 </plugins>
1064 <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
1065 <fork>true</fork>
1066 <effort>Default</effort>
1067 <threshold>Normal</threshold>
1068 </configuration>
1069949 </plugin>
1070950 <plugin>
1071951 <groupId>org.apache.maven.plugins</groupId>
11461026 </configuration>
11471027 </execution>
11481028 </executions>
1149 </plugin>
1150 <plugin>
1151 <groupId>io.fabric8</groupId>
1152 <artifactId>docker-maven-plugin</artifactId>
1153 <version>0.33.0</version>
1029
11541030 </plugin>
11551031 </plugins>
11561032 </pluginManagement>
11981074 </systemPropertyVariables>
11991075 <forkCount>1</forkCount>
12001076 <reuseForks>false</reuseForks>
1077 <excludes>
1078 <exclude>${log4j.skip.test1}</exclude>
1079 <exclude>${log4j.skip.test2}</exclude>
1080 </excludes>
12011081 </configuration>
12021082 </plugin>
12031083 <plugin>
12231103 </configuration>
12241104 </plugin>
12251105 <plugin>
1226 <groupId>org.codehaus.mojo</groupId>
1227 <artifactId>build-helper-maven-plugin</artifactId>
1228 <version>1.12</version>
1229 <executions>
1230 <execution>
1231 <id>timestamp-property</id>
1232 <goals>
1233 <goal>timestamp-property</goal>
1234 </goals>
1235 <phase>pre-site</phase>
1236 <configuration>
1237 <name>currentYear</name>
1238 <pattern>yyyy</pattern>
1239 </configuration>
1240 </execution>
1241 </executions>
1242 </plugin>
1243 <plugin>
12441106 <groupId>org.apache.maven.plugins</groupId>
12451107 <artifactId>maven-site-plugin</artifactId>
12461108 <version>${site.plugin.version}</version>
12471109 <dependencies>
12481110 <dependency>
1249 <groupId>org.asciidoctor</groupId>
1250 <artifactId>asciidoctor-maven-plugin</artifactId>
1251 <version>${asciidoc.plugin.version}</version>
1111 <groupId>org.apache.velocity</groupId>
1112 <artifactId>velocity</artifactId>
1113 <version>${velocity.plugin.version}</version>
12521114 </dependency>
12531115 <dependency>
1254 <groupId>org.asciidoctor</groupId>
1255 <artifactId>asciidoctor-maven-plugin</artifactId>
1256 <version>${asciidoc.plugin.version}</version>
1116 <groupId>org.apache.maven.wagon</groupId>
1117 <artifactId>wagon-ssh</artifactId>
1118 <version>3.1.0</version>
12571119 </dependency>
12581120 </dependencies>
12591121 <configuration>
12651127 <moduleExcludes>
12661128 <xdoc>navigation.xml,changes.xml</xdoc>
12671129 </moduleExcludes>
1268 <asciidoc>
1269 <attributes>
1270 <!-- copy any site properties wanted in asciidoc files -->
1271 <Log4jReleaseVersion>${Log4jReleaseVersion}</Log4jReleaseVersion>
1272 <Log4jReleaseManager>${Log4jReleaseManager}</Log4jReleaseManager>
1273 <Log4jReleaseKey>${Log4jReleaseKey}</Log4jReleaseKey>
1274 </attributes>
1275 </asciidoc>
1130 <templateDirectory>${log4jParentDir}/src/site</templateDirectory>
1131 <template>site.vm</template>
12761132 </configuration>
12771133 </plugin>
12781134 <!-- <plugin>
13521208 <exclude>felix-cache/**</exclude>
13531209 <exclude>**/README.md</exclude>
13541210 <exclude>RELEASE-NOTES.md</exclude>
1355 <exclude>SECURITY.md</exclude>
1356 <exclude>.java-version</exclude>
13571211 <exclude>**/*.yml</exclude>
1358 <exclude>**/*.yaml</exclude>
13591212 <exclude>**/*.json</exclude>
13601213 <excllude>**/images/*.drawio</excllude>
13611214 <exclude>**/fluent-bit.conf</exclude>
13691222 <groupId>org.apache.maven.plugins</groupId>
13701223 <artifactId>maven-doap-plugin</artifactId>
13711224 <version>1.2</version>
1372 <dependencies>
1373 <!-- Fix java.lang.IllegalArgumentException: Invalid version number: Version number may be negative or greater than 255 -->
1374 <dependency>
1375 <groupId>com.ibm.icu</groupId>
1376 <artifactId>icu4j</artifactId>
1377 <version>4.6.1</version>
1378 </dependency>
1379 </dependencies>
13801225 <configuration>
13811226 <doapOptions>
13821227 <programmingLanguage>Java</programmingLanguage>
13891234 </charter>
13901235 <pmc>https://logging.apache.org</pmc>
13911236 </asfExtOptions>
1392 <skip>${maven.doap.skip}</skip>
1237 <skip>true</skip>
13931238 </configuration>
13941239 <executions>
13951240 <execution>
14951340 <!-- Other -->
14961341 <exclude>felix-cache/**</exclude>
14971342 <exclude>**/README.md</exclude>
1498 <exclude>SECURITY.md</exclude>
14991343 <exclude>RELEASE-NOTES.md</exclude>
15001344 <exclude>**/*.yml</exclude>
1501 <exclude>**/*.yaml</exclude>
15021345 <exclude>**/*.json</exclude>
15031346 <excllude>**/images/*.drawio</excllude>
15041347 <exclude>**/fluent-bit.conf</exclude>
15051348 <exclude>**/rabbitmq.config</exclude>
15061349 <exclude>**/MANIFEST.MF</exclude>
1507 <exclude>.java-version</exclude>
15081350 </excludes>
15091351 </configuration>
15101352 </plugin>
15231365 <module>log4j-api</module>
15241366 <module>log4j-core-java9</module>
15251367 <module>log4j-core</module>
1526 <module>log4j-layout-template-json</module>
15271368 <module>log4j-core-its</module>
15281369 <module>log4j-1.2-api</module>
15291370 <module>log4j-slf4j-impl</module>
15381379 <module>log4j-jdbc-dbcp2</module>
15391380 <module>log4j-jpa</module>
15401381 <module>log4j-couchdb</module>
1382 <module>log4j-mongodb2</module>
15411383 <module>log4j-mongodb3</module>
1542 <module>log4j-mongodb4</module>
15431384 <module>log4j-cassandra</module>
15441385 <module>log4j-web</module>
1545 <module>log4j-jakarta-web</module>
15461386 <module>log4j-perf</module>
15471387 <module>log4j-iostreams</module>
15481388 <module>log4j-jul</module>
1549 <module>log4j-jpl</module>
15501389 <module>log4j-liquibase</module>
15511390 <module>log4j-appserver</module>
15521391 <module>log4j-osgi</module>
15531392 <module>log4j-docker</module>
1554 <module>log4j-kubernetes</module>
1555 <module>log4j-spring-boot</module>
15561393 <module>log4j-spring-cloud-config</module>
15571394 </modules>
15581395 <profiles>
16711508 <exclude>felix-cache/**</exclude>
16721509 <exclude>**/README.md</exclude>
16731510 <exclude>RELEASE-NOTES.md</exclude>
1674 <exclude>SECURITY.md</exclude>
16751511 <exclude>**/*.yml</exclude>
1676 <exclude>**/*.yaml</exclude>
16771512 <exclude>**/*.json</exclude>
16781513 <excllude>**/images/*.drawio</excllude>
16791514 <exclude>**/fluent-bit.conf</exclude>
16801515 <exclude>**/rabbitmq.config</exclude>
16811516 <exclude>**/MANIFEST.MF</exclude>
1682 <exclude>.java-version</exclude>
16831517 </excludes>
16841518 </configuration>
16851519 <executions>
17931627 }
17941628 }
17951629 }
1796 },
1797 {
1798 "extension": "revapi.ignore",
1799 "configuration": [
1800 {
1801 "code": "java.method.returnTypeTypeParametersChanged",
1802 "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender::newBuilder()",
1803 "new": "method <B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>> B org.apache.logging.log4j.core.appender.OutputStreamAppender::newBuilder()",
1804 "justification": "The compiler erases types (https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.6)"
1805 },
1806 {
1807 "code": "java.generics.elementNowParameterized",
1808 "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender::newBuilder()",
1809 "new": "method <B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>> B org.apache.logging.log4j.core.appender.OutputStreamAppender::newBuilder()",
1810 "justification": "The compiler erases types (https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.6)"
1811 },
1812 {
1813 "code": "java.generics.formalTypeParameterAdded",
1814 "old": "method org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder org.apache.logging.log4j.core.appender.OutputStreamAppender::newBuilder()",
1815 "new": "method <B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>> B org.apache.logging.log4j.core.appender.OutputStreamAppender::newBuilder()",
1816 "typeParameter": "B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B extends org.apache.logging.log4j.core.appender.OutputStreamAppender.Builder<B>>",
1817 "justification": "The compiler erases types (https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.6)"
1818 }
1819 ]
18201630 }
18211631 ]
18221632 ]]></analysisConfiguration>
18501660 </reporting>
18511661 </profile>
18521662 <profile>
1663 <id>jdk7</id>
1664 <activation>
1665 <jdk>1.7</jdk>
1666 </activation>
1667 <build>
1668 <plugins>
1669 <plugin>
1670 <groupId>org.codehaus.mojo</groupId>
1671 <artifactId>clirr-maven-plugin</artifactId>
1672 <version>${clirr.plugin.version}</version>
1673 <dependencies>
1674 <dependency>
1675 <groupId>org.apache.bcel</groupId>
1676 <artifactId>bcel</artifactId>
1677 <version>6.2</version>
1678 </dependency>
1679 </dependencies>
1680 <configuration>
1681 <minSeverity>${minSeverity}</minSeverity>
1682 </configuration>
1683 </plugin>
1684 <plugin>
1685 <artifactId>maven-surefire-plugin</artifactId>
1686 <configuration>
1687 <argLine>-XX:MaxPermSize=512m</argLine>
1688 </configuration>
1689 </plugin>
1690 <plugin>
1691 <artifactId>maven-failsafe-plugin</artifactId>
1692 <configuration>
1693 <argLine>-XX:MaxPermSize=512m</argLine>
1694 </configuration>
1695 </plugin>
1696 </plugins>
1697 </build>
1698 </profile>
1699 <profile>
1700 <id>useJava7</id>
1701 <activation>
1702 <property>
1703 <name>useJava7</name>
1704 </property>
1705 </activation>
1706 <build>
1707 <plugins>
1708 <plugin>
1709 <groupId>org.apache.maven.plugins</groupId>
1710 <artifactId>maven-toolchains-plugin</artifactId>
1711 <version>1.1</version>
1712 <executions>
1713 <execution>
1714 <goals>
1715 <goal>toolchain</goal>
1716 </goals>
1717 </execution>
1718 </executions>
1719 <configuration>
1720 <toolchains>
1721 <jdk>
1722 <version>1.7</version>
1723 </jdk>
1724 </toolchains>
1725 </configuration>
1726 </plugin>
1727 </plugins>
1728 </build>
1729 </profile>
1730 <profile>
18531731 <id>java8-doclint-disabled</id>
18541732 <activation>
18551733 <jdk>[1.8,)</jdk>
1919 #set($relVersion=$announceParameters.releaseVersion)
2020 #set($relCount=$announceParameters.releaseCount)
2121 #macro(formatAction $item)
22 ## Use replaceAll to fix up LF-only line ends on Windows.
23 ## Also replace < and > with entity versions to avoid HTML being misinterpreted.
24 #set($action=$item.action.replaceAll("\n","
22 ## Use replaceAll to fix up LF-only line ends on Windows.
23 ## Also replace < and > with entity versions to avoid HTML being misinterpreted.
24 #set($action=$item.action.replaceAll("\n","
2525 ").replaceAll("<", "&lt;").replaceAll(">", "&gt;"))
26 #if($item.issue)
27 #set($issue = $item.issue)
28 #set($url = "https://issues.apache.org/jira/browse/$issue")
29 #else
30 #set($issue = "")
31 #end
26 #if($item.issue)
27 #set($issue = $item.issue)
28 #set($url = "https://issues.apache.org/jira/browse/$issue")
29 #else
30 #set($issue = "")
31 #end
3232 * #if($issue)[$issue]($url):#end
3333
34 ${action}#if($item.dueTo) Thanks to ${item.dueTo}.#end
34 ${action}#if($item.dueTo) Thanks to ${item.dueTo}.#end
3535
3636 #end
3737 ## -----------------------------------------
6464
6565 The artifacts may be downloaded from https://logging.apache.org/log4j/2.x/download.html.
6666
67 This release contains the changes noted below:
68
69 * Address CVE-2021-45105.
70 * Require components that use JNDI to be enabled individually via system properties.
71 * Remove LDAP and LDAPS as supported protocols from JNDI.
67 This release contains bugfixes and minor enhancements.
7268
7369 Due to a break in compatibility in the SLF4J binding, Log4j now ships with two versions of the SLF4J to Log4j adapters.
7470 log4j-slf4j-impl should be used with SLF4J 1.7.x and earlier and log4j-slf4j18-impl should be used with SLF4J 1.8.x and
75 later. SLF4J-2.0.0 alpha releases are not fully supported. See https://issues.apache.org/jira/browse/LOG4J2-2975 and
76 https://jira.qos.ch/browse/SLF4J-511.
71 later.
7772
78 Some of the changes in Log4j ${relVersion} include:
79
80 * Disable recursive evaluation of Lookups during log event processing. Recursive evaluation is still allwoed while
81 generating the configuration.
82 * The JndiLookup, JndiContextSelector, and JMSAppender now require individual system properties to be enabled.
83 * Removed support for the LDAP and LDAPS protocols via JNDI.
73 This release addresses CVE-2021-44228 for users still using Java 7 by disabling JNDI by default, only allowing the java
74 protocol when JNDI is enabled, making the JNDI Lookup inoperable, and removing the message lookup capability.
8475
8576 The Log4j ${relVersion} API, as well as many core components, maintains binary compatibility with previous releases.
8677
124115 #end
125116 ---
126117
127 Apache Log4j ${relVersion} requires a minimum of Java 8 to build and run. Log4j 2.12.1 is the last release to support
128 Java 7. Java 7 is not longer supported by the Log4j team.
118 Apache Log4j ${relVersion} requires a minimum of Java 7 to build and run. Log4j 2.3 was the
119 last release that supported Java 6.
120
121 Basic compatibility with Log4j 1.x is provided through the log4j-1.2-api component, however it
122 does not implement some of the very implementation specific classes and methods. The package
123 names and Maven groupId have been changed to org.apache.logging.log4j to avoid any conflicts
124 with log4j 1.x.
129125
130126 For complete information on ${project.name}, including instructions on how to submit bug
131127 reports, patches, or suggestions for improvement, see the Apache ${project.name} website:
132128
133 ${project.url}
134
129 ${project.url}
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.12.3" date="2021-12-dd" description="GA Release 2.12.3">
3232 <action issue="LOG4J2-3230" dev="ckozak" type="fix">
3333 Fix string substitution recursion.
3434 </action>
35 <action issue="LOG4J2-3242" dev="rgoers" type="fix">
36 Limit JNDI to the java protocol only. JNDI will remain disabled by default. Rename JNDI enablement property from
37 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
38 </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>
43 <action issue="LOG4J2-3241" dev="rgoers" type="fix">
44 Do not declare log4j-api-java9 and log4j-core-java9 as dependencies as it causes problems with the
45 Maven enforcer plugin.
46 </action>
47 <action issue="LOG4J2-3247" dev="ggregory" type="fix">
48 PropertiesConfiguration.parseAppenderFilters NPE when parsing properties file filters.
49 </action>
50 <action issue="LOG4J2-3249" dev="ggregory" type="fix">
51 Log4j 1.2 bridge for Syslog Appender defaults to port 512 instead of 514.
52 </action>
53 <action issue="LOG4J2-3237" dev="ggregory" type="fix">
54 Log4j 1.2 bridge API hard codes the Syslog protocol to TCP.
55 </action>
56 </release>
57 <release version="2.16.0" date="2021-12-13" description="GA Release 2.16.0">
58 <action issue="LOG4J2-3208" dev="rgoers" type="fix">
59 Disable JNDI by default. Require log4j2.enableJndi to be set to true to allow JNDI.
60 </action>
61 <action issue="LOG4J2-3211" dev="rgoers" type="fix">
62 Completely remove support for Message Lookups.
63 </action>
64 </release>
65 <release version="2.15.0" date="2021-12-06" description="GA Release 2.15.0">
66 <!-- ADDS -->
67 <action issue="LOG4J2-3198" dev="ckozak" type="add">
68 Pattern layout no longer enables lookups within message text by default for cleaner API boundaries and reduced
69 formatting overhead. The old 'log4j2.formatMsgNoLookups' which enabled this behavior has been removed as well
70 as the 'nolookups' message pattern converter option. The old behavior can be enabled on a per-pattern basis
71 using '%m{lookups}'.
72 </action>
73 <action issue="LOG4J2-3194" dev="rgoers" type="add" due-to="markuss">
74 Allow fractional attributes for size attribute of SizeBsaedTriggeringPolicy.
75 </action>
76 <action issue="LOG4J2-2978" dev="rgoers" type="add" due-to="Michael Seele">
77 Add support for Jakarta EE 9 (Tomcat 10 / Jetty 11)
78 </action>
79 <action issue="LOG4J2-3189" dev="ckozak" type="add">
80 Improve NameAbbreviator worst-case performance.
81 </action>
82 <action issue="LOG4J2-3170" dev="vy" type="add" due-to="Gareth Smith">
83 Make CRLF/HTML encoding run in O(n) worst-case time, rather than O(n^2).
84 </action>
85 <action issue="LOG4J2-3133" dev="ckozak" type="add">
86 Add missing slf4j-api singleton accessors to log4j-slf4j-impl (1.7) StaticMarkerBinder and StaticMDCBinder.
87 This doesn't impact behavior or correctness, but avoids throwing and catching NoSuchMethodErrors when slf4j
88 is initialized and avoids linkage linting warnings.
89 </action>
90 <action issue="LOG4J2-2885" dev="vy" type="add" due-to="Markus Spann">
91 Add support for US-style date patterns and micro/nano seconds to FixedDateTime.
92 </action>
93 <action issue="LOG4J2-3116" dev="rgupta" type="add">
94 Add JsonTemplateLayout for Google Cloud Platform structured logging layout.
95 </action>
96 <action issue="LOG4J2-3067" dev="vy" type="add">
97 Add CounterResolver to JsonTemplateLayout.
98 </action>
99 <action issue="LOG4J2-3074" dev="vy" type="add">
100 Add replacement parameter to ReadOnlyStringMapResolver.
101 </action>
102 <action issue="LOG4J2-3051" dev="vy" type="add">
103 Add CaseConverterResolver to JsonTemplateLayout.
104 </action>
105 <action issue="LOG4J2-3064" dev="rgoers" type="add">
106 Add Arbiters and SpringProfile plugin.
107 </action>
108 <action issue="LOG4J2-3056" dev="vy" type="add" due-to="Marcono1234">
109 Refactor MD5 usage for sharing sensitive information.
110 </action>
111 <action issue="LOG4J2-3004" dev="vy" type="add">
112 Add plugin support to JsonTemplateLayout.
113 </action>
114 <action issue="LOG4J2-3050" dev="rgoers" type="add">
115 Allow AdditionalFields to be ignored if their value is null or a zero-length String.
116 </action>
117 <action issue="LOG4J2-3049" dev="rgoers" type="add">
118 Allow MapMessage and ThreadContext attributes to be prefixed.
119 </action>
120 <action issue="LOG4J2=3048" dev="rgoers" type="add">
121 Add improved MapMessge support to GelfLayout.
122 </action>
123 <action issue="LOG4J2-3044" dev="rgoers" type="add">
124 Add RepeatPatternConverter.
125 </action>
126 <action issue="LOG4J2-2940" dev="ckozak" type="add">
127 Context selectors are aware of their dependence upon the callers ClassLoader, allowing
128 basic context selectors to avoid the unnecessary overhead of walking the stack to
129 determine the caller's ClassLoader.
130 </action>
131 <action issue="LOG4J2-2940" dev="ckozak" type="add">
132 Add BasicAsyncLoggerContextSelector equivalent to AsyncLoggerContextSelector for
133 applications with a single LoggerContext. This selector avoids classloader lookup
134 overhead incurred by the existing AsyncLoggerContextSelector.
135 </action>
136 <action issue="LOG4J2-3041" dev="rgoers" type="add">
137 Allow a PatternSelector to be specified on GelfLayout.
138 </action>
139 <action issue="LOG4J2-3141" dev="ckozak" type="add">
140 Avoid ThreadLocal overhead in RandomAccessFileAppender, RollingRandomAccessFileManager,
141 and MemoryMappedFileManager due to the unused setEndOfBatch and isEndOfBatch methods.
142 The methods on LogEvent are preferred.
143 </action>
144 <action issue="LOG4J2-3144" dev="ckozak" type="add">
145 Prefer string.getBytes(Charset) over string.getBytes(String)
146 based on performance improvements in modern Java releases.
147 </action>
148 <action issue="LOG4J2-3171" dev="ckozak" type="add">
149 Improve PatternLayout performance by reducing unnecessary indirection and branching.
150 </action>
151 <!-- FIXES -->
152 <action issue="LOG4J2-3166" dev="rgoers">
153 Fix Log Event Level vs Logger Config Level table.
154 </action>
155 <action issue="LOG4J2-2540" dev="rgoers">
156 Minor documentation correctsion regarding log levels.
157 </action>
158 <action issue="LOG4J2-2541" dev="rgoers" due-to="Gerold Broser">
159 Minor documentation corrections in the configuration section.
160 </action>
161 <action issue="LOG4J2-2553" dev="rgoers">
162 Correct documentation for SyslogAppender when using TLS.
163 </action>
164 <action issue="LOG4J2-1798" dev="rgoers" due-to="Viacheslav Zhivaev">
165 Handle interrupted exceptions that occur during rollover.
166 </action>
167 <action issue="LOG4J2-2951" dev="rgoers">
168 Log4j 1.x properties were not being substituted.
169 </action>
170 <action issue="LOG4J2-3201" dev="rgoers" type="fix">
171 Limit the protocols JNDI can use by default. Limit the servers and classes that can be accessed via LDAP.
172 </action>
173 <action issue="LOG4J2-3114" dev="rgoers" type="fix" due-to="Barnabas Bodnar">
174 Enable immediate flush on RollingFileAppender when buffered i/o is not enabled.
175 </action>
176 <action issue="LOG4J2-3168" dev="rgoers" type="fix" due-to="Benjamin Wöster">
177 Fix bug when file names contain regex characters.
178 </action>
179 <action issue="LOG4J2-3110" dev="rgoers" type="fix" due-to="Arturo Bernal">
180 Fix the number of {}-placeholders in the string literal argument does not match the number of other arguments
181 to the logging call.
182 </action>
183 <action issue="LOG4J2-3060" dev="vy" type="fix" due-to=" Nikita Mikhailov">
184 Fix thread-safety issues in DefaultErrorHandler.
185 </action>
186 <action issue="LOG4J2-3185" dev="vy" type="fix" due-to="mzbonnt">
187 Fix thread-safety issues in DefaultErrorHandler.
188 </action>
189 <action issue="LOG4J2-3183" dev="vy" type="fix">
190 Avoid using MutableInstant of the event as a cache key in JsonTemplateLayout.
191 </action>
192 <action issue="LOG4J2-2829" dev="vy" type="fix">
193 SocketAppender should propagate failures when reconnection fails.
194 </action>
195 <action issue="LOG4J2-3172" dev="vy" type="fix" due-to="Barry Fleming">
196 Buffer immutable log events in the SmtpManager.
197 </action>
198 <action issue="LOG4J2-3175" dev="vy" type="fix" due-to="wuqian0808">
199 Avoid KafkaManager override when topics differ.
200 </action>
201 <action issue="LOG4J2-3160" dev="vy" type="fix" due-to="Lars Bohl">
202 Fix documentation on how to toggle log4j2.debug system property.
203 </action>
204 <action issue="LOG4J2-3159" dev="ckozak" type="fix">
205 Fixed an unlikely race condition in Log4jMarker.getParents() volatile access.
206 </action>
207 <action issue="LOG4J2-3153" dev="ckozak" type="fix">
208 DatePatternConverter performance is not impacted by microsecond-precision clocks when such precision isn't
209 required.
210 </action>
211 <action issue="LOG4J2-2808" dev="ckozak" type="fix" due-to="Asapha Halifa">
212 LoggerContext skips resolving localhost when hostName is configured.
213 </action>
214 <action issue="LOG4J2-3150" dev="ckozak" type="fix">
215 RandomAccessFile appender uses the correct default buffer size of 256 kB
216 rather than the default appender buffer size of 8 kB.
217 </action>
218 <action issue="LOG4J2-3142" dev="ckozak" type="fix" due-to="John Meikle">
219 log4j-1.2-api implements LogEventAdapter.getTimestamp() based on the original event timestamp
220 instead of returning zero.
221 </action>
222 <action issue="LOG4J2-3083" dev="ckozak" type="fix">
223 log4j-slf4j-impl and log4j-slf4j18-impl correctly detect the calling class using both LoggerFactory.getLogger
224 methods as well as LoggerFactory.getILoggerFactory().getLogger.
225 </action>
226 <action issue="LOG4J2-2816" dev="vy" type="fix" due-to="Jacob Shields">
227 Handle Disruptor event translation exceptions.
228 </action>
229 <action issue="LOG4J2-3121" dev="ggregory" type="fix" due-to="Markus Spann">
230 log4j2 config modified at run-time may trigger incomplete MBean re-initialization due to InstanceAlreadyExistsException.
231 </action>
232 <action issue="LOG4J2-3107" dev="vy" type="fix" due-to="Markus Spann">
233 SmtpManager.createManagerName ignores port.
234 </action>
235 <action issue="LOG4J2-3080" dev="vy" type="fix">
236 Use SimpleMessage in Log4j 1 Category whenever possible.
237 </action>
238 <action issue="LOG4J2-3102" dev="ckozak" type="fix">
239 Fix a regression in 2.14.1 which allowed the AsyncAppender background thread to keep the JVM alive because
240 the daemon flag was not set.
241 </action>
242 <action issue="LOG4J2-3103" dev="ckozak" type="fix" due-to="Mike Glazer">
243 Fix race condition which can result in ConcurrentModificationException on context.stop.
244 </action>
245 <action issue="LOG4J2-3092" dev="vy" type="fix" due-to="xmh51">
246 Fix JsonWriter memory leaks due to retained excessive buffer growth.
247 </action>
248 <action issue="LOG4J2-3089" dev="vy" type="fix" due-to="Tim Perry">
249 Fix sporadic JsonTemplateLayoutNullEventDelimiterTest failures on Windows.
250 </action>
251 <action issue="LOG4J2-3075" dev="vy" type="fix">
252 Fix formatting of nanoseconds in JsonTemplateLayout.
253 </action>
254 <action issue="LOG4J2-3087" dev="vy" type="fix" due-to="Anton Klarén">
255 Fix race in JsonTemplateLayout where a timestamp could end up unquoted.
256 </action>
257 <action issue="LOG4J2-3070" dev="vy" type="fix" due-to="Romain Manni-Bucau">
258 Ensure EncodingPatternConverter#handlesThrowable is implemented.
259 </action>
260 <action issue="LOG4J2-3054" dev="ckozak" type="fix">
261 BasicContextSelector hasContext and shutdown take the default context into account
262 </action>
263 <action issue="LOG4J2-2940" dev="ckozak" type="fix">
264 Slf4j implementations walk the stack at most once rather than twice to determine the caller's class loader.
265 </action>
266 <action issue="LOG4J2-2965" dev="ckozak" type="fix">
267 Fixed a deadlock between the AsyncLoggerContextSelector and java.util.logging.LogManager by updating Disruptor to 3.4.4.
268 </action>
269 <action issue="LOG4J2-3095" dev="ggregory" type="fix" due-to="Kenny MacLeod, Gary Gregory">
270 Category.setLevel should accept null value.
271 </action>
272 <action issue="LOG4J2-3174" dev="vy" type="fix" due-to="romainmoreau">
273 Wrong subject on mail when it depends on the LogEvent
274 </action>
275 <!-- UPDATES -->
276 <action dev="rgoers" issue="" type="update">
277 Update Spring framework to 5.3.13, Spring Boot to 2.5.7, and Spring Cloud to 2020.0.4.
278 </action>
279 <action issue="LOG4J2-2025" dev="rgoers" type="update">
280 Provide support for overriding the Tomcat Log class in Tomcat 8.5+.
281 </action>
282 <action dev="ggregory" issue="" type="update">
283 Updated dependencies.
284
285 - com.fasterxml.jackson.core:jackson-annotations ................. 2.12.2 -> 2.12.4
286 - com.fasterxml.jackson.core:jackson-core ........................ 2.12.2 -> 2.12.4
287 - com.fasterxml.jackson.core:jackson-databind .................... 2.12.2 -> 2.12.4
288 - com.fasterxml.jackson.dataformat:jackson-dataformat-xml ........ 2.12.2 -> 2.12.4
289 - com.fasterxml.jackson.dataformat:jackson-dataformat-yaml ....... 2.12.2 -> 2.12.4
290 - com.fasterxml.jackson.module:jackson-module-jaxb-annotations ... 2.12.2 -> 2.12.4
291 - com.fasterxml.woodstox:woodstox-core ........................... 6.2.4 -> 6.2.6
292 - commons-io:commons-io .......................................... 2.8.0 -> 2.11.0
293 - net.javacrumbs.json-unit:json-unit ............................. 2.24.0 -> 2.25.0
294 - net.javacrumbs.json-unit:json-unit ............................. 2.25.0 -> 2.27.0
295 - org.apache.activemq:activemq-broker ............................ 5.16.1 -> 5.16.2
296 - org.apache.activemq:activemq-broker ............................ 5.16.2 -> 5.16.3
297 - org.apache.commons:commons-compress ............................ 1.20 -> 1.21
298 - org.apache.commons:commons-csv ................................. 1.8 -> 1.9.0
299 - org.apache.commons:commons-dbcp2 ............................... 2.8.0 -> 2.9.0
300 - org.apache.commons:commons-pool2 ............................... 2.9.0 -> 2.11.1
301 - org.apache.maven.plugins:maven-failsafe-plugin ................. 2.22.2 -> 3.0.0-M5
302 - org.apache.maven.plugins:maven-surefire-plugin ................. 2.22.2 -> 3.0.0-M5
303 - org.apache.rat:apache-rat-plugin ............................... 0.12 -> 0.13
304 - org.assertj:assertj-core ....................................... 3.19.0 -> 3.20.2
305 - org.codehaus.groovy:groovy-dateutil ............................ 3.0.7 -> 3.0.8
306 - org.codehaus.groovy:groovy-jsr223 .............................. 3.0.7 -> 3.0.8
307 - org.codehaus.plexus:plexus-utils ............................... 3.3.0 -> 3.4.0
308 - org.eclipse.persistence:javax.persistence ...................... 2.1.1 -> 2.2.1
309 - org.eclipse.persistence:org.eclipse.persistence.jpa ............ 2.6.5 -> 2.6.9
310 - org.eclipse.persistence:org.eclipse.persistence.jpa ............ 2.7.8 -> 2.7.9
311 - org.fusesource.jansi ........................................... 2.3.2 -> 2.3.4
312 - org.fusesource.jansi:jansi ..................................... 2.3.1 -> 2.3.2
313 - org.hsqldb:hsqldb .............................................. 2.5.1 -> 2.5.2
314 - org.junit.jupiter:junit-jupiter-engine ......................... 5.7.1 -> 5.7.2
315 - org.junit.jupiter:junit-jupiter-migrationsupport ............... 5.7.1 -> 5.7.2
316 - org.junit.jupiter:junit-jupiter-params ......................... 5.7.1 -> 5.7.2
317 - org.junit.vintage:junit-vintage-engine ......................... 5.7.1 -> 5.7.2
318 - org.liquibase:liquibase-core ................................... 3.5.3 -> 3.5.5
319 - org.mockito:mockito-core ....................................... 3.8.0 -> 3.11.2
320 - org.mockito:mockito-junit-jupiter .............................. 3.8.0 -> 3.11.2
321 - org.springframework:spring-aop ................................. 5.3.3 -> 5.3.9
322 - org.springframework:spring-beans ............................... 5.3.3 -> 5.3.9
323 - org.springframework:spring-context ............................. 5.3.3 -> 5.3.9
324 - org.springframework:spring-context-support ..................... 5.3.3 -> 5.3.9
325 - org.springframework:spring-core ................................ 5.3.3 -> 5.3.9
326 - org.springframework:spring-expression .......................... 5.3.3 -> 5.3.9
327 - org.springframework:spring-oxm ................................. 5.3.3 -> 5.3.9
328 - org.springframework:spring-test ................................ 5.3.3 -> 5.3.9
329 - org.springframework:spring-web ................................. 5.3.3 -> 5.3.9
330 - org.springframework:spring-webmvc .............................. 5.3.3 -> 5.3.9
331 - org.tukaani:xz ................................................. 1.8 -> 1.9
332 </action>
333 </release>
334 <release version="2.14.1" date="2021-03-06" description="GA Release 2.14.1">
335 <!-- FIXES -->
336 <action issue="LOG4J2-3033" dev="rgoers" type="fix">
337 Add log method with no parameters - i.e. it has an empty message.
338 </action>
339 <action issue="LOG4J2-2947" dev="rgoers" type="fix">
340 Document that LogBuilder default methods do nothing.
341 </action>
342 <action issue="LOG4J2-2948" dev="vy" type="fix">
343 Replace HashSet with IdentityHashMap in ParameterFormatter to detect cycles.
344 </action>
345 <action issue="LOG4J2-3028" dev="ckozak" type="fix" due-to="Jakub Kozlowski">
346 OutputStreamManager.flushBuffer always resets the buffer, previously the buffer was not reset after an exception.
347 </action>
348 <action issue="LOG4J2-2981" dev="rgoers" type="fix">
349 OnStartupTriggeringPolicy would fail to cause the file to roll over with DirectWriteTriggeringPolicy
350 unless minSize was set to 0.
351 </action>
352 <action issue="LOG4J2-2990" dev="rgoers" type="fix" due-to="Diogo Monteiro">
353 Reduce garbage by using putAll when copying the ThreadContext for SLF4J.
354 </action>
355 <action issue="LOG4J2-3006" dev="rgoers" type="fix">
356 Directly create a thread instead of using the common ForkJoin pool when initializing ThreadContextDataInjector"
357 </action>
358 <action issue="LOG4J2-2624" dev="mattsicker" type="fix" due-to="Tim Perry">
359 Allow auto-shutdown of log4j in log4j-web to be turned off and provide a
360 ServletContextListener "Log4jShutdownOnContextDestroyedListener" to stop log4j.
361 Register the listener at the top of web.xml to ensure the shutdown happens last.
362 </action>
363 <action issue="LOG4J2-1606" dev="mattsicker" type="fix" due-to="Tim Perry">
364 Allow auto-shutdown of log4j in log4j-web to be turned off and provide a
365 ServletContextListener "Log4jShutdownOnContextDestroyedListener" to stop log4j.
366 Register the listener at the top of web.xml to ensure the shutdown happens last.
367 </action>
368 <action issue="LOG4J2-2998" dev="vy" type="fix">
369 Fix truncation of excessive strings ending with a high surrogate in JsonWriter.
370 </action>
371 <action issue="LOG4J2-2977" dev="vy" due-to="Ron Grabowski">
372 Replace outdated PatternLayout.createLayout() calls in docs with createDefaultLayout().
373 </action>
374 <action issue="LOG4J2-2973" dev="vy" type="fix" due-to="Fabio Ricchiuti">
375 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to "format".
376 </action>
377 <action issue="LOG4J2-2972" dev="vy" type="fix">
378 Refactor AsyncAppender and AppenderControl for handling of Throwables.
379 </action>
380 <action issue="LOG4J2-2985" dev="vy" type="fix">
381 Add eventTemplateRootObjectKey parameter to JsonTemplateLayout.
382 </action>
383 <action issue="LOG4J2-2974" dev="rgoers" type="fix">
384 Log4j would fail to initialize in Java 8 with log4j-spring-boot.
385 </action>
386 <action issue="LOG4J2-2964" dev="vy" type="fix" due-to="Valery Yatsynovich">
387 Merge packages from several Configurations in Composite Configuration.
388 </action>
389 <action issue="LOG4J2-2961" dev="vy" type="fix">
390 Fix reading of JsonTemplateLayout event additional fields from config.
391 </action>
392 <action issue="LOG4J2-2916" dev="vy" type="fix" due-to="wuqian0808">
393 Avoid redundant Kafka producer instantiation causing thread leaks.
394 </action>
395 <action issue="LOG4J2-2967" dev="ckozak" type="fix">
396 Fix JsonTemplateLayout index based parameter resolution when messages contain too few parameters.
397 </action>
398 <action issue="LOG4J2-2976" dev="ckozak" type="fix">
399 JdbcAppender composes an incorrect INSERT statement without a ColumnMapping element.
400 </action>
401 <action issue="LOG4J2-3014" dev="ggregory" type="fix" due-to="Lee Breisacher, Gary Gregory">
402 Log4j1ConfigurationConverter on Windows produces "&#xd;" at end of every line.
403 </action>
404 <action issue="LOG4J2-3131" dev="ggregory" type="fix" due-to="Adam Long, Gary Gregory">
405 Attempting to call getExtendedStackTraceAsString() after deserializing JSON LogEvent results in a NPE.
406 </action>
407 <action issue="LOG4J2-3131" dev="ggregory" type="fix" due-to="Gary Gregory">
408 NoGcLayout allocates empty bytes arrays for its header and footer.
409 </action>
410 <!-- ADDS -->
411 <action issue="LOG4J2-2962" dev="vy" type="add">
412 Enrich "map" resolver by unifying its backend with "mdc" resolver.
413 </action>
414 <action issue="LOG4J2-2999" dev="vy" type="add">
415 Replace JsonTemplateLayout resolver configurations table in docs with sections.
416 </action>
417 <action issue="LOG4J2-2993" dev="vy" type="add">
418 Support stack trace truncation in JsonTemplateLayout.
419 </action>
420 <!-- UPDATES -->
421 <action issue="LOG4J2-2923" dev="rgoers" type="update">
422 Add Rollover Listener to aid in unit test validation.
423 </action>
424 <action issue="LOG4J2-2893" dev="rgoers" type="update">
425 Allow reconfiguration when Log4j 1 configuration files are updated.
426 </action>
427 <action dev="rgoers" type="update">
428 Update Spring dependencies to 5.3.2, Spring Boot to 2.3.6, and Spring Cloud to Hoxton.SR9
429 </action>
430 <action dev="ggregory" type="update">
431 Update org.fusesource.jansi:jansi 1.17.1 -> 2.0.1.
432 </action>
433 <action dev="ggregory" type="update">
434 Update commons-codec:commons-codec 1.14 -> 1.15.
435 </action>
436 <action dev="ggregory" type="update">
437 Update org.apache.commons:commons-lang3 3.10 -> 3.11.
438 </action>
439 <action dev="ggregory" type="update">
440 Update org.apache.commons:commons-pool2 2.8.1 -> 2.9.0.
441 </action>
442 <action dev="ggregory" type="update">
443 Update org.apache.commons:commons-dbcp2 2.4.0 -> 2.8.0.
444 </action>
445 <action dev="ggregory" type="update">
446 Update commons-io:commons-io 2.7 -> 2.8.0.
447 </action>
448 <action dev="ggregory" type="update">
449 Update org.codehaus.groovy:* 3.0.5 -> 3.0.6.
450 </action>
451 <action dev="ggregory" type="update">
452 Update com.fasterxml.jackson.*:* 2.11.2 - 2.11.3.
453 </action>
454 <action dev="ggregory" type="update">
455 Update org.springframework:* 5.2.8.RELEASE -> 5.3.1.
456 </action>
457 <action dev="ggregory" type="update">
458 Update junit:junit 4.13 -> 4.13.1.
459 </action>
460 <action dev="ggregory" type="update">
461 Update org.xmlunit:* 2.7.0 -> 2.8.0.
462 </action>
463 <action dev="ggregory" type="update">
464 Update org.assertj:assertj-core 3.14.0 -> 3.18.1.
465 </action>
466 <action dev="ggregory" type="update">
467 Update org.awaitility:awaitility 4.0.2 -> 4.0.3.
468 </action>
469 <action dev="ggregory" type="update">
470 Update org.codehaus.plexus:plexus-utils 3.2.0 -> 3.3.0.
471 </action>
472 <action dev="ggregory" type="update">
473 Update MongoDB 3 plugin: org.mongodb:mongodb-driver 3.12.6 -> 3.12.7.
474 </action>
475 <action dev="ggregory" type="update">
476 Update MongoDB 4 plugin: org.mongodb:* 4.1.0 -> 4.1.1.
477 </action>
478 <action dev="ggregory" type="update">
479 Update org.eclipse.tycho:org.eclipse.osgi 3.12.1.v20170821-1548 -> 3.13.0.v20180226-1711.
480 </action>
481 <action dev="ggregory" type="update">
482 Update de.flapdoodle.embed:de.flapdoodle.embed.mongo 2.2.0 -> 3.0.0.
483 </action>
484 <action dev="ggregory" type="update">
485 Update net.javacrumbs.json-unit:json-unit 1.31.1 -> 2.22.0.
486 </action>
487 <action dev="ggregory" type="update">
488 Update Mockito 3.6.0 -> 3.7.0.
489 </action>
490 <action dev="ggregory" type="update">
491 Update XML Unit 2.8.0 -> 2.8.2.
492 </action>
493 <action dev="ggregory" type="update">
494 Update JSON Unit 2.21.0 -> 2.22.0.
495 </action>
496 <action dev="ggregory" type="update">
497 Update JaCoCo 0.8.3 -> 0.8.6.
498 </action>
499 <action dev="ggregory" type="update">
500 Update org.apache.activemq:* 5.16.0 -> 5.16.1.
501 </action>
502 <action dev="ggregory" type="update">
503 Update org.mockito:mockito-* 3.7.0 -> 3.7.7.
504 </action>
505 <action dev="ggregory" type="update">
506 Update org.springframework:* 5.3.2 -> 5.3.3.
507 </action>
508 <action dev="ggregory" type="update">
509 Update mongodb4.version 4.1.1 -> 4.2.0.
510 </action>
511 <action dev="ggregory" type="update">
512 Update org.fusesource.jansi:jansi 1.18 -> 2.2.0.
513 </action>
514 <action dev="ggregory" type="update">
515 Update org.assertj:assertj-core 3.18.1 -> 3.19.0.
516 </action>
517 <action dev="ggregory" type="update">
518 Update net.javacrumbs.json-unit:json-unit 2.22.0 -> 2.23.0.
519 </action>
520 <action dev="ggregory" type="update">
521 Update Woodstox 5.0.3 -> 6.2.3 to match Jackson 2.12.1.
522 </action>
523 <action dev="ggregory" type="update">
524 Update org.apache.activemq:* 5.16.0 -> 5.16.1.
525 </action>
526 <action dev="ggregory" type="update">
527 Update org.mockito:mockito-* 3.7.0 -> 3.7.7.
528 </action>
529 <action dev="ggregory" type="update">
530 Update org.springframework:* 5.3.2 -> 5.3.3.
531 </action>
532 <action dev="ggregory" type="update">
533 Update mongodb4.version 4.1.1 -> 4.2.0.
534 </action>
535 <action dev="ggregory" type="update">
536 Update org.fusesource.jansi:jansi 1.18 -> 2.3.1.
537 </action>
538 <action dev="ggregory" type="update">
539 Update org.assertj:assertj-core 3.18.1 -> 3.19.0.
540 </action>
541 <action dev="ggregory" type="update">
542 Update net.javacrumbs.json-unit:json-unit 2.22.0 -> 2.23.0.
543 </action>
544 <action dev="ggregory" type="update">
545 Update net.javacrumbs.json-unit:json-unit 2.22.0 -> 2.23.0.
546 </action>
547 <action dev="ggregory" type="update">
548 - com.fasterxml.jackson.core:jackson-annotations ................. 2.12.1 -> 2.12.2
549 - com.fasterxml.jackson.core:jackson-core ........................ 2.12.1 -> 2.12.2
550 - com.fasterxml.jackson.core:jackson-databind .................... 2.12.1 -> 2.12.2
551 - com.fasterxml.jackson.dataformat:jackson-dataformat-xml ........ 2.12.1 -> 2.12.2
552 - com.fasterxml.jackson.dataformat:jackson-dataformat-yaml ....... 2.12.1 -> 2.12.2
553 - com.fasterxml.jackson.module:jackson-module-jaxb-annotations ... 2.12.1 -> 2.12.2
554 - org.apache.commons:commons-lang3 ............................... 3.11 -> 3.12.0
555 - org.junit.jupiter:junit-jupiter-engine ......................... 5.7.0 -> 5.7.1
556 - org.junit.jupiter:junit-jupiter-migrationsupport ............... 5.7.0 -> 5.7.1
557 - org.junit.jupiter:junit-jupiter-params ......................... 5.7.0 -> 5.7.1
558 - org.junit.vintage:junit-vintage-engine ......................... 5.7.0 -> 5.7.1
559 - org.mockito:mockito-core ....................................... 3.7.7 -> 3.8.0
560 - org.mockito:mockito-junit-jupiter .............................. 3.7.7 -> 3.8.0
561 - org.mongodb:bson ............................................... 4.2.0 -> 4.2.2
562 - org.mongodb:mongodb-driver-sync ................................ 4.2.0 -> 4.2.2
563 </action>
564 </release>
565 <release version="2.14.0" date="2020-11-06" description="GA Release 2.14.0">
566 <action issue="LOG4J2-2925" dev="rgoers" type="fix">
567 Fix broken link in FAQ.
568 </action>
569 <action issue="LOG4J2-2957" dev="vy" type="add">
570 Add JsonTemplateLayout.
571 </action>
572 <action issue="LOG4J2-2911" dev="rgoers" type="fix">
573 Log4j2EventListener in spring.cloud.config.client listens for wrong event.
574 </action>
575 <action issue="LOG4J2-2889" dev="mattsicker" type="update" due-to="Geng Yuanzhe">
576 Add date pattern support for HTML layout.
577 </action>
578 <action issue="LOG4J2-2919" dev="mattsicker" type="fix" due-to="Geng Yuanzhe">
579 Call ReliabilityStrategy's beforeStopAppenders() method before stopping AsyncAppender.
580 </action>
581 <action issue="LOG4J2-2892" dev="rgoers" type="update" due-to="Jakub Lukes">
582 Allow GelfLayout to produce newline delimited events.
583 </action>
584 <action issue="LOG4J2-2906" dev="rgoers" type="fix" due-to="Stephen Joyner">
585 Fix UnsupportedOperationException when initializing the Log4j2CloudConfigLoggingSystem.
586 </action>
587 <action issue="LOG4J2-2908" dev="rgoers" type="fix">
588 Move Spring Lookup and Spring PropertySource to its own module.
589 </action>
590 <action issue="LOG4J2-2910" dev="rgoers" type="fix">
591 Log4j-web should now stores the servlet context as a map entry instead of in the single external context field.
592 </action>
593 <action issue="LOG4J2-2822" dev="rgoers" type="fix">
594 Javadoc link in ThreadContext description was incorrect.
595 </action>
596 <action issue="LOG4J2-2894" dev="rgoers" type="fix">
597 Fix spelling error in log message.
598 </action>
599 <action issue="LOG4J2-2901" dev="rgoers" type="fix">
600 Missing configuration files should be ignored when creating a composite configuration.
601 </action>
602 <action issue="LOG4J2-2883" dev="rgoers" type="fix">
603 When using DirectFileRolloverStrategy the file pattern was not being recalculated on
604 size based rollover after a time based rollover had occurred.
605 </action>
606 <action issue="LOG4J2-2875" dev="rgoers" type="fix">
607 Rollover was failing to create directories when using a DirectFileeRolloverStrategy.
608 </action>
609 <action issue="LOG4J2-2859" dev="rgoers" type="fix" due-to="Yanming Zhou">
610 Fixed typos where mergeFactory should be mergeStrategy.
611 </action>
612 <action issue="LOG4J2-2832" dev="rgoers" type="fix" due-to="Benjamin Asbach">
613 Correct class name printed in error message in RollingFileAppender.
614 </action>
615 <action issue="LOG4J2-2882" dev="rgoers" type="fix" due-to="Emmanuel Bourg">
616 Support java.util.logging filters when using that API.
617 </action>
618 <action issue="LOG4J2-2880" dev="rgoers" type="fix">
619 Create StackWalker benchmark. Revert back to StackWalker.walk based on benchmark results.
620 </action>
621 <action issue="LOG4J2-2867" dev="rgoers" type="fix">
622 Obtain ContextDataProviders asynchronously.
623 </action>
624 <action issue="LOG4J2-2877" dev="rgoers" type="fix">
625 Determine the container id to obtain container and image information.
626 </action>
627 <action issue="LOG4J2-2844" dev="ggregory" type="fix">
628 Null pointer exception when no network interfaces are available.
629 </action>
630 <action issue="LOG4J2-2848" dev="ggregory" type="add">
631 Create module log4j-mongodb4 to use new major version 4 MongoDB driver.
632 </action>
633 <action issue="LOG4J2-2851" dev="ggregory" type="remove">
634 Drop log4j-mongodb2 module.
635 </action>
636 <action dev="ggregory" type="update">
637 Update MongoDB tests to require Java 8 unconditionally now that Log4j requires Java 8.
638 </action>
639 <action dev="ggregory" type="update">
640 Update mongodb3.version from 3.12.1 to 3.12.6.
641 </action>
642 <action dev="ggregory" type="update">
643 Update com.fasterxml.jackson.* 2.10.2 -> 2.11.0.
644 </action>
645 <action dev="ggregory" type="update">
646 Update org.apache.activemq:activemq-broker 5.15.11 -> 5.16.0.
647 </action>
648 <action dev="ggregory" type="update">
649 Update org.apache.commons:commons-compress 1.19 -> 1.20.
650 </action>
651 <action dev="ggregory" type="update">
652 Update org.apache.commons:commons-csv 1.7 -> 1.8.
653 </action>
654 <action dev="ggregory" type="update">
655 Update org.apache.commons:commons-lang3 3.9 -> 3.10.
656 </action>
657 <action dev="ggregory" type="update">
658 Update org.codehaus.groovy:* 2.5.6 -> 3.0.5.
659 </action>
660 <action dev="ggregory" type="update">
661 Update tests junit:junit 4.12 -> 4.13.
662 </action>
663 <action dev="ggregory" type="update">
664 Update tests commons-io:commons-io 2.6 -> 2.7.
665 </action>
666 <action dev="ggregory" type="update">
667 Update jackson 2.11.0 -> 2.11.2.
668 </action>
669 <action dev="ggregory" type="update">
670 Update tests hsqldb 2.5.0 -> 2.5.1.
671 </action>
672 <action issue="LOG4J2-2895" dev="ckozak" type="fix">
673 Fix potential deadlock in asynchronous logging by avoiding blocking for queue space on Log4jThreads
674 </action>
675 <action issue="LOG4J2-2837" dev="ckozak" type="fix">
676 Disruptor and JUL no longer recursively start the AsyncLoggerDisruptor
677 resulting in an extra disruptor background thread constantly waiting.
678 </action>
679 <action issue="LOG4J2-2867" dev="ckozak" type="fix">
680 RingBufferLogEventTranslator uses a static ContextDataInjector instead of initializing a new object
681 on each thread.
682 </action>
683 <action issue="LOG4J2-2858" dev="ckozak" type="add" due-to="Stepan Gorban">
684 More flexible configuration of the Disruptor WaitStrategy.
685 </action>
686 <action issue="LOG4J2-2898" dev="ckozak" type="fix" due-to="Turbanov Andrey">
687 Avoid initializing volatile fields with default values.
688 </action>
689 <action issue="LOG4J2-2899" dev="ckozak" type="fix">
690 Fix log4j-1.2-api LogEventWrapper threadId and priority accessors when called multiple times.
691 </action>
692 <action issue="LOG4J2-2939" dev="ckozak" type="fix" due-to="Constantin Hirsch">
693 Fix NPE in MDCContextMap on 'contains' and 'isEmpty' invocations.
694 </action>
695 <action issue="LOG4J2-2954" dev="ckozak" type="fix" due-to="Henry Tung">
696 Prevent premature garbage collection of shutdown hooks in DefaultShutdownCallbackRegistry.
697 </action>
698 </release>
699 <release version="2.13.3" date="2020-05-10" description="GA Release 2.13.3">
700 <action issue="LOG4J2-2838" dev="rgoers" type="fix">
701 Fix NullPointerException in ThreadContextDataInjector.
702 </action>
703 </release>
704 <release version="2.13.2" date="2020-04-23" description="GA Release 2.13.2">
705 <action issue="LOG4J2-2824" dev="rgoers" type="fix" due-to="CrazyBills">
706 Implement requiresLocation in GelfLayout to reflect whether location information is used in the message Pattern.
707 </action>
708 <action issue="LOG4J2-2588" dev="rgoers" type="fix">
709 Add option to restore printing timeMillis in the JsonLayout.
710 </action>
711 <action issue="LOG4J2-2766" dev="rgoers" type="fix">
712 Initialize pattern processor before triggering policy during reconfiguration.
713 </action>
714 <action issue="LOG4J2-2457" dev="rgoers" type="update">
715 Allow the file extension in the file pattern to be modified during reconfiguration.
716 </action>
717 <action issue="LOG4J2-2810" dev="rgoers" type="fix">
718 Add information about using a url in log4j.configurationFile.
719 </action>
720 <action issue="LOG4J2-2813" dev="rgoers" type="fix" due-to="Keith D Gregory">
721 serializeToBytes was checking wrong variable for null.
722 </action>
723 <action issue="LOG4J2-2814" dev="rgoers" type="fix">
724 Fix Javadoc for ScriptPatternSelector.
725 </action>
726 <action issue="LOG4J2-2793" dev="rgoers" type="fix" due-to="Renukaprasad C">
727 Allow trailing and leading spaces in log level.
728 </action>
72935 <action issue="LOG4J2-2819" dev="mattsicker" type="update">
73036 Add support for specifying an SSL configuration for SmtpAppender.
73137 </action>
732 <action issue="LOG4J2-2520" dev="rgoers" type="update">
733 Allow servlet context path to be retrieved without "/".
734 </action>
735 <action issue="LOG4J2-2818" dev="rgoers" type="update">
736 Allow Spring Lookup to return default and active profiles.
737 </action>
738 <action issue="LOG4J2-2791" dev="rgoers" type="fix" due-to="Johan Karlberg">
739 Correct JsonLayout timestamp sorting issue.
740 </action>
741 <action issue="LOG4J2-2817" dev="rgoers" type="fix" due-to="Trejkaz">
742 Allow the file size action to parse the value without being sensitive to the current locale.
743 </action>
744 <action issue="LOG4J2-2794" dev="rgoers" type="fix" due-to="Johan Karlberg">
745 Make YamlLayoutTest more resilient to environmental differences.
746 </action>
747 <action issue="LOG4J2-2815" dev="rgoers" type="update">
748 Allow Spring Boot applications to use composite configurations.
749 </action>
750 <action issue="LOG4J2-1360" dev="rgoers" type="add" due-to="Kevin Leturc">
751 Provide a Log4j implementation of System.Logger.
752 </action>
753 <action issue="LOG4J2-2790" dev="rgoers" type="fix" due-to="Marius Volkhart">
754 Conditionally allocate PluginEntry during PluginCache loading.
755 </action>
756 <action issue="LOG4J2-2811" dev="rgoers" type="fix" due-to="Kuojian21">
757 Add missing includeLocation parameter when creating AsyncLogger.
758 </action>
759 <action issue="LOG4J2-2761" dev="rgoers" type="fix" due-to="Uwe Schindler">
760 Fix Exceptions when whitespace is in the file path and Java security manager is used.
761 </action>
762 <action issue="LOG4J2-2809" dev="rgoers" type="fix" due-to="Romain Manni-Bucau">
763 Avoid NullPointerException when StackWalker returns null.
764 </action>
765 <action issue="LOG4J2-2807" dev="rgoers" type="add">
766 Added EventLookup to retrieve fields from the log event.
767 </action>
768 <action issue="LOG4J2-2805" dev="rgoers" type="fix">
769 TimeFilter did not handle daylight saving time transitions and did not support a range over 2 days.
770 </action>
771 <action issue="LOG4J2-2779" dev="rgoers" type="update">
772 Add ContextDataProviders as an alternative to having to implement a ContextDataInjector.
773 </action>
774 <action issue="LOG4J2-2812" dev="ggregory" type="update">
775 [JDBC] Throw a AppenderLoggingException instead of an NPE in the JDBC database manager.
38 <action issue="LOG4J2-3242" dev="ggregory" type="update">
39 Rename JNDI enablement property from 'log4j2.enableJndi'
40 to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and
41 'log4j2.enableJndiContextSelector'.
77642 </action>
77743 </release>
778 <release version="2.13.1" date="2020-02-25" description="GA Release 2.13.1">
779 <action issue="LOG4J2-2717" dev="rgoers" type="fix">
780 Slow initialization on Windows due to accessing network interfaces.
781 </action>
782 <action issue="LOG4J2-2789" dev="rgeors" type="update" due-to="Marius Volkhart">
783 Conditionally perform status logging calculations in PluginRegistry.
784 </action>
785 <action issue="LOG4J2-2756" dev="rgoers" type="fix">
786 Prevent LoggerContext from being garbage collected while being created.
787 </action>
788 <action issue="LOG4J2-2769" dev="rgoers" type="fix">
789 Do not log an error if Files.move does not work.
790 </action>
791 <action issue="LOG4J2-2039" dev="rgoers" type="fix">
792 Rollover fails when file matches pattern but index is too large.
793 </action>
794 <action issue="LOG4J2-2784" dev="rgoers" type="fix">
795 Counter stuck at 10 and overwriting files when leading zeros used in the file pattern count.
796 </action>
797 <action issue="LOG4J2-2746" dev="rgoers" type="fix">
798 ClassLoaderContextSelector was not locating the LoggerContext during shutdown.
799 </action>
800 <action issue="LOG4J2-2652" dev="rgoers" type="fix">
801 JSON output wrong when using additional fields.
802 </action>
803 <action issue="LOG4J2-2649" dev="rgoers" type="fix">
804 GraalVM does not allow use of MethodHandles.
805 </action>
806 <action issue="LOG4J2-2211" dev="rgoers" type="fix">
807 Allow Lookup keys with leading dashes by using a slash as an escape character.
808 </action>
809 <action issue="LOG4J2-2782" dev="rgoers" type="update">
810 Use LinkedBlockingQueue instead of synchronized collection in StatusConfiguration.
811 </action>
812 <action issue="LOG4J2-2781" dev="rgoers" type="fix" due-to="qxo">
813 ServletContainerInitializer was obtaining the StatusLogger too soon.
814 </action>
815 <action issue="LOG4J2-2676" dev="rgoers" type="fix" due-to="Gregg Donovan">
816 PluginProcessor should use Messager instead of System.out.
817 </action>
818 <action issue="LOG4J2-2703" dev="rgoers" type="fix" due-to="Volkan Yazici">
819 MapMessage.getFormattedMesssage() would incorrectly format objects.
820 </action>
821 <action issue="LOG4J2-2760" dev="rgoers" type="fix" due-to="Christoph Kaser">
822 Always write header on a new OutputStream.
823 </action>
824 <action issue="LOG4J2-2777" dev="rgoers" type="update" due-to="joongs4">
825 Add a retry count attribute to the KafkaAppender.
826 </action>
827 <action issue="LOG4J2-2776" dev="rgoers" type="fix" due-to="Christoph Kaser">
828 An error message in RollingFileAppender uses a placeholder for the name but does not specify the name
829 argument in the logging call
830 </action>
831 <action issue="LOG4J2-2758" dev="rgoers" type="fix" due-to="Christoph Kaser">
832 NullPointerException when using a custom DirectFileRolloverStrategy without a file name.
833 </action>
834 <action issue="LOG4J2-2768" dev="rgoers" type="fix" due-to="Marius Volkhart">
835 Add mulit-parameter overloads to LogBuilder.
836 </action>
837 <action issue="LOG4J2-2770" dev="rgoers" type="fix" due-to="Bill Kuker">
838 Fixed NullPointerException after reconfiguring via JMX.
839 </action>
840 <action issue="LOG4J2-2759" dev="rgoers" type="fix">
841 RollingFileAppender was not rolling on startup if createOnDemand was set to true.
842 </action>
843 <action issue="LOG4J2-2767" dev="rgoers" type="fix">
844 Warn if pattern is missing on Routes element. Use default route.
845 </action>
846 <action issue="LOG4J2-2415" dev="ckozak" type="fix" due-to="Andrey Turbanov">
847 Fix lock contention in the classloader using new versions of slf4j without EventData on slf4j logger creation.
848 </action>
849 <action issue="LOG4J2-2677" dev="ckozak" type="fix">
850 Rollover handles parallel file deletion gracefully.
851 </action>
852 <action issue="LOG4J2-2744" dev="ckozak" type="fix">
853 Remove unnecessary EventLogger references from log4j-slf4j18-impl due to removal from slf4j.
854 </action>
855 <action issue="LOG4J2-2745" dev="ckozak" type="update">
856 Update log4j-slf4j18-impl slf4j version to 1.8.0-beta4 from 1.8.0-alpha2.
857 </action>
858 <action issue="LOG4J2-2747" dev="ckozak" type="fix">
859 Fix a memory leak using fully asynchronous logging when the queue is full using the 'discard' asynchronous queue full strategy.
860 </action>
861 <action issue="LOG4J2-2739" dev="ckozak" type="fix">
862 Fix erroneous log4j-jul recursive logger detection resulting in some no-op JUL loggers and 'WARN Recursive call to getLogger' being reported by the status logger.
863 </action>
864 <action issue="LOG4J2-2748" dev="ckozak" type="add">
865 Implement ISO8601_PERIOD_MICROS fixed date format matching ISO8601_PERIOD with support for microsecond precision.
866 </action>
867 <action issue="LOG4J2-2735" dev="ckozak" type="fix" due-to="Andy Wilkinson">
868 PluginCache output is reproducible allowing the annotation processor to produce deterministic results.
869 </action>
870 <action issue="LOG4J2-2751" dev="ckozak" type="fix">
871 Fix StackLocator.getCallerClass performance in cases where Reflection.getCallerClass is not accessible.
872 </action>
873 <action issue="LOG4J2-2752" dev="ckozak" type="fix">
874 MutableLogEvent and RingBufferLogEvent avoid StringBuffer and parameter array allocation unless reusable messages are used.
875 </action>
876 <action issue="LOG4J2-2754" dev="ckozak" type="fix">
877 LoaderUtil.getClassLoaders may discover additional loaders and no longer erroneously returns a result with a null element in some environments.
878 </action>
879 <action issue="LOG4J2-2575" dev="rgoers" type="fix" due-to="Nathan Friess">
880 CronExpression.getBeforeTime() would sometimes return incorrect result.
881 </action>
882 <action issue="LOG4J2-2762" dev="ggregory" type="fix">
883 [JDBC] MS-SQL Server JDBC driver throws SQLServerException when inserting a null value for a VARBINARY column.
884 </action>
885 <action issue="LOG4J2-2763" dev="ggregory" type="update">
886 Update dependencies.
887 </action>
888 <action issue="LOG4J2-2770" dev="ggregory" type="fix" due-to="Bill Kuker">
889 NullPointerException after reconfiguring via JMX.
890 </action>
891 </release>
892 <release version="2.13.0" date="2019-12-11" description="GA Release 2.13.0">
893 <action issue="LOG4J2-2058" dev="rgoers" type="fix">
894 Prevent recursive calls to java.util.LogManager.getLogger().
895 </action>
896 <action issue="LOG4J2-2725" dev="ckozak" type="fix" due-to="Dzmitry Anikechanka">
897 LOG4J2-2725 - Added try/finally around event.execute() for RingBufferLogEventHandler to clear memory
898 correctly in case of exception/error
899 </action>
900 <action issue="LOG4J2-2635" dev="rgoers" type="fix" due-to="Filipp Gunbin">
901 Wrong java version check in ThreadNameCachingStrategy.
902 </action>
903 <action issue="LOG4J2-2674" dev="rgoers" type="fix" due-to="Anton Korenkov">
904 Use a less confusing name for the CompositeConfiguration source.
905 </action>
906 <action issue="LOG4J2-2732" dev="rgoers" type="add" due-to="Matt Pavlovich">
907 Add ThreadContext.putIfNotNull method.
908 </action>
909 <action issue="LOG4J2-2731" dev="rgoers" type="add">
910 Add a Level Patttern Selector.
911 </action>
912 <action issue="LOG4J2-2701" dev="rgoers" type="update">
913 Update Jackson to 2.9.10.
914 </action>
915 <action issue="LOG4J2-2727" dev="rogers" type="fix" due-to="Clément Mathieu">
916 Add setKey method to Kafka Appender Builder.
917 </action>
918 <action issue="LOG4J2-2707" dev="rgoers" type="fix" due-to="Christian Frank">
919 ArrayIndexOutOfBoundsException could occur with MAC address longer than 6 bytes.
920 </action>
921 <action issue="LOG4J2-63" dev="rgoers" type="add">
922 Add experimental support for Log4j 1 configuration files.
923 </action>
924 <action issue="LOG4J2-2712" dev="rgoers" type="fix">
925 The rolling file appenders would fail to compress the file after rollover if the file name matched the
926 file pattern.
927 </action>
928 <action issue="LOG4J2-2716" dev="rgoers" type="add">
929 Add the ability to lookup Kubernetes attributes in the Log4j configuration. Allow Log4j properties to
930 be retrieved from the Spring environment if it is available.
931 </action>
932 <action issue="LOG4J2-2710" dev="rgoers" type="add">
933 Allow Spring Boot application properties to be accessed in the Log4j 2 configuration. Add
934 lower and upper case Lookups.
935 </action>
936 <action issue="LOG4J2-2709" dev="rgoers" type="update">
937 Allow message portion of GELF layout to be formatted using a PatternLayout. Allow
938 ThreadContext attributes to be explicitly included or excluded in the GelfLayout.
939 </action>
940 <action issue="LOG4J2-2693" dev="mattsicker" type="fix">
941 @PluginValue does not support attribute names besides "value".
942 </action>
943 <action issue="LOG4J2-2647" dev="mattsicker" type="fix">
944 Validation blocks definition of script in properties configuration.
945 </action>
946 <action issue="LOG4J2-2680" dev="rgoers" type="fix" due-to="Guillermo Xavier Hurtado Garcia">
947 Set result of rename action to true if file was copied.
948 </action>
949 <action issue="LOG4J-2672" dev="rgoers" type="fix" due-to="Stephen Colebourne">
950 Add automatic module names where missing.
951 </action>
952 <action issue="LOG4J2-2639" dev="rgoers" type="add">
953 Add builder pattern to Logger interface.
954 </action>
955 <action issue="LOG4J2-2673" dev="ggregory" type="fix" due-to="Yuichi Sugimura">
956 OutputStreamAppender.Builder ignores setFilter().
957 </action>
958 <action issue="LOG4J2-2725" dev="ckozak" type="fix" due-to="Dzmitry Anikechanka">
959 Prevent a memory leak when async loggers throw errors.
44 <release version="2.12.2" date="2021-12-14" description="GA Release 2.12.2">
45 <action issue="LOG4J-3220" dev="rgoers" type="fix">
46 Disable JNDI by default, remove JNDI Lookup, remove message lookups. When enabled JNDI only supports the
47 java protocol.
96048 </action>
96149 </release>
96250 <release version="2.12.1" date="2019-08-06" description="GA Release 2.12.1">
1015103 Add filter that will match events when no marker is present.
1016104 </action>
1017105 <action issue="LOG4J2-1143" dev="rgoers" type="fix" due-to="Pascal Heinrich">
1018 Lookups were not found if the plugin key was not lower case.
106 Lookups were not found if the plugin key was not lowercase.
1019107 </action>
1020108 <action issue="LOG4J2-2406" dev="rgoers" type="add">
1021109 Add reconfiguration methods to Configurator.
1135223 Direct write was creating files with the wrong date/time.
1136224 </action>
1137225 <action issue="LOG4J2-2453" dev="rgoers" type="fix" due-to="theit">
1138 Add Log4j-slf4j18-impl dependency to BOM POM.
226 Add Log4j-slf4j18-impl dependency to bom pom.
1139227 </action>
1140228 <action issue="LOG4J2-2515" dev="rgoers" type="fix" due-to="MakarovS">
1141229 Configuration documentation referenced incorrect method name.
1153241 an additional buffer for stack trace contents.
1154242 </action>
1155243 <action issue="LOG4J2-2397" dev="ggregory" type="fix" due-to="EckelDong">
1156 Pre-deployment of PersistenceUnit that using Log4j as session logger failed (#198).
244 Predeployment of PersistenceUnit that using Log4j as session logger failed (#198).
1157245 </action>
1158246 <action issue="LOG4J2-2365" dev="ckozak" type="fix" due-to="Eugene Zimichev">
1159247 NameAbbreviator correctly abbreviates first fragments (#188).
1418506 </release>
1419507 <release version="2.11.0" date="2018-03-11" description="GA Release 2.11.0">
1420508 <action issue="LOG4J2-2104" dev="rgoers" type="fix">
1421 LoaderUtil was not looping properly over class loaders.
509 LoaderUtil was not looping properly over classloaders.
1422510 </action>
1423511 <action issue="LOG4J2-1976" dev="rgoers" type="fix">
1424512 Revert OSGi API version to 4.3.1.
+0
-101
toolchains-jenkins-ubuntu.xml less more
0 <?xml version="1.0" encoding="UTF8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <toolchains>
18 <!-- JDK toolchains -->
19 <toolchain>
20 <type>jdk</type>
21 <provides>
22 <version>1.8</version>
23 <vendor>sun</vendor>
24 </provides>
25 <configuration>
26 <jdkHome>/home/jenkins/tools/java/latest1.8</jdkHome>
27 </configuration>
28 </toolchain>
29 <toolchain>
30 <type>jdk</type>
31 <provides>
32 <version>9</version>
33 <vendor>sun</vendor>
34 </provides>
35 <configuration>
36 <jdkHome>/home/jenkins/tools/java/latest1.9</jdkHome>
37 </configuration>
38 </toolchain>
39 <toolchain>
40 <type>jdk</type>
41 <provides>
42 <version>10</version>
43 <vendor>sun</vendor>
44 </provides>
45 <configuration>
46 <jdkHome>/home/jenkins/tools/java/latest10</jdkHome>
47 </configuration>
48 </toolchain>
49 <toolchain>
50 <type>jdk</type>
51 <provides>
52 <version>11</version>
53 <vendor>sun</vendor>
54 </provides>
55 <configuration>
56 <jdkHome>/home/jenkins/tools/java/latest11/</jdkHome>
57 </configuration>
58 </toolchain>
59 <toolchain>
60 <type>jdk</type>
61 <provides>
62 <version>12</version>
63 <vendor>sun</vendor>
64 </provides>
65 <configuration>
66 <jdkHome>/home/jenkins/tools/java/latest12/</jdkHome>
67 </configuration>
68 </toolchain>
69 <toolchain>
70 <type>jdk</type>
71 <provides>
72 <version>13</version>
73 <vendor>sun</vendor>
74 </provides>
75 <configuration>
76 <jdkHome>/home/jenkins/tools/java/latest13/</jdkHome>
77 </configuration>
78 </toolchain>
79 <toolchain>
80 <type>jdk</type>
81 <provides>
82 <version>14</version>
83 <vendor>sun</vendor>
84 </provides>
85 <configuration>
86 <jdkHome>/home/jenkins/tools/java/latest14/</jdkHome>
87 </configuration>
88 </toolchain>
89 <toolchain>
90 <type>jdk</type>
91 <provides>
92 <version>15</version>
93 <vendor>sun</vendor>
94 </provides>
95 <configuration>
96 <jdkHome>/home/jenkins/tools/java/latest15/</jdkHome>
97 </configuration>
98 </toolchain>
99 <!-- other toolchains -->
100 </toolchains>
+0
-101
toolchains-jenkins-win.xml less more
0 <?xml version="1.0" encoding="UTF8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <toolchains>
18 <!-- JDK toolchains -->
19 <toolchain>
20 <type>jdk</type>
21 <provides>
22 <version>1.8</version>
23 <vendor>sun</vendor>
24 </provides>
25 <configuration>
26 <jdkHome>F:\jenkins\tools\java\latest1.8</jdkHome>
27 </configuration>
28 </toolchain>
29 <toolchain>
30 <type>jdk</type>
31 <provides>
32 <version>9</version>
33 <vendor>sun</vendor>
34 </provides>
35 <configuration>
36 <jdkHome>F:\jenkins\tools\java\latest9</jdkHome>
37 </configuration>
38 </toolchain>
39 <toolchain>
40 <type>jdk</type>
41 <provides>
42 <version>10</version>
43 <vendor>sun</vendor>
44 </provides>
45 <configuration>
46 <jdkHome>F:\jenkins\tools\java\latest10</jdkHome>
47 </configuration>
48 </toolchain>
49 <toolchain>
50 <type>jdk</type>
51 <provides>
52 <version>11</version>
53 <vendor>sun</vendor>
54 </provides>
55 <configuration>
56 <jdkHome>F:\jenkins\tools\java\latest11</jdkHome>
57 </configuration>
58 </toolchain>
59 <toolchain>
60 <type>jdk</type>
61 <provides>
62 <version>12</version>
63 <vendor>sun</vendor>
64 </provides>
65 <configuration>
66 <jdkHome>F:\jenkins\tools\java\latest12</jdkHome>
67 </configuration>
68 </toolchain>
69 <toolchain>
70 <type>jdk</type>
71 <provides>
72 <version>13</version>
73 <vendor>sun</vendor>
74 </provides>
75 <configuration>
76 <jdkHome>F:\jenkins\tools\java\latest13</jdkHome>
77 </configuration>
78 </toolchain>
79 <toolchain>
80 <type>jdk</type>
81 <provides>
82 <version>14</version>
83 <vendor>sun</vendor>
84 </provides>
85 <configuration>
86 <jdkHome>F:\jenkins\tools\java\latest14</jdkHome>
87 </configuration>
88 </toolchain>
89 <!--toolchain>
90 <type>jdk</type>
91 <provides>
92 <version>15</version>
93 <vendor>sun</vendor>
94 </provides>
95 <configuration>
96 <jdkHome>F:\jenkins\tools\java\latest15</jdkHome>
97 </configuration>
98 </toolchain-->
99 <!-- other toolchains -->
100 </toolchains>
+0
-37
workflows/maven-toolchains.xml less more
0 <?xml version="1.0" encoding="UTF8"?>
1 <!--
2 ~ Licensed to the Apache Software Foundation (ASF) under one or more
3 ~ contributor license agreements. See the NOTICE file distributed with
4 ~ this work for additional information regarding copyright ownership.
5 ~ The ASF licenses this file to You under the Apache license, Version 2.0
6 ~ (the "License"); you may not use this file except in compliance with
7 ~ the License. You may obtain a copy of the License at
8 ~
9 ~ http://www.apache.org/licenses/LICENSE-2.0
10 ~
11 ~ Unless required by applicable law or agreed to in writing, software
12 ~ distributed under the License is distributed on an "AS IS" BASIS,
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the license for the specific language governing permissions and
15 ~ limitations under the license.
16 -->
17 <toolchains>
18 <toolchain>
19 <type>jdk</type>
20 <provides>
21 <version>1.8</version>
22 </provides>
23 <configuration>
24 <jdkHome>${env.JAVA_HOME_8_X64}</jdkHome>
25 </configuration>
26 </toolchain>
27 <toolchain>
28 <type>jdk</type>
29 <provides>
30 <version>11</version>
31 </provides>
32 <configuration>
33 <jdkHome>${env.JAVA_HOME_11_X64}</jdkHome>
34 </configuration>
35 </toolchain>
36 </toolchains>
+0
-55
workflows/maven.yml less more
0 name: Maven
1
2 on: [push]
3
4 jobs:
5 build:
6
7 runs-on: ${{ matrix.os }}
8
9 strategy:
10 matrix:
11 os: [ubuntu-latest, windows-latest]
12
13 steps:
14
15 - name: Checkout repository
16 uses: actions/checkout@v2
17
18 - name: Setup Maven caching
19 uses: actions/cache@v2
20 with:
21 path: ~/.m2/repository
22 key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
23 restore-keys: |
24 ${{ runner.os }}-maven-
25
26 - name: Setup JDK 11
27 uses: actions/setup-java@v1
28 with:
29 java-version: 11
30 java-package: jdk
31 architecture: x64
32
33 - name: Setup JDK 8
34 uses: actions/setup-java@v1
35 with:
36 java-version: 8
37 java-package: jdk
38 architecture: x64
39
40 - name: Inspect environment (Linux)
41 if: runner.os == 'Linux'
42 run: env | grep '^JAVA'
43
44 - name: Build with Maven (Linux)
45 if: runner.os == 'Linux'
46 run: ./mvnw -V -B -e -DtrimStackTrace=false verify --global-toolchains .github/workflows/maven-toolchains.xml
47
48 - name: Inspect environment (Windows)
49 if: runner.os == 'Windows'
50 run: set java
51
52 - name: Build with Maven (Windows)
53 if: runner.os == 'Windows'
54 run: ./mvnw -V -B -e -DtrimStackTrace=false verify --global-toolchains ".github\workflows\maven-toolchains.xml"