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.log4j.builders.appender;
018
019import static org.apache.log4j.builders.BuilderManager.CATEGORY;
020import static org.apache.log4j.config.Log4j1Configuration.APPENDER_REF_TAG;
021import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
022import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
023import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
024import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
025import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
026import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
027
028import java.util.ArrayList;
029import java.util.List;
030import java.util.Properties;
031import java.util.concurrent.atomic.AtomicReference;
032
033import org.apache.log4j.Appender;
034import org.apache.log4j.bridge.AppenderWrapper;
035import org.apache.log4j.bridge.RewritePolicyAdapter;
036import org.apache.log4j.bridge.RewritePolicyWrapper;
037import org.apache.log4j.builders.AbstractBuilder;
038import org.apache.log4j.config.Log4j1Configuration;
039import org.apache.log4j.config.PropertiesConfiguration;
040import org.apache.log4j.helpers.OptionConverter;
041import org.apache.log4j.rewrite.RewritePolicy;
042import org.apache.log4j.spi.Filter;
043import org.apache.log4j.xml.XmlConfiguration;
044import org.apache.logging.log4j.Logger;
045import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
046import org.apache.logging.log4j.core.config.AppenderRef;
047import org.apache.logging.log4j.core.config.plugins.Plugin;
048import org.apache.logging.log4j.status.StatusLogger;
049import org.apache.logging.log4j.util.Strings;
050import org.w3c.dom.Element;
051
052
053/**
054 * Build an Asynch Appender
055 */
056@Plugin(name = "org.apache.log4j.rewrite.RewriteAppender", category = CATEGORY)
057public class RewriteAppenderBuilder extends AbstractBuilder implements AppenderBuilder {
058
059    private static final Logger LOGGER = StatusLogger.getLogger();
060    private static final String REWRITE_POLICY_TAG = "rewritePolicy";
061
062    public RewriteAppenderBuilder() {
063    }
064
065    public RewriteAppenderBuilder(String prefix, Properties props) {
066        super(prefix, props);
067    }
068
069    @Override
070    public Appender parseAppender(final Element appenderElement, final XmlConfiguration config) {
071        String name = appenderElement.getAttribute(NAME_ATTR);
072        AtomicReference<List<String>> appenderRefs = new AtomicReference<>(new ArrayList<>());
073        AtomicReference<RewritePolicy> rewritePolicyHolder = new AtomicReference<>();
074        AtomicReference<String> level = new AtomicReference<>();
075        AtomicReference<Filter> filter = new AtomicReference<>();
076        forEachElement(appenderElement.getChildNodes(), currentElement -> {
077            switch (currentElement.getTagName()) {
078                case APPENDER_REF_TAG:
079                    Appender appender = config.findAppenderByReference(currentElement);
080                    if (appender != null) {
081                        appenderRefs.get().add(appender.getName());
082                    }
083                    break;
084                case REWRITE_POLICY_TAG: {
085                    RewritePolicy policy = config.parseRewritePolicy(currentElement);
086                    if (policy != null) {
087                        rewritePolicyHolder.set(policy);
088                    }
089                    break;
090                }
091                case FILTER_TAG: {
092                    filter.set(config.parseFilters(currentElement));
093                    break;
094                }
095                case PARAM_TAG: {
096                    if (currentElement.getAttribute(NAME_ATTR).equalsIgnoreCase(THRESHOLD_PARAM)) {
097                        String value = currentElement.getAttribute(VALUE_ATTR);
098                        if (value == null) {
099                            LOGGER.warn("No value supplied for Threshold parameter, ignoring.");
100                        } else {
101                            level.set(value);
102                        }
103                    }
104                    break;
105                }
106            }
107        });
108        return createAppender(name, level.get(), appenderRefs.get().toArray(Strings.EMPTY_ARRAY), rewritePolicyHolder.get(),
109                filter.get(), config);
110    }
111
112    @Override
113    public Appender parseAppender(final String name, final String appenderPrefix, final String layoutPrefix,
114            final String filterPrefix, final Properties props, final PropertiesConfiguration configuration) {
115        String appenderRef = getProperty(APPENDER_REF_TAG);
116        Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name);
117        String policyPrefix = appenderPrefix + ".rewritePolicy";
118        String className = getProperty(policyPrefix);
119        RewritePolicy policy = configuration.getBuilderManager().parseRewritePolicy(className, policyPrefix,
120                props, configuration);
121        String level = getProperty(THRESHOLD_PARAM);
122        if (appenderRef == null) {
123            LOGGER.warn("No appender references configured for AsyncAppender {}", name);
124            return null;
125        }
126        Appender appender = configuration.parseAppender(props, appenderRef);
127        if (appender == null) {
128            LOGGER.warn("Cannot locate Appender {}", appenderRef);
129            return null;
130        }
131        return createAppender(name, level, new String[] {appenderRef}, policy, filter, configuration);
132    }
133
134    private <T extends Log4j1Configuration> Appender createAppender(String name, String level,
135            String[] appenderRefs, RewritePolicy policy, Filter filter, T configuration) {
136        org.apache.logging.log4j.Level logLevel = OptionConverter.convertLevel(level,
137                org.apache.logging.log4j.Level.TRACE);
138        AppenderRef[] refs = new AppenderRef[appenderRefs.length];
139        int index = 0;
140        for (String appenderRef : appenderRefs) {
141            refs[index++] = AppenderRef.createAppenderRef(appenderRef, logLevel, null);
142        }
143        org.apache.logging.log4j.core.Filter rewriteFilter = buildFilters(level, filter);
144        org.apache.logging.log4j.core.appender.rewrite.RewritePolicy rewritePolicy;
145        if (policy instanceof RewritePolicyWrapper) {
146            rewritePolicy = ((RewritePolicyWrapper) policy).getPolicy();
147        } else {
148            rewritePolicy = new RewritePolicyAdapter(policy);
149        }
150        return new AppenderWrapper(RewriteAppender.createAppender(name, "true", refs, configuration,
151                rewritePolicy, rewriteFilter));
152    }
153}