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
021 import org.apache.logging.log4j.core.LogEvent;
022 import org.apache.logging.log4j.core.config.Configuration;
023 import org.apache.logging.log4j.core.config.plugins.Plugin;
024 import 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" })
031 public 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 }