1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.status;
15
16 import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR;
17
18 import java.io.IOException;
19 import java.io.PrintWriter;
20 import java.io.StringWriter;
21 import java.util.List;
22
23 import jakarta.servlet.ServletException;
24 import jakarta.servlet.http.HttpServlet;
25 import jakarta.servlet.http.HttpServletRequest;
26 import jakarta.servlet.http.HttpServletResponse;
27
28 import ch.qos.logback.core.CoreConstants;
29 import ch.qos.logback.core.helpers.Transform;
30 import ch.qos.logback.core.util.CachingDateFormatter;
31
32 abstract public class ViewStatusMessagesServletBase extends HttpServlet {
33
34 private static final long serialVersionUID = -3551928133801157219L;
35 private static CachingDateFormatter SDF = new CachingDateFormatter("yyyy-MM-dd HH:mm:ss");
36
37 static String SUBMIT = "submit";
38 static String CLEAR = "Clear";
39
40 protected abstract StatusManager getStatusManager(HttpServletRequest req, HttpServletResponse resp);
41
42 protected abstract String getPageTitle(HttpServletRequest req, HttpServletResponse resp);
43
44 int count;
45
46 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
47
48 count = 0;
49 StatusManager sm = getStatusManager(req, resp);
50
51 resp.setContentType("text/html");
52 PrintWriter output = resp.getWriter();
53
54 output.append("<html>\r\n");
55 output.append("<head>\r\n");
56 printCSS(req.getContextPath(), output);
57 output.append("</head>\r\n");
58 output.append("<body>\r\n");
59 output.append(getPageTitle(req, resp));
60
61 output.append("<form method=\"POST\">\r\n");
62 output.append("<input type=\"submit\" name=\"" + SUBMIT + "\" value=\"" + CLEAR + "\">");
63 output.append("</form>\r\n");
64
65 if (CLEAR.equalsIgnoreCase(req.getParameter(SUBMIT))) {
66 sm.clear();
67 sm.add(new InfoStatus("Cleared all status messages", this));
68 }
69
70 output.append("<table>");
71 StringBuilder buf = new StringBuilder();
72 if (sm != null) {
73 printList(buf, sm);
74 } else {
75 output.append("Could not find status manager");
76 }
77 output.append(buf);
78 output.append("</table>");
79 output.append("</body>\r\n");
80 output.append("</html>\r\n");
81 output.flush();
82 output.close();
83 }
84
85 public void printCSS(String localRef, PrintWriter output) {
86 output.append(" <STYLE TYPE=\"text/css\">\r\n");
87 output.append(" .warn { font-weight: bold; color: #FF6600;} \r\n");
88 output.append(" .error { font-weight: bold; color: #CC0000;} \r\n");
89 output.append(" table { margin-left: 2em; margin-right: 2em; border-left: 2px solid #AAA; }\r\n");
90 output.append(" tr.even { background: #FFFFFF; }\r\n");
91 output.append(" tr.odd { background: #EAEAEA; }\r\n");
92 output.append(" td { padding-right: 1ex; padding-left: 1ex; border-right: 2px solid #AAA; }\r\n");
93 output.append(" td.date { text-align: right; font-family: courier, monospace; font-size: smaller; }");
94 output.append(LINE_SEPARATOR);
95
96 output.append(" td.level { text-align: right; }");
97 output.append(LINE_SEPARATOR);
98 output.append(" tr.header { background: #596ED5; color: #FFF; font-weight: bold; font-size: larger; }");
99 output.append(CoreConstants.LINE_SEPARATOR);
100
101 output.append(" td.exception { background: #A2AEE8; white-space: pre; font-family: courier, monospace;}");
102 output.append(LINE_SEPARATOR);
103
104 output.append(" </STYLE>\r\n");
105
106 }
107
108 public void printList(StringBuilder buf, StatusManager sm) {
109 buf.append("<table>\r\n");
110 printHeader(buf);
111 List<Status> statusList = sm.getCopyOfStatusList();
112 for (Status s : statusList) {
113 count++;
114 printStatus(buf, s);
115 }
116 buf.append("</table>\r\n");
117 }
118
119 public void printHeader(StringBuilder buf) {
120 buf.append(" <tr class=\"header\">\r\n");
121 buf.append(" <th>Date </th>\r\n");
122 buf.append(" <th>Level</th>\r\n");
123 buf.append(" <th>Origin</th>\r\n");
124 buf.append(" <th>Message</th>\r\n");
125 buf.append(" </tr>\r\n");
126
127 }
128
129 String statusLevelAsString(Status s) {
130 switch (s.getEffectiveLevel()) {
131 case Status.INFO:
132 return "INFO";
133 case Status.WARN:
134 return "<span class=\"warn\">WARN</span>";
135 case Status.ERROR:
136 return "<span class=\"error\">ERROR</span>";
137 }
138 return null;
139 }
140
141 String abbreviatedOrigin(Status s) {
142 Object o = s.getOrigin();
143 if (o == null) {
144 return null;
145 }
146 String fqClassName = o.getClass().getName();
147 int lastIndex = fqClassName.lastIndexOf(CoreConstants.DOT);
148 if (lastIndex != -1) {
149 return fqClassName.substring(lastIndex + 1, fqClassName.length());
150 } else {
151 return fqClassName;
152 }
153 }
154
155 private void printStatus(StringBuilder buf, Status s) {
156 String trClass;
157 if (count % 2 == 0) {
158 trClass = "even";
159 } else {
160 trClass = "odd";
161 }
162 buf.append(" <tr class=\"").append(trClass).append("\">\r\n");
163 String dateStr = SDF.format(s.getTimestamp());
164 buf.append(" <td class=\"date\">").append(dateStr).append("</td>\r\n");
165 buf.append(" <td class=\"level\">").append(statusLevelAsString(s)).append("</td>\r\n");
166 buf.append(" <td>").append(abbreviatedOrigin(s)).append("</td>\r\n");
167 buf.append(" <td>").append(s.getMessage()).append("</td>\r\n");
168 buf.append(" </tr>\r\n");
169 if (s.getThrowable() != null) {
170 printThrowable(buf, s.getThrowable());
171 }
172 }
173
174 private void printThrowable(StringBuilder buf, Throwable t) {
175 buf.append(" <tr>\r\n");
176 buf.append(" <td colspan=\"4\" class=\"exception\"><pre>");
177 StringWriter sw = new StringWriter();
178 PrintWriter pw = new PrintWriter(sw);
179 t.printStackTrace(pw);
180 buf.append(Transform.escapeTags(sw.getBuffer()));
181 buf.append(" </pre></td>\r\n");
182 buf.append(" </tr>\r\n");
183
184 }
185 }