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    }