| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache license, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the license for the specific language governing permissions and |
| * limitations under the license. |
| */ |
| package org.apache.logging.log4j.core.pattern; |
| |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.apache.logging.log4j.core.LogEvent; |
| import org.apache.logging.log4j.core.config.Configuration; |
| import org.apache.logging.log4j.core.config.plugins.Plugin; |
| import org.apache.logging.log4j.core.layout.PatternLayout; |
| import org.apache.logging.log4j.util.PerformanceSensitive; |
| |
| /** |
| * Style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| public abstract class AbstractStyleNameConverter extends LogEventPatternConverter /*TODO: implements AnsiConverter*/ { |
| |
| private final List<PatternFormatter> formatters; |
| |
| private final String style; |
| |
| /** |
| * Constructs the converter. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| protected AbstractStyleNameConverter(final String name, final List<PatternFormatter> formatters, |
| final String styling) { |
| super(name, "style"); |
| this.formatters = formatters; |
| this.style = styling; |
| } |
| |
| /** |
| * Black style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = Black.NAME, category = "Converter") |
| @ConverterKeys(Black.NAME) |
| public static final class Black extends AbstractStyleNameConverter { |
| |
| /** Black */ |
| protected static final String NAME = "black"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public Black(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static Black newInstance(final Configuration config, final String[] options) { |
| return newInstance(Black.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * Blue style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = Blue.NAME, category = "Converter") |
| @ConverterKeys(Blue.NAME) |
| public static final class Blue extends AbstractStyleNameConverter { |
| |
| /** Blue */ |
| protected static final String NAME = "blue"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public Blue(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static Blue newInstance(final Configuration config, final String[] options) { |
| return newInstance(Blue.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * Cyan style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = Cyan.NAME, category = "Converter") |
| @ConverterKeys(Cyan.NAME) |
| public static final class Cyan extends AbstractStyleNameConverter { |
| |
| /** Cyan */ |
| protected static final String NAME = "cyan"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public Cyan(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static Cyan newInstance(final Configuration config, final String[] options) { |
| return newInstance(Cyan.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * Green style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = Green.NAME, category = "Converter") |
| @ConverterKeys(Green.NAME) |
| public static final class Green extends AbstractStyleNameConverter { |
| |
| /** Green */ |
| protected static final String NAME = "green"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public Green(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static Green newInstance(final Configuration config, final String[] options) { |
| return newInstance(Green.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * Magenta style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = Magenta.NAME, category = "Converter") |
| @ConverterKeys(Magenta.NAME) |
| public static final class Magenta extends AbstractStyleNameConverter { |
| |
| /** Magenta */ |
| protected static final String NAME = "magenta"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public Magenta(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static Magenta newInstance(final Configuration config, final String[] options) { |
| return newInstance(Magenta.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * Red style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = Red.NAME, category = "Converter") |
| @ConverterKeys(Red.NAME) |
| public static final class Red extends AbstractStyleNameConverter { |
| |
| /** Red */ |
| protected static final String NAME = "red"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public Red(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static Red newInstance(final Configuration config, final String[] options) { |
| return newInstance(Red.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * White style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = White.NAME, category = "Converter") |
| @ConverterKeys(White.NAME) |
| public static final class White extends AbstractStyleNameConverter { |
| |
| /** White */ |
| protected static final String NAME = "white"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public White(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static White newInstance(final Configuration config, final String[] options) { |
| return newInstance(White.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * Yellow style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. |
| */ |
| @Plugin(name = Yellow.NAME, category = "Converter") |
| @ConverterKeys(Yellow.NAME) |
| public static final class Yellow extends AbstractStyleNameConverter { |
| |
| /** Yellow */ |
| protected static final String NAME = "yellow"; |
| |
| /** |
| * Constructs the converter. This constructor must be public. |
| * |
| * @param formatters The PatternFormatters to generate the text to manipulate. |
| * @param styling The styling that should encapsulate the pattern. |
| */ |
| public Yellow(final List<PatternFormatter> formatters, final String styling) { |
| super(NAME, formatters, styling); |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| public static Yellow newInstance(final Configuration config, final String[] options) { |
| return newInstance(Yellow.class, NAME, config, options); |
| } |
| } |
| |
| /** |
| * Gets an instance of the class (called via reflection). |
| * |
| * @param config The current Configuration. |
| * @param options The pattern options, may be null. If the first element is "short", only the first line of the |
| * throwable will be formatted. |
| * @return new instance of class or null |
| */ |
| protected static <T extends AbstractStyleNameConverter> T newInstance(final Class<T> asnConverterClass, |
| final String name, final Configuration config, |
| final String[] options) { |
| final List<PatternFormatter> formatters = toPatternFormatterList(config, options); |
| if (formatters == null) { |
| return null; |
| } |
| try { |
| final Constructor<T> constructor = asnConverterClass.getConstructor(List.class, String.class); |
| return constructor.newInstance(formatters, AnsiEscape.createSequence(name)); |
| } catch (final SecurityException e) { |
| LOGGER.error(e.toString(), e); |
| } catch (final NoSuchMethodException e) { |
| LOGGER.error(e.toString(), e); |
| } catch (final IllegalArgumentException e) { |
| LOGGER.error(e.toString(), e); |
| } catch (final InstantiationException e) { |
| LOGGER.error(e.toString(), e); |
| } catch (final IllegalAccessException e) { |
| LOGGER.error(e.toString(), e); |
| } catch (final InvocationTargetException e) { |
| LOGGER.error(e.toString(), e); |
| } |
| return null; |
| } |
| |
| /** |
| * Creates a list of PatternFormatter from the given configuration and options or null if no pattern is supplied. |
| * |
| * @param config A configuration. |
| * @param options pattern options. |
| * @return a list of PatternFormatter from the given configuration and options or null if no pattern is supplied. |
| */ |
| private static List<PatternFormatter> toPatternFormatterList(final Configuration config, final String[] options) { |
| if (options.length == 0 || options[0] == null) { |
| LOGGER.error("No pattern supplied on style for config=" + config); |
| return null; |
| } |
| final PatternParser parser = PatternLayout.createPatternParser(config); |
| if (parser == null) { |
| LOGGER.error("No PatternParser created for config=" + config + ", options=" + Arrays.toString(options)); |
| return null; |
| } |
| return parser.parse(options[0]); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| @PerformanceSensitive("allocation") |
| public void format(final LogEvent event, final StringBuilder toAppendTo) { |
| final int start = toAppendTo.length(); |
| for (int i = 0; i < formatters.size(); i++) { |
| final PatternFormatter formatter = formatters.get(i); |
| formatter.format(event, toAppendTo); |
| } |
| if (toAppendTo.length() > start) { |
| toAppendTo.insert(start, style); |
| toAppendTo.append(AnsiEscape.getDefaultStyle()); |
| } |
| } |
| } |