Skip to content

Commit 024e54c

Browse files
Merge branch 'apache:2.x' into issue-3074
2 parents 98cad4f + 4a7ddf1 commit 024e54c

File tree

12 files changed

+317
-83
lines changed

12 files changed

+317
-83
lines changed

log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@
2323
import java.util.Collections;
2424
import java.util.List;
2525
import java.util.stream.Collectors;
26+
import java.util.stream.Stream;
2627
import org.apache.logging.log4j.Level;
2728
import org.apache.logging.log4j.message.ParameterFormatter.MessagePatternAnalysis;
2829
import org.apache.logging.log4j.status.StatusData;
2930
import org.apache.logging.log4j.test.ListStatusListener;
3031
import org.apache.logging.log4j.test.junit.UsingStatusListener;
3132
import org.junit.jupiter.api.Test;
3233
import org.junit.jupiter.params.ParameterizedTest;
34+
import org.junit.jupiter.params.provider.Arguments;
3335
import org.junit.jupiter.params.provider.CsvSource;
3436
import org.junit.jupiter.params.provider.MethodSource;
3537

@@ -146,6 +148,18 @@ static Object[][] messageFormattingTestCases() {
146148
};
147149
}
148150

151+
@Test
152+
void testIdentityToString() {
153+
final List<Object> list = new ArrayList<>();
154+
list.add(1);
155+
// noinspection CollectionAddedToSelf
156+
list.add(list);
157+
list.add(2);
158+
final String actual = ParameterFormatter.identityToString(list);
159+
final String expected = list.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(list));
160+
assertThat(actual).isEqualTo(expected);
161+
}
162+
149163
@Test
150164
void testDeepToString() {
151165
final List<Object> list = new ArrayList<>();
@@ -172,15 +186,22 @@ void testDeepToStringUsingNonRecursiveButConsequentObjects() {
172186
assertThat(actual).isEqualTo(expected);
173187
}
174188

175-
@Test
176-
void testIdentityToString() {
177-
final List<Object> list = new ArrayList<>();
178-
list.add(1);
179-
// noinspection CollectionAddedToSelf
180-
list.add(list);
181-
list.add(2);
182-
final String actual = ParameterFormatter.identityToString(list);
183-
final String expected = list.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(list));
189+
@ParameterizedTest
190+
@MethodSource("deepToStringArgumentsPrimitiveArrays")
191+
void testDeepToStringPrimitiveArrays(Object obj, String expected) {
192+
final String actual = ParameterFormatter.deepToString(obj);
184193
assertThat(actual).isEqualTo(expected);
185194
}
195+
196+
static Stream<Arguments> deepToStringArgumentsPrimitiveArrays() {
197+
return Stream.of(
198+
Arguments.of(new byte[] {0, 1, 2, 3, 4}, "[0, 1, 2, 3, 4]"),
199+
Arguments.of(new short[] {0, 1, 2, 3, 4}, "[0, 1, 2, 3, 4]"),
200+
Arguments.of(new int[] {0, 1, 2, 3, 4}, "[0, 1, 2, 3, 4]"),
201+
Arguments.of(new long[] {0, 1, 2, 3, 4}, "[0, 1, 2, 3, 4]"),
202+
Arguments.of(new float[] {0, 1, 2, 3, 4}, "[0.0, 1.0, 2.0, 3.0, 4.0]"),
203+
Arguments.of(new double[] {0, 1, 2, 3, 4}, "[0.0, 1.0, 2.0, 3.0, 4.0]"),
204+
Arguments.of(new char[] {'a', 'b', 'c'}, "[a, b, c]"),
205+
Arguments.of(new boolean[] {false, true}, "[false, true]"));
206+
}
186207
}

log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java

Lines changed: 139 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,12 @@ static void formatMessage(
257257
}
258258
}
259259

260-
// Fast-path for patterns containing no escapes
260+
// Slow-path for patterns containing escapes
261261
if (analysis.escapedCharFound) {
262262
formatMessageContainingEscapes(buffer, pattern, args, argCount, analysis);
263263
}
264264

