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.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 }