View Javadoc

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