265-
// Slow-path for patterns containing escapes
265+
// Fast-path for patterns containing no escapes
266266
else {
267267
formatMessageContainingNoEscapes(buffer, pattern, args, argCount, analysis);
268268
}
@@ -487,21 +487,21 @@ private static void appendPotentiallyRecursiveValue(
487487
private static void appendArray(
488488
final Object o, final StringBuilder str, final Set<Object> dejaVu, final Class<?> oClass) {
489489
if (oClass == byte[].class) {
490-
str.append(Arrays.toString((byte[]) o));
490+
appendArray((byte[]) o, str);
491491
} else if (oClass == short[].class) {
492-
str.append(Arrays.toString((short[]) o));
492+
appendArray((short[]) o, str);
493493
} else if (oClass == int[].class) {
494-
str.append(Arrays.toString((int[]) o));
494+
appendArray((int[]) o, str);
495495
} else if (oClass == long[].class) {
496-
str.append(Arrays.toString((long[]) o));
496+
appendArray((long[]) o, str);
497497
} else if (oClass == float[].class) {
498-
str.append(Arrays.toString((float[]) o));
498+
appendArray((float[]) o, str);
499499
} else if (oClass == double[].class) {
500-
str.append(Arrays.toString((double[]) o));
500+
appendArray((double[]) o, str);
501501
} else if (oClass == boolean[].class) {
502-
str.append(Arrays.toString((boolean[]) o));
502+
appendArray((boolean[]) o, str);
503503
} else if (oClass == char[].class) {
504-
str.append(Arrays.toString((char[]) o));
504+
appendArray((char[]) o, str);
505505
} else {
506506
// special handling of container Object[]
507507
final Set<Object> effectiveDejaVu = getOrCreateDejaVu(dejaVu);
@@ -643,4 +643,133 @@ static String identityToString(final Object obj) {
643643
}
644644
return obj.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(obj));
645645
}
646+
647+
/**
648+
* @see Arrays#toString(byte[])
649+
*/
650+
private static void appendArray(final byte[] a, final StringBuilder str) {
651+
int len = a.length;
652+
if (len == 0) {
653+
str.append("[]");
654+
return;
655+
}
656+
str.append('[').append(a[0]);
657+
for (int i = 1; i < len; i++) {
658+
str.append(", ").append(a[i]);
659+
}
660+
str.append(']');
661+
}
662+
663+
/**
664+
* @see Arrays#toString(short[])
665+
*/
666+
private static void appendArray(final short[] a, final StringBuilder str) {
667+
int len = a.length;
668+
if (len == 0) {
669+
str.append("[]");
670+
return;
671+
}
672+
str.append('[').append(a[0]);
673+
for (int i = 1; i < len; i++) {
674+
str.append(", ").append(a[i]);
675+
}
676+
str.append(']');
677+
}
678+
679+
/**
680+
* @see Arrays#toString(int[])
681+
*/
682+
// package protected to allow access from ParameterFormatterBenchmark
683+
static void appendArray(final int[] a, final StringBuilder str) {
684+
int len = a.length;
685+
if (len == 0) {
686+
str.append("[]");
687+
return;
688+
}
689+
str.append('[').append(a[0]);
690+
for (int i = 1; i < len; i++) {
691+
str.append(", ").append(a[i]);
692+
}
693+
str.append(']');
694+
}
695+
696+
/**
697+
* @see Arrays#toString(long[])
698+
*/
699+
private static void appendArray(final long[] a, final StringBuilder str) {
700+
int len = a.length;
701+
if (len == 0) {
702+
str.append("[]");
703+
return;
704+
}
705+
str.append('[').append(a[0]);
706+
for (int i = 1; i < len; i++) {
707+
str.append(", ").append(a[i]);
708+
}
709+
str.append(']');
710+
}
711+
712+
/**
713+
* @see Arrays#toString(float[])
714+
*/
715+
private static void appendArray(final float[] a, final StringBuilder str) {
716+
int len = a.length;
717+
if (len == 0) {
718+
str.append("[]");
719+
return;
720+
}
721+
str.append('[').append(a[0]);
722+
for (int i = 1; i < len; i++) {
723+
str.append(", ").append(a[i]);
724+
}
725+
str.append(']');
726+
}
727+
728+
/**
729+
* @see Arrays#toString(double[])
730+
*/
731+
private static void appendArray(final double[] a, final StringBuilder str) {
732+
int len = a.length;
733+
if (len == 0) {
734+
str.append("[]");
735+
return;
736+
}
737+
str.append('[').append(a[0]);
738+
for (int i = 1; i < len; i++) {
739+
str.append(", ").append(a[i]);
740+
}
741+
str.append(']');
742+
}
743+
744+
/**
745+
* @see Arrays#toString(boolean[])
746+
*/
747+
private static void appendArray(final boolean[] a, final StringBuilder str) {
748+
int len = a.length;
749+
if (len == 0) {
750+
str.append("[]");
751+
return;
752+
}
753+
str.append('[').append(a[0]);
754+
for (int i = 1; i < len; i++) {
755+
str.append(", ").append(a[i]);
756+
}
757+
str.append(']');
758+
}
759+
760+
/**
761+
* @see Arrays#toString(char[])
762+
*/
763+
private static void appendArray(char[] a, final StringBuilder str) {
764+
int len = a.length;
765+
if (len == 0) {
766+
str.append("[]");
767+
return;
768+
}
769+
str.append('[').append(a[0]);
770+
for (int i = 1; i < len; i++) {
771+
str.append(", ").append(a[i]);
772+
}
773+
str.append(']');
774+
}
646775
}

