1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.pattern;
15
16 import java.util.HashMap;
17 import java.util.Map;
18 import java.util.function.Supplier;
19
20 import ch.qos.logback.core.Context;
21 import ch.qos.logback.core.CoreConstants;
22 import ch.qos.logback.core.LayoutBase;
23 import ch.qos.logback.core.pattern.color.ConverterSupplierByClassName;
24 import ch.qos.logback.core.pattern.parser.Node;
25 import ch.qos.logback.core.pattern.parser.Parser;
26 import ch.qos.logback.core.spi.ScanException;
27 import ch.qos.logback.core.status.ErrorStatus;
28 import ch.qos.logback.core.status.StatusManager;
29
30 abstract public class PatternLayoutBase<E> extends LayoutBase<E> {
31
32 static final int INTIAL_STRING_BUILDER_SIZE = 256;
33 Converter<E> head;
34 String pattern;
35 protected PostCompileProcessor<E> postCompileProcessor;
36
37
38
39
40
41
42
43
44
45 Map<String, Supplier<DynamicConverter>> instanceConverterMap = new HashMap<>();
46 protected boolean outputPatternAsHeader = false;
47
48
49
50
51
52
53
54
55 protected abstract Map<String, Supplier<DynamicConverter>> getDefaultConverterSupplierMap();
56
57
58
59
60
61
62
63
64
65
66
67
68 @Deprecated
69 abstract public Map<String, String> getDefaultConverterMap();
70
71
72
73
74
75 public Map<String, Supplier<DynamicConverter>> getEffectiveConverterMap() {
76 Map<String, Supplier<DynamicConverter>> effectiveMap = new HashMap<>();
77
78
79 Map<String, Supplier<DynamicConverter>> defaultConverterSupplierMap = getDefaultConverterSupplierMap();
80 if (defaultConverterSupplierMap != null) {
81 effectiveMap.putAll(defaultConverterSupplierMap);
82 }
83
84 caterForLegacyConverterMaps(effectiveMap);
85
86
87 Context context = getContext();
88 if (context != null) {
89 @SuppressWarnings("unchecked")
90 Map<String, Supplier<DynamicConverter>> contextMap = (Map<String, Supplier<DynamicConverter>>) context
91 .getObject(CoreConstants.PATTERN_RULE_REGISTRY_FOR_SUPPLIERS);
92 if (contextMap != null) {
93 effectiveMap.putAll(contextMap);
94 }
95 }
96
97 effectiveMap.putAll(instanceConverterMap);
98 return effectiveMap;
99 }
100
101
102
103
104
105
106
107 private void caterForLegacyConverterMaps(Map<String, Supplier<DynamicConverter>> effectiveMap) {
108 Map<String, String> mapFromContext = (Map<String, String>) this.context
109 .getObject(CoreConstants.PATTERN_RULE_REGISTRY);
110
111 migrateFromStringMapToSupplierMap(mapFromContext, effectiveMap);
112
113 Map<String, String> defaultConverterMap = getDefaultConverterMap();
114 migrateFromStringMapToSupplierMap(defaultConverterMap, effectiveMap);
115 }
116
117 private void migrateFromStringMapToSupplierMap(Map<String, String> legacyMap, Map<String, Supplier<DynamicConverter>> targetSupplierMap) {
118 if(legacyMap == null)
119 return;
120
121
122 for(Map.Entry<String, String> entry: legacyMap.entrySet()) {
123 String key = entry.getKey();
124 String converterClassName = entry.getValue();
125 ConverterSupplierByClassName converterSupplierByClassName = new ConverterSupplierByClassName(key, converterClassName);
126 converterSupplierByClassName.setContext(getContext());
127 targetSupplierMap.put(key, converterSupplierByClassName);
128 }
129
130 }
131
132 public void start() {
133 if (pattern == null || pattern.length() == 0) {
134 addError("Empty or null pattern.");
135 return;
136 }
137 try {
138 Parser<E> p = new Parser<E>(pattern);
139 if (getContext() != null) {
140 p.setContext(getContext());
141 }
142 Node t = p.parse();
143 this.head = p.compile(t, getEffectiveConverterMap());
144 if (postCompileProcessor != null) {
145 postCompileProcessor.process(context, head);
146 }
147 ConverterUtil.setContextForConverters(getContext(), head);
148 ConverterUtil.startConverters(this.head);
149 super.start();
150 } catch (ScanException sce) {
151 StatusManager sm = getContext().getStatusManager();
152 sm.add(new ErrorStatus("Failed to parse pattern \"" + getPattern() + "\".", this, sce));
153 }
154 }
155
156 public void setPostCompileProcessor(PostCompileProcessor<E> postCompileProcessor) {
157 this.postCompileProcessor = postCompileProcessor;
158 }
159
160
161
162
163
164
165
166 protected void setContextForConverters(Converter<E> head) {
167 ConverterUtil.setContextForConverters(getContext(), head);
168 }
169
170 protected String writeLoopOnConverters(E event) {
171 StringBuilder strBuilder = new StringBuilder(INTIAL_STRING_BUILDER_SIZE);
172 Converter<E> c = head;
173 while (c != null) {
174 c.write(strBuilder, event);
175 c = c.getNext();
176 }
177 return strBuilder.toString();
178 }
179
180 public String getPattern() {
181 return pattern;
182 }
183
184 public void setPattern(String pattern) {
185 this.pattern = pattern;
186 }
187
188 public String toString() {
189 return this.getClass().getName() + "(\"" + getPattern() + "\")";
190 }
191
192 public Map<String, Supplier<DynamicConverter>> getInstanceConverterMap() {
193 return instanceConverterMap;
194 }
195
196 protected String getPresentationHeaderPrefix() {
197 return CoreConstants.EMPTY_STRING;
198 }
199
200 public boolean isOutputPatternAsHeader() {
201 return outputPatternAsHeader;
202 }
203
204 public void setOutputPatternAsHeader(boolean outputPatternAsHeader) {
205 this.outputPatternAsHeader = outputPatternAsHeader;
206 }
207
208 @Override
209 public String getPresentationHeader() {
210 if (outputPatternAsHeader)
211 return getPresentationHeaderPrefix() + pattern;
212 else
213 return super.getPresentationHeader();
214 }
215 }