1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.impl;
18
19 import java.net.URI;
20
21 import org.apache.logging.log4j.core.LifeCycle;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configuration;
24 import org.apache.logging.log4j.core.config.ConfigurationFactory;
25 import org.apache.logging.log4j.core.config.ConfigurationSource;
26 import org.apache.logging.log4j.core.selector.ClassLoaderContextSelector;
27 import org.apache.logging.log4j.core.selector.ContextSelector;
28 import org.apache.logging.log4j.core.util.Assert;
29 import org.apache.logging.log4j.core.util.Cancellable;
30 import org.apache.logging.log4j.core.util.Constants;
31 import org.apache.logging.log4j.core.util.DefaultShutdownCallbackRegistry;
32 import org.apache.logging.log4j.core.util.Loader;
33 import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
34 import org.apache.logging.log4j.spi.LoggerContextFactory;
35 import org.apache.logging.log4j.status.StatusLogger;
36 import org.apache.logging.log4j.util.PropertiesUtil;
37
38
39
40
41 public class Log4jContextFactory implements LoggerContextFactory, ShutdownCallbackRegistry {
42
43 private static final StatusLogger LOGGER = StatusLogger.getLogger();
44 private static final boolean SHUTDOWN_HOOK_ENABLED =
45 PropertiesUtil.getProperties().getBooleanProperty(ShutdownCallbackRegistry.SHUTDOWN_HOOK_ENABLED, true);
46
47 private final ContextSelector selector;
48 private final ShutdownCallbackRegistry shutdownCallbackRegistry;
49
50
51
52
53 public Log4jContextFactory() {
54 this(createContextSelector(), createShutdownCallbackRegistry());
55 }
56
57
58
59
60
61 public Log4jContextFactory(final ContextSelector selector) {
62 this(selector, createShutdownCallbackRegistry());
63 }
64
65
66
67
68
69
70
71
72 public Log4jContextFactory(final ShutdownCallbackRegistry shutdownCallbackRegistry) {
73 this(createContextSelector(), shutdownCallbackRegistry);
74 }
75
76
77
78
79
80
81
82
83 public Log4jContextFactory(final ContextSelector selector,
84 final ShutdownCallbackRegistry shutdownCallbackRegistry) {
85 this.selector = Assert.requireNonNull(selector, "No ContextSelector provided");
86 this.shutdownCallbackRegistry = Assert.requireNonNull(shutdownCallbackRegistry,
87 "No ShutdownCallbackRegistry provided");
88 LOGGER.debug("Using ShutdownCallbackRegistry {}", shutdownCallbackRegistry.getClass());
89 initializeShutdownCallbackRegistry();
90 }
91
92 private static ContextSelector createContextSelector() {
93 final String sel = PropertiesUtil.getProperties().getStringProperty(Constants.LOG4J_CONTEXT_SELECTOR);
94 if (sel != null) {
95 try {
96 return Loader.newCheckedInstanceOf(sel, ContextSelector.class);
97 } catch (final Exception ex) {
98 LOGGER.error("Unable to create context {}", sel, ex);
99 }
100 }
101 return new ClassLoaderContextSelector();
102 }
103
104 private static ShutdownCallbackRegistry createShutdownCallbackRegistry() {
105
106 final String registry = PropertiesUtil.getProperties().getStringProperty(
107 ShutdownCallbackRegistry.SHUTDOWN_CALLBACK_REGISTRY);
108 if (registry != null) {
109 try {
110 return Loader.newCheckedInstanceOf(registry, ShutdownCallbackRegistry.class);
111 } catch (final Exception e) {
112 LOGGER.error(SHUTDOWN_HOOK_MARKER,
113 "There was an error loading the ShutdownCallbackRegistry [{}]. "
114 + "Falling back to DefaultShutdownCallbackRegistry.", registry, e);
115 }
116 }
117 return new DefaultShutdownCallbackRegistry();
118 }
119
120 private void initializeShutdownCallbackRegistry() {
121 if (SHUTDOWN_HOOK_ENABLED && this.shutdownCallbackRegistry instanceof LifeCycle) {
122 try {
123 ((LifeCycle) this.shutdownCallbackRegistry).start();
124 } catch (final Exception e) {
125 LOGGER.error("There was an error starting the ShutdownCallbackRegistry.", e);
126 }
127 }
128 }
129
130
131
132
133
134
135
136
137
138
139 @Override
140 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
141 final boolean currentContext) {
142 final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext);
143 if (externalContext != null && ctx.getExternalContext() == null) {
144 ctx.setExternalContext(externalContext);
145 }
146 if (ctx.getState() == LifeCycle.State.INITIALIZED) {
147 ctx.start();
148 }
149 return ctx;
150 }
151
152
153
154
155
156
157
158
159
160
161
162 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
163 final boolean currentContext, final ConfigurationSource source) {
164 final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, null);
165 if (externalContext != null && ctx.getExternalContext() == null) {
166 ctx.setExternalContext(externalContext);
167 }
168 if (ctx.getState() == LifeCycle.State.INITIALIZED) {
169 if (source != null) {
170 ContextAnchor.THREAD_CONTEXT.set(ctx);
171 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(source);
172 LOGGER.debug("Starting LoggerContext[name={}] from configuration {}", ctx.getName(), source);
173 ctx.start(config);
174 ContextAnchor.THREAD_CONTEXT.remove();
175 } else {
176 ctx.start();
177 }
178 }
179 return ctx;
180 }
181
182
183
184
185
186
187
188
189
190
191
192 @Override
193 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
194 final boolean currentContext, final URI configLocation, final String name) {
195 final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, configLocation);
196 if (externalContext != null && ctx.getExternalContext() == null) {
197 ctx.setExternalContext(externalContext);
198 }
199 if (ctx.getState() == LifeCycle.State.INITIALIZED) {
200 if (configLocation != null || name != null) {
201 ContextAnchor.THREAD_CONTEXT.set(ctx);
202 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(name, configLocation);
203 LOGGER.debug("Starting LoggerContext[name={}] from configuration at {}", ctx.getName(), configLocation);
204 ctx.start(config);
205 ContextAnchor.THREAD_CONTEXT.remove();
206 } else {
207 ctx.start();
208 }
209 }
210 return ctx;
211 }
212
213
214
215
216
217 public ContextSelector getSelector() {
218 return selector;
219 }
220
221
222
223
224
225
226 @Override
227 public void removeContext(final org.apache.logging.log4j.spi.LoggerContext context) {
228 if (context instanceof LoggerContext) {
229 selector.removeContext((LoggerContext) context);
230 }
231 }
232
233 @Override
234 public Cancellable addShutdownCallback(final Runnable callback) {
235 return SHUTDOWN_HOOK_ENABLED ? shutdownCallbackRegistry.addShutdownCallback(callback) : null;
236 }
237 }