1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.config.properties;
18
19 import org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.core.config.ConfigurationException;
21 import org.apache.logging.log4j.core.config.ConfigurationFactory;
22 import org.apache.logging.log4j.core.config.ConfigurationSource;
23 import org.apache.logging.log4j.core.config.LoggerConfig;
24 import org.apache.logging.log4j.core.config.Order;
25 import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
26 import org.apache.logging.log4j.core.config.builder.api.AppenderRefComponentBuilder;
27 import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
28 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
29 import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
30 import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
31 import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
32 import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
33 import org.apache.logging.log4j.core.config.builder.api.ScriptComponentBuilder;
34 import org.apache.logging.log4j.core.config.builder.api.ScriptFileComponentBuilder;
35 import org.apache.logging.log4j.core.config.plugins.Plugin;
36 import org.apache.logging.log4j.util.PropertiesUtil;
37 import org.apache.logging.log4j.util.Strings;
38
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.util.Properties;
42
43
44
45
46
47
48 @Plugin(name = "PropertiesConfigurationFactory", category = ConfigurationFactory.CATEGORY)
49 @Order(8)
50 public class PropertiesConfigurationFactory extends ConfigurationFactory {
51 private static final String ADVERTISER_KEY = "advertiser";
52 private static final String STATUS_KEY = "status";
53 private static final String SHUTDOWN_HOOK = "shutdownHook";
54 private static final String VERBOSE = "verbose";
55 private static final String PACKAGES = "packages";
56 private static final String CONFIG_NAME = "name";
57 private static final String MONITOR_INTERVAL = "monitorInterval";
58 private static final String CONFIG_TYPE = "type";
59
60 @Override
61 protected String[] getSupportedTypes() {
62 return new String[] {".properties"};
63 }
64
65 @Override
66 public PropertiesConfiguration getConfiguration(ConfigurationSource source) {
67 final InputStream configStream = source.getInputStream();
68 Properties properties = new Properties();
69 try {
70 properties.load(configStream);
71 } catch (IOException ioe) {
72 throw new ConfigurationException("Unable to load " + source.toString(), ioe);
73 }
74 ConfigurationBuilder<PropertiesConfiguration> builder = newConfigurationBuilder(PropertiesConfiguration.class);
75 String value = properties.getProperty(STATUS_KEY);
76 if (value != null) {
77 builder.setStatusLevel(Level.toLevel(value, Level.ERROR));
78 } else {
79 builder.setStatusLevel(Level.ERROR);
80 }
81 value = properties.getProperty(SHUTDOWN_HOOK);
82 if (value != null) {
83 builder.setShutdownHook(value);
84 }
85 value = properties.getProperty(VERBOSE);
86 if (value != null) {
87 builder.setVerbosity(value);
88 }
89 value = properties.getProperty(PACKAGES);
90 if (value != null) {
91 builder.setPackages(value);
92 }
93 value = properties.getProperty(CONFIG_NAME);
94 if (value != null) {
95 builder.setConfigurationName(value);
96 }
97 value = properties.getProperty(MONITOR_INTERVAL);
98 if (value != null) {
99 builder.setMonitorInterval(value);
100 }
101 value = properties.getProperty(ADVERTISER_KEY);
102 if (value != null) {
103 builder.setAdvertiser(value);
104 }
105 Properties props = PropertiesUtil.extractSubset(properties, "property");
106 for (String key : props.stringPropertyNames()) {
107 builder.addProperty(key, props.getProperty(key));
108 }
109
110 String scriptProp = properties.getProperty("scripts");
111 if (scriptProp != null) {
112 String[] scriptNames = scriptProp.split(",");
113 for (String scriptName : scriptNames) {
114 String name = scriptName.trim();
115 Properties scriptProps = PropertiesUtil.extractSubset(properties, "script." + name);
116 String type = scriptProps.getProperty("type");
117 if (type == null) {
118 throw new ConfigurationException("No type provided for script - must be Script or ScriptFile");
119 }
120 scriptProps.remove("type");
121 if (type.equalsIgnoreCase("script")) {
122 builder.add(createScript(builder, name, scriptProps));
123 } else {
124 builder.add(createScriptFile(builder, name, scriptProps));
125 }
126 }
127 }
128
129 Properties levelProps = PropertiesUtil.extractSubset(properties, "customLevel");
130 if (levelProps.size() > 0) {
131 for (String key : levelProps.stringPropertyNames()) {
132 builder.add(builder.newCustomLevel(key, Integer.parseInt(props.getProperty(key))));
133 }
134 }
135
136 String filterProp = properties.getProperty("filters");
137 if (filterProp != null) {
138 String[] filterNames = filterProp.split(",");
139 for (String filterName : filterNames) {
140 String name = filterName.trim();
141 builder.add(createFilter(builder, name, PropertiesUtil.extractSubset(properties, "filter." + name)));
142 }
143 }
144 String appenderProp = properties.getProperty("appenders");
145 if (appenderProp != null) {
146 String[] appenderNames = appenderProp.split(",");
147 for (String appenderName : appenderNames) {
148 String name = appenderName.trim();
149 builder.add(createAppender(builder, name, PropertiesUtil.extractSubset(properties, "appender." +
150 name)));
151 }
152 }
153 String loggerProp = properties.getProperty("loggers");
154 if (loggerProp != null) {
155 String[] loggerNames = loggerProp.split(",");
156 for (String loggerName : loggerNames) {
157 String name = loggerName.trim();
158 if (!name.equals(LoggerConfig.ROOT)) {
159 builder.add(createLogger(builder, name, PropertiesUtil.extractSubset(properties, "logger." +
160 name)));
161 }
162 }
163 }
164
165 props = PropertiesUtil.extractSubset(properties, "rootLogger");
166 if (props.size() > 0) {
167 builder.add(createRootLogger(builder, props));
168 }
169
170 return builder.build();
171 }
172
173
174 private ScriptComponentBuilder createScript(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
175 Properties properties) {
176 String name = properties.getProperty("name");
177 if (name != null) {
178 properties.remove("name");
179 }
180 String language = properties.getProperty("language");
181 if (language!= null) {
182 properties.remove("language");
183 }
184 String text = properties.getProperty("text");
185 if (text != null) {
186 properties.remove("text");
187 }
188 ScriptComponentBuilder scriptBuilder = builder.newScript(name, language, text);
189 processRemainingProperties(scriptBuilder, key, properties);
190 return scriptBuilder;
191 }
192
193 private ScriptFileComponentBuilder createScriptFile(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
194 Properties properties) {
195 String name = properties.getProperty("name");
196 if (name != null) {
197 properties.remove("name");
198 }
199 String path = properties.getProperty("path");
200 if (path != null) {
201 properties.remove("path");
202 }
203 ScriptFileComponentBuilder scriptFileBuilder = builder.newScriptFile(name, path);
204 processRemainingProperties(scriptFileBuilder, key, properties);
205 return scriptFileBuilder;
206 }
207
208
209 private AppenderComponentBuilder createAppender(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
210 Properties properties) {
211 String name = properties.getProperty(CONFIG_NAME);
212 if (Strings.isEmpty(name)) {
213 throw new ConfigurationException("No name attribute provided for Appender " + key);
214 }
215 properties.remove(CONFIG_NAME);
216 String type = properties.getProperty(CONFIG_TYPE);
217 if (Strings.isEmpty(type)) {
218 throw new ConfigurationException("No type attribute provided for Appender " + key);
219 }
220 properties.remove(CONFIG_TYPE);
221 AppenderComponentBuilder appenderBuilder = builder.newAppender(name, type);
222 String filters = properties.getProperty("filters");
223 if (filters != null) {
224 properties.remove("filters");
225 String[] filterNames = filters.split(",");
226 for (String filterName : filterNames) {
227 filterName = filterName.trim();
228 Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
229 appenderBuilder.add(createFilter(builder, filterName, filterProps));
230 }
231 }
232 Properties layoutProps = PropertiesUtil.extractSubset(properties, "layout");
233 if (layoutProps.size() > 0) {
234 appenderBuilder.add(createLayout(builder, name, layoutProps));
235 }
236
237 processRemainingProperties(appenderBuilder, name, properties);
238 return appenderBuilder;
239 }
240
241 private FilterComponentBuilder createFilter(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
242 Properties properties) {
243 String type = properties.getProperty(CONFIG_TYPE);
244 if (Strings.isEmpty(type)) {
245 throw new ConfigurationException("No type attribute provided for Appender " + key);
246 }
247 properties.remove(CONFIG_TYPE);
248 String onMatch = properties.getProperty("onMatch");
249 if (onMatch != null) {
250 properties.remove("onMatch");
251 }
252 String onMisMatch = properties.getProperty("onMisMatch");
253 if (onMisMatch != null) {
254 properties.remove("onMisMatch");
255 }
256 FilterComponentBuilder filterBuilder = builder.newFilter(type, onMatch, onMisMatch);
257 processRemainingProperties(filterBuilder, key, properties);
258 return filterBuilder;
259 }
260
261 private AppenderRefComponentBuilder createAppenderRef(ConfigurationBuilder<PropertiesConfiguration> builder,
262 String key, Properties properties) {
263 String ref = properties.getProperty("ref");
264 if (Strings.isEmpty(ref)) {
265 throw new ConfigurationException("No ref attribute provided for AppenderRef " + key);
266 }
267 properties.remove("ref");
268 AppenderRefComponentBuilder appenderRefBuilder = builder.newAppenderRef(ref);
269 String level = properties.getProperty("level");
270 if (!Strings.isEmpty(level)) {
271 appenderRefBuilder.addAttribute("level", level);
272 }
273 String filters = properties.getProperty("filters");
274 if (filters != null) {
275 properties.remove("filters");
276 String[] filterNames = filters.split(",");
277 for (String filterName : filterNames) {
278 filterName = filterName.trim();
279 Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
280 appenderRefBuilder.add(createFilter(builder, filterName, filterProps));
281 }
282 }
283 return appenderRefBuilder;
284 }
285
286 private LoggerComponentBuilder createLogger(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
287 Properties properties) {
288 String name = properties.getProperty(CONFIG_NAME);
289 if (Strings.isEmpty(name)) {
290 throw new ConfigurationException("No name attribute provided for Logger " + key);
291 }
292 properties.remove(CONFIG_NAME);
293 String level = properties.getProperty("level");
294 if (level != null) {
295 properties.remove("level");
296 }
297 LoggerComponentBuilder loggerBuilder;
298 String type = properties.getProperty(CONFIG_TYPE);
299 if (type != null) {
300 if (type.equalsIgnoreCase("asyncLogger")) {
301 loggerBuilder = builder.newAsyncLogger(name, level);
302 } else {
303 throw new ConfigurationException("Unknown Logger type " + type + " for Logger " + name);
304 }
305 } else {
306 loggerBuilder = builder.newLogger(name, level);
307 }
308 String appenderRefs = properties.getProperty("appenderRefs");
309 if (appenderRefs != null) {
310 properties.remove("appenderRefs");
311 String[] refNames = appenderRefs.split(",");
312 for (String appenderRef : refNames) {
313 appenderRef = appenderRef.trim();
314 Properties refProps = PropertiesUtil.extractSubset(properties, "appenderRef." + appenderRef);
315 loggerBuilder.add(createAppenderRef(builder, appenderRef, refProps));
316 }
317 }
318 String filters = properties.getProperty("filters");
319 if (filters != null) {
320 properties.remove("filters");
321 String[] filterNames = filters.split(",");
322 for (String filterName : filterNames) {
323 filterName = filterName.trim();
324 Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
325 loggerBuilder.add(createFilter(builder, filterName, filterProps));
326 }
327 }
328 String additivity = properties.getProperty("additivity");
329 if (!Strings.isEmpty(additivity)) {
330 loggerBuilder.addAttribute("additivity", additivity);
331 }
332 return loggerBuilder;
333 }
334
335 private RootLoggerComponentBuilder createRootLogger(ConfigurationBuilder<PropertiesConfiguration> builder,
336 Properties properties) {
337 String level = properties.getProperty("level");
338 if (level != null) {
339 properties.remove("level");
340 }
341 RootLoggerComponentBuilder loggerBuilder;
342 String type = properties.getProperty(CONFIG_TYPE);
343 if (type != null) {
344 if (type.equalsIgnoreCase("asyncRoot")) {
345 loggerBuilder = builder.newAsyncRootLogger(level);
346 } else {
347 throw new ConfigurationException("Unknown Logger type for root logger" + type);
348 }
349 } else {
350 loggerBuilder = builder.newRootLogger(level);
351 }
352 String appenderRefs = properties.getProperty("appenderRefs");
353 if (appenderRefs != null) {
354 properties.remove("appenderRefs");
355 String[] refNames = appenderRefs.split(",");
356 for (String appenderRef : refNames) {
357 appenderRef = appenderRef.trim();
358 Properties refProps = PropertiesUtil.extractSubset(properties, "appenderRef." + appenderRef);
359 loggerBuilder.add(createAppenderRef(builder, appenderRef, refProps));
360 }
361 }
362 String filters = properties.getProperty("filters");
363 if (filters != null) {
364 properties.remove("filters");
365 String[] filterNames = filters.split(",");
366 for (String filterName : filterNames) {
367 filterName = filterName.trim();
368 Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
369 loggerBuilder.add(createFilter(builder, filterName, filterProps));
370 }
371 }
372 return loggerBuilder;
373 }
374
375 private LayoutComponentBuilder createLayout(ConfigurationBuilder<PropertiesConfiguration> builder,
376 String appenderName, Properties properties) {
377 String type = properties.getProperty(CONFIG_TYPE);
378 if (Strings.isEmpty(type)) {
379 throw new ConfigurationException("No type attribute provided for Layout on Appender " + appenderName);
380 }
381 properties.remove(CONFIG_TYPE);
382 LayoutComponentBuilder layoutBuilder = builder.newLayout(type);
383 processRemainingProperties(layoutBuilder, appenderName, properties);
384 return layoutBuilder;
385 }
386
387 private <B extends ComponentBuilder<B>> ComponentBuilder<B> createComponent(ComponentBuilder<?> parent, String key,
388 Properties properties) {
389 String name = properties.getProperty(CONFIG_NAME);
390 if (name != null) {
391 properties.remove(CONFIG_NAME);
392 }
393 String type = properties.getProperty(CONFIG_TYPE);
394 if (Strings.isEmpty(type)) {
395 throw new ConfigurationException("No type attribute provided for component " + key);
396 }
397 properties.remove(CONFIG_TYPE);
398 ComponentBuilder<B> componentBuilder = parent.getBuilder().newComponent(name, type);
399 processRemainingProperties(componentBuilder, name, properties);
400 return componentBuilder;
401 }
402
403 private void processRemainingProperties(ComponentBuilder<?> builder, String name, Properties properties) {
404 while (properties.size() > 0) {
405 String propertyName = properties.stringPropertyNames().iterator().next();
406
407 int index = propertyName.indexOf('.');
408 if (index > 0) {
409 String prefix = propertyName.substring(0, index);
410 Properties componentProperties = PropertiesUtil.extractSubset(properties, prefix);
411 builder.addComponent(createComponent(builder, prefix, componentProperties));
412 } else {
413 builder.addAttribute(propertyName, properties.getProperty(propertyName));
414 properties.remove(propertyName);
415 }
416 }
417 }
418 }