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.core.config.Configuration; 023import org.apache.logging.log4j.core.config.plugins.Plugin; 024import org.apache.logging.log4j.core.layout.PatternLayout; 025 026/** 027 * Returns the event's rendered message in a StringBuilder. 028 */ 029@Plugin(name = "encode", category = PatternConverter.CATEGORY) 030@ConverterKeys({ "enc", "encode" }) 031public final class EncodingPatternConverter extends LogEventPatternConverter { 032 033 private final List<PatternFormatter> formatters; 034 035 /** 036 * Private constructor. 037 * 038 * @param formatters The PatternFormatters to generate the text to manipulate. 039 */ 040 private EncodingPatternConverter(final List<PatternFormatter> formatters) { 041 super("encode", "encode"); 042 this.formatters = formatters; 043 } 044 045 /** 046 * Obtains an instance of pattern converter. 047 * 048 * @param config The Configuration. 049 * @param options options, may be null. 050 * @return instance of pattern converter. 051 */ 052 public static EncodingPatternConverter newInstance(final Configuration config, final String[] options) { 053 if (options.length != 1) { 054 LOGGER.error("Incorrect number of options on escape. Expected 1, received " + options.length); 055 return null; 056 } 057 if (options[0] == null) { 058 LOGGER.error("No pattern supplied on escape"); 059 return null; 060 } 061 final PatternParser parser = PatternLayout.createPatternParser(config); 062 final List<PatternFormatter> formatters = parser.parse(options[0]); 063 return new EncodingPatternConverter(formatters); 064 } 065 066 /** 067 * {@inheritDoc} 068 */ 069 @Override 070 public void format(final LogEvent event, final StringBuilder toAppendTo) { 071 final StringBuilder buf = new StringBuilder(); 072 for (final PatternFormatter formatter : formatters) { 073 formatter.format(event, buf); 074 } 075 for (int i = 0; i < buf.length(); i++) { 076 final char c = buf.charAt(i); 077 switch (c) { 078 case '\r': 079 toAppendTo.append("\\r"); 080 break; 081 case '\n': 082 toAppendTo.append("\\n"); 083 break; 084 case '&': 085 toAppendTo.append("&"); 086 break; 087 case '<': 088 toAppendTo.append("<"); 089 break; 090 case '>': 091 toAppendTo.append(">"); 092 break; 093 case '"': 094 toAppendTo.append("""); 095 break; 096 case '\'': 097 toAppendTo.append("'"); 098 break; 099 case '/': 100 toAppendTo.append("/"); 101 break; 102 default: 103 toAppendTo.append(c); 104 break; 105 } 106 } 107 } 108}