PdfFormFiller.WrongParamsExeption.java Source code

Java tutorial

Introduction

Here is the source code for PdfFormFiller.WrongParamsExeption.java

Source

/** 
 * pdfformfiller 1.0-alpha is a command line utility for filling in Adobe PDF Forms. 
 * 
 * Well known pdftk utility can be used for filling in Adobe Pdf Forms. 
 * However, I was not able to get the version pdftk1.4 to work with UTF-8. 
 * It's XFDF format support UTF-8 encoding, however it assumes Adobe uses an UTF-8
 * font by default. Whereas, Adobe Readers (at least upto version X) do not, 
 * and UTF-8 text is entered by pdftk but is not shown in its form until user clicks 
 * on the form and edits it.
 * 
 * In PdfFormFiller, you can use the -font option to specify a UTF-8 font 
 * to use to fill in the forms to resolve this issue.
 * 
 * Also, our fields input file format is much simpler then XFDF of pdftk that
 * requires XML parsing.
 * 
 * Based on the Belgian iText library v. 5.2.0, http://www.itextpdf.com/
 *
 * (C) copyleft AGPL license, http://itextpdf.com/terms-of-use/agpl.php, Nikolay Kitsul.
 * 
 * @author Nikolay Kitsul
 * @version 1.0-alpha
 */

package PdfFormFiller;

import java.io.*;
import java.io.OutputStream;
import java.util.*;
import java.util.Map;
import java.util.Scanner;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.*;
//import com.itextpdf.text.pdf.Item;

class WrongParamsExeption extends Exception {
};

public class PdfFormFiller {
    static Boolean verbose;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String document, operation = "fill", fields = null, font = null, output = null;
        Boolean flatten = false;
        verbose = false;

