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.util.HashMap;
20  import java.util.Locale;
21  import java.util.Map;
22  
23  import org.apache.logging.log4j.Level;
24  import org.apache.logging.log4j.core.LogEvent;
25  import org.apache.logging.log4j.core.config.plugins.Plugin;
26  import org.apache.logging.log4j.core.util.Patterns;
27  
28  /**
29   * Returns the event's level in a StringBuilder.
30   */
31  @Plugin(name = "LevelPatternConverter", category = PatternConverter.CATEGORY)
32  @ConverterKeys({ "p", "level" })
33  public final class LevelPatternConverter extends LogEventPatternConverter {
34      private static final String OPTION_LENGTH = "length";
35      private static final String OPTION_LOWER = "lowerCase";
36  
37      /**
38       * Singleton.
39       */
40      private static final LevelPatternConverter INSTANCE = new LevelPatternConverter(null);
41  
42      private final Map<Level, String> levelMap;
43  
44      /**
45       * Private constructor.
46       */
47      private LevelPatternConverter(final Map<Level, String> map) {
48          super("Level", "level");
49          this.levelMap = map;
50      }
51  
52      /**
53       * Obtains an instance of pattern converter.
54       *
55       * @param options
56       *            options, may be null. May contain a list of level names and The value that should be displayed for the
57       *            Level.
58       * @return instance of pattern converter.
59       */
60      public static LevelPatternConverter newInstance(final String[] options) {
61          if (options == null || options.length == 0) {
62              return INSTANCE;
63          }
64          final Map<Level, String> levelMap = new HashMap<Level, String>();
65          int length = Integer.MAX_VALUE; // More than the longest level name.
66          boolean lowerCase = false;
67          final String[] definitions = options[0].split(Patterns.COMMA_SEPARATOR);
68          for (final String def : definitions) {
69              final String[] pair = def.split("=");
70              if (pair == null || pair.length != 2) {
71                  LOGGER.error("Invalid option {}", def);
72                  continue;
73              }
74              final String key = pair[0].trim();
75              final String value = pair[1].trim();
76              if (OPTION_LENGTH.equalsIgnoreCase(key)) {
77                  length = Integer.parseInt(value);
78              } else if (OPTION_LOWER.equalsIgnoreCase(key)) {
79                  lowerCase = Boolean.parseBoolean(value);
80              } else {
81                  final Level level = Level.toLevel(key, null);
82                  if (level == null) {
83                      LOGGER.error("Invalid Level {}", key);
84                  } else {
85                      levelMap.put(level, value);
86                  }
87              }
88          }
89          if (levelMap.isEmpty() && length == Integer.MAX_VALUE && !lowerCase) {
90              return INSTANCE;
91          }
92          for (final Level level : Level.values()) {
93              if (!levelMap.containsKey(level)) {
94                  final String left = left(level, length);
95                  levelMap.put(level, lowerCase ? left.toLowerCase(Locale.US) : left);
96              }
97          }
98          return new LevelPatternConverter(levelMap);
99      }
100 
101     /**
102      * Returns the leftmost chars of the level name for the given level.
103      *
104      * @param level
105      *            The level
106      * @param length
107      *            How many chars to return
108      * @return The abbreviated level name, or the whole level name if the {@code length} is greater than the level name
109      *         length,
110      */
111     private static String left(final Level level, final int length) {
112         final String string = level.toString();
113         if (length >= string.length()) {
114             return string;
115         }
116         return string.substring(0, length);
117     }
118 
119     /**
120      * {@inheritDoc}
121      */
122     @Override
123     public void format(final LogEvent event, final StringBuilder output) {
124         output.append(levelMap == null ? event.getLevel().toString() : levelMap.get(event.getLevel()));
125     }
126 
127     /**
128      * {@inheritDoc}
129      */
130     @Override
131     public String getStyleClass(final Object e) {
132         if (e instanceof LogEvent) {
133             return "level " + ((LogEvent) e).getLevel().name().toLowerCase(Locale.ENGLISH);
134         }
135 
136         return "level";
137     }
138 }