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