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.Map;
020 import java.util.Set;
021 import java.util.TreeSet;
022
023 import org.apache.logging.log4j.core.LogEvent;
024 import org.apache.logging.log4j.core.config.plugins.Plugin;
025 import org.apache.logging.log4j.message.MapMessage;
026
027 /**
028 * Able to handle the contents of the LogEvent's MapMessage and either
029 * output the entire contents of the properties in a similar format to the
030 * java.util.Hashtable.toString(), or to output the value of a specific key
031 * within the Map.
032 */
033 @Plugin(name = "MapPatternConverter", category = PatternConverter.CATEGORY)
034 @ConverterKeys({ "K", "map", "MAP" })
035 public final class MapPatternConverter extends LogEventPatternConverter {
036 /**
037 * Name of property to output.
038 */
039 private final String key;
040
041 /**
042 * Private constructor.
043 *
044 * @param options options, may be null.
045 */
046 private MapPatternConverter(final String[] options) {
047 super(options != null && options.length > 0 ? "MAP{" + options[0] + '}' : "MAP", "map");
048 key = options != null && options.length > 0 ? options[0] : null;
049 }
050
051 /**
052 * Obtains an instance of PropertiesPatternConverter.
053 *
054 * @param options options, may be null or first element contains name of property to format.
055 * @return instance of PropertiesPatternConverter.
056 */
057 public static MapPatternConverter newInstance(final String[] options) {
058 return new MapPatternConverter(options);
059 }
060
061 /**
062 * {@inheritDoc}
063 */
064 @Override
065 public void format(final LogEvent event, final StringBuilder toAppendTo) {
066 MapMessage msg;
067 if (event.getMessage() instanceof MapMessage) {
068 msg = (MapMessage) event.getMessage();
069 } else {
070 return;
071 }
072 final Map<String, String> map = msg.getData();
073 // if there is no additional options, we output every single
074 // Key/Value pair for the Map in a similar format to Hashtable.toString()
075 if (key == null) {
076 if (map.isEmpty()) {
077 toAppendTo.append("{}");
078 return;
079 }
080 final StringBuilder sb = new StringBuilder("{");
081 final Set<String> keys = new TreeSet<String>(map.keySet());
082 for (final String key : keys) {
083 if (sb.length() > 1) {
084 sb.append(", ");
085 }
086 sb.append(key).append('=').append(map.get(key));
087
088 }
089 sb.append('}');
090 toAppendTo.append(sb);
091 } else {
092 // otherwise they just want a single key output
093 final String val = map.get(key);
094
095 if (val != null) {
096 toAppendTo.append(val);
097 }
098 }
099 }
100 }