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