1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.lookup;
18
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Locale;
22 import java.util.Map;
23
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.config.ConfigurationAware;
27 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
28 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
29 import org.apache.logging.log4j.core.util.Loader;
30 import org.apache.logging.log4j.core.util.ReflectionUtil;
31 import org.apache.logging.log4j.status.StatusLogger;
32 import org.apache.logging.log4j.util.Constants;
33
34
35
36
37 public class Interpolator extends AbstractConfigurationAwareLookup {
38
39
40 public static final char PREFIX_SEPARATOR = ':';
41
42 private static final String LOOKUP_KEY_WEB = "web";
43
44 private static final String LOOKUP_KEY_DOCKER = "docker";
45
46 private static final String LOOKUP_KEY_KUBERNETES = "kubernetes";
47
48 private static final String LOOKUP_KEY_SPRING = "spring";
49
50 private static final String LOOKUP_KEY_JNDI = "jndi";
51
52 private static final String LOOKUP_KEY_JVMRUNARGS = "jvmrunargs";
53
54 private static final Logger LOGGER = StatusLogger.getLogger();
55
56 private final Map<String, StrLookup> strLookupMap = new HashMap<>();
57
58 private final StrLookup defaultLookup;
59
60 public Interpolator(final StrLookup defaultLookup) {
61 this(defaultLookup, null);
62 }
63
64
65
66
67
68
69
70
71 public Interpolator(final StrLookup defaultLookup, final List<String> pluginPackages) {
72 this.defaultLookup = defaultLookup == null ? new MapLookup(new HashMap<String, String>()) : defaultLookup;
73 final PluginManager manager = new PluginManager(CATEGORY);
74 manager.collectPlugins(pluginPackages);
75 final Map<String, PluginType<?>> plugins = manager.getPlugins();
76
77 for (final Map.Entry<String, PluginType<?>> entry : plugins.entrySet()) {
78 try {
79 final Class<? extends StrLookup> clazz = entry.getValue().getPluginClass().asSubclass(StrLookup.class);
80 strLookupMap.put(entry.getKey().toLowerCase(), ReflectionUtil.instantiate(clazz));
81 } catch (final Throwable t) {
82 handleError(entry.getKey(), t);
83 }
84 }
85 }
86
87
88
89
90 public Interpolator() {
91 this((Map<String, String>) null);
92 }
93
94
95
96
97 public Interpolator(final Map<String, String> properties) {
98 this.defaultLookup = new MapLookup(properties == null ? new HashMap<String, String>() : properties);
99
100 strLookupMap.put("log4j", new Log4jLookup());
101 strLookupMap.put("sys", new SystemPropertiesLookup());
102 strLookupMap.put("env", new EnvironmentLookup());
103 strLookupMap.put("main", MainMapLookup.MAIN_SINGLETON);
104 strLookupMap.put("marker", new MarkerLookup());
105 strLookupMap.put("java", new JavaLookup());
106 strLookupMap.put("lower", new LowerLookup());
107 strLookupMap.put("upper", new UpperLookup());
108
109 try {
110
111 strLookupMap.put(LOOKUP_KEY_JNDI,
112 Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JndiLookup", StrLookup.class));
113 } catch (final LinkageError | Exception e) {
114 handleError(LOOKUP_KEY_JNDI, e);
115 }
116
117 try {
118
119 strLookupMap.put(LOOKUP_KEY_JVMRUNARGS,
120 Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup",
121 StrLookup.class));
122 } catch (final LinkageError | Exception e) {
123 handleError(LOOKUP_KEY_JVMRUNARGS, e);
124 }
125 strLookupMap.put("date", new DateLookup());
126 strLookupMap.put("ctx", new ContextMapLookup());
127 if (Constants.IS_WEB_APP) {
128 try {
129 strLookupMap.put(LOOKUP_KEY_WEB,
130 Loader.newCheckedInstanceOf("org.apache.logging.log4j.web.WebLookup", StrLookup.class));
131 } catch (final Exception ignored) {
132 handleError(LOOKUP_KEY_WEB, ignored);
133 }
134 } else {
135 LOGGER.debug("Not in a ServletContext environment, thus not loading WebLookup plugin.");
136 }
137 try {
138 strLookupMap.put(LOOKUP_KEY_DOCKER,
139 Loader.newCheckedInstanceOf("org.apache.logging.log4j.docker.DockerLookup", StrLookup.class));
140 } catch (final Exception ignored) {
141 handleError(LOOKUP_KEY_DOCKER, ignored);
142 }
143 try {
144 strLookupMap.put(LOOKUP_KEY_SPRING,
145 Loader.newCheckedInstanceOf("org.apache.logging.log4j.spring.cloud.config.client.SpringLookup", StrLookup.class));
146 } catch (final Exception ignored) {
147 handleError(LOOKUP_KEY_SPRING, ignored);
148 }
149 try {
150 strLookupMap.put(LOOKUP_KEY_KUBERNETES,
151 Loader.newCheckedInstanceOf("org.apache.logging.log4j.kubernetes.KubernetesLookup", StrLookup.class));
152 } catch (final Exception ignored) {
153 handleError(LOOKUP_KEY_KUBERNETES, ignored);
154 } catch (final NoClassDefFoundError error) {
155 handleError(LOOKUP_KEY_KUBERNETES, error);
156 }
157 }
158
159 public Map<String, StrLookup> getStrLookupMap() {
160 return strLookupMap;
161 }
162
163 private void handleError(final String lookupKey, final Throwable t) {
164 switch (lookupKey) {
165 case LOOKUP_KEY_JNDI:
166
167 LOGGER.warn(
168 "JNDI lookup class is not available because this JRE does not support JNDI." +
169 " JNDI string lookups will not be available, continuing configuration. Ignoring " + t);
170 break;
171 case LOOKUP_KEY_JVMRUNARGS:
172
173 LOGGER.warn(
174 "JMX runtime input lookup class is not available because this JRE does not support JMX. " +
175 "JMX lookups will not be available, continuing configuration. Ignoring " + t);
176 break;
177 case LOOKUP_KEY_WEB:
178 LOGGER.info("Log4j appears to be running in a Servlet environment, but there's no log4j-web module " +
179 "available. If you want better web container support, please add the log4j-web JAR to your " +
180 "web archive or server lib directory.");
181 break;
182 case LOOKUP_KEY_DOCKER: case LOOKUP_KEY_SPRING:
183 break;
184 case LOOKUP_KEY_KUBERNETES:
185 if (t instanceof NoClassDefFoundError) {
186 LOGGER.warn("Unable to create Kubernetes lookup due to missing dependency: {}", t.getMessage());
187 }
188 break;
189 default:
190 LOGGER.error("Unable to create Lookup for {}", lookupKey, t);
191 }
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 @Override
208 public String lookup(final LogEvent event, String var) {
209 if (var == null) {
210 return null;
211 }
212
213 final int prefixPos = var.indexOf(PREFIX_SEPARATOR);
214 if (prefixPos >= 0) {
215 final String prefix = var.substring(0, prefixPos).toLowerCase(Locale.US);
216 final String name = var.substring(prefixPos + 1);
217 final StrLookup lookup = strLookupMap.get(prefix);
218 if (lookup instanceof ConfigurationAware) {
219 ((ConfigurationAware) lookup).setConfiguration(configuration);
220 }
221 String value = null;
222 if (lookup != null) {
223 value = event == null ? lookup.lookup(name) : lookup.lookup(event, name);
224 }
225
226 if (value != null) {
227 return value;
228 }
229 var = var.substring(prefixPos + 1);
230 }
231 if (defaultLookup != null) {
232 return event == null ? defaultLookup.lookup(var) : defaultLookup.lookup(event, var);
233 }
234 return null;
235 }
236
237 @Override
238 public String toString() {
239 final StringBuilder sb = new StringBuilder();
240 for (final String name : strLookupMap.keySet()) {
241 if (sb.length() == 0) {
242 sb.append('{');
243 } else {
244 sb.append(", ");
245 }
246
247 sb.append(name);
248 }
249 if (sb.length() > 0) {
250 sb.append('}');
251 }
252 return sb.toString();
253 }
254
255 }