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.Logger;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.core.config.Configuration;
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
25 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
26 import org.apache.logging.log4j.core.config.plugins.PluginElement;
27 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
28 import org.apache.logging.log4j.core.pattern.PatternFormatter;
29 import org.apache.logging.log4j.core.pattern.PatternParser;
30 import org.apache.logging.log4j.core.script.AbstractScript;
31 import org.apache.logging.log4j.core.script.ScriptRef;
32 import org.apache.logging.log4j.status.StatusLogger;
33
34 import javax.script.SimpleBindings;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38
39
40
41
42 @Plugin(name = "ScriptPatternSelector", category = Node.CATEGORY, elementType = PatternSelector.ELEMENT_TYPE, printObject = true)
43 public class ScriptPatternSelector implements PatternSelector {
44
45 private final Map<String, PatternFormatter[]> formatterMap = new HashMap<>();
46
47 private final Map<String, String> patternMap = new HashMap<>();
48
49 private final PatternFormatter[] defaultFormatters;
50
51 private final String defaultPattern;
52
53 private static Logger LOGGER = StatusLogger.getLogger();
54 private final AbstractScript script;
55 private final Configuration configuration;
56
57
58 public ScriptPatternSelector(final AbstractScript script, final PatternMatch[] properties, final String defaultPattern,
59 final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi,
60 final Configuration config) {
61 this.script = script;
62 this.configuration = config;
63 if (!(script instanceof ScriptRef)) {
64 config.getScriptManager().addScript(script);
65 }
66 final PatternParser parser = PatternLayout.createPatternParser(config);
67 for (final PatternMatch property : properties) {
68 try {
69 final List<PatternFormatter> list = parser.parse(property.getPattern(), alwaysWriteExceptions, noConsoleNoAnsi);
70 formatterMap.put(property.getKey(), list.toArray(new PatternFormatter[list.size()]));
71 patternMap.put(property.getKey(), property.getPattern());
72 } catch (final RuntimeException ex) {
73 throw new IllegalArgumentException("Cannot parse pattern '" + property.getPattern() + "'", ex);
74 }
75 }
76 try {
77 final List<PatternFormatter> list = parser.parse(defaultPattern, alwaysWriteExceptions, noConsoleNoAnsi);
78 defaultFormatters = list.toArray(new PatternFormatter[list.size()]);
79 this.defaultPattern = defaultPattern;
80 } catch (final RuntimeException ex) {
81 throw new IllegalArgumentException("Cannot parse pattern '" + defaultPattern + "'", ex);
82 }
83 }
84
85 @Override
86 public PatternFormatter[] getFormatters(final LogEvent event) {
87 final SimpleBindings bindings = new SimpleBindings();
88 bindings.putAll(configuration.getProperties());
89 bindings.put("substitutor", configuration.getStrSubstitutor());
90 bindings.put("logEvent", event);
91 final Object object = configuration.getScriptManager().execute(script.getName(), bindings);
92 if (object == null) {
93 return defaultFormatters;
94 }
95 final PatternFormatter[] patternFormatter = formatterMap.get(object.toString());
96
97 return patternFormatter == null ? defaultFormatters : patternFormatter;
98 }
99
100
101 @PluginFactory
102 public static ScriptPatternSelector createSelector(@PluginElement("Script") final AbstractScript script,
103 @PluginElement("PatternMatch") final PatternMatch[] properties,
104 @PluginAttribute("defaultPattern") String defaultPattern,
105 @PluginAttribute(value = "alwaysWriteExceptions", defaultBoolean = true) final boolean alwaysWriteExceptions,
106 @PluginAttribute(value = "noConsoleNoAnsi", defaultBoolean = false) final boolean noConsoleNoAnsi,
107 @PluginConfiguration final Configuration config) {
108 if (script == null) {
109 LOGGER.error("A Script, ScriptFile or ScriptRef element must be provided for this ScriptFilter");
110 return null;
111 }
112 if (script instanceof ScriptRef) {
113 if (config.getScriptManager().getScript(script.getName()) == null) {
114 LOGGER.error("No script with name {} has been declared.", script.getName());
115 return null;
116 }
117 }
118 if (defaultPattern == null) {
119 defaultPattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
120 }
121 if (properties == null || properties.length == 0) {
122 LOGGER.warn("No marker patterns were provided");
123 }
124 return new ScriptPatternSelector(script, properties, defaultPattern, alwaysWriteExceptions, noConsoleNoAnsi, config);
125 }
126
127 @Override
128 public String toString() {
129 final StringBuilder sb = new StringBuilder();
130 boolean first = true;
131 for (final Map.Entry<String, String> entry : patternMap.entrySet()) {
132 if (!first) {
133 sb.append(", ");
134 }
135 sb.append("key=\"").append(entry.getKey()).append("\", pattern=\"").append(entry.getValue()).append("\"");
136 first = false;
137 }
138 if (!first) {
139 sb.append(", ");
140 }
141 sb.append("default=\"").append(defaultPattern).append("\"");
142 return sb.toString();
143 }
144 }