blob: 27644d8e5b12940d04d6cc4764a63eb67577c6bb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache license, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the license for the specific language governing permissions and
* limitations under the license.
*/
package org.apache.logging.log4j.core.config.properties;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.ConfigurationException;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.AppenderRefComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.Strings;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* Creates a PropertiesConfiguration from a properties file.
*
* @since 2.4
*/
@Plugin(name = "PropertiesConfigurationFactory", category = ConfigurationFactory.CATEGORY)
@Order(8)
public class PropertiesConfigurationFactory extends ConfigurationFactory {
private static final String ADVERTISER_KEY = "advertiser";
private static final String STATUS_KEY = "status";
private static final String SHUTDOWN_HOOK = "shutdownHook";
private static final String VERBOSE = "verbose";
private static final String PACKAGES = "packages";
private static final String CONFIG_NAME = "name";
private static final String MONITOR_INTERVAL = "monitorInterval";
private static final String CONFIG_TYPE = "type";
@Override
protected String[] getSupportedTypes() {
return new String[] {".properties"};
}
@Override
public PropertiesConfiguration getConfiguration(ConfigurationSource source) {
final InputStream configStream = source.getInputStream();
Properties properties = new Properties();
try {
properties.load(configStream);
} catch (IOException ioe) {
throw new ConfigurationException("Unable to load " + source.toString(), ioe);
}
ConfigurationBuilder<PropertiesConfiguration> builder = newConfigurationBuilder(PropertiesConfiguration.class);
String value = properties.getProperty(STATUS_KEY);
if (value != null) {
builder.setStatusLevel(Level.toLevel(value, Level.ERROR));
} else {
builder.setStatusLevel(Level.ERROR);
}
value = properties.getProperty(SHUTDOWN_HOOK);
if (value != null) {
builder.setShutdownHook(value);
}
value = properties.getProperty(VERBOSE);
if (value != null) {
builder.setVerbosity(value);
}
value = properties.getProperty(PACKAGES);
if (value != null) {
builder.setPackages(value);
}
value = properties.getProperty(CONFIG_NAME);
if (value != null) {
builder.setConfigurationName(value);
}
value = properties.getProperty(MONITOR_INTERVAL);
if (value != null) {
builder.setMonitorInterval(value);
}
value = properties.getProperty(ADVERTISER_KEY);
if (value != null) {
builder.setAdvertiser(value);
}
Properties props = PropertiesUtil.extractSubset(properties, "property");
for (String key : props.stringPropertyNames()) {
builder.addProperty(key, props.getProperty(key));
}
Properties levelProps = PropertiesUtil.extractSubset(properties, "customLevel");
if (levelProps.size() > 0) {
for (String key : levelProps.stringPropertyNames()) {
builder.add(builder.newCustomLevel(key, Integer.parseInt(props.getProperty(key))));
}
}
String filterProp = properties.getProperty("filters");
if (filterProp != null) {
String[] filterNames = filterProp.split(",");
for (String filterName : filterNames) {
String name = filterName.trim();
builder.add(createFilter(builder, name, PropertiesUtil.extractSubset(properties, "filter." + name)));
}
}
String appenderProp = properties.getProperty("appenders");
if (appenderProp != null) {
String[] appenderNames = appenderProp.split(",");
for (String appenderName : appenderNames) {
String name = appenderName.trim();
builder.add(createAppender(builder, name, PropertiesUtil.extractSubset(properties, "appender." +
name)));
}
}
String loggerProp = properties.getProperty("loggers");
if (loggerProp != null) {
String[] loggerNames = loggerProp.split(",");
for (String loggerName : loggerNames) {
String name = loggerName.trim();
if (!name.equals(LoggerConfig.ROOT)) {
builder.add(createLogger(builder, name, PropertiesUtil.extractSubset(properties, "logger." +
name)));
}
}
}
props = PropertiesUtil.extractSubset(properties, "rootLogger");
if (props.size() > 0) {
builder.add(createRootLogger(builder, props));
}
return builder.build();
}
private AppenderComponentBuilder createAppender(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
Properties properties) {
String name = properties.getProperty(CONFIG_NAME);
if (Strings.isEmpty(name)) {
throw new ConfigurationException("No name attribute provided for Appender " + key);
}
properties.remove(CONFIG_NAME);
String type = properties.getProperty(CONFIG_TYPE);
if (Strings.isEmpty(type)) {
throw new ConfigurationException("No type attribute provided for Appender " + key);
}
properties.remove(CONFIG_TYPE);
AppenderComponentBuilder appenderBuilder = builder.newAppender(name, type);
String filters = properties.getProperty("filters");
if (filters != null) {
properties.remove("filters");
String[] filterNames = filters.split(",");
for (String filterName : filterNames) {
filterName = filterName.trim();
Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
appenderBuilder.add(createFilter(builder, filterName, filterProps));
}
}
Properties layoutProps = PropertiesUtil.extractSubset(properties, "layout");
if (layoutProps.size() > 0) {
appenderBuilder.add(createLayout(builder, name, layoutProps));
}
processRemainingProperties(appenderBuilder, name, properties);
return appenderBuilder;
}
private FilterComponentBuilder createFilter(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
Properties properties) {
String type = properties.getProperty(CONFIG_TYPE);
if (Strings.isEmpty(type)) {
throw new ConfigurationException("No type attribute provided for Appender " + key);
}
properties.remove(CONFIG_TYPE);
String onMatch = properties.getProperty("onMatch");
if (onMatch != null) {
properties.remove("onMatch");
}
String onMisMatch = properties.getProperty("onMisMatch");
if (onMisMatch != null) {
properties.remove("onMisMatch");
}
FilterComponentBuilder filterBuilder = builder.newFilter(type, onMatch, onMisMatch);
processRemainingProperties(filterBuilder, key, properties);
return filterBuilder;
}
private AppenderRefComponentBuilder createAppenderRef(ConfigurationBuilder<PropertiesConfiguration> builder,
String key, Properties properties) {
String ref = properties.getProperty("ref");
if (Strings.isEmpty(ref)) {
throw new ConfigurationException("No ref attribute provided for AppenderRef " + key);
}
properties.remove("ref");
AppenderRefComponentBuilder appenderRefBuilder = builder.newAppenderRef(ref);
String level = properties.getProperty("level");
if (!Strings.isEmpty(level)) {
appenderRefBuilder.addAttribute("level", level);
}
String filters = properties.getProperty("filters");
if (filters != null) {
properties.remove("filters");
String[] filterNames = filters.split(",");
for (String filterName : filterNames) {
filterName = filterName.trim();
Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
appenderRefBuilder.add(createFilter(builder, filterName, filterProps));
}
}
return appenderRefBuilder;
}
private LoggerComponentBuilder createLogger(ConfigurationBuilder<PropertiesConfiguration> builder, String key,
Properties properties) {
String name = properties.getProperty(CONFIG_NAME);
if (Strings.isEmpty(name)) {
throw new ConfigurationException("No name attribute provided for Logger " + key);
}
properties.remove(CONFIG_NAME);
String level = properties.getProperty("level");
if (level != null) {
properties.remove("level");
}
LoggerComponentBuilder loggerBuilder;
String type = properties.getProperty(CONFIG_TYPE);
if (type != null) {
if (type.equalsIgnoreCase("asyncLogger")) {
loggerBuilder = builder.newAsyncLogger(name, level);
} else {
throw new ConfigurationException("Unknown Logger type " + type + " for Logger " + name);
}
} else {
loggerBuilder = builder.newLogger(name, level);
}
String appenderRefs = properties.getProperty("appenderRefs");
if (appenderRefs != null) {
properties.remove("appenderRefs");
String[] refNames = appenderRefs.split(",");
for (String appenderRef : refNames) {
appenderRef = appenderRef.trim();
Properties refProps = PropertiesUtil.extractSubset(properties, "appenderRef." + appenderRef);
loggerBuilder.add(createAppenderRef(builder, appenderRef, refProps));
}
}
String filters = properties.getProperty("filters");
if (filters != null) {
properties.remove("filters");
String[] filterNames = filters.split(",");
for (String filterName : filterNames) {
filterName = filterName.trim();
Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
loggerBuilder.add(createFilter(builder, filterName, filterProps));
}
}
String additivity = properties.getProperty("additivity");
if (!Strings.isEmpty(additivity)) {
loggerBuilder.addAttribute("additivity", additivity);
}
return loggerBuilder;
}
private RootLoggerComponentBuilder createRootLogger(ConfigurationBuilder<PropertiesConfiguration> builder,
Properties properties) {
String level = properties.getProperty("level");
if (level != null) {
properties.remove("level");
}
RootLoggerComponentBuilder loggerBuilder;
String type = properties.getProperty(CONFIG_TYPE);
if (type != null) {
if (type.equalsIgnoreCase("asyncRoot")) {
loggerBuilder = builder.newAsyncRootLogger(level);
} else {
throw new ConfigurationException("Unknown Logger type for root logger" + type);
}
} else {
loggerBuilder = builder.newRootLogger(level);
}
String appenderRefs = properties.getProperty("appenderRefs");
if (appenderRefs != null) {
properties.remove("appenderRefs");
String[] refNames = appenderRefs.split(",");
for (String appenderRef : refNames) {
appenderRef = appenderRef.trim();
Properties refProps = PropertiesUtil.extractSubset(properties, "appenderRef." + appenderRef);
loggerBuilder.add(createAppenderRef(builder, appenderRef, refProps));
}
}
String filters = properties.getProperty("filters");
if (filters != null) {
properties.remove("filters");
String[] filterNames = filters.split(",");
for (String filterName : filterNames) {
filterName = filterName.trim();
Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
loggerBuilder.add(createFilter(builder, filterName, filterProps));
}
}
return loggerBuilder;
}
private LayoutComponentBuilder createLayout(ConfigurationBuilder<PropertiesConfiguration> builder,
String appenderName, Properties properties) {
String type = properties.getProperty(CONFIG_TYPE);
if (Strings.isEmpty(type)) {
throw new ConfigurationException("No type attribute provided for Layout on Appender " + appenderName);
}
properties.remove(CONFIG_TYPE);
LayoutComponentBuilder layoutBuilder = builder.newLayout(type);
processRemainingProperties(layoutBuilder, appenderName, properties);
return layoutBuilder;
}
private <B extends ComponentBuilder<B>> ComponentBuilder<B> createComponent(ComponentBuilder<?> parent, String key,
Properties properties) {
String name = properties.getProperty(CONFIG_NAME);
if (name != null) {
properties.remove(CONFIG_NAME);
}
String type = properties.getProperty(CONFIG_TYPE);
if (Strings.isEmpty(type)) {
throw new ConfigurationException("No type attribute provided for component " + key);
}
properties.remove(CONFIG_TYPE);
ComponentBuilder<B> componentBuilder = parent.getBuilder().newComponent(name, type);
processRemainingProperties(componentBuilder, name, properties);
return componentBuilder;
}
private void processRemainingProperties(ComponentBuilder<?> builder, String name, Properties properties) {
while (properties.size() > 0) {
String propertyName = properties.stringPropertyNames().iterator().next();
int index = propertyName.indexOf('.');
if (index > 0) {
String prefix = propertyName.substring(0, index);
Properties componentProperties = PropertiesUtil.extractSubset(properties, prefix);
builder.addComponent(createComponent(builder, prefix, componentProperties));
} else {
builder.addAttribute(propertyName, properties.getProperty(propertyName));
properties.remove(propertyName);
}
}
}
}