001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.pattern; 018 019import java.lang.reflect.Constructor; 020import java.lang.reflect.InvocationTargetException; 021import java.util.Arrays; 022import java.util.List; 023 024import org.apache.logging.log4j.core.LogEvent; 025import org.apache.logging.log4j.core.config.Configuration; 026import org.apache.logging.log4j.core.config.plugins.Plugin; 027import org.apache.logging.log4j.core.layout.PatternLayout; 028 029/** 030 * Style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. 031 */ 032public abstract class AbstractStyleNameConverter extends LogEventPatternConverter /*TODO: implements AnsiConverter*/ { 033 034 private final List<PatternFormatter> formatters; 035 036 private final String style; 037 038 /** 039 * Constructs the converter. 040 * 041 * @param formatters The PatternFormatters to generate the text to manipulate. 042 * @param styling The styling that should encapsulate the pattern. 043 */ 044 protected AbstractStyleNameConverter(final String name, final List<PatternFormatter> formatters, 045 final String styling) { 046 super(name, "style"); 047 this.formatters = formatters; 048 this.style = styling; 049 } 050 051 /** 052 * Black style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. 053 */ 054 @Plugin(name = Black.NAME, category = "Converter") 055 @ConverterKeys(Black.NAME) 056 public static final class Black extends AbstractStyleNameConverter { 057 058 /** Black */ 059 protected static final String NAME = "black"; 060 061 /** 062 * Constructs the converter. This constructor must be public. 063 * 064 * @param formatters The PatternFormatters to generate the text to manipulate. 065 * @param styling The styling that should encapsulate the pattern. 066 */ 067 public Black(final List<PatternFormatter> formatters, final String styling) { 068 super(NAME, formatters, styling); 069 } 070 071 /** 072 * Gets an instance of the class (called via reflection). 073 * 074 * @param config The current Configuration. 075 * @param options The pattern options, may be null. If the first element is "short", only the first line of the 076 * throwable will be formatted. 077 * @return new instance of class or null 078 */ 079 public static Black newInstance(final Configuration config, final String[] options) { 080 return newInstance(Black.class, NAME, config, options); 081 } 082 } 083 084 /** 085 * Blue style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. 086 */ 087 @Plugin(name = Blue.NAME, category = "Converter") 088 @ConverterKeys(Blue.NAME) 089 public static final class Blue extends AbstractStyleNameConverter { 090 091 /** Blue */ 092 protected static final String NAME = "blue"; 093 094 /** 095 * Constructs the converter. This constructor must be public. 096 * 097 * @param formatters The PatternFormatters to generate the text to manipulate. 098 * @param styling The styling that should encapsulate the pattern. 099 */ 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}