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.pattern;
018
019import java.util.List;
020
021import org.apache.logging.log4j.core.LogEvent;
022import org.apache.logging.log4j.util.PerformanceSensitive;
023
024/**
025 * Equals pattern converter.
026 */
027@PerformanceSensitive("allocation")
028public abstract class EqualsBaseReplacementConverter extends LogEventPatternConverter {
029    private final List<PatternFormatter> formatters;
030    private final List<PatternFormatter> substitutionFormatters;
031    private final String substitution;
032    private final String testString;
033
034    /**
035     * Construct the converter.
036     *
037     * @param name          converter name
038     * @param style         converter style
039     * @param formatters   The PatternFormatters to generate the text to manipulate.
040     * @param testString   The test string.
041     * @param substitution The substitution string.
042     * @param parser        The PatternParser.
043     */
044    protected EqualsBaseReplacementConverter(final String name, final String style,
045                                            final List<PatternFormatter> formatters, final String testString,
046                                            final String substitution, final PatternParser parser) {
047        super(name, style);
048        this.testString = testString;
049        this.substitution = substitution;
050        this.formatters = formatters;
051
052        // check if substitution needs to be parsed
053        substitutionFormatters = substitution.contains("%") ? parser.parse(substitution) : null;
054    }
055
056    /**
057     * {@inheritDoc}
058     */
059    @Override
060    public void format(final LogEvent event, final StringBuilder toAppendTo) {
061        final int initialSize = toAppendTo.length();
062        for (int i = 0; i < formatters.size(); i++) {
063            final PatternFormatter formatter = formatters.get(i);
064            formatter.format(event, toAppendTo);
065        }
066        if (equals(testString, toAppendTo, initialSize, toAppendTo.length() - initialSize)) {
067            toAppendTo.setLength(initialSize);
068            parseSubstitution(event, toAppendTo);
069        }
070    }
071
072    /**
073     * Returns true if the specified String equals the specified section of the specified StringBuilder.
074     *
075     * @param str the String to compare
076     * @param buff the StringBuilder to compare a section of
077     * @param from start index in the StringBuilder
078     * @param len length of the section in the StringBuilder
079     * @return true if equal, false otherwise
080     */
081    protected abstract boolean equals(String str, StringBuilder buff, int from, int len);
082
083    /**
084     * Adds the parsed substitution text to the specified buffer.
085     *
086     * @param event the current log event
087     * @param substitutionBuffer the StringBuilder to append the parsed substitution text to
088     */
089    void parseSubstitution(final LogEvent event, final StringBuilder substitutionBuffer) {
090        if (substitutionFormatters != null) {
091            for (int i = 0; i < substitutionFormatters.size(); i++) {
092                final PatternFormatter formatter = substitutionFormatters.get(i);
093                formatter.format(event, substitutionBuffer);
094            }
095        } else {
096            substitutionBuffer.append(substitution);
097        }
098    }
099}