View Javadoc

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  package org.apache.logging.log4j.core.impl;
18  
19  import java.net.URI;
20  
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.ConfigurationFactory;
24  import org.apache.logging.log4j.core.helpers.Constants;
25  import org.apache.logging.log4j.core.helpers.Loader;
26  import org.apache.logging.log4j.core.selector.ClassLoaderContextSelector;
27  import org.apache.logging.log4j.core.selector.ContextSelector;
28  import org.apache.logging.log4j.spi.LoggerContextFactory;
29  import org.apache.logging.log4j.status.StatusLogger;
30  import org.apache.logging.log4j.util.PropertiesUtil;
31  
32  /**
33   * Factory to locate a ContextSelector and then load a LoggerContext.
34   */
35  public class Log4jContextFactory implements LoggerContextFactory {
36  
37      private static final StatusLogger LOGGER = StatusLogger.getLogger();
38  
39      private ContextSelector selector;
40  
41      /**
42       * Constructor that initializes the ContextSelector.
43       */
44      public Log4jContextFactory() {
45          final String sel = PropertiesUtil.getProperties().getStringProperty(Constants.LOG4J_CONTEXT_SELECTOR);
46          if (sel != null) {
47              try {
48                  final Class<?> clazz = Loader.loadClass(sel);
49                  if (clazz != null && ContextSelector.class.isAssignableFrom(clazz)) {
50                      selector = (ContextSelector) clazz.newInstance();
51                  }
52              } catch (final Exception ex) {
53                  LOGGER.error("Unable to create context " + sel, ex);
54              }
55          }
56          if (selector == null) {
57              selector = new ClassLoaderContextSelector();
58          }
59      }
60  
61      /**
62       * Returns the ContextSelector.
63       * @return The ContextSelector.
64       */
65      public ContextSelector getSelector() {
66          return selector;
67      }
68  
69      /**
70       * Load the LoggerContext using the ContextSelector.
71       * @param fqcn The fully qualified class name of the caller.
72       * @param loader The ClassLoader to use or null.
73       * @param currentContext If true returns the current Context, if false returns the Context appropriate
74       * for the caller if a more appropriate Context can be determined.
75       * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
76       * @return The LoggerContext.
77       */
78      @Override
79      public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
80                                      final boolean currentContext) {
81          final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext);
82          ctx.setExternalContext(externalContext);
83          if (ctx.getStatus() == LoggerContext.Status.INITIALIZED) {
84              ctx.start();
85          }
86          return ctx;
87      }
88  
89      /**
90       * Load the LoggerContext using the ContextSelector.
91       * @param fqcn The fully qualified class name of the caller.
92       * @param loader The ClassLoader to use or null.
93       * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
94       * @param currentContext If true returns the current Context, if false returns the Context appropriate
95       * for the caller if a more appropriate Context can be determined.
96       * @param configLocation The location of the configuration for the LoggerContext.
97       * @return The LoggerContext.
98       */
99      @Override
100     public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
101                                     final boolean currentContext, final URI configLocation, final String name) {
102         final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, configLocation);
103         if (externalContext != null && ctx.getExternalContext() == null) {
104             ctx.setExternalContext(externalContext);
105         }
106         if (ctx.getStatus() == LoggerContext.Status.INITIALIZED) {
107             if (configLocation != null || name != null) {
108                 ContextAnchor.THREAD_CONTEXT.set(ctx);
109                 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(name, configLocation);
110                 ctx.start(config);
111                 ContextAnchor.THREAD_CONTEXT.remove();
112             } else {
113                 ctx.start();
114             }
115         }
116         return ctx;
117     }
118 
119     /**
120      * Load the LoggerContext using the ContextSelector.
121      * @param fqcn The fully qualified class name of the caller.
122      * @param loader The ClassLoader to use or null.
123      * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
124      * @param currentContext If true returns the current Context, if false returns the Context appropriate
125      * for the caller if a more appropriate Context can be determined.
126      * @param source The configuration source.
127      * @return The LoggerContext.
128      */
129     public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
130                                     final boolean currentContext, final ConfigurationFactory.ConfigurationSource source) {
131         final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, null);
132         if (externalContext != null && ctx.getExternalContext() == null) {
133             ctx.setExternalContext(externalContext);
134         }
135         if (ctx.getStatus() == LoggerContext.Status.INITIALIZED) {
136             if (source != null) {
137                 ContextAnchor.THREAD_CONTEXT.set(ctx);
138                 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(source);
139                 ctx.start(config);
140                 ContextAnchor.THREAD_CONTEXT.remove();
141             } else {
142                 ctx.start();
143             }
144         }
145         return ctx;
146     }
147 
148 
149 
150     /**
151      * Removes knowledge of a LoggerContext.
152      *
153      * @param context The context to remove.
154      */
155     @Override
156     public void removeContext(final org.apache.logging.log4j.spi.LoggerContext context) {
157         if (context instanceof LoggerContext) {
158             selector.removeContext((LoggerContext) context);
159         }
160     }
161 }