org.sleuthkit.autopsy.report.ReportExcel.java Source code

Java tutorial

Introduction

Here is the source code for org.sleuthkit.autopsy.report.ReportExcel.java

Source

/*
 * Autopsy Forensic Browser
 *
 * Copyright 2013-2014 Basis Technology Corp.
 * Contact: carrier <at> sleuthkit <dot> org
 *
 * 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 org.sleuthkit.autopsy.report;

import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.logging.Level;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskCoreException;

class ReportExcel implements TableReportModule {
    private static final Logger logger = Logger.getLogger(ReportExcel.class.getName());
    private static ReportExcel instance;

    private Workbook wb;
    private Sheet sheet;
    private CellStyle titleStyle;
    private CellStyle setStyle;
    private CellStyle elementStyle;
    private int rowIndex = 0;
    private int sheetColCount = 0;
    private String reportPath;

    // Get the default instance of this report
    public static synchronized ReportExcel getDefault() {
        if (instance == null) {
            instance = new ReportExcel();
        }
        return instance;
    }

    // Hidden constructor
    private ReportExcel() {
    }

    /**
     * Start the Excel report by creating the Workbook, initializing styles,
     * and writing the summary.
     * @param path path to save the report
     */
    @Override
    public void startReport(String path) {
        // Set the path and save it for when the report is written to disk.
        this.reportPath = path + getRelativeFilePath();

        // Make a workbook.
        wb = new XSSFWorkbook();

        // Create some cell styles.
        // TODO: The commented out cell style settings below do not work as desired when
        // the output file is loaded by MS Excel or OfficeLibre. The font height and weight
        // settings only work as expected when the output file is loaded by OfficeLibre.
        // The alignment and text wrap settings appear to have no effect.
        titleStyle = wb.createCellStyle();
        //        titleStyle.setBorderBottom((short) 1);
        Font titleFont = wb.createFont();
        titleFont.setFontHeightInPoints((short) 12);
        titleStyle.setFont(titleFont);
        titleStyle.setAlignment(CellStyle.ALIGN_LEFT);
        titleStyle.setWrapText(true);

        setStyle = wb.createCellStyle();
        Font setFont = wb.createFont();
        setFont.setFontHeightInPoints((short) 14);
        setFont.setBoldweight((short) 10);
        setStyle.setFont(setFont);
        setStyle.setAlignment(CellStyle.ALIGN_LEFT);
        setStyle.setWrapText(true);

        elementStyle = wb.createCellStyle();
        //        elementStyle.setF illBackgroundColor(HSSFColor.LIGHT_YELLOW.index);
        Font elementFont = wb.createFont();
        elementFont.setFontHeightInPoints((short) 14);
        elementStyle.setFont(elementFont);
        elementStyle.setAlignment(CellStyle.ALIGN_LEFT);
        elementStyle.setWrapText(true);

        writeSummaryWorksheet();
    }

    /**
     * Write the Workbook to a file and end the report.
     */
    @Override
    public void endReport() {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(reportPath);
            wb.write(out);
            Case.getCurrentCase().addReport(reportPath,
                    NbBundle.getMessage(this.getClass(), "ReportExcel.endReport.srcModuleName.text"), "");
        } catch (IOException ex) {
            logger.log(Level.SEVERE, "Failed to write Excel report.", ex); //NON-NLS
        } catch (TskCoreException ex) {
            String errorMessage = String.format("Error adding %s to case as a report", reportPath); //NON-NLS
            logger.log(Level.SEVERE, errorMessage, ex);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException ex) {
                }
            }
        }
    }

    /**
     * Start a new worksheet for the given data type.
     * Note: This method is a temporary workaround to avoid modifying the TableReportModule interface.     
     * 
     * @param name Name of the data type
     * @param comment Comment on the data type, may be the empty string
     */
    @Override
    public void startDataType(String name, String description) {
        // Create a worksheet for the data type (assumed to be an artifact type).
        name = escapeForExcel(name);
        sheet = wb.createSheet(name);
        sheet.setAutobreaks(true);
        rowIndex = 0;

        // There will be at least two columns, one each for the artifacts count and its label.
        sheetColCount = 2;
    }

    /**
     * End the current data type and sheet.
     */
    @Override
    public void endDataType() {
        // Now that the sheet is complete, size the columns to the content.
        for (int i = 0; i < sheetColCount; ++i) {
            sheet.autoSizeColumn(i);
        }
    }

    /**
     * Start a new set for the current data type.
     * @param setName name of the set
     */
    @Override
    public void startSet(String setName) {
        setName = escapeForExcel(setName);
        Row row = sheet.createRow(rowIndex);
        row.setRowStyle(setStyle);
        row.createCell(0).setCellValue(setName);
        ++rowIndex;
    }

    /**
     * End the current set.
     */
    @Override
    public void endSet() {
        // Add an empty row as a separator.
        sheet.createRow(rowIndex);
        ++rowIndex;
    }

    @Override
    public void addSetIndex(List<String> sets) {
        // Ignored in Excel Report
    }

    /**
     * Add an element to the set
     * @param elementName element name
     */
    @Override
    public void addSetElement(String elementName) {
        elementName = escapeForExcel(elementName);
        Row row = sheet.createRow(rowIndex);
        row.setRowStyle(elementStyle);
        row.createCell(0).setCellValue(elementName);
        ++rowIndex;
    }

    /**
     * Label the top of this sheet with the table column names.
     * @param titles column names
     */
    @Override
    public void startTable(List<String> titles) {
        int tableColCount = 0;
        Row row = sheet.createRow(rowIndex);
        row.setRowStyle(titleStyle);
        for (int i = 0; i < titles.size(); i++) {
            row.createCell(i).setCellValue(titles.get(i));
            ++tableColCount;
        }
        ++rowIndex;

        // Keep track of the number of columns with data in them for later column auto-sizing.
        if (tableColCount > sheetColCount) {
            sheetColCount = tableColCount;
        }
    }

    @Override
    public void endTable() {
        // Add an empty row as a separator.
        sheet.createRow(rowIndex);
        ++rowIndex;
    }

    /**
     * Add a row of information to the report.
     * @param row cells to add
     */
    @Override
    public void addRow(List<String> rowData) {
        Row row = sheet.createRow(rowIndex);
        for (int i = 0; i < rowData.size(); ++i) {
            row.createCell(i).setCellValue(rowData.get(i));
        }
        ++rowIndex;
    }

    /**
     * Return the given long date as a String.
     * @param date as a long
     * @return String date
     */
    @Override
    public String dateToString(long date) {
        SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        return sdf.format(new java.util.Date(date * 1000));
    }

    @Override
    public String getName() {
        return NbBundle.getMessage(this.getClass(), "ReportExcel.getName.text");
    }

    @Override
    public String getDescription() {
        return NbBundle.getMessage(this.getClass(), "ReportExcel.getDesc.text");
    }

    @Override
    public String getRelativeFilePath() {
        return "Excel.xlsx"; //NON-NLS
    }

    /**
     * Escape special chars for Excel that would cause errors/hangs in generating report
     * The following are not valid for sheet names: ? / \ * :
     * @param text
     * @return 
     */
    private static String escapeForExcel(String text) {
        return text.replaceAll("[\\/\\:\\?\\*\\\\]", "_");
    }

    private void writeSummaryWorksheet() {
        sheet = wb.createSheet(NbBundle.getMessage(this.getClass(), "ReportExcel.sheetName.text"));
        rowIndex = 0;

        Row row = sheet.createRow(rowIndex);
        row.setRowStyle(setStyle);
        row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.summary"));
        ++rowIndex;

        sheet.createRow(rowIndex);
        ++rowIndex;

        Case currentCase = Case.getCurrentCase();

        row = sheet.createRow(rowIndex);
        row.setRowStyle(setStyle);
        row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.caseName"));
        row.createCell(1).setCellValue(currentCase.getName());
        ++rowIndex;

        row = sheet.createRow(rowIndex);
        row.setRowStyle(setStyle);
        row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.caseNum"));
        row.createCell(1).setCellValue(currentCase.getNumber());
        ++rowIndex;

        row = sheet.createRow(rowIndex);
        row.setRowStyle(setStyle);
        row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.examiner"));
        row.createCell(1).setCellValue(currentCase.getExaminer());
        ++rowIndex;

        row = sheet.createRow(rowIndex);
        row.setRowStyle(setStyle);
        row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.numImages"));
        int numImages;
        try {
            numImages = currentCase.getDataSources().size();
        } catch (TskCoreException ex) {
            numImages = 0;
        }
        row.createCell(1).setCellValue(numImages);
        ++rowIndex;

        sheet.autoSizeColumn(0);
        sheet.autoSizeColumn(1);
    }
}