1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.osgi;
18
19 import java.lang.ref.WeakReference;
20 import java.net.URI;
21 import java.util.Objects;
22 import java.util.concurrent.atomic.AtomicReference;
23
24 import org.apache.logging.log4j.core.LoggerContext;
25 import org.apache.logging.log4j.core.impl.ContextAnchor;
26 import org.apache.logging.log4j.core.selector.ClassLoaderContextSelector;
27 import org.apache.logging.log4j.util.ReflectionUtil;
28 import org.osgi.framework.Bundle;
29 import org.osgi.framework.BundleReference;
30 import org.osgi.framework.FrameworkUtil;
31
32
33
34
35
36
37
38
39 public class BundleContextSelector extends ClassLoaderContextSelector {
40
41 @Override
42 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
43 final URI configLocation) {
44 if (currentContext) {
45 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
46 if (ctx != null) {
47 return ctx;
48 }
49 return getDefault();
50 }
51
52 if (loader instanceof BundleReference) {
53 return locateContext(((BundleReference) loader).getBundle(), configLocation);
54 }
55 final Class<?> callerClass = ReflectionUtil.getCallerClass(fqcn);
56 if (callerClass != null) {
57 return locateContext(FrameworkUtil.getBundle(callerClass), configLocation);
58 }
59 final LoggerContext lc = ContextAnchor.THREAD_CONTEXT.get();
60 return lc == null ? getDefault() : lc;
61 }
62
63 private static LoggerContext locateContext(final Bundle bundle, final URI configLocation) {
64 final String name = Objects.requireNonNull(bundle, "No Bundle provided").getSymbolicName();
65 final AtomicReference<WeakReference<LoggerContext>> ref = CONTEXT_MAP.get(name);
66 if (ref == null) {
67 final LoggerContext context = new LoggerContext(name, bundle, configLocation);
68 CONTEXT_MAP.putIfAbsent(name,
69 new AtomicReference<>(new WeakReference<>(context)));
70 return CONTEXT_MAP.get(name).get().get();
71 }
72 final WeakReference<LoggerContext> r = ref.get();
73 final LoggerContext ctx = r.get();
74 if (ctx == null) {
75 final LoggerContext context = new LoggerContext(name, bundle, configLocation);
76 ref.compareAndSet(r, new WeakReference<>(context));
77 return ref.get().get();
78 }
79 final URI oldConfigLocation = ctx.getConfigLocation();
80 if (oldConfigLocation == null && configLocation != null) {
81 LOGGER.debug("Setting bundle ({}) configuration to {}", name, configLocation);
82 ctx.setConfigLocation(configLocation);
83 } else if (oldConfigLocation != null && configLocation != null && !configLocation.equals(oldConfigLocation)) {
84 LOGGER.warn("locateContext called with URI [{}], but existing LoggerContext has URI [{}]",
85 configLocation, oldConfigLocation);
86 }
87 return ctx;
88 }
89 }