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