blob: a82aa1f12ddc697fd3d724f77ab1e1a1218a7eca [file] [log] [blame]
/*
* 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.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());
}
}
}