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