| /* |
| * 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.builder.impl; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.StringWriter; |
| import java.lang.reflect.Constructor; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.TimeUnit; |
| |
| import javax.xml.stream.XMLOutputFactory; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamWriter; |
| |
| import org.apache.logging.log4j.Level; |
| import org.apache.logging.log4j.core.Filter; |
| import org.apache.logging.log4j.core.LoggerContext; |
| import org.apache.logging.log4j.core.config.Configuration; |
| import org.apache.logging.log4j.core.config.ConfigurationException; |
| import org.apache.logging.log4j.core.config.ConfigurationSource; |
| import org.apache.logging.log4j.core.config.LoggerConfig; |
| 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.Component; |
| 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.CustomLevelComponentBuilder; |
| import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder; |
| import org.apache.logging.log4j.core.config.builder.api.KeyValuePairComponentBuilder; |
| 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.PropertyComponentBuilder; |
| import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder; |
| import org.apache.logging.log4j.core.config.builder.api.ScriptComponentBuilder; |
| import org.apache.logging.log4j.core.config.builder.api.ScriptFileComponentBuilder; |
| import org.apache.logging.log4j.core.util.Throwables; |
| |
| /** |
| * @param <T> The BuiltConfiguration type. |
| * @since 2.4 |
| */ |
| public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implements ConfigurationBuilder<T> { |
| |
| private static final String INDENT = " "; |
| private static final String EOL = System.lineSeparator(); |
| |
| private final Component root = new Component(); |
| private final Component loggers; |
| private final Component appenders; |
| private final Component filters; |
| private final Component properties; |
| private final Component customLevels; |
| private final Component scripts; |
| private final Class<T> clazz; |
| private ConfigurationSource source; |
| private int monitorInterval; |
| private Level level; |
| private String verbosity; |
| private String destination; |
| private String packages; |
| private String shutdownFlag; |
| private long shutdownTimeoutMillis; |
| private String advertiser; |
| private LoggerContext loggerContext; |
| private String name; |
| |
| @SuppressWarnings("unchecked") |
| public DefaultConfigurationBuilder() { |
| this((Class<T>) BuiltConfiguration.class); |
| root.addAttribute("name", "Built"); |
| } |
| |
| public DefaultConfigurationBuilder(final Class<T> clazz) { |
| if (clazz == null) { |
| throw new IllegalArgumentException("A Configuration class must be provided"); |
| } |
| this.clazz = clazz; |
| final List<Component> components = root.getComponents(); |
| properties = new Component("Properties"); |
| components.add(properties); |
| scripts = new Component("Scripts"); |
| components.add(scripts); |
| customLevels = new Component("CustomLevels"); |
| components.add(customLevels); |
| filters = new Component("Filters"); |
| components.add(filters); |
| appenders = new Component("Appenders"); |
| components.add(appenders); |
| loggers = new Component("Loggers"); |
| components.add(loggers); |
| } |
| |
| protected ConfigurationBuilder<T> add(final Component parent, final ComponentBuilder<?> builder) { |
| parent.getComponents().add(builder.build()); |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> add(final AppenderComponentBuilder builder) { |
| return add(appenders, builder); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> add(final CustomLevelComponentBuilder builder) { |
| return add(customLevels, builder); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> add(final FilterComponentBuilder builder) { |
| return add(filters, builder); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> add(final ScriptComponentBuilder builder) { |
| return add(scripts, builder); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> add(final ScriptFileComponentBuilder builder) { |
| return add(scripts, builder); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> add(final LoggerComponentBuilder builder) { |
| return add(loggers, builder); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> add(final RootLoggerComponentBuilder builder) { |
| for (final Component c : loggers.getComponents()) { |
| if (c.getPluginType().equals(LoggerConfig.ROOT)) { |
| throw new ConfigurationException("Root Logger was previously defined"); |
| } |
| } |
| return add(loggers, builder); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> addProperty(final String key, final String value) { |
| properties.addComponent(newComponent(key, "Property", value).build()); |
| return this; |
| } |
| |
| @Override |
| public T build() { |
| return build(true); |
| } |
| |
| @Override |
| public T build(final boolean initialize) { |
| T configuration; |
| try { |
| if (source == null) { |
| source = ConfigurationSource.NULL_SOURCE; |
| } |
| final Constructor<T> constructor = clazz.getConstructor(LoggerContext.class, ConfigurationSource.class, Component.class); |
| configuration = constructor.newInstance(loggerContext, source, root); |
| configuration.getRootNode().getAttributes().putAll(root.getAttributes()); |
| if (name != null) { |
| configuration.setName(name); |
| } |
| if (level != null) { |
| configuration.getStatusConfiguration().setStatus(level); |
| } |
| if (verbosity != null) { |
| configuration.getStatusConfiguration().setVerbosity(verbosity); |
| } |
| if (destination != null) { |
| configuration.getStatusConfiguration().setDestination(destination); |
| } |
| if (packages != null) { |
| configuration.setPluginPackages(packages); |
| } |
| if (shutdownFlag != null) { |
| configuration.setShutdownHook(shutdownFlag); |
| } |
| if (shutdownTimeoutMillis > 0) { |
| configuration.setShutdownTimeoutMillis(shutdownTimeoutMillis); |
| } |
| if (advertiser != null) { |
| configuration.createAdvertiser(advertiser, source); |
| } |
| configuration.setMonitorInterval(monitorInterval); |
| } catch (final Exception ex) { |
| throw new IllegalArgumentException("Invalid Configuration class specified", ex); |
| } |
| configuration.getStatusConfiguration().initialize(); |
| if (initialize) { |
| configuration.initialize(); |
| } |
| return configuration; |
| } |
| |
| @Override |
| public void writeXmlConfiguration(final OutputStream output) throws IOException { |
| try { |
| final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(output); |
| writeXmlConfiguration(xmlWriter); |
| xmlWriter.close(); |
| } catch (final XMLStreamException e) { |
| if (e.getNestedException() instanceof IOException) { |
| throw (IOException)e.getNestedException(); |
| } |
| Throwables.rethrow(e); |
| } |
| } |
| |
| @Override |
| public String toXmlConfiguration() { |
| final StringWriter sw = new StringWriter(); |
| try { |
| final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(sw); |
| writeXmlConfiguration(xmlWriter); |
| xmlWriter.close(); |
| } catch (final XMLStreamException e) { |
| Throwables.rethrow(e); |
| } |
| return sw.toString(); |
| } |
| |
| private void writeXmlConfiguration(final XMLStreamWriter xmlWriter) throws XMLStreamException { |
| xmlWriter.writeStartDocument(); |
| xmlWriter.writeCharacters(EOL); |
| |
| xmlWriter.writeStartElement("Configuration"); |
| if (name != null) { |
| xmlWriter.writeAttribute("name", name); |
| } |
| if (level != null) { |
| xmlWriter.writeAttribute("status", level.name()); |
| } |
| if (verbosity != null) { |
| xmlWriter.writeAttribute("verbose", verbosity); |
| } |
| if (destination != null) { |
| xmlWriter.writeAttribute("dest", destination); |
| } |
| if (packages != null) { |
| xmlWriter.writeAttribute("packages", packages); |
| } |
| if (shutdownFlag != null) { |
| xmlWriter.writeAttribute("shutdownHook", shutdownFlag); |
| } |
| if (shutdownTimeoutMillis > 0) { |
| xmlWriter.writeAttribute("shutdownTimeout", String.valueOf(shutdownTimeoutMillis)); |
| } |
| if (advertiser != null) { |
| xmlWriter.writeAttribute("advertiser", advertiser); |
| } |
| if (monitorInterval > 0) { |
| xmlWriter.writeAttribute("monitorInterval", String.valueOf(monitorInterval)); |
| } |
| |
| xmlWriter.writeCharacters(EOL); |
| |
| writeXmlSection(xmlWriter, properties); |
| writeXmlSection(xmlWriter, scripts); |
| writeXmlSection(xmlWriter, customLevels); |
| if (filters.getComponents().size() == 1) { |
| writeXmlComponent(xmlWriter, filters.getComponents().get(0), 1); |
| } else if (filters.getComponents().size() > 1) { |
| writeXmlSection(xmlWriter, filters); |
| } |
| writeXmlSection(xmlWriter, appenders); |
| writeXmlSection(xmlWriter, loggers); |
| |
| xmlWriter.writeEndElement(); // "Configuration" |
| xmlWriter.writeCharacters(EOL); |
| |
| xmlWriter.writeEndDocument(); |
| } |
| |
| private void writeXmlSection(final XMLStreamWriter xmlWriter, final Component component) throws XMLStreamException { |
| if (!component.getAttributes().isEmpty() || !component.getComponents().isEmpty() || component.getValue() != null) { |
| writeXmlComponent(xmlWriter, component, 1); |
| } |
| } |
| |
| private void writeXmlComponent(final XMLStreamWriter xmlWriter, final Component component, final int nesting) throws XMLStreamException { |
| if (!component.getComponents().isEmpty() || component.getValue() != null) { |
| writeXmlIndent(xmlWriter, nesting); |
| xmlWriter.writeStartElement(component.getPluginType()); |
| writeXmlAttributes(xmlWriter, component); |
| if (!component.getComponents().isEmpty()) { |
| xmlWriter.writeCharacters(EOL); |
| } |
| for (final Component subComponent : component.getComponents()) { |
| writeXmlComponent(xmlWriter, subComponent, nesting + 1); |
| } |
| if (component.getValue() != null) { |
| xmlWriter.writeCharacters(component.getValue()); |
| } |
| if (!component.getComponents().isEmpty()) { |
| writeXmlIndent(xmlWriter, nesting); |
| } |
| xmlWriter.writeEndElement(); |
| } else { |
| writeXmlIndent(xmlWriter, nesting); |
| xmlWriter.writeEmptyElement(component.getPluginType()); |
| writeXmlAttributes(xmlWriter, component); |
| } |
| xmlWriter.writeCharacters(EOL); |
| } |
| |
| private void writeXmlIndent(final XMLStreamWriter xmlWriter, final int nesting) throws XMLStreamException { |
| for (int i = 0; i < nesting; i++) { |
| xmlWriter.writeCharacters(INDENT); |
| } |
| } |
| |
| private void writeXmlAttributes(final XMLStreamWriter xmlWriter, final Component component) throws XMLStreamException { |
| for (final Map.Entry<String, String> attribute : component.getAttributes().entrySet()) { |
| xmlWriter.writeAttribute(attribute.getKey(), attribute.getValue()); |
| } |
| } |
| |
| @Override |
| public ScriptComponentBuilder newScript(final String name, final String language, final String text) { |
| return new DefaultScriptComponentBuilder(this, name, language, text); |
| } |
| |
| |
| @Override |
| public ScriptFileComponentBuilder newScriptFile(final String path) { |
| return new DefaultScriptFileComponentBuilder(this, path, path); |
| } |
| |
| @Override |
| public ScriptFileComponentBuilder newScriptFile(final String name, final String path) { |
| return new DefaultScriptFileComponentBuilder(this, name, path); |
| } |
| |
| @Override |
| public AppenderComponentBuilder newAppender(final String name, final String type) { |
| return new DefaultAppenderComponentBuilder(this, name, type); |
| } |
| |
| @Override |
| public AppenderRefComponentBuilder newAppenderRef(final String ref) { |
| return new DefaultAppenderRefComponentBuilder(this, ref); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newAsyncLogger(String name) { |
| return new DefaultLoggerComponentBuilder(this, name, null, "AsyncLogger"); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newAsyncLogger(String name, boolean includeLocation) { |
| return new DefaultLoggerComponentBuilder(this, name, null, "AsyncLogger", includeLocation); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newAsyncLogger(final String name, final Level level) { |
| return new DefaultLoggerComponentBuilder(this, name, level.toString(), "AsyncLogger"); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newAsyncLogger(final String name, final Level level, final boolean includeLocation) { |
| return new DefaultLoggerComponentBuilder(this, name, level.toString(), "AsyncLogger", includeLocation); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newAsyncLogger(final String name, final String level) { |
| return new DefaultLoggerComponentBuilder(this, name, level, "AsyncLogger"); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newAsyncLogger(final String name, final String level, final boolean includeLocation) { |
| return new DefaultLoggerComponentBuilder(this, name, level, "AsyncLogger", includeLocation); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newAsyncRootLogger() { |
| return new DefaultRootLoggerComponentBuilder(this, "AsyncRoot"); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newAsyncRootLogger(boolean includeLocation) { |
| return new DefaultRootLoggerComponentBuilder(this, null, "AsyncRoot", includeLocation); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newAsyncRootLogger(final Level level) { |
| return new DefaultRootLoggerComponentBuilder(this, level.toString(), "AsyncRoot"); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newAsyncRootLogger(final Level level, final boolean includeLocation) { |
| return new DefaultRootLoggerComponentBuilder(this, level.toString(), "AsyncRoot", includeLocation); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newAsyncRootLogger(final String level) { |
| return new DefaultRootLoggerComponentBuilder(this, level, "AsyncRoot"); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newAsyncRootLogger(final String level, final boolean includeLocation) { |
| return new DefaultRootLoggerComponentBuilder(this, level, "AsyncRoot", includeLocation); |
| } |
| |
| |
| @Override |
| public <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(final String type) { |
| return new DefaultComponentBuilder<>(this, type); |
| } |
| |
| @Override |
| public <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(final String name, final String type) { |
| return new DefaultComponentBuilder<>(this, name, type); |
| } |
| |
| @Override |
| public <B extends ComponentBuilder<B>> ComponentBuilder<B> newComponent(final String name, final String type, |
| final String value) { |
| return new DefaultComponentBuilder<>(this, name, type, value); |
| } |
| |
| @Override |
| public PropertyComponentBuilder newProperty(final String name, final String value) { |
| return new DefaultPropertyComponentBuilder(this, name, value); |
| } |
| |
| @Override |
| public KeyValuePairComponentBuilder newKeyValuePair(final String key, final String value) { |
| return new DefaultKeyValuePairComponentBuilder(this, key, value); |
| } |
| |
| @Override |
| public CustomLevelComponentBuilder newCustomLevel(final String name, final int level) { |
| return new DefaultCustomLevelComponentBuilder(this, name, level); |
| } |
| |
| @Override |
| public FilterComponentBuilder newFilter(final String type, final Filter.Result onMatch, |
| final Filter.Result onMismatch) { |
| return new DefaultFilterComponentBuilder(this, type, onMatch.name(), onMismatch.name()); |
| } |
| |
| @Override |
| public FilterComponentBuilder newFilter(final String type, final String onMatch, final String onMismatch) { |
| return new DefaultFilterComponentBuilder(this, type, onMatch, onMismatch); |
| } |
| |
| @Override |
| public LayoutComponentBuilder newLayout(final String type) { |
| return new DefaultLayoutComponentBuilder(this, type); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newLogger(String name) { |
| return new DefaultLoggerComponentBuilder(this, name, null); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newLogger(String name, boolean includeLocation) { |
| return new DefaultLoggerComponentBuilder(this, name, null, includeLocation); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newLogger(final String name, final Level level) { |
| return new DefaultLoggerComponentBuilder(this, name, level.toString()); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newLogger(final String name, final Level level, final boolean includeLocation) { |
| return new DefaultLoggerComponentBuilder(this, name, level.toString(), includeLocation); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newLogger(final String name, final String level) { |
| return new DefaultLoggerComponentBuilder(this, name, level); |
| } |
| |
| @Override |
| public LoggerComponentBuilder newLogger(final String name, final String level, final boolean includeLocation) { |
| return new DefaultLoggerComponentBuilder(this, name, level, includeLocation); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newRootLogger() { |
| return new DefaultRootLoggerComponentBuilder(this, null); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newRootLogger(boolean includeLocation) { |
| return new DefaultRootLoggerComponentBuilder(this, null, includeLocation); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newRootLogger(final Level level) { |
| return new DefaultRootLoggerComponentBuilder(this, level.toString()); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newRootLogger(final Level level, final boolean includeLocation) { |
| return new DefaultRootLoggerComponentBuilder(this, level.toString(), includeLocation); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newRootLogger(final String level) { |
| return new DefaultRootLoggerComponentBuilder(this, level); |
| } |
| |
| @Override |
| public RootLoggerComponentBuilder newRootLogger(final String level, final boolean includeLocation) { |
| return new DefaultRootLoggerComponentBuilder(this, level, includeLocation); |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setAdvertiser(final String advertiser) { |
| this.advertiser = advertiser; |
| return this; |
| } |
| |
| /** |
| * Set the name of the configuration. |
| * |
| * @param name the name of the {@link Configuration}. By default is {@code "Assembled"}. |
| * @return this builder instance |
| */ |
| @Override |
| public ConfigurationBuilder<T> setConfigurationName(final String name) { |
| this.name = name; |
| return this; |
| } |
| |
| /** |
| * Set the ConfigurationSource. |
| * |
| * @param configurationSource the {@link ConfigurationSource} |
| * @return this builder instance |
| */ |
| @Override |
| public ConfigurationBuilder<T> setConfigurationSource(final ConfigurationSource configurationSource) { |
| source = configurationSource; |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setMonitorInterval(final String intervalSeconds) { |
| monitorInterval = Integer.parseInt(intervalSeconds); |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setPackages(final String packages) { |
| this.packages = packages; |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setShutdownHook(final String flag) { |
| this.shutdownFlag = flag; |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setShutdownTimeout(final long timeout, final TimeUnit timeUnit) { |
| this.shutdownTimeoutMillis = timeUnit.toMillis(timeout); |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setStatusLevel(final Level level) { |
| this.level = level; |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setVerbosity(final String verbosity) { |
| this.verbosity = verbosity; |
| return this; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> setDestination(final String destination) { |
| this.destination = destination; |
| return this; |
| } |
| |
| @Override |
| public void setLoggerContext(final LoggerContext loggerContext) { |
| this.loggerContext = loggerContext; |
| } |
| |
| @Override |
| public ConfigurationBuilder<T> addRootProperty(final String key, final String value) { |
| root.getAttributes().put(key, value); |
| return this; |
| } |
| |
| } |