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