/* * Copyright 2008-2017 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.io.OutputStream; import java.util.HashMap; import java.util.Locale; import java.util.Map; import com.lowagie.text.BadElementException; import com.lowagie.text.ChapterAutoNumber; 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.HeaderFooter; import com.lowagie.text.Image; import com.lowagie.text.PageSize; import com.lowagie.text.Paragraph; import com.lowagie.text.Phrase; import com.lowagie.text.Rectangle; import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfPageEventHelper; import com.lowagie.text.pdf.PdfTemplate; import com.lowagie.text.pdf.PdfWriter; /** * Factory pour les documents pdf. * @author Emeric Vernat */ class PdfDocumentFactory { private final String application; private final Range range; private final OutputStream output; private final Map<String, Image> paragraphImagesByResourceName = new HashMap<String, Image>(); private final Map<String, Image> smallImagesByResourceName = new HashMap<String, Image>(); private final Font paragraphTitleFont = PdfFonts.PARAGRAPH_TITLE.getFont(); private static class PdfAdvancedPageNumberEvents extends PdfPageEventHelper { // This is the contentbyte object of the writer private PdfContentByte cb; // we will put the final number of pages in a template private PdfTemplate template; // this is the BaseFont we are going to use for the header / footer private final BaseFont bf; PdfAdvancedPageNumberEvents() throws DocumentException, IOException { super(); bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); } // we override the onGenericTag method /** {@inheritDoc} */ @Override public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) { // rien ici } // we override the onOpenDocument method /** {@inheritDoc} */ @Override public void onOpenDocument(PdfWriter writer, Document document) { cb = writer.getDirectContent(); template = cb.createTemplate(50, 50); } // we override the onChapter method /** {@inheritDoc} */ @Override public void onChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) { // rien ici } // we override the onEndPage method /** {@inheritDoc} */ @Override public void onEndPage(PdfWriter writer, Document document) { final int pageN = writer.getPageNumber(); final String text = pageN + " / "; final float len = bf.getWidthPoint(text, 8); cb.beginText(); cb.setFontAndSize(bf, 8); final float width = document.getPageSize().getWidth(); cb.setTextMatrix(width / 2, 30); cb.showText(text); cb.endText(); cb.addTemplate(template, width / 2 + len, 30); } // we override the onCloseDocument method /** {@inheritDoc} */ @Override public void onCloseDocument(PdfWriter writer, Document document) { template.beginText(); template.setFontAndSize(bf, 8); template.showText(String.valueOf(writer.getPageNumber() - 1)); template.endText(); } } PdfDocumentFactory(String application, Range range, OutputStream output) { super(); assert application != null; assert output != null; // range peut être null this.application = application; this.range = range; this.output = output; } Document createDocument() throws DocumentException, IOException { return createDocument(false); } Document createDocument(boolean landscape) throws DocumentException, IOException { // creation of a document-object final Rectangle pageSize = getPageSize(landscape); // marges de 20 à gauche, à droite et en haut pour bien utiliser la largeur // et avoir une meilleur lisibilité sur les tableaux larges, // mais marge de 40 en bas pour ne pas empiéter sur les numéros de pages final Document document = new Document(pageSize, 20, 20, 20, 40); final String title; if (range == null) { title = I18N.getFormattedString("Monitoring_sur", application); } else { title = I18N.getFormattedString("Monitoring_sur", application) + " - " + range.getLabel(); } createWriter(document, title); // we add some meta information to the document (after writer) document.addAuthor(application); document.addCreator( "JavaMelody par E. Vernat, https://github.com/javamelody/javamelody/wiki"); document.addTitle(title); return document; } private Rectangle getPageSize(boolean landscape) { Rectangle pageSize; if (Locale.US.getCountry().equals(I18N.getCurrentLocale().getCountry())) { // Letter size paper is used in the US instead of the ISO standard A4 pageSize = PageSize.LETTER; } else { pageSize = PageSize.A4; } if (landscape) { pageSize = pageSize.rotate(); } return pageSize; } // We create a writer that listens to the document and directs a PDF-stream to output private void createWriter(Document document, String title) throws DocumentException, IOException { final PdfWriter writer = PdfWriter.getInstance(document, output); //writer.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft); // title final HeaderFooter header = new HeaderFooter(new Phrase(title), false); header.setAlignment(Element.ALIGN_LEFT); header.setBorder(Rectangle.NO_BORDER); document.setHeader(header); // simple page numbers : x //HeaderFooter footer = new HeaderFooter(new Phrase(), true); //footer.setAlignment(Element.ALIGN_RIGHT); //footer.setBorder(Rectangle.TOP); //document.setFooter(footer); // add the event handler for advanced page numbers : x/y writer.setPageEvent(new PdfAdvancedPageNumberEvents()); } Element createParagraphElement(String paragraphTitle, String iconName) throws DocumentException, IOException { final Paragraph paragraph = new Paragraph("", paragraphTitleFont); paragraph.setSpacingBefore(5); paragraph.setSpacingAfter(5); if (iconName != null) { paragraph.add(new Chunk(getParagraphImage(iconName), 0, -5)); } final Phrase element = new Phrase(' ' + paragraphTitle, paragraphTitleFont); element.setLeading(12); paragraph.add(element); // chapter pour avoir la liste des signets final ChapterAutoNumber chapter = new ChapterAutoNumber(paragraph); // sans numéro de chapitre chapter.setNumberDepth(0); chapter.setBookmarkOpen(false); chapter.setTriggerNewPage(false); return chapter; } private Image getParagraphImage(String resourceFileName) throws DocumentException, IOException { Image image = paragraphImagesByResourceName.get(resourceFileName); if (image == null) { image = getImage(resourceFileName); image.scaleAbsolute(16, 16); paragraphImagesByResourceName.put(resourceFileName, image); } return image; } Image getSmallImage(String resourceFileName) throws DocumentException, IOException { Image image = smallImagesByResourceName.get(resourceFileName); if (image == null) { image = getImage(resourceFileName); image.scaleAbsolute(8, 8); smallImagesByResourceName.put(resourceFileName, image); } return image; } static Image getImage(String resourceFileName) throws BadElementException, IOException { return Image.getInstance( PdfDocumentFactory.class.getResource(Parameters.getResourcePath(resourceFileName))); } }