1 /*
2  * Copyright 2008-2019 by Emeric Vernat
3  *
4  *     This file is part of Java Melody.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package net.bull.javamelody.internal.web.html;
19
20 import java.io.IOException;
21 import java.io.Writer;
22 import java.text.DateFormat;
23 import java.util.List;
24
25 import net.bull.javamelody.internal.common.I18N;
26 import net.bull.javamelody.internal.model.Counter;
27 import net.bull.javamelody.internal.model.CounterError;
28
29 /**
30  * Partie du rapport html pour les erreurs http et dans les logs.
31  * @author Emeric Vernat
32  */

33 public class HtmlCounterErrorReport extends HtmlAbstractReport {
34     private final Counter counter;
35     private final DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,
36             DateFormat.MEDIUM, I18N.getCurrentLocale());
37
38     HtmlCounterErrorReport(Counter counter, Writer writer) {
39         super(writer);
40         assert counter != null;
41         assert counter.isErrorCounter();
42
43         this.counter = counter;
44     }
45
46     @Override
47     void toHtml() throws IOException {
48         final List<CounterError> errors = counter.getErrors();
49         if (errors.isEmpty()) {
50             writeln("#Aucune_erreur#");
51         } else {
52             writeErrors(errors);
53         }
54     }
55
56     private void writeErrors(List<CounterError> errors) throws IOException {
57         assert errors != null;
58         final boolean displayUser = shouldDisplayUser(errors);
59         final boolean displayHttpRequest = shouldDisplayHttpRequest(errors);
60         if (errors.size() >= Counter.MAX_ERRORS_COUNT) {
61             write("<div class='severe' align='left'>");
62             writeln(getFormattedString("Dernieres_erreurs_seulement", Counter.MAX_ERRORS_COUNT));
63             write("</div>");
64         }
65         final String tableName = counter.getName();
66         final HtmlTable table = new HtmlTable();
67         table.beginTable(tableName);
68         write("<th class='sorttable_date'>#Date#</th>");
69         if (displayHttpRequest) {
70             write("<th>#Requete#</th>");
71         }
72         if (displayUser) {
73             write("<th>#Utilisateur#</th>");
74         }
75         write("<th>#Erreur#</th>");
76         for (final CounterError error : errors) {
77             table.nextRow();
78             writeError(error, displayUser, displayHttpRequest);
79         }
80         table.endTable();
81     }
82
83     private void writeError(CounterError error, boolean displayUser, boolean displayHttpRequest)
84             throws IOException {
85         write("<td align='right'>");
86         write(dateTimeFormat.format(error.getDate()));
87         if (displayHttpRequest) {
88             write("</td><td class='wrappedText'>");
89             if (error.getHttpRequest() == null) {
90                 write("&nbsp;");
91             } else {
92                 writeDirectly(htmlEncode(error.getHttpRequest()));
93             }
94         }
95         if (displayUser) {
96             write("</td><td class='wrappedText'>");
97             if (error.getRemoteUser() == null) {
98                 write("&nbsp;");
99             } else {
100                 writeDirectly(htmlEncode(error.getRemoteUser()));
101             }
102         }
103         if (error.getStackTrace() != null) {
104             write("</td><td>"); // pas wrappedText ici, sinon bug de largeur du tooltip sous IE11 en résolution réduite
105             writeln("<div class='tooltip'>");
106             writeln("<em>");
107             writeStackTrace(error);
108             writeln("</em>");
109             // writeDirectly pour ne pas gérer de traductions si le message contient '#'
110             writeDirectly(htmlEncode(error.getMessage()));
111             writeln("</div>");
112         } else {
113             write("</td><td class='wrappedText'>");
114             // writeDirectly pour ne pas gérer de traductions si le message contient '#'
115             writeDirectly(htmlEncode(error.getMessage()));
116         }
117         write("</td>");
118     }
119
120     private void writeStackTrace(CounterError error) throws IOException {
121         for (final String element : error.getStackTrace().split("[\n\r]")) {
122             if (!element.isEmpty()) {
123                 // writeDirectly pour ne pas gérer de traductions car les liens contiennent '#'
124                 writeDirectly(HtmlSourceReport.htmlEncodeStackTraceElementAndTabs(element));
125                 writeDirectly("<br/>\n");
126             }
127         }
128     }
129
130     public static boolean shouldDisplayUser(List<CounterError> errors) {
131         for (final CounterError error : errors) {
132             if (error.getRemoteUser() != null) {
133                 return true;
134             }
135         }
136         return false;
137     }
138
139     public static boolean shouldDisplayHttpRequest(List<CounterError> errors) {
140         for (final CounterError error : errors) {
141             if (error.getHttpRequest() != null) {
142                 return true;
143             }
144         }
145         return false;
146     }
147 }
148