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