1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.pattern;
18
19 import java.util.Locale;
20
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.config.Configuration;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.util.ArrayUtils;
25 import org.apache.logging.log4j.core.util.Constants;
26 import org.apache.logging.log4j.core.util.Loader;
27 import org.apache.logging.log4j.message.Message;
28 import org.apache.logging.log4j.message.MultiformatMessage;
29 import org.apache.logging.log4j.status.StatusLogger;
30 import org.apache.logging.log4j.util.MultiFormatStringBuilderFormattable;
31 import org.apache.logging.log4j.util.PerformanceSensitive;
32 import org.apache.logging.log4j.util.StringBuilderFormattable;
33
34
35
36
37 @Plugin(name = "MessagePatternConverter", category = PatternConverter.CATEGORY)
38 @ConverterKeys({ "m", "msg", "message" })
39 @PerformanceSensitive("allocation")
40 public final class MessagePatternConverter extends LogEventPatternConverter {
41
42 private static final String NOLOOKUPS = "nolookups";
43
44 private final String[] formats;
45 private final Configuration config;
46 private final TextRenderer textRenderer;
47 private final boolean noLookups;
48
49
50
51
52
53
54
55 private MessagePatternConverter(final Configuration config, final String[] options) {
56 super("Message", "message");
57 this.formats = options;
58 this.config = config;
59 final int noLookupsIdx = loadNoLookups(options);
60 this.noLookups = Constants.FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS || noLookupsIdx >= 0;
61 this.textRenderer = loadMessageRenderer(noLookupsIdx >= 0 ? ArrayUtils.remove(options, noLookupsIdx) : options);
62 }
63
64 private int loadNoLookups(final String[] options) {
65 if (options != null) {
66 for (int i = 0; i < options.length; i++) {
67 final String option = options[i];
68 if (NOLOOKUPS.equalsIgnoreCase(option)) {
69 return i;
70 }
71 }
72 }
73 return -1;
74 }
75
76 private TextRenderer loadMessageRenderer(final String[] options) {
77 if (options != null) {
78 for (final String option : options) {
79 switch (option.toUpperCase(Locale.ROOT)) {
80 case "ANSI":
81 if (Loader.isJansiAvailable()) {
82 return new JAnsiTextRenderer(options, JAnsiTextRenderer.DefaultMessageStyleMap);
83 }
84 StatusLogger.getLogger()
85 .warn("You requested ANSI message rendering but JANSI is not on the classpath.");
86 return null;
87 case "HTML":
88 return new HtmlTextRenderer(options);
89 }
90 }
91 }
92 return null;
93 }
94
95
96
97
98
99
100
101
102
103
104 public static MessagePatternConverter newInstance(final Configuration config, final String[] options) {
105 return new MessagePatternConverter(config, options);
106 }
107
108
109
110
111 @Override
112 public void format(final LogEvent event, final StringBuilder toAppendTo) {
113 final Message msg = event.getMessage();
114 if (msg instanceof StringBuilderFormattable) {
115
116 final boolean doRender = textRenderer != null;
117 final StringBuilder workingBuilder = doRender ? new StringBuilder(80) : toAppendTo;
118
119 final int offset = workingBuilder.length();
120 if (msg instanceof MultiFormatStringBuilderFormattable) {
121 ((MultiFormatStringBuilderFormattable) msg).formatTo(formats, workingBuilder);
122 } else {
123 ((StringBuilderFormattable) msg).formatTo(workingBuilder);
124 }
125
126
127 if (config != null && !noLookups) {
128 for (int i = offset; i < workingBuilder.length() - 1; i++) {
129 if (workingBuilder.charAt(i) == '$' && workingBuilder.charAt(i + 1) == '{') {
130 final String value = workingBuilder.substring(offset, workingBuilder.length());
131 workingBuilder.setLength(offset);
132 workingBuilder.append(config.getStrSubstitutor().replace(event, value));
133 }
134 }
135 }
136 if (doRender) {
137 textRenderer.render(workingBuilder, toAppendTo);
138 }
139 return;
140 }
141 if (msg != null) {
142 String result;
143 if (msg instanceof MultiformatMessage) {
144 result = ((MultiformatMessage) msg).getFormattedMessage(formats);
145 } else {
146 result = msg.getFormattedMessage();
147 }
148 if (result != null) {
149 toAppendTo.append(config != null && result.contains("${")
150 ? config.getStrSubstitutor().replace(event, result) : result);
151 } else {
152 toAppendTo.append("null");
153 }
154 }
155 }
156 }