1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache license, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the license for the specific language governing permissions and
15 * limitations under the license.
16 */
17 package org.apache.logging.log4j.core.pattern;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.InvocationTargetException;
21 import java.util.Arrays;
22 import java.util.List;
23
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.config.Configuration;
26 import org.apache.logging.log4j.core.config.plugins.Plugin;
27 import org.apache.logging.log4j.core.layout.PatternLayout;
28
29 /**
30 * Style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
31 */
32 public abstract class AbstractStyleNameConverter extends LogEventPatternConverter /*TODO: implements AnsiConverter*/ {
33
34 private final List<PatternFormatter> formatters;
35
36 private final String style;
37
38 /**
39 * Constructs the converter.
40 *
41 * @param formatters The PatternFormatters to generate the text to manipulate.
42 * @param styling The styling that should encapsulate the pattern.
43 */
44 protected AbstractStyleNameConverter(final String name, final List<PatternFormatter> formatters,
45 final String styling) {
46 super(name, "style");
47 this.formatters = formatters;
48 this.style = styling;
49 }
50
51 /**
52 * Black style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
53 */
54 @Plugin(name = Black.NAME, category = "Converter")
55 @ConverterKeys(Black.NAME)
56 public static final class Black extends AbstractStyleNameConverter {
57
58 /** Black */
59 protected static final String NAME = "black";
60
61 /**
62 * Constructs the converter. This constructor must be public.
63 *
64 * @param formatters The PatternFormatters to generate the text to manipulate.
65 * @param styling The styling that should encapsulate the pattern.
66 */
67 public Black(final List<PatternFormatter> formatters, final String styling) {
68 super(NAME, formatters, styling);
69 }
70
71 /**
72 * Gets an instance of the class (called via reflection).
73 *
74 * @param config The current Configuration.
75 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
76 * throwable will be formatted.
77 * @return new instance of class or null
78 */
79 public static Black newInstance(final Configuration config, final String[] options) {
80 return newInstance(Black.class, NAME, config, options);
81 }
82 }
83
84 /**
85 * Blue style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
86 */
87 @Plugin(name = Blue.NAME, category = "Converter")
88 @ConverterKeys(Blue.NAME)
89 public static final class Blue extends AbstractStyleNameConverter {
90
91 /** Blue */
92 protected static final String NAME = "blue";
93
94 /**
95 * Constructs the converter. This constructor must be public.
96 *
97 * @param formatters The PatternFormatters to generate the text to manipulate.
98 * @param styling The styling that should encapsulate the pattern.
99 */
100 public Blue(final List<PatternFormatter> formatters, final String styling) {
101 super(NAME, formatters, styling);
102 }
103
104 /**
105 * Gets an instance of the class (called via reflection).
106 *
107 * @param config The current Configuration.
108 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
109 * throwable will be formatted.
110 * @return new instance of class or null
111 */
112 public static Blue newInstance(final Configuration config, final String[] options) {
113 return newInstance(Blue.class, NAME, config, options);
114 }
115 }
116
117 /**
118 * Cyan style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
119 */
120 @Plugin(name = Cyan.NAME, category = "Converter")
121 @ConverterKeys(Cyan.NAME)
122 public static final class Cyan extends AbstractStyleNameConverter {
123
124 /** Cyan */
125 protected static final String NAME = "cyan";
126
127 /**
128 * Constructs the converter. This constructor must be public.
129 *
130 * @param formatters The PatternFormatters to generate the text to manipulate.
131 * @param styling The styling that should encapsulate the pattern.
132 */
133 public Cyan(final List<PatternFormatter> formatters, final String styling) {
134 super(NAME, formatters, styling);
135 }
136
137 /**
138 * Gets an instance of the class (called via reflection).
139 *
140 * @param config The current Configuration.
141 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
142 * throwable will be formatted.
143 * @return new instance of class or null
144 */
145 public static Cyan newInstance(final Configuration config, final String[] options) {
146 return newInstance(Cyan.class, NAME, config, options);
147 }
148 }
149
150 /**
151 * Green style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
152 */
153 @Plugin(name = Green.NAME, category = "Converter")
154 @ConverterKeys(Green.NAME)
155 public static final class Green extends AbstractStyleNameConverter {
156
157 /** Green */
158 protected static final String NAME = "green";
159
160 /**
161 * Constructs the converter. This constructor must be public.
162 *
163 * @param formatters The PatternFormatters to generate the text to manipulate.
164 * @param styling The styling that should encapsulate the pattern.
165 */
166 public Green(final List<PatternFormatter> formatters, final String styling) {
167 super(NAME, formatters, styling);
168 }
169
170 /**
171 * Gets an instance of the class (called via reflection).
172 *
173 * @param config The current Configuration.
174 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
175 * throwable will be formatted.
176 * @return new instance of class or null
177 */
178 public static Green newInstance(final Configuration config, final String[] options) {
179 return newInstance(Green.class, NAME, config, options);
180 }
181 }
182
183 /**
184 * Magenta style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
185 */
186 @Plugin(name = Magenta.NAME, category = "Converter")
187 @ConverterKeys(Magenta.NAME)
188 public static final class Magenta extends AbstractStyleNameConverter {
189
190 /** Magenta */
191 protected static final String NAME = "magenta";
192
193 /**
194 * Constructs the converter. This constructor must be public.
195 *
196 * @param formatters The PatternFormatters to generate the text to manipulate.
197 * @param styling The styling that should encapsulate the pattern.
198 */
199 public Magenta(final List<PatternFormatter> formatters, final String styling) {
200 super(NAME, formatters, styling);
201 }
202
203 /**
204 * Gets an instance of the class (called via reflection).
205 *
206 * @param config The current Configuration.
207 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
208 * throwable will be formatted.
209 * @return new instance of class or null
210 */
211 public static Magenta newInstance(final Configuration config, final String[] options) {
212 return newInstance(Magenta.class, NAME, config, options);
213 }
214 }
215
216 /**
217 * Red style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
218 */
219 @Plugin(name = Red.NAME, category = "Converter")
220 @ConverterKeys(Red.NAME)
221 public static final class Red extends AbstractStyleNameConverter {
222
223 /** Red */
224 protected static final String NAME = "red";
225
226 /**
227 * Constructs the converter. This constructor must be public.
228 *
229 * @param formatters The PatternFormatters to generate the text to manipulate.
230 * @param styling The styling that should encapsulate the pattern.
231 */
232 public Red(final List<PatternFormatter> formatters, final String styling) {
233 super(NAME, formatters, styling);
234 }
235
236 /**
237 * Gets an instance of the class (called via reflection).
238 *
239 * @param config The current Configuration.
240 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
241 * throwable will be formatted.
242 * @return new instance of class or null
243 */
244 public static Red newInstance(final Configuration config, final String[] options) {
245 return newInstance(Red.class, NAME, config, options);
246 }
247 }
248
249 /**
250 * White style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
251 */
252 @Plugin(name = White.NAME, category = "Converter")
253 @ConverterKeys(White.NAME)
254 public static final class White extends AbstractStyleNameConverter {
255
256 /** White */
257 protected static final String NAME = "white";
258
259 /**
260 * Constructs the converter. This constructor must be public.
261 *
262 * @param formatters The PatternFormatters to generate the text to manipulate.
263 * @param styling The styling that should encapsulate the pattern.
264 */
265 public White(final List<PatternFormatter> formatters, final String styling) {
266 super(NAME, formatters, styling);
267 }
268
269 /**
270 * Gets an instance of the class (called via reflection).
271 *
272 * @param config The current Configuration.
273 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
274 * throwable will be formatted.
275 * @return new instance of class or null
276 */
277 public static White newInstance(final Configuration config, final String[] options) {
278 return newInstance(White.class, NAME, config, options);
279 }
280 }
281
282 /**
283 * Yellow style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
284 */
285 @Plugin(name = Yellow.NAME, category = "Converter")
286 @ConverterKeys(Yellow.NAME)
287 public static final class Yellow extends AbstractStyleNameConverter {
288
289 /** Yellow */
290 protected static final String NAME = "yellow";
291
292 /**
293 * Constructs the converter. This constructor must be public.
294 *
295 * @param formatters The PatternFormatters to generate the text to manipulate.
296 * @param styling The styling that should encapsulate the pattern.
297 */
298 public Yellow(final List<PatternFormatter> formatters, final String styling) {
299 super(NAME, formatters, styling);
300 }
301
302 /**
303 * Gets an instance of the class (called via reflection).
304 *
305 * @param config The current Configuration.
306 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
307 * throwable will be formatted.
308 * @return new instance of class or null
309 */
310 public static Yellow newInstance(final Configuration config, final String[] options) {
311 return newInstance(Yellow.class, NAME, config, options);
312 }
313 }
314
315 /**
316 * Gets an instance of the class (called via reflection).
317 *
318 * @param config The current Configuration.
319 * @param options The pattern options, may be null. If the first element is "short", only the first line of the
320 * throwable will be formatted.
321 * @return new instance of class or null
322 */
323 protected static <T extends AbstractStyleNameConverter> T newInstance(final Class<T> asnConverterClass,
324 final String name, final Configuration config,
325 final String[] options) {
326 final List<PatternFormatter> formatters = toPatternFormatterList(config, options);
327 if (formatters == null) {
328 return null;
329 }
330 try {
331 final Constructor<T> constructor = asnConverterClass.getConstructor(List.class, String.class);
332 return constructor.newInstance(formatters, AnsiEscape.createSequence(name));
333 } catch (final SecurityException e) {
334 LOGGER.error(e.toString(), e);
335 } catch (final NoSuchMethodException e) {
336 LOGGER.error(e.toString(), e);
337 } catch (final IllegalArgumentException e) {
338 LOGGER.error(e.toString(), e);
339 } catch (final InstantiationException e) {
340 LOGGER.error(e.toString(), e);
341 } catch (final IllegalAccessException e) {
342 LOGGER.error(e.toString(), e);
343 } catch (final InvocationTargetException e) {
344 LOGGER.error(e.toString(), e);
345 }
346 return null;
347 }
348
349 /**
350 * Creates a list of PatternFormatter from the given configuration and options or null if no pattern is supplied.
351 *
352 * @param config A configuration.
353 * @param options pattern options.
354 * @return a list of PatternFormatter from the given configuration and options or null if no pattern is supplied.
355 */
356 private static List<PatternFormatter> toPatternFormatterList(final Configuration config, final String[] options) {
357 if (options.length == 0 || options[0] == null) {
358 LOGGER.error("No pattern supplied on style for config=" + config);
359 return null;
360 }
361 final PatternParser parser = PatternLayout.createPatternParser(config);
362 if (parser == null) {
363 LOGGER.error("No PatternParser created for config=" + config + ", options=" + Arrays.toString(options));
364 return null;
365 }
366 return parser.parse(options[0]);
367 }
368
369 /**
370 * {@inheritDoc}
371 */
372 @Override
373 public void format(final LogEvent event, final StringBuilder toAppendTo) {
374 final StringBuilder buf = new StringBuilder();
375 for (final PatternFormatter formatter : formatters) {
376 formatter.format(event, buf);
377 }
378 if (buf.length() > 0) {
379 toAppendTo.append(style).append(buf.toString()).append(AnsiEscape.getDefaultStyle());
380 }
381 }
382 }