org.wso2.carbon.apimgt.impl.reportgen.ReportGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.apimgt.impl.reportgen.ReportGenerator.java

Source

/*
 * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you 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 org.wso2.carbon.apimgt.impl.reportgen;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
import org.wso2.carbon.apimgt.impl.internal.APIManagerComponent;
import org.wso2.carbon.apimgt.impl.reportgen.model.RowEntry;
import org.wso2.carbon.apimgt.impl.reportgen.model.TableData;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
import java.util.List;

public class ReportGenerator {
    private static final Log log = LogFactory.getLog(ReportGenerator.class);

    private static final String MGW_META = "MGW_CODE";
    private static final String MGW_KEY = "dmMzU0R5MTI4N2ExRlNnMQ==";
    private static final String MGW_ALGO = "AES";

    private static final float[] COLUMN_WIDTH = { 50, 200, 150 };
    private static final float ROW_HEIGHT = 25;
    private static final float CELL_PADDING = 10;
    private static final float CELL_MARGIN = 40; // margin on left side;
    private static final float TABLE_WIDTH = 500;
    private static final float TABLE_TOP_Y = 700;

    // Font configuration
    private static final PDFont TEXT_FONT = PDType1Font.HELVETICA;
    private static final float FONT_SIZE = 9;

    /**
     * Generate PDF file for API microgateway request summary
     *
     * @param table object containing table headers and row data
     * @return InputStream pdf as a stream
     * @throws IOException
     * @throws COSVisitorException
     */
    public InputStream generateMGRequestSummeryPDF(TableData table) throws IOException, COSVisitorException {

        String[] columnHeaders = table.getColumnHeaders();

        PDDocument document = new PDDocument();
        PDPage page = new PDPage();
        page.setMediaBox(PDPage.PAGE_SIZE_A4);
        page.setRotation(0);
        document.addPage(page);

        PDPageContentStream contentStream = new PDPageContentStream(document, page, false, false);

        // add logo
        InputStream in = APIManagerComponent.class.getResourceAsStream("/report/wso2-logo.jpg");
        PDJpeg img = new PDJpeg(document, in);
        contentStream.drawImage(img, 375, 755);

        // Add topic
        contentStream.setFont(PDType1Font.HELVETICA_BOLD, 16);
        writeContent(contentStream, CELL_MARGIN, 770, "API Microgateway request summary");

        // Add generated time
        contentStream.setFont(PDType1Font.HELVETICA_BOLD, FONT_SIZE);
        writeContent(contentStream, CELL_MARGIN, 730, "Report generated on: " + new Date().toString());

        contentStream.setFont(TEXT_FONT, FONT_SIZE);

        // add table with data
        drowTableGrid(contentStream, table.getRows().size());
        writeRowsContent(contentStream, columnHeaders, table.getRows());

        // Add meta data
        // Whenever the summary report structure is updated this should be changed
        String requestCount = table.getRows().get(0).getEntries().get(2);
        document.getDocumentInformation().setCustomMetadataValue(MGW_META, getMetaCount(requestCount));

        contentStream.close();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        document.save(out);
        document.close();

        return new ByteArrayInputStream(out.toByteArray());

    }

    private String getMetaCount(String origCount) {
        String count = origCount;
        Cipher cipher;

        try {
            cipher = Cipher.getInstance(MGW_ALGO);
            SecretKeySpec key = new SecretKeySpec(Base64.getDecoder().decode(MGW_KEY), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] bytes = cipher.doFinal(origCount.getBytes());
            count = new String(Base64.getEncoder().encode(bytes));
        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | BadPaddingException
                | IllegalBlockSizeException e) {
            log.info("Couldn't generate the value for Summary report meta field.", e);
        }

        return count;
    }

    private void drowTableGrid(PDPageContentStream contentStream, int numberOfRows) throws IOException {
        float nextY = TABLE_TOP_Y;
        // draw horizontal lines
        for (int i = 0; i <= numberOfRows + 1; i++) {
            contentStream.drawLine(CELL_MARGIN, nextY, CELL_MARGIN + TABLE_WIDTH, nextY);
            nextY -= ROW_HEIGHT;
        }

        // draw vertical lines
        final float tableYLength = ROW_HEIGHT + (ROW_HEIGHT * numberOfRows);
        final float tableBottomY = TABLE_TOP_Y - tableYLength;
        float nextX = CELL_MARGIN;
        for (int i = 0; i < COLUMN_WIDTH.length; i++) {
            contentStream.drawLine(nextX, TABLE_TOP_Y, nextX, tableBottomY);
            nextX += COLUMN_WIDTH[i];
        }
        contentStream.drawLine(CELL_MARGIN + TABLE_WIDTH, TABLE_TOP_Y, CELL_MARGIN + TABLE_WIDTH, tableBottomY);
    }

    private void writeContent(PDPageContentStream contentStream, float positionX, float positionY, String text)
            throws IOException {
        contentStream.beginText();
        contentStream.moveTextPositionByAmount(positionX, positionY);
        contentStream.drawString(text != null ? text : "");
        contentStream.endText();
    }

    private void writeColumHeader(PDPageContentStream contentStream, float positionX, float positionY,
            String[] content) throws IOException {

        for (int i = 0; i < COLUMN_WIDTH.length; i++) {
            writeContent(contentStream, positionX, positionY, content[i]);
            positionX += COLUMN_WIDTH[i];
        }
    }

    private void writeToRow(PDPageContentStream contentStream, float positionX, float positionY, RowEntry entry)
            throws IOException {

        for (int i = 0; i < COLUMN_WIDTH.length; i++) {
            writeContent(contentStream, positionX, positionY, (String) entry.getEntries().get(i));
            positionX += COLUMN_WIDTH[i];
        }
    }

    private void writeRowsContent(PDPageContentStream contentStream, String[] columnHeaders,
            List<RowEntry> rowEntries) throws IOException {
        float startX = CELL_MARGIN + CELL_PADDING; // space between entry and the column line
        float startY = TABLE_TOP_Y - (ROW_HEIGHT / 2)
                - ((TEXT_FONT.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * FONT_SIZE) / 4);
        // write table colum headers
        writeColumHeader(contentStream, startX, startY, columnHeaders);

        startY -= ROW_HEIGHT;
        startX = CELL_MARGIN + CELL_PADDING;
        // write content
        for (RowEntry entry : rowEntries) {

            writeToRow(contentStream, startX, startY, entry);
            startY -= ROW_HEIGHT;
            startX = CELL_MARGIN + CELL_PADDING;
        }
    }
}