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