1
18 package net.bull.javamelody.internal.web.html;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.Writer;
23 import java.net.URL;
24 import java.nio.charset.StandardCharsets;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.Map;
30
31 import net.bull.javamelody.Parameter;
32 import net.bull.javamelody.SpringContext;
33 import net.bull.javamelody.internal.common.I18N;
34 import net.bull.javamelody.internal.common.InputOutput;
35 import net.bull.javamelody.internal.common.Parameters;
36 import net.bull.javamelody.internal.model.CacheInformations;
37 import net.bull.javamelody.internal.model.Collector;
38 import net.bull.javamelody.internal.model.CollectorServer;
39 import net.bull.javamelody.internal.model.ConnectionInformations;
40 import net.bull.javamelody.internal.model.Counter;
41 import net.bull.javamelody.internal.model.CounterRequestContext;
42 import net.bull.javamelody.internal.model.DatabaseInformations;
43 import net.bull.javamelody.internal.model.HeapHistogram;
44 import net.bull.javamelody.internal.model.HsErrPid;
45 import net.bull.javamelody.internal.model.JCacheInformations;
46 import net.bull.javamelody.internal.model.JavaInformations;
47 import net.bull.javamelody.internal.model.JndiBinding;
48 import net.bull.javamelody.internal.model.MBeanNode;
49 import net.bull.javamelody.internal.model.MavenArtifact;
50 import net.bull.javamelody.internal.model.Period;
51 import net.bull.javamelody.internal.model.ProcessInformations;
52 import net.bull.javamelody.internal.model.Range;
53 import net.bull.javamelody.internal.model.SamplingProfiler.SampledMethod;
54 import net.bull.javamelody.internal.model.SessionInformations;
55
56
60 public class HtmlReport extends HtmlAbstractReport {
61 private static final URL THEMED_MONITORING_CSS = HtmlReport.class
62 .getResource("/net/bull/javamelody/resource/themedMonitoring.css");
63 private static final URL THEMED_MONITORING_JS = HtmlReport.class
64 .getResource("/net/bull/javamelody/resource/themedMonitoring.js");
65
66 private final Collector collector;
67 private final CollectorServer collectorServer;
68 private final List<JavaInformations> javaInformationsList;
69 private final Range range;
70 private final HtmlCoreReport htmlCoreReport;
71
72 public HtmlReport(Collector collector, CollectorServer collectorServer,
73 List<JavaInformations> javaInformationsList, Range range, Writer writer) {
74 super(writer);
75 assert collector != null;
76 assert javaInformationsList != null && !javaInformationsList.isEmpty();
77 assert range != null;
78
79 this.collector = collector;
80 this.collectorServer = collectorServer;
81 this.javaInformationsList = javaInformationsList;
82 this.range = range;
83 this.htmlCoreReport = new HtmlCoreReport(collector, collectorServer, javaInformationsList,
84 range, writer);
85 }
86
87 public HtmlReport(Collector collector, CollectorServer collectorServer,
88 List<JavaInformations> javaInformationsList, Period period, Writer writer) {
89 this(collector, collectorServer, javaInformationsList, period.getRange(), writer);
90 }
91
92 @Override
93 void toHtml() throws IOException {
94 writeHtmlHeader();
95 htmlCoreReport.toHtml();
96 writeHtmlFooter();
97 }
98
99 public void toHtml(String message, String anchorNameForRedirect) throws IOException {
100 writeHtmlHeader();
101 htmlCoreReport.toHtml(message, anchorNameForRedirect);
102 writeHtmlFooter();
103 }
104
105 public void writeLastShutdown() throws IOException {
106 writeHtmlHeader(false, true);
107 htmlCoreReport.toHtml();
108 writeHtmlFooter();
109 }
110
111 public static void writeAddAndRemoveApplicationLinks(String currentApplication,
112 Collection<String> applications, Writer writer) throws IOException {
113 HtmlCoreReport.writeAddAndRemoveApplicationLinks(currentApplication, applications, writer);
114 }
115
116 public void writeAllCurrentRequestsAsPart() throws IOException {
117 writeHtmlHeader();
118 final List<Counter> counters = collector.getRangeCountersToBeDisplayed(range);
119 final Map<JavaInformations, List<CounterRequestContext>> currentRequests;
120 if (collectorServer == null) {
121 assert javaInformationsList.size() == 1;
122 final JavaInformations javaInformations = javaInformationsList.get(0);
123 final List<CounterRequestContext> rootCurrentContexts = collector
124 .getRootCurrentContexts(counters);
125 currentRequests = Collections.singletonMap(javaInformations, rootCurrentContexts);
126 } else {
127 currentRequests = collectorServer.collectCurrentRequests(collector.getApplication());
128 final List<CounterRequestContext> allCurrentRequests = new ArrayList<>();
129 for (final List<CounterRequestContext> rootCurrentContexts : currentRequests.values()) {
130 allCurrentRequests.addAll(rootCurrentContexts);
131 }
132 CounterRequestContext.replaceParentCounters(allCurrentRequests, counters);
133 }
134 htmlCoreReport.writeAllCurrentRequestsAsPart(currentRequests);
135 writeHtmlFooter();
136 }
137
138 public void writeAllThreadsAsPart() throws IOException {
139 writeHtmlHeader();
140 htmlCoreReport.writeAllThreadsAsPart();
141 writeHtmlFooter();
142 }
143
144 public void writeThreadsDump() throws IOException {
145 htmlCoreReport.writeThreadsDump();
146 }
147
148 public void writeCounterSummaryPerClass(String counterName, String requestId)
149 throws IOException {
150 writeHtmlHeader();
151 htmlCoreReport.writeCounterSummaryPerClass(counterName, requestId);
152 writeHtmlFooter();
153 }
154
155 public void writeSource(String className) throws IOException {
156 assert className != null;
157 writeHtmlHeader();
158 new HtmlSourceReport(className, getWriter()).toHtml();
159 writeHtmlFooter();
160 }
161
162 public void writeDependencies() throws IOException {
163 writeHtmlHeader();
164 final Map<String, MavenArtifact> dependencies = MavenArtifact.getWebappDependencies();
165 new HtmlDependenciesReport(dependencies, getWriter()).toHtml();
166 writeHtmlFooter();
167 }
168
169 public void writeSpringContext() throws IOException {
170 writeHtmlHeader();
171 final SpringContext springContext = SpringContext.getSingleton();
172 new HtmlSpringContextReport(springContext, getWriter()).toHtml();
173 writeHtmlFooter();
174 }
175
176 public void writeHtmlHeader() throws IOException {
177 writeHtmlHeader(false, false);
178 }
179
180 private void writeHtmlHeader(boolean includeSlider, boolean includeCssAndJsInline)
181 throws IOException {
182 writeln("<!DOCTYPE html PUBLIC \"-
183 writeDirectly("<html lang='" + I18N.getCurrentLocale().getLanguage() + "'><head><title>"
184 + getFormattedString("Monitoring_sur", collector.getApplication()) + "</title>");
185 writeln("");
186 if (includeCssAndJsInline) {
187 writeln("<style type='text/css'>");
188 try (InputStream in = getClass()
189 .getResourceAsStream(Parameters.getResourcePath("monitoring.css"))) {
190 final String monitoringCss = InputOutput.pumpToString(in, StandardCharsets.UTF_8);
191 writeDirectly(monitoringCss);
192 }
193 writeln("</style>");
194 writeln("<script type='text/javascript'>");
195 try (InputStream in = getClass()
196 .getResourceAsStream(Parameters.getResourcePath("prototype.js"))) {
197 final String monitoringJs = InputOutput.pumpToString(in, StandardCharsets.UTF_8);
198 writeDirectly(monitoringJs);
199 }
200 try (InputStream in = getClass()
201 .getResourceAsStream(Parameters.getResourcePath("monitoring.js"))) {
202 final String monitoringJs = InputOutput.pumpToString(in, StandardCharsets.UTF_8);
203 writeDirectly(monitoringJs);
204 }
205 writeln("</script>");
206 } else {
207 writeln("<link rel='stylesheet' href='?resource=monitoring.css' type='text/css'/>");
208
209 writeln("<script type='text/javascript' src='?resource=prototype.js'></script>");
210 writeln("<script type='text/javascript' src='?resource=monitoring.js'></script>");
211 if (THEMED_MONITORING_CSS != null) {
212 writeln("<link rel='stylesheet' href='?resource=themedMonitoring.css' type='text/css'/>");
213 }
214 writeln("<link rel='stylesheet' href='?resource=customizableMonitoring.css' type='text/css'/>");
215 }
216 writeln("<link type='image/png' rel='shortcut icon' href='?resource=systemmonitor.png' />");
217 writeln("<script type='text/javascript' src='?resource=resizable_tables.js'></script>");
218 writeln("<script type='text/javascript' src='?resource=sorttable.js'></script>");
219
220 writeln("<script type='text/javascript' src='?resource=effects.js'></script>");
221
222 writeln("<script type='text/javascript' src='?resource=lightwindow.js'></script>");
223 if (includeSlider) {
224 writeln("<script type='text/javascript' src='?resource=slider.js'></script>");
225 }
226 if (THEMED_MONITORING_JS != null) {
227 writeln("<script type='text/javascript' src='?resource=themedMonitoring.js'></script>");
228 }
229 writeln("<script type='text/javascript' src='?resource=customizableMonitoring.js'></script>");
230 writeln("</head><body>");
231 }
232
233 public void writeHtmlFooter() throws IOException {
234 final String analyticsId = Parameter.ANALYTICS_ID.getValue();
235 if (analyticsId != null && !"disabled".equals(analyticsId)) {
236 writeDirectly(
237 "<script type=\"text/javascript\" src=\"https:
238 + htmlEncodeButNotSpace(analyticsId) + "\"></script>");
239 }
240 writeln("</body></html>");
241 }
242
243 public void writeMessageIfNotNull(String message, String partToRedirectTo) throws IOException {
244 htmlCoreReport.writeMessageIfNotNull(message, partToRedirectTo, null);
245 }
246
247 public void writeRequestAndGraphDetail(String graphName) throws IOException {
248 writeHtmlHeader(true, false);
249
250 writeln("<div align='center'>");
251 htmlCoreReport.writeRefreshAndPeriodLinks(graphName, "graph");
252 writeln("</div>");
253
254 new HtmlCounterRequestGraphReport(range, getWriter()).writeRequestAndGraphDetail(collector,
255 collectorServer, graphName);
256
257 writeHtmlFooter();
258 }
259
260 public void writeRequestUsages(String graphName) throws IOException {
261 writeHtmlHeader(true, false);
262
263 writeln("<div align='center'>");
264 htmlCoreReport.writeRefreshAndPeriodLinks(graphName, "usages");
265 writeln("</div>");
266
267 new HtmlCounterRequestGraphReport(range, getWriter()).writeRequestUsages(collector,
268 graphName);
269
270 writeHtmlFooter();
271 }
272
273 public void writeSessions(List<SessionInformations> sessionsInformations, String message,
274 String sessionsPart) throws IOException {
275 assert sessionsInformations != null;
276 writeHtmlHeader();
277 writeMessageIfNotNull(message, sessionsPart);
278 new HtmlSessionInformationsReport(sessionsInformations, getWriter()).toHtml();
279 writeHtmlFooter();
280 }
281
282 public void writeSessionDetail(String sessionId, SessionInformations sessionInformations)
283 throws IOException {
284 assert sessionId != null;
285 writeHtmlHeader();
286 new HtmlSessionInformationsReport(null, getWriter()).writeSessionDetails(sessionId,
287 sessionInformations);
288 writeHtmlFooter();
289 }
290
291 public void writeHotspots(List<SampledMethod> hotspots) throws IOException {
292 writeHtmlHeader();
293 new HtmlHotspotsReport(hotspots, getWriter()).toHtml();
294 writeHtmlFooter();
295 }
296
297 public void writeHeapHistogram(HeapHistogram heapHistogram, String message,
298 String heapHistoPart) throws IOException {
299 assert heapHistogram != null;
300 writeHtmlHeader();
301 writeMessageIfNotNull(message, heapHistoPart);
302 new HtmlHeapHistogramReport(heapHistogram, getWriter()).toHtml();
303 writeHtmlFooter();
304 }
305
306 public void writeProcesses(List<ProcessInformations> processInformationsList)
307 throws IOException {
308 assert processInformationsList != null;
309 writeHtmlHeader();
310 new HtmlProcessInformationsReport(processInformationsList, getWriter()).toHtml();
311 writeHtmlFooter();
312 }
313
314 public void writeProcesses(Map<String, List<ProcessInformations>> processesByTitle)
315 throws IOException {
316 assert processesByTitle != null;
317 writeHtmlHeader();
318 new HtmlProcessInformationsReport(new ArrayList<ProcessInformations>(), getWriter())
319 .writeLinks();
320 for (final Map.Entry<String, List<ProcessInformations>> entry : processesByTitle
321 .entrySet()) {
322 final String title = entry.getKey();
323 final List<ProcessInformations> processes = entry.getValue();
324 writeDirectly("<h3 class='chapterTitle'><img src='?resource=processes.png' alt='"
325 + title + "'/> " + title + "</h3>");
326
327 new HtmlProcessInformationsReport(processes, getWriter()).writeTable();
328 }
329 writeHtmlFooter();
330 }
331
332 public void writeDatabase(DatabaseInformations databaseInformations) throws IOException {
333 assert databaseInformations != null;
334 writeHtmlHeader();
335 new HtmlDatabaseInformationsReport(databaseInformations, getWriter()).toHtml();
336 writeHtmlFooter();
337 }
338
339 public void writeConnections(List<ConnectionInformations> connectionInformationsList,
340 boolean withoutHeaders) throws IOException {
341 assert connectionInformationsList != null;
342 final HtmlConnectionInformationsReport htmlConnectionInformationsReport = new HtmlConnectionInformationsReport(
343 connectionInformationsList, getWriter());
344 if (withoutHeaders) {
345
346 htmlConnectionInformationsReport.writeConnections();
347 } else {
348 writeHtmlHeader();
349 htmlConnectionInformationsReport.toHtml();
350 writeHtmlFooter();
351 }
352 }
353
354 public void writeJndi(List<JndiBinding> jndiBindings, String path) throws IOException {
355 assert jndiBindings != null;
356 writeHtmlHeader();
357 new HtmlJndiTreeReport(jndiBindings, path, getWriter()).toHtml();
358 writeHtmlFooter();
359 }
360
361 public void writeMBeans(List<MBeanNode> mbeans) throws IOException {
362 assert mbeans != null;
363 writeHtmlHeader();
364 new HtmlMBeansReport(mbeans, getWriter()).toHtml();
365 writeHtmlFooter();
366 }
367
368 public void writeMBeans(Map<String, List<MBeanNode>> mbeansByTitle) throws IOException {
369 assert mbeansByTitle != null;
370 writeHtmlHeader();
371 new HtmlMBeansReport(new ArrayList<MBeanNode>(), getWriter()).writeLinks();
372 for (final Map.Entry<String, List<MBeanNode>> entry : mbeansByTitle.entrySet()) {
373 final String title = entry.getKey();
374 final List<MBeanNode> nodes = entry.getValue();
375 writeDirectly("<h3 class='chapterTitle'><img src='?resource=mbeans.png' alt='" + title
376 + "'/> " + title + "</h3>");
377
378 new HtmlMBeansReport(nodes, getWriter()).writeTree();
379 }
380 writeHtmlFooter();
381 }
382
383 public void writeCacheWithKeys(String cacheId, CacheInformations cacheInformations,
384 String message, String cacheKeyPart, boolean withoutHeaders) throws IOException {
385 assert cacheId != null;
386 assert cacheInformations != null;
387 final HtmlCacheInformationsReport htmlCacheInformationsReport = new HtmlCacheInformationsReport(
388 Collections.singletonList(cacheInformations), getWriter());
389 if (withoutHeaders) {
390 htmlCacheInformationsReport.writeCacheWithKeys(cacheId, withoutHeaders);
391 } else {
392 writeHtmlHeader();
393 htmlCacheInformationsReport.writeCacheWithKeys(cacheId, withoutHeaders);
394 writeHtmlFooter();
395 writeMessageIfNotNull(message, cacheKeyPart);
396 }
397 }
398
399 public void writeJCacheWithKeys(String cacheId, JCacheInformations jcacheInformations,
400 String message, String cacheKeyPart, boolean withoutHeaders) throws IOException {
401 assert cacheId != null;
402 assert jcacheInformations != null;
403 final HtmlJCacheInformationsReport htmlJCacheInformationsReport = new HtmlJCacheInformationsReport(
404 Collections.singletonList(jcacheInformations), getWriter());
405 if (withoutHeaders) {
406 htmlJCacheInformationsReport.writeJCacheWithKeys(cacheId, withoutHeaders);
407 } else {
408 writeHtmlHeader();
409 htmlJCacheInformationsReport.writeJCacheWithKeys(cacheId, withoutHeaders);
410 writeHtmlFooter();
411 writeMessageIfNotNull(message, cacheKeyPart);
412 }
413 }
414
415 public void writeCrashes() throws IOException {
416 writeHtmlHeader();
417 final List<HsErrPid> hsErrPidList = htmlCoreReport.getHsErrPidList();
418 final HtmlHsErrPidReport htmlHsErrPidReport = new HtmlHsErrPidReport(hsErrPidList,
419 getWriter());
420 htmlHsErrPidReport.toHtml();
421 writeHtmlFooter();
422 }
423
424 public void writeHashPassword(String algorithm, String password) throws IOException {
425 writeHtmlHeader();
426 final HtmlHashPasswordReport htmlHashPasswordReport = new HtmlHashPasswordReport(
427 getWriter());
428 htmlHashPasswordReport.writeHashPassword(algorithm, password);
429 writeHtmlFooter();
430 }
431 }
432