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 }