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