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 */ 017 package org.apache.logging.log4j.core.pattern; 018 019 import java.lang.reflect.Constructor; 020 import java.lang.reflect.InvocationTargetException; 021 import java.util.List; 022 023 import org.apache.logging.log4j.core.LogEvent; 024 import org.apache.logging.log4j.core.config.Configuration; 025 import org.apache.logging.log4j.core.config.plugins.Plugin; 026 import org.apache.logging.log4j.core.layout.PatternLayout; 027 028 /** 029 * Style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. 030 */ 031 public abstract class AbstractStyleNameConverter extends LogEventPatternConverter { 032 033 private final List<PatternFormatter> formatters; 034 035 private final String style; 036 037 /** 038 * Constructs the converter. 039 * 040 * @param formatters The PatternFormatters to generate the text to manipulate. 041 * @param styling The styling that should encapsulate the pattern. 042 */ 043 protected AbstractStyleNameConverter(final String name, final List<PatternFormatter> formatters, 044 final String styling) { 045 super(name, "style"); 046 this.formatters = formatters; 047 this.style = styling; 048 } 049 050 /** 051 * Black style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. 052 */ 053 @Plugin(name = Black.NAME, category = "Converter") 054 @ConverterKeys(Black.NAME) 055 public static final class Black extends AbstractStyleNameConverter { 056 057 /** Black */ 058 protected static final String NAME = "black"; 059 060 /** 061 * Constructs the converter. This constructor must be public. 062 * 063 * @param formatters The PatternFormatters to generate the text to manipulate. 064 * @param styling The styling that should encapsulate the pattern. 065 */ 066 public Black(final List<PatternFormatter> formatters, final String styling) { 067 super(NAME, formatters, styling); 068 } 069 070 /** 071 * Gets an instance of the class (called via reflection). 072 * 073 * @param config The current Configuration. 074 * @param options The pattern options, may be null. If the first element is "short", only the first line of the 075 * throwable will be formatted. 076 * @return new instance of class or null 077 */ 078 public static Black newInstance(final Configuration config, final String[] options) { 079 return newInstance(Black.class, NAME, config, options); 080 } 081 } 082 083 /** 084 * Blue style pattern converter. Adds ANSI color styling to the result of the enclosed pattern. 085 */ 086 @Plugin(name = Blue.NAME, category = "Converter") 087 @ConverterKeys(Blue.NAME) 088 public static final class Blue extends AbstractStyleNameConverter { 089 090 /** Blue */ 091 protected static final String NAME = "blue"; 092 093 /** 094 * Constructs the converter. This constructor must be public. 095 * 096 * @param formatters The PatternFormatters to generate the text to manipulate. 097 * @param styling The styling that should encapsulate the pattern. 098 */ 099 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, category = "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, category = "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, category = "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, category = "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, category = "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, category = "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 }