de.ee.hezel.PDFCompareMain.java Source code

Java tutorial

Introduction

Here is the source code for de.ee.hezel.PDFCompareMain.java

Source

/*
* PDFCompareMain
* 
* Copyright (c) 2012, E&E information consultants AG. All rights reserved.
* Authors:
*   Peter Jentsch
*   Nico Hezel
*   
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package de.ee.hezel;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

import javax.swing.JOptionPane;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

/**
 * This program compares PDF documents.
 * Two directories gets searched and every
 * identically named PDF document gets compared. 
 * 
 * The program returns if all documents are the same.
 * 
 * If desired the differences can be visualized and
 * saved in an image file.
 * 
 * @author hezeln
 *
 */
public class PDFCompareMain {

    static String newline = System.getProperty("line.separator");

    static Logger log = Logger.getLogger(PDFCompareMain.class.getName());

    /**
     * Args[]
     *       [1. path]
     *       [2. path]
     *       -output [true/false]
     *       -visualise [output path] 
     * 
     * return value
     *       1 = not enough parameters
     *       2 = 
     * 
     * @param args 
     * @return int 
     */
    public static void main(String[] args) {
        // not enough parameters
        if (args.length < 1) {
            System.out.println("usage: java -jar PDFCompare.jar "
                    + "<path 1> <path 2> [-output <true/false>] [-visualise <path 3>] [-log <path 4>] [-compare <compare type>] [-prefix <pdf prefix>]"
                    + newline + newline + "<path 1> = path with PDF documents from old version" + newline
                    + "<path 2> = path with PDF documents from new version" + newline + "[output] = console output"
                    + newline + "[visualise] = output folder for visualizing differnces " + newline
                    + "[log] = path for log files and differnce images" + newline
                    + "[compare type] = type of comparison <\"SIMPLE\" | \"STRUCTURAL\" | \"VISUAL\">" + newline
                    + "[prefix] = compare only pdfs where the name starts with this prefix" + newline);
            return;
        }

        boolean output = false;
        File targetPath = null, logPath = null;
        int compareType = 1; // simple (Modes: SIMPLE/STRUCTURAL/VISUAL)
        String prefix = null;

        // read the incoming arguments
        for (int i = 2; i < args.length; i++) {
            if (args[i].equals("-output")) {
                output = Boolean.parseBoolean(args[++i]);
            } else if (args[i].equals("-visualise")) {
                targetPath = new File(args[++i]);
            } else if (args[i].equals("-log")) {
                logPath = new File(args[++i]);
            } else if (args[i].equals("-compare")) {
                String nextArg = args[++i];
                if (nextArg.equalsIgnoreCase("STRUCTURAL"))
                    compareType = 2;
                else if (nextArg.equalsIgnoreCase("VISUAL"))
                    compareType = 3;
            } else if ((args[i]).equals("-prefix")) {
                prefix = args[++i];
            }
        }

        // create or clear the output path
        checkOutputPath(targetPath);

        // configure log4j
        Properties props = getLog4jProperties(output, logPath);
        LogManager.resetConfiguration();
        PropertyConfigurator.configure(props);

        // check the output paths
        File path1 = new File(args[0]);
        File path2 = new File(args[1]);
        if (!path1.isDirectory() || !path2.isDirectory()) {
            if (!path1.isDirectory())
                log.error("[Path 1] does not exist");
            if (!path2.isDirectory())
                log.error("[Path 2] does not exist");
        }

        // compare the files in path 1 with the files in path 2 and 
        // save the results in path 3 (if given)
        PDFComparator pdfComparer = new PDFComparator(logPath, compareType);
        boolean foundDifference = pdfComparer.run(path1, path2, targetPath, prefix);

        // exit parameter (interesting for jenkins)
        System.exit(foundDifference ? 1 : 0);
    }

    /**
     * delete the old difference image and create the output path if not exists
     * 
     * @param targetPath
     */
    public static void checkOutputPath(File targetPath) {

        if (targetPath != null && targetPath.exists()) {
            // shows a window which asks you if the old content of the output directory should be deleted
            //          int confirmation = JOptionPane.showConfirmDialog(null, "Output directory not empty. Delete all contents of '" + targetPath + "' and continue?", "Confirmation", JOptionPane.YES_NO_OPTION);
            //          if (confirmation == JOptionPane.NO_OPTION)
            //              return;

            try {
                FileUtils.deleteDirectory(targetPath);
            } catch (IOException e1) {
                throw new RuntimeException("Unable to clean output directory: " + e1.getMessage(), e1);
            }
            targetPath.mkdirs();
        }
        if (!targetPath.exists())
            targetPath.mkdir();
    }

    public static Properties getLog4jProperties(boolean output, File logPath) {
        Properties props = new Properties();

        if (output) {
            props.setProperty("log4j.rootLogger", "debug, stdout, errorfile, resultfile");

            props.setProperty("log4j.appender.stdout", "org.apache.log4j.ConsoleAppender");
            props.setProperty("log4j.appender.stdout.layout", "org.apache.log4j.PatternLayout");
            props.setProperty("log4j.appender.stdout.layout.ConversionPattern", "%5p [%t] (%F:%L) - %m%n");
        } else
            props.setProperty("log4j.rootLogger", "debug, errorfile, resultfile");

        File logfile = new File(logPath, "_error.log");
        props.setProperty("log4j.appender.errorfile", "org.apache.log4j.FileAppender");
        props.setProperty("log4j.appender.errorfile.File", logfile.getAbsolutePath());
        props.setProperty("log4j.appender.errorfile.Append", "false");
        props.setProperty("log4j.appender.errorfile.Threshold", "ERROR");
        props.setProperty("log4j.appender.errorfile.layout", "org.apache.log4j.PatternLayout");
        props.setProperty("log4j.appender.errorfile.layout.ConversionPattern", "%d %p %F - %m%n");

        File logfile1 = new File(logPath, "_results.log");
        props.setProperty("log4j.appender.resultfile", "org.apache.log4j.FileAppender");
        props.setProperty("log4j.appender.resultfile.File", logfile1.getAbsolutePath());
        props.setProperty("log4j.appender.resultfile.Append", "false");

        // filters in property files are supported from 1.2.16 and above 
        // http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PropertyConfigurator.html
        props.setProperty("log4j.appender.resultfile.filter.ID", "org.apache.log4j.varia.LevelRangeFilter");
        props.setProperty("log4j.appender.resultfile.filter.ID.LevelMin", "INFO");
        props.setProperty("log4j.appender.resultfile.filter.ID.LevelMax", "INFO");
        props.setProperty("log4j.appender.resultfile.layout", "org.apache.log4j.PatternLayout");
        props.setProperty("log4j.appender.resultfile.layout.ConversionPattern", "%d %p %F - %m%n");

        return props;
    }
}