/* * Copyright 2008-2014 by Emeric Vernat * * This file is part of Java Melody. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.bull.javamelody; import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.lowagie.text.Chunk; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.Image; import com.lowagie.text.Paragraph; import com.lowagie.text.Phrase; import com.lowagie.text.pdf.PdfPCell; /** * Partie du rapport pdf pour les threads sur le serveur. * @author Emeric Vernat */ class PdfThreadInformationsReport extends PdfAbstractTableReport { private final List<ThreadInformations> threadInformationsList; private final DecimalFormat integerFormat = I18N.createIntegerFormat(); private final boolean stackTraceEnabled; private final boolean cpuTimeEnabled; private final Font cellFont = PdfFonts.TABLE_CELL.getFont(); private final PdfDocumentFactory pdfDocumentFactory; PdfThreadInformationsReport(List<ThreadInformations> threadInformationsList, boolean stackTraceEnabled, PdfDocumentFactory pdfDocumentFactory, Document document) { super(document); assert threadInformationsList != null; assert pdfDocumentFactory != null; this.threadInformationsList = threadInformationsList; this.pdfDocumentFactory = pdfDocumentFactory; this.stackTraceEnabled = stackTraceEnabled; this.cpuTimeEnabled = !threadInformationsList.isEmpty() && threadInformationsList.get(0).getCpuTimeMillis() != -1; } @Override void toPdf() throws DocumentException, IOException { writeHeader(); for (final ThreadInformations threadInformations : threadInformationsList) { nextRow(); writeThreadInformations(threadInformations); } addTableToDocument(); final Paragraph tempsThreads = new Paragraph(getString("Temps_threads") + '\n', cellFont); tempsThreads.setAlignment(Element.ALIGN_RIGHT); addToDocument(tempsThreads); // rq stack-trace: on n'inclue pas dans le pdf les stack-traces des threads // car c'est très verbeux et cela remplirait des pages pour pas grand chose // d'autant que si le pdf est généré de nuit pour être envoyé par mail // alors ces stack-traces n'ont pas beaucoup d'intérêt // if (stackTrace != null && !stackTrace.isEmpty()) { // // même si stackTraceEnabled, ce thread n'a pas forcément de stack-trace // writeln(threadInformations.getName()); // for (final StackTraceElement stackTraceElement : stackTrace) { // writeln(stackTraceElement.toString()); // } // } } void writeDeadlocks() throws DocumentException { final List<ThreadInformations> deadlockedThreads = new ArrayList<ThreadInformations>(); for (final ThreadInformations thread : threadInformationsList) { if (thread.isDeadlocked()) { deadlockedThreads.add(thread); } } if (!deadlockedThreads.isEmpty()) { final StringBuilder sb = new StringBuilder(); sb.append('\n'); sb.append(getString("Threads_deadlocks")); String separator = " "; for (final ThreadInformations thread : deadlockedThreads) { sb.append(separator); sb.append(thread.getName()); separator = ", "; } sb.append('\n'); addToDocument(new Phrase(sb.toString(), PdfFonts.SEVERE_CELL.getFont())); } } private void writeHeader() throws DocumentException { final List<String> headers = createHeaders(); final int[] relativeWidths = new int[headers.size()]; Arrays.fill(relativeWidths, 0, headers.size(), 1); relativeWidths[0] = 3; // thread relativeWidths[3] = 2; // état if (stackTraceEnabled) { relativeWidths[4] = 6; // méthode exécutée } initTable(headers, relativeWidths); } private List<String> createHeaders() { final List<String> headers = new ArrayList<String>(); headers.add(getString("Thread")); headers.add(getString("Demon")); headers.add(getString("Priorite")); headers.add(getString("Etat")); if (stackTraceEnabled) { headers.add(getString("Methode_executee")); } if (cpuTimeEnabled) { headers.add(getString("Temps_cpu")); headers.add(getString("Temps_user")); } return headers; } private void writeThreadInformations(ThreadInformations threadInformations) throws DocumentException, IOException { final PdfPCell defaultCell = getDefaultCell(); defaultCell.setHorizontalAlignment(Element.ALIGN_LEFT); addCell(threadInformations.getName()); defaultCell.setHorizontalAlignment(Element.ALIGN_CENTER); if (threadInformations.isDaemon()) { addCell(getString("oui")); } else { addCell(getString("non")); } defaultCell.setHorizontalAlignment(Element.ALIGN_RIGHT); addCell(integerFormat.format(threadInformations.getPriority())); defaultCell.setHorizontalAlignment(Element.ALIGN_LEFT); final PdfPCell cell = new PdfPCell(); final Paragraph paragraph = new Paragraph(getDefaultCell().getLeading() + cellFont.getSize()); paragraph.add(new Chunk(getImage("bullets/" + HtmlThreadInformationsReport.getStateIcon(threadInformations)), 0, -1)); paragraph.add(new Phrase(String.valueOf(threadInformations.getState()), cellFont)); cell.addElement(paragraph); addCell(cell); if (stackTraceEnabled) { addCell(threadInformations.getExecutedMethod()); } if (cpuTimeEnabled) { defaultCell.setHorizontalAlignment(Element.ALIGN_RIGHT); addCell(integerFormat.format(threadInformations.getCpuTimeMillis())); addCell(integerFormat.format(threadInformations.getUserTimeMillis())); } } private Image getImage(String resourceFileName) throws DocumentException, IOException { return pdfDocumentFactory.getSmallImage(resourceFileName); } }