1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.layout;
18
19 import org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.Marker;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.config.Configuration;
24 import org.apache.logging.log4j.core.config.Node;
25 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
27 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
28 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
29 import org.apache.logging.log4j.core.config.plugins.PluginElement;
30 import org.apache.logging.log4j.core.impl.LocationAware;
31 import org.apache.logging.log4j.core.pattern.PatternFormatter;
32 import org.apache.logging.log4j.core.pattern.PatternParser;
33 import org.apache.logging.log4j.status.StatusLogger;
34
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38
39
40
41
42 @Plugin(name = "LevelPatternSelector", category = Node.CATEGORY, elementType = PatternSelector.ELEMENT_TYPE, printObject = true)
43 public class LevelPatternSelector implements PatternSelector, LocationAware {
44
45
46
47
48 public static class Builder implements org.apache.logging.log4j.core.util.Builder<LevelPatternSelector> {
49
50 @PluginElement("PatternMatch")
51 private PatternMatch[] properties;
52
53 @PluginBuilderAttribute("defaultPattern")
54 private String defaultPattern;
55
56 @PluginBuilderAttribute(value = "alwaysWriteExceptions")
57 private boolean alwaysWriteExceptions = true;
58
59 @PluginBuilderAttribute(value = "disableAnsi")
60 private boolean disableAnsi;
61
62 @PluginBuilderAttribute(value = "noConsoleNoAnsi")
63 private boolean noConsoleNoAnsi;
64
65 @PluginConfiguration
66 private Configuration configuration;
67
68 @Override
69 public LevelPatternSelector build() {
70 if (defaultPattern == null) {
71 defaultPattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
72 }
73 if (properties == null || properties.length == 0) {
74 LOGGER.warn("No marker patterns were provided with PatternMatch");
75 return null;
76 }
77 return new LevelPatternSelector(properties, defaultPattern, alwaysWriteExceptions, disableAnsi,
78 noConsoleNoAnsi, configuration);
79 }
80
81 public Builder setProperties(final PatternMatch[] properties) {
82 this.properties = properties;
83 return this;
84 }
85
86 public Builder setDefaultPattern(final String defaultPattern) {
87 this.defaultPattern = defaultPattern;
88 return this;
89 }
90
91 public Builder setAlwaysWriteExceptions(final boolean alwaysWriteExceptions) {
92 this.alwaysWriteExceptions = alwaysWriteExceptions;
93 return this;
94 }
95
96 public Builder setDisableAnsi(final boolean disableAnsi) {
97 this.disableAnsi = disableAnsi;
98 return this;
99 }
100
101 public Builder setNoConsoleNoAnsi(final boolean noConsoleNoAnsi) {
102 this.noConsoleNoAnsi = noConsoleNoAnsi;
103 return this;
104 }
105
106 public Builder setConfiguration(final Configuration configuration) {
107 this.configuration = configuration;
108 return this;
109 }
110
111 }
112
113 private final Map<String, PatternFormatter[]> formatterMap = new HashMap<>();
114
115 private final Map<String, String> patternMap = new HashMap<>();
116
117 private final PatternFormatter[] defaultFormatters;
118
119 private final String defaultPattern;
120
121 private static Logger LOGGER = StatusLogger.getLogger();
122
123 private final boolean requiresLocation;
124
125
126
127
128 @Deprecated
129 public LevelPatternSelector(final PatternMatch[] properties, final String defaultPattern,
130 final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi,
131 final Configuration config) {
132 this(properties, defaultPattern, alwaysWriteExceptions, false, noConsoleNoAnsi, config);
133 }
134
135 private LevelPatternSelector(final PatternMatch[] properties, final String defaultPattern,
136 final boolean alwaysWriteExceptions, final boolean disableAnsi,
137 final boolean noConsoleNoAnsi, final Configuration config) {
138 boolean needsLocation = false;
139 final PatternParser parser = PatternLayout.createPatternParser(config);
140 for (final PatternMatch property : properties) {
141 try {
142 final List<PatternFormatter> list = parser.parse(property.getPattern(), alwaysWriteExceptions,
143 disableAnsi, noConsoleNoAnsi);
144 PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
145 formatterMap.put(property.getKey(), formatters);
146 for (int i = 0; !needsLocation && i < formatters.length; ++i) {
147 needsLocation = formatters[i].requiresLocation();
148 }
149
150 patternMap.put(property.getKey(), property.getPattern());
151 } catch (final RuntimeException ex) {
152 throw new IllegalArgumentException("Cannot parse pattern '" + property.getPattern() + "'", ex);
153 }
154 }
155 try {
156 final List<PatternFormatter> list = parser.parse(defaultPattern, alwaysWriteExceptions, disableAnsi,
157 noConsoleNoAnsi);
158 defaultFormatters = list.toArray(new PatternFormatter[0]);
159 this.defaultPattern = defaultPattern;
160 for (int i = 0; !needsLocation && i < defaultFormatters.length; ++i) {
161 needsLocation = defaultFormatters[i].requiresLocation();
162 }
163 } catch (final RuntimeException ex) {
164 throw new IllegalArgumentException("Cannot parse pattern '" + defaultPattern + "'", ex);
165 }
166 requiresLocation = needsLocation;
167 }
168
169 @Override
170 public boolean requiresLocation() {
171 return requiresLocation;
172 }
173
174 @Override
175 public PatternFormatter[] getFormatters(final LogEvent event) {
176 final Level level = event.getLevel();
177 if (level == null) {
178 return defaultFormatters;
179 }
180 for (final String key : formatterMap.keySet()) {
181 if (level.name().equalsIgnoreCase(key)) {
182 return formatterMap.get(key);
183 }
184 }
185 return defaultFormatters;
186 }
187
188
189
190
191
192
193 @PluginBuilderFactory
194 public static Builder newBuilder() {
195 return new Builder();
196 }
197
198
199
200
201
202
203
204
205
206
207
208 @Deprecated
209 public static LevelPatternSelector createSelector(
210 final PatternMatch[] properties,
211 final String defaultPattern,
212 final boolean alwaysWriteExceptions,
213 final boolean noConsoleNoAnsi,
214 final Configuration configuration) {
215 final Builder builder = newBuilder();
216 builder.setProperties(properties);
217 builder.setDefaultPattern(defaultPattern);
218 builder.setAlwaysWriteExceptions(alwaysWriteExceptions);
219 builder.setNoConsoleNoAnsi(noConsoleNoAnsi);
220 builder.setConfiguration(configuration);
221 return builder.build();
222 }
223
224 @Override
225 public String toString() {
226 final StringBuilder sb = new StringBuilder();
227 boolean first = true;
228 for (final Map.Entry<String, String> entry : patternMap.entrySet()) {
229 if (!first) {
230 sb.append(", ");
231 }
232 sb.append("key=\"").append(entry.getKey()).append("\", pattern=\"").append(entry.getValue()).append("\"");
233 first = false;
234 }
235 if (!first) {
236 sb.append(", ");
237 }
238 sb.append("default=\"").append(defaultPattern).append("\"");
239 return sb.toString();
240 }
241 }