16
16
*/
17
17
package org .apache .logging .log4j .core ;
18
18
19
+ import static java .util .Objects .requireNonNull ;
20
+
19
21
import java .io .ObjectStreamException ;
20
22
import java .io .Serializable ;
21
23
import java .util .ArrayList ;
31
33
import org .apache .logging .log4j .core .config .LoggerConfig ;
32
34
import org .apache .logging .log4j .core .config .ReliabilityStrategy ;
33
35
import org .apache .logging .log4j .core .filter .CompositeFilter ;
36
+ import org .apache .logging .log4j .core .util .Constants ;
37
+ import org .apache .logging .log4j .message .DefaultFlowMessageFactory ;
38
+ import org .apache .logging .log4j .message .FlowMessageFactory ;
34
39
import org .apache .logging .log4j .message .Message ;
35
40
import org .apache .logging .log4j .message .MessageFactory ;
41
+ import org .apache .logging .log4j .message .ParameterizedMessageFactory ;
42
+ import org .apache .logging .log4j .message .ReusableMessageFactory ;
36
43
import org .apache .logging .log4j .message .SimpleMessage ;
37
44
import org .apache .logging .log4j .spi .AbstractLogger ;
45
+ import org .apache .logging .log4j .util .LoaderUtil ;
38
46
import org .apache .logging .log4j .util .Strings ;
39
47
import org .apache .logging .log4j .util .Supplier ;
40
48
@@ -54,6 +62,10 @@ public class Logger extends AbstractLogger implements Supplier<LoggerConfig> {
54
62
55
63
private static final long serialVersionUID = 1L ;
56
64
65
+ private static final String MESSAGE_FACTORY_PROPERTY_NAME = "log4j2.messageFactory" ;
66
+
67
+ private static final String FLOW_MESSAGE_FACTORY_PROPERTY_NAME = "log4j2.flowMessageFactory" ;
68
+
57
69
/**
58
70
* Config should be consistent across threads.
59
71
*/
@@ -63,16 +75,75 @@ public class Logger extends AbstractLogger implements Supplier<LoggerConfig> {
63
75
private final LoggerContext context ;
64
76
65
77
/**
66
- * The constructor .
78
+ * Constructs an instance using the given {@link LoggerContext}, logger name, and {@link MessageFactory} .
67
79
*
68
- * @param context The LoggerContext this Logger is associated with.
69
- * @param messageFactory The message factory.
70
- * @param name The name of the Logger.
80
+ * @param context the {@link LoggerContext} this logger is associated with
81
+ * @param messageFactory The message factory to be used.
82
+ * If null, first the {@value #MESSAGE_FACTORY_PROPERTY_NAME} property will be used to instantiate the message factory.
83
+ * If the property is missing and the {@code log4j2.enableThreadLocals} property is not {@code false}, {@link ReusableMessageFactory} will be used.
84
+ * Otherwise, we will fall back to {@link ParameterizedMessageFactory}.
85
+ * @param name the logger name
71
86
*/
72
87
protected Logger (final LoggerContext context , final String name , final MessageFactory messageFactory ) {
73
- super (name , messageFactory );
74
- this .context = context ;
75
- privateConfig = new PrivateConfig (context .getConfiguration (), this );
88
+ this (context , name , messageFactory , null );
89
+ }
90
+
91
+ /**
92
+ * The canonical constructor.
93
+ *
94
+ * @param context the {@link LoggerContext} this logger is associated with
95
+ * @param messageFactory The message factory to be used.
96
+ * If null, first the {@value #MESSAGE_FACTORY_PROPERTY_NAME} property will be used to instantiate the message factory.
97
+ * If the property is missing and the {@code log4j2.enableThreadLocals} property is not {@code false}, {@link ReusableMessageFactory} will be used.
98
+ * Otherwise, we will fall back to {@link ParameterizedMessageFactory}.
99
+ * @param flowMessageFactory The flow message factory to be used.
100
+ * If null, first the {@value #FLOW_MESSAGE_FACTORY_PROPERTY_NAME} property will be used to instantiate the flow message factory.
101
+ * If the property is missing, {@link DefaultFlowMessageFactory} will be used.
102
+ * @param name the logger name
103
+ */
104
+ protected Logger (
105
+ final LoggerContext context ,
106
+ final String name ,
107
+ final MessageFactory messageFactory ,
108
+ final FlowMessageFactory flowMessageFactory ) {
109
+ super (name , getEffectiveMessageFactory (messageFactory ), getEffectiveFlowMessageFactory (flowMessageFactory ));
110
+ this .context = requireNonNull (context , "context" );
111
+ this .privateConfig = new PrivateConfig (context .getConfiguration (), this );
112
+ }
113
+
114
+ private static MessageFactory getEffectiveMessageFactory (final MessageFactory messageFactory ) {
115
+ return createInstanceFromFactoryProperty (
116
+ MessageFactory .class ,
117
+ messageFactory ,
118
+ MESSAGE_FACTORY_PROPERTY_NAME ,
119
+ () -> Constants .ENABLE_THREADLOCALS
120
+ ? ReusableMessageFactory .INSTANCE
121
+ : ParameterizedMessageFactory .INSTANCE );
122
+ }
123
+
124
+ private static FlowMessageFactory getEffectiveFlowMessageFactory (final FlowMessageFactory flowMessageFactory ) {
125
+ return createInstanceFromFactoryProperty (
126
+ FlowMessageFactory .class ,
127
+ flowMessageFactory ,
128
+ FLOW_MESSAGE_FACTORY_PROPERTY_NAME ,
129
+ () -> DefaultFlowMessageFactory .INSTANCE );
130
+ }
131
+
132
+ private static <V > V createInstanceFromFactoryProperty (
133
+ final Class <V > instanceType ,
134
+ final V providedInstance ,
135
+ final String propertyName ,
136
+ final java .util .function .Supplier <V > fallbackInstanceSupplier ) {
137
+ if (providedInstance != null ) {
138
+ return providedInstance ;
139
+ }
140
+ try {
141
+ return LoaderUtil .newCheckedInstanceOfProperty (propertyName , instanceType , fallbackInstanceSupplier );
142
+ } catch (final Exception error ) {
143
+ final String message =
144
+ String .format ("failed instantiating the class pointed by the `%s` property" , propertyName );
145
+ throw new RuntimeException (message , error );
146
+ }
76
147
}
77
148
78
149
protected Object writeReplace () throws ObjectStreamException {
0 commit comments