1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.html;
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 static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR;
23 import ch.qos.logback.core.LayoutBase;
24 import ch.qos.logback.core.pattern.Converter;
25 import ch.qos.logback.core.pattern.ConverterUtil;
26 import ch.qos.logback.core.pattern.DynamicConverter;
27 import ch.qos.logback.core.pattern.parser.Node;
28 import ch.qos.logback.core.pattern.parser.Parser;
29 import ch.qos.logback.core.spi.ScanException;
30
31
32
33
34
35
36
37
38 public abstract class HTMLLayoutBase<E> extends LayoutBase<E> {
39
40 protected String pattern;
41
42 protected Converter<E> head;
43
44 protected String title = "Logback Log Messages";
45
46
47
48 protected CssBuilder cssBuilder;
49
50
51 protected long counter = 0;
52
53
54
55
56
57
58 public void setPattern(String conversionPattern) {
59 pattern = conversionPattern;
60 }
61
62
63
64
65 public String getPattern() {
66 return pattern;
67 }
68
69 public CssBuilder getCssBuilder() {
70 return cssBuilder;
71 }
72
73 public void setCssBuilder(CssBuilder cssBuilder) {
74 this.cssBuilder = cssBuilder;
75 }
76
77
78
79
80 @Override
81 public void start() {
82 int errorCount = 0;
83
84 try {
85 Parser<E> p = new Parser<E>(pattern);
86 p.setContext(getContext());
87 Node t = p.parse();
88 this.head = p.compile(t, getEffectiveConverterMap());
89 ConverterUtil.startConverters(this.head);
90 } catch (ScanException ex) {
91 addError("Incorrect pattern found", ex);
92 errorCount++;
93 }
94
95 if (errorCount == 0) {
96 super.started = true;
97 }
98 }
99
100 protected abstract Map<String, Supplier<DynamicConverter>> getDefaultConverterSupplierMap();
101
102
103
104
105
106 public Map<String, Supplier<DynamicConverter>> getEffectiveConverterMap() {
107 Map<String, Supplier<DynamicConverter>> effectiveMap = new HashMap<>();
108
109
110 Map<String, Supplier<DynamicConverter>> defaultSupplierMap = getDefaultConverterSupplierMap();
111 if (defaultSupplierMap != null) {
112 effectiveMap.putAll(defaultSupplierMap);
113 }
114
115
116 Context context = getContext();
117 if (context != null) {
118 @SuppressWarnings("unchecked")
119 Map<String, Supplier<DynamicConverter>> contextMap = (Map<String, Supplier<DynamicConverter>>) context
120 .getObject(CoreConstants.PATTERN_RULE_REGISTRY_FOR_SUPPLIERS);
121 if (contextMap != null) {
122 effectiveMap.putAll(contextMap);
123 }
124 }
125 return effectiveMap;
126 }
127
128
129
130
131
132
133
134
135 public void setTitle(String title) {
136 this.title = title;
137 }
138
139
140
141
142 public String getTitle() {
143 return title;
144 }
145
146
147
148
149 @Override
150 public String getContentType() {
151 return "text/html";
152 }
153
154
155
156
157 @Override
158 public String getFileHeader() {
159 StringBuilder sbuf = new StringBuilder();
160 sbuf.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"");
161 sbuf.append(" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
162 sbuf.append(LINE_SEPARATOR);
163 sbuf.append("<html>");
164 sbuf.append(LINE_SEPARATOR);
165 sbuf.append(" <head>");
166 sbuf.append(LINE_SEPARATOR);
167 sbuf.append(" <title>");
168 sbuf.append(title);
169 sbuf.append("</title>");
170 sbuf.append(LINE_SEPARATOR);
171
172 cssBuilder.addCss(sbuf);
173
174 sbuf.append(LINE_SEPARATOR);
175 sbuf.append(" </head>");
176 sbuf.append(LINE_SEPARATOR);
177 sbuf.append("<body>");
178 sbuf.append(LINE_SEPARATOR);
179
180 return sbuf.toString();
181 }
182
183 public String getPresentationHeader() {
184 StringBuilder sbuf = new StringBuilder();
185 sbuf.append("<hr/>");
186 sbuf.append(LINE_SEPARATOR);
187 sbuf.append("<p>Log session start time ");
188 sbuf.append(new java.util.Date());
189 sbuf.append("</p><p></p>");
190 sbuf.append(LINE_SEPARATOR);
191 sbuf.append(LINE_SEPARATOR);
192 sbuf.append("<table cellspacing=\"0\">");
193 sbuf.append(LINE_SEPARATOR);
194
195 buildHeaderRowForTable(sbuf);
196
197 return sbuf.toString();
198 }
199
200 private void buildHeaderRowForTable(StringBuilder sbuf) {
201 Converter<E> c = head;
202 String name;
203 sbuf.append("<tr class=\"header\">");
204 sbuf.append(LINE_SEPARATOR);
205 while (c != null) {
206 name = computeConverterName(c);
207 if (name == null) {
208 c = c.getNext();
209 continue;
210 }
211 sbuf.append("<td class=\"");
212 sbuf.append(computeConverterName(c));
213 sbuf.append("\">");
214 sbuf.append(computeConverterName(c));
215 sbuf.append("</td>");
216 sbuf.append(LINE_SEPARATOR);
217 c = c.getNext();
218 }
219 sbuf.append("</tr>");
220 sbuf.append(LINE_SEPARATOR);
221 }
222
223 public String getPresentationFooter() {
224 StringBuilder sbuf = new StringBuilder();
225 sbuf.append("</table>");
226 return sbuf.toString();
227 }
228
229
230
231
232 @Override
233 public String getFileFooter() {
234 StringBuilder sbuf = new StringBuilder();
235 sbuf.append(LINE_SEPARATOR);
236 sbuf.append("</body></html>");
237 return sbuf.toString();
238 }
239
240 protected void startNewTableIfLimitReached(StringBuilder sbuf) {
241 if (this.counter >= CoreConstants.TABLE_ROW_LIMIT) {
242 counter = 0;
243 sbuf.append("</table>");
244 sbuf.append(LINE_SEPARATOR);
245 sbuf.append("<p></p>");
246 sbuf.append("<table cellspacing=\"0\">");
247 sbuf.append(LINE_SEPARATOR);
248 buildHeaderRowForTable(sbuf);
249 }
250 }
251
252 protected String computeConverterName(Converter<E> c) {
253 String className = c.getClass().getSimpleName();
254 int index = className.indexOf("Converter");
255 if (index == -1) {
256 return className;
257 } else {
258 return className.substring(0, index);
259 }
260 }
261
262 }