        try {
            if (args.length < 1)
                throw new WrongParamsExeption();
            document = args[0];
            for (int i = 1; i < args.length; i++) {
                if (args[i].equals("-v")) {
                    verbose = true;
                } else if (args[i].equals("-flatten")) {
                    flatten = true;
                } else if (args[i].equals("-l")) {
                    operation = "list";
                } else if (args[i].equals("-f")) {
                    if (i + 1 >= args.length)
                        throw new WrongParamsExeption();
                    fields = args[++i];
                } else if (args[i].equals("-font")) {
                    if (i + 1 >= args.length)
                        throw new WrongParamsExeption();
                    font = args[++i];
                } else if (i + 1 == args.length) {
                    output = args[i];
                } else {
                    throw new WrongParamsExeption();
                }
            }

            fillPDFFile(document, output, fields, font, operation, flatten, verbose);

        } catch (WrongParamsExeption e) {
            if (e.getMessage() != null)
                System.out.println(e.getMessage());
            System.out.println(
                    "USAGE: pdfformfiller document.pdf [ -l ] [ -v ] [ -f fields_filename ] [ -font font_file ] [ -flatten] [ output.pdf ]\n\n"
                            + "    document.pdf - name of source pdf file (required).\n"
                            + "    -l - only list availible fields in document.pdf.\n"
                            + "    -v - verbose. Use to debug the fields_filename file. \n"
                            + "    -f fields_filename - name of file with the list of fields values to apply to document.pdf. \n"
                            + "                         if ommited, stdin is used.\n"
                            + "    -font font_file - font to use. Needed UTF-8 support, e.g. cyrillic and non-latin alphabets.\n"
                            + "    -flatten - Flatten pdf forms (convert them to text disabling editing in PDF Reader).\n"
                            + "    output.pdf - name of output file. If omitted, the output if sent to stdout. \n\n"
                            + "fields_filename file can be in UTF-8 as is of the following format:\n"
                            + "    On each line, one entry consists of 'field name' followed by value of that field without any quotes.\n"
                            + "    Any number of whitespaces allowed before 'field name', and one space separates 'field name' and its value.\n"
                            + "    In value, newline characters should be encoded as \"\\n\",\n"
                            + "    'U+2029 utf-8 E280A9 : PARAGRAPH SEPARATOR PS' should be encoded as \"\\p\",\n"
                            + "    and '\\' characters should be escaped as \"\\\\\".\n"
                            + "    For checkboxes, values are 'Yes'/'Off'.\n\n"
                            + "    Based on the Belgian iText library v. 5.2.0, http://www.itextpdf.com/\n");
            System.exit(1);
        }

    }

    public static void fillPDFFile(String pdf_filename_in, String pdf_filename_out, String fields_filename) {
        fillPDFFile(pdf_filename_in, pdf_filename_out, fields_filename, null, "fill", false, false);
    }

    public static void fillPDFFile(String pdf_filename_in, String pdf_filename_out, String fields_filename,
            String font_file, String op, Boolean flatten, Boolean verbose) {
        OutputStream os;
        PdfStamper stamp;
        try {
            PdfReader reader = new PdfReader(pdf_filename_in);

            if (pdf_filename_out != null) {
                os = new FileOutputStream(pdf_filename_out);
            } else {
                os = System.out;
            }

            stamp = new PdfStamper(reader, os, '\0');

            AcroFields form = stamp.getAcroFields();

            if (op.equals("list")) {
                formList(form);
            } else {
                if (font_file != null) {
                    BaseFont bf = BaseFont.createFont(font_file, BaseFont.IDENTITY_H, true);
                    form.addSubstitutionFont(bf);
                }
                Map<String, String> fields = readFile(fields_filename);
                for (Map.Entry<String, String> entry : fields.entrySet()) {
                    if (verbose)
                        System.out.println("Field name = '" + entry.getKey() + "', New field value: '"
                                + entry.getValue() + "'");
                    form.setField(entry.getKey(), entry.getValue());
                }

                stamp.setFormFlattening(flatten);
                stamp.close();
            }
        } catch (FileNotFoundException e) {
            System.err.println("FileNotFoundException: " + e.getMessage());
            System.exit(2);
        } catch (IOException e) {
            System.err.println("Input output error: " + e.getMessage());
            System.exit(3);
        } catch (DocumentException e) {
            System.err.println("Error while processing document: " + e.getMessage());
            System.exit(4);
        }
    }

    public static void formList(AcroFields form) {
        Map<String, AcroFields.Item> map = form.getFields();
        System.out.println("Field names:");
        for (Map.Entry<String, AcroFields.Item> entry : map.entrySet())
            System.out.println(entry.getKey());
        System.out.println("END: Field names");
    }

    /**
     * <var>filename</var> file can be in UTF-8 and in of the following format:<br><br>
     *  On each line, one entry consists of <i>field name</i> followed by value of that field without any quotes. <br>
     *  Any number of whitespaces allowed before <i>field name</i> and between <i>field name</i> and its value.<br>
     *  In value, newline characters should be encoded as \n 
     *  and '\' characters should be escaped as "\\". <br>
     *  For checkboxes, values are 'Yes'/'Off'."<br>
     * 
     * @param filename name of file with fields and their values.
     * @return
     * @throws java.io.FileNotFoundException 
     */
    public static Map<String, String> readFile(String filename) throws java.io.FileNotFoundException {
        Map<String, String> fields = new HashMap<String, String>();
        String s, v;
        String[] t;
        Scanner input;

        if (filename != null)
            //input = new Scanner(new File(filename));
            input = new Scanner(new BufferedReader(new FileReader(filename)));
        else
            input = new Scanner(System.in);

        int i = 1;
        while (input.hasNext()) {
            s = input.nextLine().trim();
            t = s.split("\\s", 2);
            if (t.length == 2) {
                // Unescape "\n":
                v = unescape(t[1]);
                fields.put(t[0], v);
            } else {
                if (verbose)
                    System.out.println("Line " + i + ": " + s + "\nskipped.");
            }
            i++;
        }
        IOException ex = input.ioException();
        if (ex != null)
            ex.printStackTrace(System.out);

        if (verbose)
            System.out.println((i - 1) + " lines from " + (filename == null ? "stdin" : filename) + " parsed.");
        input.close();
        return fields;
    }

    /**
    * Unescapes "\n", etc.
    * 
    * @param str
    * @return resuling string. 
    */
    public static String unescape(String str) {
        String out = "";
        char ch, next;

        if (str == null) {
            return null;
        }
        final int length = str.length();
        for (int offset = 0; offset < length;) {

            ch = str.charAt(offset);

            if ((ch == '\\') && ((offset + 1) < length)) {
                next = str.charAt(offset + 1);
                switch (next) {
                case '\\':
                    out += '\\';
                    break;
                case 'n':
                    out += '\n';
                    break;
                case 'p':
                    // U+2029 utf-8 E280A9 : PARAGRAPH SEPARATOR PS
                    out += '\u2029';
                    break;
                default: {
                    out += (ch + next);
                }
                }
                offset++;
            } else
                out += ch;

            offset++;
        }

        return out;
    }

}