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.layout; 018 019import org.apache.logging.log4j.Logger; 020import org.apache.logging.log4j.Marker; 021import org.apache.logging.log4j.core.LogEvent; 022import org.apache.logging.log4j.core.config.Configuration; 023import org.apache.logging.log4j.core.config.Node; 024import org.apache.logging.log4j.core.config.plugins.Plugin; 025import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 026import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; 027import org.apache.logging.log4j.core.config.plugins.PluginElement; 028import org.apache.logging.log4j.core.config.plugins.PluginFactory; 029import org.apache.logging.log4j.core.pattern.PatternFormatter; 030import org.apache.logging.log4j.core.pattern.PatternParser; 031import org.apache.logging.log4j.core.util.KeyValuePair; 032import org.apache.logging.log4j.status.StatusLogger; 033 034import java.util.HashMap; 035import java.util.List; 036import java.util.Map; 037 038/** 039 * Selects the pattern to use based on the Marker in the LogEvent. 040 */ 041@Plugin(name = "MarkerPatternSelector", category = Node.CATEGORY, elementType = PatternSelector.ELEMENT_TYPE, printObject = true) 042public class MarkerPatternSelector implements PatternSelector { 043 044 private final Map<String, PatternFormatter[]> formatterMap = new HashMap<>(); 045 046 private final Map<String, String> patternMap = new HashMap<>(); 047 048 private final PatternFormatter[] defaultFormatters; 049 050 private final String defaultPattern; 051 052 private static Logger LOGGER = StatusLogger.getLogger(); 053 054 055 public MarkerPatternSelector(final PatternMatch[] properties, final String defaultPattern, 056 final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi, 057 final Configuration config) { 058 final PatternParser parser = PatternLayout.createPatternParser(config); 059 for (PatternMatch property : properties) { 060 try { 061 List<PatternFormatter> list = parser.parse(property.getPattern(), alwaysWriteExceptions, noConsoleNoAnsi); 062 formatterMap.put(property.getKey(), list.toArray(new PatternFormatter[list.size()])); 063 patternMap.put(property.getKey(), property.getPattern()); 064 } catch (RuntimeException ex) { 065 throw new IllegalArgumentException("Cannot parse pattern '" + property.getPattern() + "'", ex); 066 } 067 } 068 try { 069 List<PatternFormatter> list = parser.parse(defaultPattern, alwaysWriteExceptions, noConsoleNoAnsi); 070 defaultFormatters = list.toArray(new PatternFormatter[list.size()]); 071 this.defaultPattern = defaultPattern; 072 } catch (RuntimeException ex) { 073 throw new IllegalArgumentException("Cannot parse pattern '" + defaultPattern + "'", ex); 074 } 075 } 076 077 @Override 078 public PatternFormatter[] getFormatters(LogEvent event) { 079 Marker marker = event.getMarker(); 080 if (marker == null) { 081 return defaultFormatters; 082 } 083 for (String key : formatterMap.keySet()) { 084 if (marker.isInstanceOf(key)) { 085 return formatterMap.get(key); 086 } 087 } 088 return defaultFormatters; 089 } 090 091 092 @PluginFactory 093 public static MarkerPatternSelector createSelector(@PluginElement("PatternMatch") final PatternMatch[] properties, 094 @PluginAttribute("defaultPattern") String defaultPattern, 095 @PluginAttribute(value = "alwaysWriteExceptions", defaultBoolean = true) final boolean alwaysWriteExceptions, 096 @PluginAttribute(value = "noConsoleNoAnsi", defaultBoolean = false) final boolean noConsoleNoAnsi, 097 @PluginConfiguration final Configuration config) { 098 if (defaultPattern == null) { 099 defaultPattern = PatternLayout.DEFAULT_CONVERSION_PATTERN; 100 } 101 if (properties == null || properties.length == 0) { 102 LOGGER.warn("No marker patterns were provided"); 103 } 104 return new MarkerPatternSelector(properties, defaultPattern, alwaysWriteExceptions, 105 noConsoleNoAnsi, config); 106 } 107 108 @Override 109 public String toString() { 110 StringBuilder sb = new StringBuilder(); 111 boolean first = true; 112 for (Map.Entry<String, String> entry : patternMap.entrySet()) { 113 if (!first) { 114 sb.append(", "); 115 } 116 sb.append("key=\"").append(entry.getKey()).append("\", pattern=\"").append(entry.getValue()).append("\""); 117 first = false; 118 } 119 if (!first) { 120 sb.append(", "); 121 } 122 sb.append("default=\"").append(defaultPattern).append("\""); 123 return sb.toString(); 124 } 125}