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