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.pdf;
19
20 import java.io.IOException;
21 import java.io.OutputStream;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Map;
25
26 import com.lowagie.text.Document;
27 import com.lowagie.text.DocumentException;
28 import com.lowagie.text.Element;
29 import com.lowagie.text.Font;
30 import com.lowagie.text.Phrase;
31
32 import net.bull.javamelody.internal.common.I18N;
33 import net.bull.javamelody.internal.model.Collector;
34 import net.bull.javamelody.internal.model.CollectorServer;
35 import net.bull.javamelody.internal.model.Counter;
36 import net.bull.javamelody.internal.model.CounterRequest;
37 import net.bull.javamelody.internal.model.CounterRequestAggregation;
38 import net.bull.javamelody.internal.model.CounterRequestContext;
39 import net.bull.javamelody.internal.model.DatabaseInformations;
40 import net.bull.javamelody.internal.model.HeapHistogram;
41 import net.bull.javamelody.internal.model.JavaInformations;
42 import net.bull.javamelody.internal.model.JndiBinding;
43 import net.bull.javamelody.internal.model.MBeanNode;
44 import net.bull.javamelody.internal.model.Period;
45 import net.bull.javamelody.internal.model.ProcessInformations;
46 import net.bull.javamelody.internal.model.Range;
47 import net.bull.javamelody.internal.model.SamplingProfiler.SampledMethod;
48 import net.bull.javamelody.internal.model.SessionInformations;
49
50 /**
51  * Rapports pdf secondaires (avec iText).
52  * @author Emeric Vernat
53  */

