001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.config.builder.impl;
018
019import org.apache.logging.log4j.Level;
020import org.apache.logging.log4j.core.Filter;
021import org.apache.logging.log4j.core.config.Configuration;
022import org.apache.logging.log4j.core.config.ConfigurationException;
023import org.apache.logging.log4j.core.config.ConfigurationSource;
024import org.apache.logging.log4j.core.config.LoggerConfig;
025import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
026import org.apache.logging.log4j.core.config.builder.api.AppenderRefComponentBuilder;
027import org.apache.logging.log4j.core.config.builder.api.Component;
028import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
029import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
030import org.apache.logging.log4j.core.config.builder.api.CustomLevelComponentBuilder;
031import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
032import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
033import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
034import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
035
036import java.lang.reflect.Constructor;
037import java.util.List;
038
039/**
040 * @param <T> The BuiltConfiguration type.
041 *
042 */
043public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implements ConfigurationBuilder<T> {
044
045    private final Component root = new Component();
046    private Component loggers;
047    private Component appenders;
048    private Component filters;
049    private Component properties;
050    private Component customLevels;
051    private final Class<T> clazz;
052    private ConfigurationSource source;
053    private int monitorInterval = 0;
054    private Level level = null;
055    private String verbosity = null;
056    private String packages = null;
057    private String shutdownFlag = null;
058    private String advertiser = null;
059
060    private String name = null;
061
062    public DefaultConfigurationBuilder() {
063        this((Class<T>) BuiltConfiguration.class);
064        root.addAttribute("name", "Built");
065    }
066
067    public DefaultConfigurationBuilder(final Class<T> clazz) {
068        if (clazz == null) {
069            throw new IllegalArgumentException("A Configuration class must be provided");
070        }
071        this.clazz = clazz;
072        final List<Component> components = root.getComponents();
073        properties = new Component("Properties");
074        components.add(properties);
075        customLevels = new Component("CustomLevels");
076        components.add(customLevels);
077        filters = new Component("Filters");
078        components.add(filters);
079        appenders = new Component("Appenders");
080        components.add(appenders);
081        loggers = new Component("Loggers");
082        components.add(loggers);
083    }
084    
085    protected ConfigurationBuilder<T> add(final Component parent, final ComponentBuilder<?> builder) {
086        parent.getComponents().add(builder.build());
087        return this;
088    }
089
090    @Override
091    public ConfigurationBuilder<T> add(final AppenderComponentBuilder builder) {
092        return add(appenders, builder);
093    }
094
095    @Override
096    public ConfigurationBuilder<T> add(final CustomLevelComponentBuilder builder) {
097        return add(customLevels, builder);
098    }
099
100    @Override
101    public ConfigurationBuilder<T> add(final FilterComponentBuilder builder) {
102        return add(filters, builder);
103    }
104
105    @Override
106    public ConfigurationBuilder<T> add(final LoggerComponentBuilder builder) {
107        return add(loggers, builder);
108    }
109
110    @Override
111    public ConfigurationBuilder<T> add(final RootLoggerComponentBuilder builder) {
112        for (final Component c : loggers.getComponents()) {
113            if (c.getPluginType().equals(LoggerConfig.ROOT)) {
114                throw new ConfigurationException("Root Logger was previously defined");
115            }
116        }
117        return add(loggers, builder);
118    }
119
120    @Override
121    public ConfigurationBuilder<T> addProperty(final String key, final String value) {
122        properties.addComponent(newComponent(key, "Property", value).build());
123        return this;
124    }
125
126    @Override
127    public T build() {
128        T configuration;
129        try {
130            if (source == null) {
131                source = ConfigurationSource.NULL_SOURCE;
132            }
133            final Constructor<T> constructor = clazz.getConstructor(ConfigurationSource.class, Component.class);
134            configuration = constructor.newInstance(source, root);
135            configuration.setMonitorInterval(monitorInterval);
136            if (name != null) {
137                configuration.setName(name);
138            }
139            if (level != null) {
140                configuration.getStatusConfiguration().withStatus(level);
141            }
142            if (verbosity != null) {
143                configuration.getStatusConfiguration().withVerbosity(verbosity);
144            }
145            if (packages != null) {
146                configuration.setPluginPackages(packages);
147            }
148            if (shutdownFlag != null) {
149                configuration.setShutdownHook(shutdownFlag);
150            }
151            if (advertiser != null) {
152                configuration.createAdvertiser(advertiser, source);
153            }
154        } catch (final Exception ex) {
155            throw new IllegalArgumentException("Invalid Configuration class specified", ex);
156        }
157        configuration.getStatusConfiguration().initialize();
158        configuration.initialize();
159        return configuration;
160    }
161
162    @Override
163    public AppenderComponentBuilder newAppender(final String name, final String type) {
164        return new DefaultAppenderComponentBuilder(this, name, type);
165    }
166
167    @Override
168    public AppenderRefComponentBuilder newAppenderRef(final String ref) {
169        return new DefaultAppenderRefComponentBuilder(this, ref);
170    }
171
172    @Override
173    public LoggerComponentBuilder newAsyncLogger(final String name, final Level level) {
174        return new DefaultLoggerComponentBuilder(this, name, level.toString(), "AsyncLogger");
175    }
176
177    @Override
178    public LoggerComponentBuilder newAsyncLogger(final String name, final String level) {
179        return new DefaultLoggerComponentBuilder(this, name, level, "AsyncLogger");
180    }
181
182    @Override
183    public RootLoggerComponentBuilder newAsyncRootLogger(final Level level) {
184        return new DefaultRootLoggerComponentBuilder(this, level.toString(), "AsyncRoot");
185    }
186
187    @Override
188    public RootLoggerComponentBuilder newAsyncRootLogger(final String level) {
189        return new DefaultRootLoggerComponentBuilder(this, level, "AsyncRoot");
190    }
191
192    @Override
193    public <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(final String name, final String type) {
194        return new DefaultComponentBuilder<>(this, name, type);
195    }
196
197    @Override
198    public <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(final String name, final String type, final String value) {
199        return new DefaultComponentBuilder<>(this, name, type, value);
200    }
201
202
203    @Override
204    public CustomLevelComponentBuilder newCustomLevel(final String name, final int level) {
205        return new DefaultCustomLevelComponentBuilder(this, name, level);
206    }
207
208    @Override
209    public FilterComponentBuilder newFilter(final String type, final Filter.Result onMatch, final Filter.Result onMisMatch) {
210        return new DefaultFilterComponentBuilder(this, type, onMatch.name(), onMisMatch.name());
211    }
212
213    @Override
214    public FilterComponentBuilder newFilter(final String type, final String onMatch, final String onMisMatch) {
215        return new DefaultFilterComponentBuilder(this, type, onMatch, onMisMatch);
216    }
217
218    @Override
219    public LayoutComponentBuilder newLayout(final String type) {
220        return new DefaultLayoutComponentBuilder(this, type);
221    }
222
223
224    @Override
225    public LoggerComponentBuilder newLogger(final String name, final Level level) {
226        return new DefaultLoggerComponentBuilder(this, name, level.toString());
227    }
228
229    @Override
230    public LoggerComponentBuilder newLogger(final String name, final String level) {
231        return new DefaultLoggerComponentBuilder(this, name, level);
232    }
233
234    @Override
235    public RootLoggerComponentBuilder newRootLogger(final Level level) {
236        return new DefaultRootLoggerComponentBuilder(this, level.toString());
237    }
238
239    @Override
240    public RootLoggerComponentBuilder newRootLogger(final String level) {
241        return new DefaultRootLoggerComponentBuilder(this, level);
242    }
243
244    @Override
245    public ConfigurationBuilder<T> setAdvertiser(final String advertiser) {
246        this.advertiser = advertiser;
247        return this;
248    }
249
250    /**
251     * Set the name of the configuration.
252     *
253     * @param name the name of the {@link Configuration}. By default is {@code "Assembled"}.
254     * @return this builder instance
255     */
256    @Override
257    public ConfigurationBuilder<T> setConfigurationName(final String name) {
258        this.name = name;
259        return this;
260    }
261
262    /**
263     * Set the ConfigurationSource.
264     *
265     * @param configurationSource the {@link ConfigurationSource}
266     * @return this builder instance
267     */
268    @Override
269    public ConfigurationBuilder<T> setConfigurationSource(final ConfigurationSource configurationSource) {
270        source = configurationSource;
271        return this;
272    }
273
274    @Override
275    public ConfigurationBuilder<T> setMonitorInterval(final String intervalSeconds) {
276        monitorInterval = Integer.parseInt(intervalSeconds);
277        return this;
278    }
279
280    @Override
281    public ConfigurationBuilder<T> setPackages(final String packages) {
282        this.packages = packages;
283        return this;
284    }
285
286    @Override
287    public ConfigurationBuilder<T> setShutdownHook(final String flag) {
288        this.shutdownFlag = flag;
289        return this;
290    }
291
292    @Override
293    public ConfigurationBuilder<T> setStatusLevel(final Level level) {
294        this.level = level;
295        return this;
296    }
297
298    @Override
299    public ConfigurationBuilder<T> setVerbosity(final String verbosity) {
300        this.verbosity = verbosity;
301        return this;
302    }
303}