View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
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"); // orange
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 }