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