1818
1919import java .io .FileNotFoundException ;
2020import java .io .IOException ;
21- import java .io .InputStream ;
22- import java .net .URL ;
23- import java .net .URLConnection ;
2421import java .util .ArrayList ;
2522import java .util .Collections ;
2623import java .util .LinkedHashMap ;
3835import org .apache .logging .log4j .core .config .AbstractConfiguration ;
3936import org .apache .logging .log4j .core .config .Configuration ;
4037import org .apache .logging .log4j .core .config .ConfigurationFactory ;
41- import org .apache .logging .log4j .core .config .ConfigurationSource ;
4238import org .apache .logging .log4j .core .config .LoggerConfig ;
4339import org .apache .logging .log4j .core .config .composite .CompositeConfiguration ;
4440import org .apache .logging .log4j .core .filter .DenyAllFilter ;
45- import org .apache .logging .log4j .core .net .UrlConnectionFactory ;
46- import org .apache .logging .log4j .core .net .ssl .SslConfiguration ;
47- import org .apache .logging .log4j .core .net .ssl .SslConfigurationFactory ;
48- import org .apache .logging .log4j .core .util .AuthorizationProvider ;
4941import org .apache .logging .log4j .core .util .NameUtil ;
5042import org .apache .logging .log4j .jul .Log4jBridgeHandler ;
43+ import org .apache .logging .log4j .spi .LoggerContextFactory ;
5144import org .apache .logging .log4j .status .StatusConsoleListener ;
5245import org .apache .logging .log4j .status .StatusLogger ;
5346import org .apache .logging .log4j .util .PropertiesUtil ;
7265import org .springframework .core .io .ResourceLoader ;
7366import org .springframework .util .Assert ;
7467import org .springframework .util .ClassUtils ;
75- import org .springframework .util .CollectionUtils ;
7668import org .springframework .util .StringUtils ;
7769
7870/**
@@ -94,41 +86,6 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem {
9486
9587 private static final String LOG4J_LOG_MANAGER = "org.apache.logging.log4j.jul.LogManager" ;
9688
97- /**
98- * JSON tree parser used by Log4j 2 (optional dependency).
99- */
100- private static final String JSON_TREE_PARSER_V2 = "com.fasterxml.jackson.databind.ObjectMapper" ;
101-
102- /**
103- * JSON tree parser embedded in Log4j 3.
104- */
105- private static final String JSON_TREE_PARSER_V3 = "org.apache.logging.log4j.kit.json.JsonReader" ;
106-
107- /**
108- * Configuration factory for properties files (Log4j 2).
109- */
110- private static final String PROPS_CONFIGURATION_FACTORY_V2 = "org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory" ;
111-
112- /**
113- * Configuration factory for properties files (Log4j 3, optional dependency).
114- */
115- private static final String PROPS_CONFIGURATION_FACTORY_V3 = "org.apache.logging.log4j.config.properties.JavaPropsConfigurationFactory" ;
116-
117- /**
118- * YAML tree parser used by Log4j 2 (optional dependency).
119- */
120- private static final String YAML_TREE_PARSER_V2 = "com.fasterxml.jackson.dataformat.yaml.YAMLMapper" ;
121-
122- /**
123- * Configuration factory for YAML files (Log4j 2, embedded).
124- */
125- private static final String YAML_CONFIGURATION_FACTORY_V2 = "org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory" ;
126-
127- /**
128- * Configuration factory for YAML files (Log4j 3, optional dependency).
129- */
130- private static final String YAML_CONFIGURATION_FACTORY_V3 = "org.apache.logging.log4j.config.yaml.YamlConfigurationFactory" ;
131-
13289 private static final SpringEnvironmentPropertySource propertySource = new SpringEnvironmentPropertySource ();
13390
13491 static final String ENVIRONMENT_KEY = Conventions .getQualifiedAttributeName (Log4J2LoggingSystem .class ,
@@ -151,73 +108,43 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem {
151108
152109 private static final Filter FILTER = DenyAllFilter .newBuilder ().build ();
153110
154- public Log4J2LoggingSystem (ClassLoader classLoader ) {
111+ private final LoggerContext loggerContext ;
112+
113+ private Log4J2LoggingSystem (ClassLoader classLoader , org .apache .logging .log4j .spi .LoggerContext loggerContext ) {
155114 super (classLoader );
115+ this .loggerContext = (LoggerContext ) loggerContext ;
156116 }
157117
118+ /**
119+ * {@inheritDoc}
120+ * @deprecated Since 4.0.0, in favor of the {@link ConfigurationFactory} SPI.
121+ */
158122 @ Override
123+ @ Deprecated (since = "4.0.0" , forRemoval = true )
159124 protected String [] getStandardConfigLocations () {
160- List <String > locations = new ArrayList <>();
161- addLocationsFromProperties (locations );
162- addStandardLocations (locations );
163- return StringUtils .toStringArray (locations );
164- }
165-
166- private void addLocationsFromProperties (List <String > locations ) {
167- for (String property : List .of ("log4j2.configurationFile" , "log4j.configuration.location" )) {
168- String propertyDefinedLocation = PropertiesUtil .getProperties ().getStringProperty (property );
169- if (propertyDefinedLocation != null ) {
170- locations .add (propertyDefinedLocation );
171- }
172- }
125+ return new String [] { "log4j2.xml" };
173126 }
174127
175- private void addStandardLocations (List <String > locations ) {
176- LoggerContext loggerContext = getLoggerContext ();
177- String contextName = loggerContext .getName ();
178- List <String > extensions = getStandardConfigExtensions ();
179- addLocation (locations , "log4j2-test" + contextName , extensions );
180- addLocation (locations , "log4j2-test" , extensions );
181- addLocation (locations , "log4j2" + contextName , extensions );
182- addLocation (locations , "log4j2" , extensions );
183- }
184-
185- private List <String > getStandardConfigExtensions () {
186- List <String > extensions = new ArrayList <>();
187- // These classes need to be visible by the classloader that loads Log4j Core.
188- ClassLoader classLoader = LoggerContext .class .getClassLoader ();
189- // The order of the extensions corresponds to the order in which Log4j Core 2 and
190- // 3 will try to load them, in decreasing value of @Order.
191- if (isPresent (classLoader , PROPS_CONFIGURATION_FACTORY_V2 )
192- || isPresent (classLoader , PROPS_CONFIGURATION_FACTORY_V3 )) {
193- extensions .add (".properties" );
194- }
195- if (isPresent (classLoader , YAML_CONFIGURATION_FACTORY_V2 , YAML_TREE_PARSER_V2 )
196- || isPresent (classLoader , YAML_CONFIGURATION_FACTORY_V3 )) {
197- Collections .addAll (extensions , ".yaml" , ".yml" );
198- }
199- if (isPresent (classLoader , JSON_TREE_PARSER_V2 ) || isPresent (classLoader , JSON_TREE_PARSER_V3 )) {
200- Collections .addAll (extensions , ".json" , ".jsn" );
201- }
202- extensions .add (".xml" );
203- return extensions ;
204- }
205-
206- private void addLocation (List <String > locations , String location , List <String > extensions ) {
207- extensions .forEach ((extension ) -> locations .add (location + extension ));
128+ @ Override
129+ protected @ Nullable String getSelfInitializationConfig () {
130+ Configuration currentConfiguration = getLoggerContext ().getConfiguration ();
131+ return getConfigLocation (currentConfiguration );
208132 }
209133
210- private boolean isPresent (ClassLoader classLoader , String ... classNames ) {
211- for (String className : classNames ) {
212- if (!isClassAvailable (classLoader , className )) {
213- return false ;
214- }
215- }
216- return true ;
134+ @ Override
135+ protected @ Nullable String getSpringInitializationConfig () {
136+ ConfigurationFactory configurationFactory = ConfigurationFactory .getInstance ();
137+ Configuration springConfiguration = configurationFactory .getConfiguration (getLoggerContext (), "-spring" , null ,
138+ getClassLoader ());
139+ return getConfigLocation (springConfiguration );
217140 }
218141
219- protected boolean isClassAvailable (ClassLoader classLoader , String className ) {
220- return ClassUtils .isPresent (className , classLoader );
142+ private @ Nullable String getConfigLocation (Configuration configuration ) {
143+ // The location may be:
144+ // - null: if DefaultConfiguration is used (no explicit config loaded)
145+ // - a file path: if provided explicitly by the user
146+ // - a URI: if loaded from the classpath default or a custom location
147+ return configuration .getConfigurationSource ().getLocation ();
221148 }
222149
223150 @ Deprecated (since = "4.0.0" , forRemoval = true )
@@ -329,7 +256,7 @@ private void load(LoggingInitializationContext initializationContext, String loc
329256 Environment environment = initializationContext .getEnvironment ();
330257 Assert .state (environment != null , "'environment' must not be null" );
331258 applySystemProperties (environment , logFile );
332- loadConfiguration (location , logFile , overrides );
259+ reconfigure (location , overrides );
333260 }
334261
335262 private List <String > getOverrides (LoggingInitializationContext initializationContext ) {
@@ -340,66 +267,43 @@ private List<String> getOverrides(LoggingInitializationContext initializationCon
340267 return overrides .orElse (Collections .emptyList ());
341268 }
342269
343- /**
344- * Load the configuration from the given {@code location}, creating a composite using
345- * the configuration from the given {@code overrides}.
346- * @param location the location
347- * @param logFile log file configuration
348- * @param overrides the overriding locations
349- * @since 2.6.0
350- */
351- protected void loadConfiguration (String location , @ Nullable LogFile logFile , List <String > overrides ) {
270+ private void reconfigure (String location , List <String > overrides ) {
352271 Assert .notNull (location , "'location' must not be null" );
353272 try {
354273 List <Configuration > configurations = new ArrayList <>();
355- LoggerContext context = getLoggerContext ();
356- ResourceLoader resourceLoader = ApplicationResourceLoader .get ();
357- configurations .add (load (resourceLoader .getResource (location ), context ));
274+ ResourceLoader resourceLoader = ApplicationResourceLoader .get (getClassLoader ());
275+ configurations .add (load (resourceLoader , location ));
358276 for (String override : overrides ) {
359- Configuration overrideConfiguration = loadOverride (resourceLoader , override , context );
277+ Configuration overrideConfiguration = loadOverride (resourceLoader , override );
360278 if (overrideConfiguration != null ) {
361279 configurations .add (overrideConfiguration );
362280 }
363281 }
364- context . start (mergeConfigurations (configurations ));
282+ this . loggerContext . reconfigure (mergeConfigurations (configurations ));
365283 }
366284 catch (Exception ex ) {
367285 throw new IllegalStateException ("Could not initialize Log4J2 logging from " + location , ex );
368286 }
369287 }
370288
371- private Configuration load (Resource resource , LoggerContext context ) throws IOException {
289+ private Configuration load (ResourceLoader resourceLoader , String location ) throws IOException {
372290 ConfigurationFactory factory = ConfigurationFactory .getInstance ();
373- if (resource .isFile ()) {
374- try (InputStream inputStream = resource .getInputStream ()) {
375- return factory .getConfiguration (context , new ConfigurationSource (inputStream , resource .getFile ()));
376- }
377- }
378- URL url = resource .getURL ();
379- AuthorizationProvider authorizationProvider = ConfigurationFactory
380- .authorizationProvider (PropertiesUtil .getProperties ());
381- SslConfiguration sslConfiguration = url .getProtocol ().equals ("https" )
382- ? SslConfigurationFactory .getSslConfiguration () : null ;
383- URLConnection connection = UrlConnectionFactory .createConnection (url , 0 , sslConfiguration ,
384- authorizationProvider );
385- try (InputStream inputStream = connection .getInputStream ()) {
386- return factory .getConfiguration (context ,
387- new ConfigurationSource (inputStream , url , connection .getLastModified ()));
388- }
291+ Resource resource = resourceLoader .getResource (location );
292+ return factory .getConfiguration (getLoggerContext (), null , resource .getURI (), getClassLoader ());
389293 }
390294
391- private @ Nullable Configuration loadOverride (ResourceLoader resourceLoader , String location , LoggerContext context )
392- throws IOException {
295+ private @ Nullable Configuration loadOverride (ResourceLoader resourceLoader , String location ) throws IOException {
393296 if (location .startsWith (OPTIONAL_PREFIX )) {
394- Resource resource = resourceLoader .getResource (location .substring (OPTIONAL_PREFIX .length ()));
297+ String actualLocation = location .substring (OPTIONAL_PREFIX .length ());
298+ Resource resource = resourceLoader .getResource (actualLocation );
395299 try {
396- return (resource .exists ()) ? load (resource , context ) : null ;
300+ return (resource .exists ()) ? load (resourceLoader , actualLocation ) : null ;
397301 }
398302 catch (FileNotFoundException ex ) {
399303 return null ;
400304 }
401305 }
402- return load (resourceLoader . getResource ( location ), context );
306+ return load (resourceLoader , location );
403307 }
404308
405309 private Configuration mergeConfigurations (List <Configuration > configurations ) {
@@ -411,33 +315,11 @@ private Configuration mergeConfigurations(List<Configuration> configurations) {
411315
412316 @ Override
413317 protected void reinitialize (LoggingInitializationContext initializationContext ) {
414- List <String > overrides = getOverrides (initializationContext );
415- if (!CollectionUtils .isEmpty (overrides )) {
416- reinitializeWithOverrides (overrides );
417- }
418- else {
419- LoggerContext context = getLoggerContext ();
420- context .reconfigure ();
421- }
422- }
423-
424- private void reinitializeWithOverrides (List <String > overrides ) {
425- LoggerContext context = getLoggerContext ();
426- List <Configuration > configurations = new ArrayList <>();
427- configurations .add (context .getConfiguration ());
428- ResourceLoader resourceLoader = ApplicationResourceLoader .get ();
429- for (String override : overrides ) {
430- try {
431- Configuration overrideConfiguration = loadOverride (resourceLoader , override , context );
432- if (overrideConfiguration != null ) {
433- configurations .add (overrideConfiguration );
434- }
435- }
436- catch (IOException ex ) {
437- throw new RuntimeException ("Failed to load overriding configuration from '" + override + "'" , ex );
438- }
439- }
440- context .reconfigure (mergeConfigurations (configurations ));
318+ String currentLocation = getSelfInitializationConfig ();
319+ // `reinitialize` is only triggered when `getSelfInitializationConfig` returns a
320+ // non-null value
321+ Assert .notNull (currentLocation , "'currentLocation' must not be null" );
322+ load (initializationContext , currentLocation , null );
441323 }
442324
443325 @ Override
@@ -579,7 +461,7 @@ public void cleanUp() {
579461 }
580462
581463 private LoggerContext getLoggerContext () {
582- return ( LoggerContext ) LogManager . getContext ( false ) ;
464+ return this . loggerContext ;
583465 }
584466
585467 private boolean isAlreadyInitialized (LoggerContext loggerContext ) {
@@ -614,15 +496,20 @@ protected String getDefaultLogCorrelationPattern() {
614496 * {@link LoggingSystemFactory} that returns {@link Log4J2LoggingSystem} if possible.
615497 */
616498 @ Order (0 )
617- public static class Factory implements LoggingSystemFactory {
499+ public static class Factory extends LogManager implements LoggingSystemFactory {
500+
501+ private static final String FQCN = Factory .class .getName ();
618502
619- private static final boolean PRESENT = ClassUtils
620- .isPresent ("org.apache.logging.log4j.core.impl.Log4jContextFactory" , Factory .class .getClassLoader ());
503+ private static final String LOG4J_CORE_CONTEXT_FACTORY = "org.apache.logging.log4j.core.impl.Log4jContextFactory" ;
621504
622505 @ Override
623506 public @ Nullable LoggingSystem getLoggingSystem (ClassLoader classLoader ) {
624- if (PRESENT ) {
625- return new Log4J2LoggingSystem (classLoader );
507+ LoggerContextFactory contextFactory = getFactory ();
508+ // At the same time, we check that Log4j Core is present and that it is the
509+ // active
510+ // implementation.
511+ if (LOG4J_CORE_CONTEXT_FACTORY .equals (contextFactory .getClass ().getName ())) {
512+ return new Log4J2LoggingSystem (classLoader , contextFactory .getContext (FQCN , classLoader , null , false ));
626513 }
627514 return null ;
628515 }
0 commit comments