54 public class PdfOtherReport {
55     private final OutputStream output;
56     private final Document document;
57     private final PdfDocumentFactory pdfDocumentFactory;
58
59     public PdfOtherReport(String application, OutputStream output) throws IOException {
60         super();
61         assert output != null;
62         this.output = output;
63
64         try {
65             pdfDocumentFactory = new PdfDocumentFactory(application, null, output);
66             this.document = pdfDocumentFactory.createDocument();
67         } catch (final DocumentException e) {
68             throw createIOException(e);
69         }
70     }
71
72     public void close() throws IOException {
73         output.close();
74     }
75
76     public void writeSessionInformations(List<SessionInformations> sessionsInformations)
77             throws IOException {
78         try {
79             document.open();
80             addParagraph(getString("Sessions"), "system-users.png");
81             new PdfSessionInformationsReport(sessionsInformations, document).toPdf();
82         } catch (final DocumentException e) {
83             throw createIOException(e);
84         }
85         document.close();
86     }
87
88     public void writeHeapHistogram(HeapHistogram heapHistogram) throws IOException {
89         try {
90             document.open();
91             addParagraph(
92                     getFormattedString("heap_histo_du",
93                             I18N.createDateAndTimeFormat().format(heapHistogram.getTime())),
94                     "memory.png");
95             new PdfHeapHistogramReport(heapHistogram, document).toPdf();
96         } catch (final DocumentException e) {
97             throw createIOException(e);
98         }
99         document.close();
100     }
101
102     public void writeHotspots(List<SampledMethod> hotspots) throws IOException {
103         try {
104             document.open();
105             addParagraph(getString("hotspots"), "clock.png");
106             new PdfHotspotsReport(hotspots, document).toPdf();
107         } catch (final DocumentException e) {
108             throw createIOException(e);
109         }
110         document.close();
111     }
112
113     public void writeProcessInformations(List<ProcessInformations> processInformations)
114             throws IOException {
115         try {
116             document.open();
117             addParagraph(getString("Processus"), "processes.png");
118             new PdfProcessInformationsReport(processInformations, document).toPdf();
119         } catch (final DocumentException e) {
120             throw createIOException(e);
121         }
122         document.close();
123     }
124
125     public void writeProcessInformations(
126             Map<String, List<ProcessInformations>> processInformationsByTitle) throws IOException {
127         try {
128             document.open();
129             for (final Map.Entry<String, List<ProcessInformations>> entry : processInformationsByTitle
130                     .entrySet()) {
131                 addParagraph(entry.getKey(), "processes.png");
132                 new PdfProcessInformationsReport(entry.getValue(), document).toPdf();
133             }
134         } catch (final DocumentException e) {
135             throw createIOException(e);
136         }
137         document.close();
138     }
139
140     public void writeDatabaseInformations(DatabaseInformations databaseInformations)
141             throws IOException {
142         try {
143             document.open();
144             final String selectedRequestName = databaseInformations.getSelectedRequestName();
145             addParagraph(getString("database") + " : " + getString(selectedRequestName), "db.png");
146             new PdfDatabaseInformationsReport(databaseInformations, document).toPdf();
147         } catch (final DocumentException e) {
148             throw createIOException(e);
149         }
150         document.close();
151     }
152
153     public void writeJndi(List<JndiBinding> jndiBindings, String path) throws IOException {
154         try {
155             document.open();
156             if (path.isEmpty()) {
157                 addParagraph(getString("Arbre_JNDI"), "jndi.png");
158             } else {
159                 addParagraph(getFormattedString("Arbre_JNDI_pour_contexte", path), "jndi.png");
160             }
161             new PdfJndiReport(jndiBindings, document).toPdf();
162         } catch (final DocumentException e) {
163             throw createIOException(e);
164         }
165         document.close();
166     }
167
168     public void writeMBeans(List<MBeanNode> mbeans) throws IOException {
169         try {
170             document.open();
171             addParagraph(getString("MBeans"), "mbeans.png");
172             new PdfMBeansReport(mbeans, document).toPdf();
173         } catch (final DocumentException e) {
174             throw createIOException(e);
175         }
176         document.close();
177     }
178
179     public void writeMBeans(Map<String, List<MBeanNode>> mbeansByTitle) throws IOException {
180         try {
181             document.open();
182             for (final Map.Entry<String, List<MBeanNode>> entry : mbeansByTitle.entrySet()) {
183                 addParagraph(entry.getKey(), "mbeans.png");
184                 new PdfMBeansReport(entry.getValue(), document).toPdf();
185             }
186         } catch (final DocumentException e) {
187             throw createIOException(e);
188         }
189         document.close();
190     }
191
192     public void writeAllCurrentRequestsAsPart(
193             Map<JavaInformations, List<CounterRequestContext>> currentRequests, Collector collector,
194             List<Counter> counters, long timeOfSnapshot) throws IOException {
195         try {
196             document.open();
197
198             // on remplace les parentCounters
199             final List<CounterRequestContext> allCurrentRequests = new ArrayList<>();
200             for (final List<CounterRequestContext> rootCurrentContexts : currentRequests.values()) {
201                 allCurrentRequests.addAll(rootCurrentContexts);
202             }
203             CounterRequestContext.replaceParentCounters(allCurrentRequests, counters);
204             final List<PdfCounterReport> pdfCounterReports = new ArrayList<>();
205             // ce range n'a pas d'importance pour ce pdf
206             final Range range = Period.TOUT.getRange();
207             for (final Counter counter : counters) {
208                 final PdfCounterReport pdfCounterReport = new PdfCounterReport(collector, counter,
209                         range, false, document);
210                 pdfCounterReports.add(pdfCounterReport);
211             }
212             final Font normalFont = PdfFonts.NORMAL.getFont();
213             for (final Map.Entry<JavaInformations, List<CounterRequestContext>> entry : currentRequests
214                     .entrySet()) {
215                 final JavaInformations javaInformations = entry.getKey();
216                 final List<CounterRequestContext> rootCurrentContexts = entry.getValue();
217                 addParagraph(getString("Requetes_en_cours"), "hourglass.png");
218                 if (rootCurrentContexts.isEmpty()) {
219                     addToDocument(new Phrase(getString("Aucune_requete_en_cours"), normalFont));
220                 } else {
221                     final PdfCounterRequestContextReport pdfCounterRequestContextReport = new PdfCounterRequestContextReport(
222                             rootCurrentContexts, pdfCounterReports,
223                             javaInformations.getThreadInformationsList(),
224                             javaInformations.isStackTraceEnabled(), pdfDocumentFactory, document);
225                     pdfCounterRequestContextReport.setTimeOfSnapshot(timeOfSnapshot);
226                     pdfCounterRequestContextReport.writeContextDetails();
227                 }
228             }
229         } catch (final DocumentException e) {
230             throw createIOException(e);
231         }
232         document.close();
233     }
234
235     public void writeRequestAndGraphDetail(Collector collector, CollectorServer collectorServer,
236             Range range, String requestId) throws IOException {
237         try {
238             document.open();
239             new PdfRequestAndGraphDetailReport(collector, collectorServer, range, requestId,
240                     pdfDocumentFactory, document).toPdf();
241         } catch (final DocumentException e) {
242             throw createIOException(e);
243         }
244         document.close();
245     }
246
247     public void writeRuntimeDependencies(Counter counter, Range range) throws IOException {
248         try {
249             final Document myDocument = pdfDocumentFactory.createDocument(true);
250             myDocument.open();
251             final String counterLabel = getString(counter.getName() + "Label");
252             final String paragraphTitle = getFormattedString("Dependance_compteur", counterLabel)
253                     + " - " + range.getLabel();
254             myDocument.add(pdfDocumentFactory.createParagraphElement(paragraphTitle,
255                     counter.getIconName()));
256             new PdfRuntimeDependenciesReport(counter, myDocument).toPdf();
257             myDocument.close();
258         } catch (final DocumentException e) {
259             throw createIOException(e);
260         }
261     }
262
263     public void writeCounterSummaryPerClass(Collector collector, Counter counter, String requestId,
264             Range range) throws IOException {
265         final List<CounterRequest> requestList = new CounterRequestAggregation(counter)
266                 .getRequestsAggregatedOrFilteredByClassName(requestId);
267         try {
268             document.open();
269             final String counterLabel = getString(counter.getName() + "Label");
270             final String title = getFormattedString("Statistiques_compteur", counterLabel) + " - "
271                     + range.getLabel();
272             addParagraph(title, counter.getIconName());
273             new PdfCounterReport(collector, counter, range, false, document)
274                     .writeRequests(counter.getChildCounterName(), requestList);
275         } catch (final DocumentException e) {
276             throw createIOException(e);
277         }
278         document.close();
279     }
280
281     public void writeThreads(List<JavaInformations> javaInformationsList) throws IOException {
282         try {
283             document.open();
284             addParagraph(getString("Threads"), "threads.png");
285             String eol = "";
286             final Font normalFont = PdfFonts.NORMAL.getFont();
287             for (final JavaInformations javaInformations : javaInformationsList) {
288                 addToDocument(new Phrase(eol, normalFont));
289
290                 final PdfThreadInformationsReport pdfThreadInformationsReport = new PdfThreadInformationsReport(
291                         javaInformations.getThreadInformationsList(),
292                         javaInformations.isStackTraceEnabled(), pdfDocumentFactory, document);
293                 pdfThreadInformationsReport.writeIntro(javaInformations);
294                 pdfThreadInformationsReport.writeDeadlocks();
295
296                 pdfThreadInformationsReport.toPdf();
297                 eol = "\n";
298             }
299         } catch (final DocumentException e) {
300             throw createIOException(e);
301         }
302         document.close();
303     }
304
305     private static IOException createIOException(Exception e) {
306         // Rq: le constructeur de IOException avec message et cause n'existe qu'en jdk 1.6
307         return new IOException(e.getMessage(), e);
308     }
309
310     private void addParagraph(String paragraphTitle, String iconName)
311             throws DocumentException, IOException {
312         addToDocument(pdfDocumentFactory.createParagraphElement(paragraphTitle, iconName));
313     }
314
315     private static String getString(String key) {
316         return I18N.getString(key);
317     }
318
319     private static String getFormattedString(String key, Object... arguments) {
320         return I18N.getFormattedString(key, arguments);
321     }
322
323     private void addToDocument(Element element) throws DocumentException {
324         document.add(element);
325     }
326 }
327