    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     */
    017    package org.apache.logging.log4j.core.pattern;
    018
    019    import java.util.List;
    020    import java.util.regex.Pattern;
    021
    022    import org.apache.logging.log4j.core.LogEvent;
    023    import org.apache.logging.log4j.core.config.Configuration;
    024    import org.apache.logging.log4j.core.config.plugins.Plugin;
    025    import org.apache.logging.log4j.core.layout.PatternLayout;
    026
    027    /**
    028     * Replacement pattern converter.
    029     */
    030    @Plugin(name = "replace", category = PatternConverter.CATEGORY)
    031    @ConverterKeys({ "replace" })
    032    public final class RegexReplacementConverter extends LogEventPatternConverter {
    033
    034        private final Pattern pattern;
    035
    036        private final String substitution;
    037
    038        private final List<PatternFormatter> formatters;
    039
    040        /**
    041         * Construct the converter.
    042         * @param formatters The PatternFormatters to generate the text to manipulate.
    043         * @param pattern The regular expression Pattern.
    044         * @param substitution The substitution string.
    045         */
    046        private RegexReplacementConverter(final List<PatternFormatter> formatters,
    047                                          final Pattern pattern, final String substitution) {
    048            super("replace", "replace");
    049            this.pattern = pattern;
    050            this.substitution = substitution;
    051            this.formatters = formatters;
    052        }
    053
    054        /**
    055         * Gets an instance of the class.
    056         *
    057         * @param config The current Configuration.
    058         * @param options pattern options, may be null.  If first element is "short",
    059         *                only the first line of the throwable will be formatted.
    060         * @return instance of class.
    061         */
    062        public static RegexReplacementConverter newInstance(final Configuration config, final String[] options) {
    063            if (options.length != 3) {
    064                LOGGER.error("Incorrect number of options on replace. Expected 3 received " + options.length);
    065                return null;
    066            }
    067            if (options[0] == null) {
    068                LOGGER.error("No pattern supplied on replace");
    069                return null;
    070            }
    071            if (options[1] == null) {
    072                LOGGER.error("No regular expression supplied on replace");
    073                return null;
    074            }
    075            if (options[2] == null) {
    076                LOGGER.error("No substitution supplied on replace");
    077                return null;
    078            }
    079            final Pattern p = Pattern.compile(options[1]);
    080            final PatternParser parser = PatternLayout.createPatternParser(config);
    081            final List<PatternFormatter> formatters = parser.parse(options[0]);
    082            return new RegexReplacementConverter(formatters, p, options[2]);
    083        }
    084
    085
    086        /**
    087         * {@inheritDoc}
    088         */
    089        @Override
    090        public void format(final LogEvent event, final StringBuilder toAppendTo) {
    091            final StringBuilder buf = new StringBuilder();
    092            for (final PatternFormatter formatter : formatters) {
    093                formatter.format(event, buf);
    094            }
    095            toAppendTo.append(pattern.matcher(buf.toString()).replaceAll(substitution));
    096        }
    097    }