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.layout;
18  
19  import org.apache.logging.log4j.Logger;
20  import org.apache.logging.log4j.Marker;
21  import org.apache.logging.log4j.core.LogEvent;
22  import org.apache.logging.log4j.core.config.Configuration;
23  import org.apache.logging.log4j.core.config.Node;
24  import org.apache.logging.log4j.core.config.plugins.Plugin;
25  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
26  import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
27  import org.apache.logging.log4j.core.config.plugins.PluginElement;
28  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29  import org.apache.logging.log4j.core.pattern.PatternFormatter;
30  import org.apache.logging.log4j.core.pattern.PatternParser;
31  import org.apache.logging.log4j.core.util.KeyValuePair;
32  import org.apache.logging.log4j.status.StatusLogger;
33  
34  import java.util.HashMap;
35  import java.util.List;
36  import java.util.Map;
37  
38  /**
39   * Selects the pattern to use based on the Marker in the LogEvent.
40   */
41  @Plugin(name = "MarkerPatternSelector", category = Node.CATEGORY, elementType = PatternSelector.ELEMENT_TYPE, printObject = true)
42  public class MarkerPatternSelector implements PatternSelector {
43  
44      private final Map<String, PatternFormatter[]> formatterMap = new HashMap<>();
45  
46      private final Map<String, String> patternMap = new HashMap<>();
47  
48      private final PatternFormatter[] defaultFormatters;
49  
50      private final String defaultPattern;
51  
52      private static Logger LOGGER = StatusLogger.getLogger();
53  
54  
55      public MarkerPatternSelector(final PatternMatch[] properties, final String defaultPattern,
56                                   final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi,
57                                   final Configuration config) {
58          final PatternParser parser = PatternLayout.createPatternParser(config);
59          for (PatternMatch property : properties) {
60              try {
61                  List<PatternFormatter> list = parser.parse(property.getPattern(), alwaysWriteExceptions, noConsoleNoAnsi);
62                  formatterMap.put(property.getKey(), list.toArray(new PatternFormatter[list.size()]));
63                  patternMap.put(property.getKey(), property.getPattern());
64              } catch (RuntimeException ex) {
65                  throw new IllegalArgumentException("Cannot parse pattern '" + property.getPattern() + "'", ex);
66              }
67          }
68          try {
69              List<PatternFormatter> list = parser.parse(defaultPattern, alwaysWriteExceptions, noConsoleNoAnsi);
70              defaultFormatters = list.toArray(new PatternFormatter[list.size()]);
71              this.defaultPattern = defaultPattern;
72          } catch (RuntimeException ex) {
73              throw new IllegalArgumentException("Cannot parse pattern '" + defaultPattern + "'", ex);
74          }
75      }
76  
77      @Override
78      public PatternFormatter[] getFormatters(LogEvent event) {
79          Marker marker = event.getMarker();
80          if (marker == null) {
81              return defaultFormatters;
82          }
83          for (String key : formatterMap.keySet()) {
84              if (marker.isInstanceOf(key)) {
85                  return formatterMap.get(key);
86              }
87          }
88          return defaultFormatters;
89      }
90  
91  
92      @PluginFactory
93      public static MarkerPatternSelector createSelector(@PluginElement("PatternMatch") final PatternMatch[] properties,
94                                                         @PluginAttribute("defaultPattern") String defaultPattern,
95                                                         @PluginAttribute(value = "alwaysWriteExceptions", defaultBoolean = true) final boolean alwaysWriteExceptions,
96                                                         @PluginAttribute(value = "noConsoleNoAnsi", defaultBoolean = false) final boolean noConsoleNoAnsi,
97                                                         @PluginConfiguration final Configuration config) {
98          if (defaultPattern == null) {
99              defaultPattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
100         }
101         if (properties == null || properties.length == 0) {
102             LOGGER.warn("No marker patterns were provided");
103         }
104         return new MarkerPatternSelector(properties, defaultPattern, alwaysWriteExceptions,
105                 noConsoleNoAnsi, config);
106     }
107 
108     @Override
109     public String toString() {
110         StringBuilder sb = new StringBuilder();
111         boolean first = true;
112         for (Map.Entry<String, String> entry : patternMap.entrySet()) {
113             if (!first) {
114                 sb.append(", ");
115             }
116             sb.append("key=\"").append(entry.getKey()).append("\", pattern=\"").append(entry.getValue()).append("\"");
117             first = false;
118         }
119         if (!first) {
120             sb.append(", ");
121         }
122         sb.append("default=\"").append(defaultPattern).append("\"");
123         return sb.toString();
124     }
125 }