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