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.appender;
018
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.logging.log4j.core.Appender;
024import org.apache.logging.log4j.core.Core;
025import org.apache.logging.log4j.core.config.Configuration;
026import org.apache.logging.log4j.core.config.Node;
027import org.apache.logging.log4j.core.config.plugins.Plugin;
028import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
029import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
030import org.apache.logging.log4j.core.config.plugins.PluginNode;
031import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
032import org.apache.logging.log4j.status.StatusLogger;
033
034/**
035 * A deferred plugin for appenders.
036 */
037@Plugin(name = "AppenderSet", category = Core.CATEGORY_NAME, printObject = true, deferChildren = true)
038public class AppenderSet {
039
040    public static class Builder implements org.apache.logging.log4j.core.util.Builder<AppenderSet> {
041
042        @PluginNode
043        private Node node;
044
045        @PluginConfiguration
046        @Required
047        private Configuration configuration;
048
049        @Override
050        public AppenderSet build() {
051            if (configuration == null) {
052                LOGGER.error("Configuration is missing from AppenderSet {}", this);
053                return null;
054            }
055            if (node == null) {
056                LOGGER.error("No node in AppenderSet {}", this);
057                return null;
058            }
059            final List<Node> children = node.getChildren();
060            if (children == null) {
061                LOGGER.error("No children node in AppenderSet {}", this);
062                return null;
063            }
064            final Map<String, Node> map = new HashMap<>(children.size());
065            for (final Node childNode : children) {
066                final String key = childNode.getAttributes().get("name");
067                if (key == null) {
068                    LOGGER.error("The attribute 'name' is missing from from the node {} in AppenderSet {}",
069                            childNode, children);
070                } else {
071                    map.put(key, childNode);
072                }
073            }
074            return new AppenderSet(configuration, map);
075        }
076
077        public Node getNode() {
078            return node;
079        }
080
081        public Configuration getConfiguration() {
082            return configuration;
083        }
084
085        public Builder withNode(@SuppressWarnings("hiding") final Node node) {
086            this.node = node;
087            return this;
088        }
089
090        public Builder withConfiguration(@SuppressWarnings("hiding") final Configuration configuration) {
091            this.configuration = configuration;
092            return this;
093        }
094
095        @Override
096        public String toString() {
097            return getClass().getName() + " [node=" + node + ", configuration=" + configuration + "]";
098        }
099
100    }
101
102    private static final StatusLogger LOGGER = StatusLogger.getLogger();
103
104    private final Configuration configuration;
105    private final Map<String, Node> nodeMap;
106
107    @PluginBuilderFactory
108    public static Builder newBuilder() {
109        return new Builder();
110    }
111
112    private AppenderSet(final Configuration configuration, final Map<String, Node> appenders) {
113        this.configuration = configuration;
114        this.nodeMap = appenders;
115    }
116
117    public Appender createAppender(final String actualAppenderName, final String sourceAppenderName) {
118        final Node node = nodeMap.get(actualAppenderName);
119        if (node == null) {
120            LOGGER.error("No node named {} in {}", actualAppenderName, this);
121            return null;
122        }
123        node.getAttributes().put("name", sourceAppenderName);
124        if (node.getType().getElementName().equals(Appender.ELEMENT_TYPE)) {
125            final Node appNode = new Node(node);
126            configuration.createConfiguration(appNode, null);
127            if (appNode.getObject() instanceof Appender) {
128                final Appender app = appNode.getObject();
129                app.start();
130                return app;
131            }
132            LOGGER.error("Unable to create Appender of type " + node.getName());
133            return null;
134        }
135        LOGGER.error("No Appender was configured for name {} " + actualAppenderName);
136        return null;
137    }
138}