log4j-api/src/main/java/org/apache/logging/log4j/util/PrivateSecurityManagerStackTraceUtil.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,35 @@ final class PrivateSecurityManagerStackTraceUtil {
2929
private static final PrivateSecurityManager SECURITY_MANAGER;
3030

3131
static {
32+
PrivateSecurityManager candidate = createPrivateSecurityManager();
33+
if (isCapable(candidate)) {
34+
SECURITY_MANAGER = candidate;
35+
} else {
36+
SECURITY_MANAGER = null;
37+
}
38+
}
39+
40+
private static boolean isCapable(PrivateSecurityManager candidate) {
41+
if (candidate == null) {
42+
return false;
43+
}
44+
45+
try {
46+
final Class<?>[] result = candidate.getClassContext();
47+
if (result == null || result.length == 0) {
48+
// This happens e.g. on Android which has real implementation of SecurityManager replaced with merely
49+
// stubs. So the PrivateSecurityManager, though can be instantiated, will not produce meaningful
50+
// results
51+
return false;
52+
}
53+
// Add more checks here as needed
54+
return true;
55+
} catch (Exception ignored) {
56+
return false;
57+
}
58+
}
59+
60+
private static PrivateSecurityManager createPrivateSecurityManager() {
3261
PrivateSecurityManager psm;
3362
try {
3463
final SecurityManager sm = System.getSecurityManager();
@@ -40,7 +69,7 @@ final class PrivateSecurityManagerStackTraceUtil {
4069
psm = null;
4170
}
4271

43-
SECURITY_MANAGER = psm;
72+
return psm;
4473
}
4574

4675
private PrivateSecurityManagerStackTraceUtil() {

log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/LoggerConfigTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package org.apache.logging.log4j.core.config;
1818

1919
import static org.junit.jupiter.api.Assertions.assertEquals;
20+
import static org.junit.jupiter.api.Assertions.assertNotNull;
2021
import static org.junit.jupiter.api.Assertions.assertNotSame;
2122
import static org.junit.jupiter.api.Assertions.assertNull;
2223
import static org.junit.jupiter.api.Assertions.assertSame;
24+
import static org.junit.jupiter.api.Assertions.assertTrue;
2325
import static org.mockito.ArgumentMatchers.any;
2426
import static org.mockito.Mockito.mock;
2527
import static org.mockito.Mockito.times;
@@ -32,6 +34,7 @@
3234
import org.apache.logging.log4j.Level;
3335
import org.apache.logging.log4j.core.Appender;
3436
import org.apache.logging.log4j.core.Filter;
37+
import org.apache.logging.log4j.core.config.properties.PropertiesConfiguration;
3538
import org.apache.logging.log4j.core.impl.Log4jLogEvent.Builder;
3639
import org.apache.logging.log4j.message.SimpleMessage;
3740
import org.junit.jupiter.api.Test;
@@ -137,4 +140,18 @@ void testSingleFilterInvocation() {
137140
verify(appender, times(1)).append(any());
138141
verify(filter, times(1)).filter(any());
139142
}
143+
144+
@Test
145+
void testLevelAndRefsWithoutAppenderRef() {
146+
final Configuration configuration = mock(PropertiesConfiguration.class);
147+
final LoggerConfig.Builder builder = LoggerConfig.newBuilder()
148+
.withLoggerName(FQCN)
149+
.withConfig(configuration)
150+
.withLevelAndRefs(Level.INFO.name());
151+
152+
final LoggerConfig loggerConfig = builder.build();
153+
154+
assertNotNull(loggerConfig.getAppenderRefs());
155+
assertTrue(loggerConfig.getAppenderRefs().isEmpty());
156+
}
140157
}

log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,13 +1009,13 @@ protected static LevelAndRefs getLevelAndRefs(
10091009
}
10101010
final String[] parts = Strings.splitList(levelAndRefs);
10111011
result.level = Level.getLevel(parts[0]);
1012+
final List<AppenderRef> refList = new ArrayList<>();
10121013
if (parts.length > 1) {
1013-
final List<AppenderRef> refList = new ArrayList<>();
10141014
Arrays.stream(parts)
10151015
.skip(1)
10161016
.forEach((ref) -> refList.add(AppenderRef.createAppenderRef(ref, null, null)));
1017-
result.refs = refList;
10181017
}
1018+
result.refs = refList;
10191019
} else {
10201020
LOGGER.warn("levelAndRefs are only allowed in a properties configuration. The value is ignored.");
10211021
result.level = level;

0 commit comments

Comments
 (0)