1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.util;
18
19 import java.net.URL;
20 import java.security.Permission;
21 import java.util.Collection;
22 import java.util.List;
23
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.spi.LoggerContextFactory;
26 import org.apache.logging.log4j.spi.Provider;
27 import org.apache.logging.log4j.status.StatusLogger;
28 import org.osgi.framework.AdaptPermission;
29 import org.osgi.framework.AdminPermission;
30 import org.osgi.framework.Bundle;
31 import org.osgi.framework.BundleActivator;
32 import org.osgi.framework.BundleContext;
33 import org.osgi.framework.BundleEvent;
34 import org.osgi.framework.InvalidSyntaxException;
35 import org.osgi.framework.ServiceReference;
36 import org.osgi.framework.SynchronousBundleListener;
37 import org.osgi.framework.wiring.BundleWire;
38 import org.osgi.framework.wiring.BundleWiring;
39
40
41
42
43
44
45
46
47 public class Activator implements BundleActivator, SynchronousBundleListener {
48
49 private static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
50
51 private static final Logger LOGGER = StatusLogger.getLogger();
52
53
54
55 private boolean lockingProviderUtil;
56
57 private static void checkPermission(final Permission permission) {
58 if (SECURITY_MANAGER != null) {
59 SECURITY_MANAGER.checkPermission(permission);
60 }
61 }
62
63 private void loadProvider(final Bundle bundle) {
64 if (bundle.getState() == Bundle.UNINSTALLED) {
65 return;
66 }
67 try {
68 checkPermission(new AdminPermission(bundle, AdminPermission.RESOURCE));
69 checkPermission(new AdaptPermission(BundleWiring.class.getName(), bundle, AdaptPermission.ADAPT));
70 final BundleContext bundleContext = bundle.getBundleContext();
71 if (bundleContext == null) {
72 LOGGER.debug("Bundle {} has no context (state={}), skipping loading provider", bundle.getSymbolicName(), toStateString(bundle.getState()));
73 } else {
74 loadProvider(bundleContext, bundle.adapt(BundleWiring.class));
75 }
76 } catch (final SecurityException e) {
77 LOGGER.debug("Cannot access bundle [{}] contents. Ignoring.", bundle.getSymbolicName(), e);
78 } catch (final Exception e) {
79 LOGGER.warn("Problem checking bundle {} for Log4j 2 provider.", bundle.getSymbolicName(), e);
80 }
81 }
82
83 private String toStateString(final int state) {
84 switch (state) {
85 case Bundle.UNINSTALLED:
86 return "UNINSTALLED";
87 case Bundle.INSTALLED:
88 return "INSTALLED";
89 case Bundle.RESOLVED:
90 return "RESOLVED";
91 case Bundle.STARTING:
92 return "STARTING";
93 case Bundle.STOPPING:
94 return "STOPPING";
95 case Bundle.ACTIVE:
96 return "ACTIVE";
97 default:
98 return Integer.toString(state);
99 }
100 }
101
102 private void loadProvider(final BundleContext bundleContext, final BundleWiring bundleWiring) {
103 final String filter = "(APIVersion>=2.6.0)";
104 try {
105 final Collection<ServiceReference<Provider>> serviceReferences = bundleContext.getServiceReferences(Provider.class, filter);
106 Provider maxProvider = null;
107 for (final ServiceReference<Provider> serviceReference : serviceReferences) {
108 final Provider provider = bundleContext.getService(serviceReference);
109 if (maxProvider == null || provider.getPriority() > maxProvider.getPriority()) {
110 maxProvider = provider;
111 }
112 }
113 if (maxProvider != null) {
114 ProviderUtil.addProvider(maxProvider);
115 }
116 } catch (final InvalidSyntaxException ex) {
117 LOGGER.error("Invalid service filter: " + filter, ex);
118 }
119 final List<URL> urls = bundleWiring.findEntries("META-INF", "log4j-provider.properties", 0);
120 for (final URL url : urls) {
121 ProviderUtil.loadProvider(url, bundleWiring.getClassLoader());
122 }
123 }
124
125 @Override
126 public void start(final BundleContext bundleContext) throws Exception {
127 ProviderUtil.STARTUP_LOCK.lock();
128 lockingProviderUtil = true;
129 final BundleWiring self = bundleContext.getBundle().adapt(BundleWiring.class);
130 final List<BundleWire> required = self.getRequiredWires(LoggerContextFactory.class.getName());
131 for (final BundleWire wire : required) {
132 loadProvider(bundleContext, wire.getProviderWiring());
133 }
134 bundleContext.addBundleListener(this);
135 final Bundle[] bundles = bundleContext.getBundles();
136 for (final Bundle bundle : bundles) {
137 loadProvider(bundle);
138 }
139 unlockIfReady();
140 }
141
142 private void unlockIfReady() {
143 if (lockingProviderUtil && !ProviderUtil.PROVIDERS.isEmpty()) {
144 ProviderUtil.STARTUP_LOCK.unlock();
145 lockingProviderUtil = false;
146 }
147 }
148
149 @Override
150 public void stop(final BundleContext bundleContext) throws Exception {
151 bundleContext.removeBundleListener(this);
152 unlockIfReady();
153 }
154
155 @Override
156 public void bundleChanged(final BundleEvent event) {
157 switch (event.getType()) {
158 case BundleEvent.STARTED:
159 loadProvider(event.getBundle());
160 unlockIfReady();
161 break;
162
163 default:
164 break;
165 }
166 }
167
168 }