lucee.runtime.text.pdf.PDFUtil.java Source code

Java tutorial

Introduction

Here is the source code for lucee.runtime.text.pdf.PDFUtil.java

Source

/**
 *
 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 * 
 **/
package lucee.runtime.text.pdf;

import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import lucee.commons.io.IOUtil;
import lucee.commons.io.res.Resource;
import lucee.commons.lang.StringUtil;
import lucee.runtime.PageContext;
import lucee.runtime.exp.ApplicationException;
import lucee.runtime.exp.CasterException;
import lucee.runtime.exp.PageException;
import lucee.runtime.img.Image;
import lucee.runtime.op.Caster;
import lucee.runtime.op.Constants;
import lucee.runtime.op.Decision;

import org.pdfbox.exceptions.CryptographyException;
import org.pdfbox.exceptions.InvalidPasswordException;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.util.PDFText2HTML;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PRAcroForm;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.SimpleBookmark;

public class PDFUtil {

    public static final int ENCRYPT_RC4_40 = PdfWriter.STANDARD_ENCRYPTION_40;
    public static final int ENCRYPT_RC4_128 = PdfWriter.STANDARD_ENCRYPTION_128;
    public static final int ENCRYPT_RC4_128M = PdfWriter.STANDARD_ENCRYPTION_128;
    public static final int ENCRYPT_AES_128 = PdfWriter.ENCRYPTION_AES_128;
    public static final int ENCRYPT_NONE = -1;

    private static final int PERMISSION_ALL = PdfWriter.ALLOW_ASSEMBLY + PdfWriter.ALLOW_COPY
            + PdfWriter.ALLOW_DEGRADED_PRINTING + PdfWriter.ALLOW_FILL_IN + PdfWriter.ALLOW_MODIFY_ANNOTATIONS
            + PdfWriter.ALLOW_MODIFY_CONTENTS + PdfWriter.ALLOW_PRINTING + PdfWriter.ALLOW_SCREENREADERS
            + PdfWriter.ALLOW_COPY;// muss 2 mal sein, keine ahnung wieso

    /**
     * convert a string list of permission 
     * @param strPermissions
     * @return
     * @throws PageException
     */
    public static int toPermissions(String strPermissions) throws PageException {
        if (strPermissions == null)
            return 0;
        int permissions = 0;
        strPermissions = strPermissions.trim();

        String[] arr = lucee.runtime.type.util.ListUtil
                .toStringArray(lucee.runtime.type.util.ListUtil.listToArrayRemoveEmpty(strPermissions, ','));
        for (int i = 0; i < arr.length; i++) {
            permissions = add(permissions, toPermission(arr[i]));
        }
        return permissions;
    }

    /**
     * convert a string defintion of a permision in a integer Constant (PdfWriter.ALLOW_XXX)
     * @param strPermission
     * @return
     * @throws ApplicationException
     */
    public static int toPermission(String strPermission) throws ApplicationException {
        strPermission = strPermission.trim().toLowerCase();
        if ("allowassembly".equals(strPermission))
            return PdfWriter.ALLOW_ASSEMBLY;
        else if ("none".equals(strPermission))
            return 0;
        else if ("all".equals(strPermission))
            return PERMISSION_ALL;
        else if ("assembly".equals(strPermission))
            return PdfWriter.ALLOW_ASSEMBLY;
        else if ("documentassembly".equals(strPermission))
            return PdfWriter.ALLOW_ASSEMBLY;
        else if ("allowdegradedprinting".equals(strPermission))
            return PdfWriter.ALLOW_DEGRADED_PRINTING;
        else if ("degradedprinting".equals(strPermission))
            return PdfWriter.ALLOW_DEGRADED_PRINTING;
        else if ("printing".equals(strPermission))
            return PdfWriter.ALLOW_DEGRADED_PRINTING;
        else if ("allowfillin".equals(strPermission))
            return PdfWriter.ALLOW_FILL_IN;
        else if ("fillin".equals(strPermission))
            return PdfWriter.ALLOW_FILL_IN;
        else if ("fillingform".equals(strPermission))
            return PdfWriter.ALLOW_FILL_IN;
        else if ("allowmodifyannotations".equals(strPermission))
            return PdfWriter.ALLOW_MODIFY_ANNOTATIONS;
        else if ("modifyannotations".equals(strPermission))
            return PdfWriter.ALLOW_MODIFY_ANNOTATIONS;
        else if ("allowmodifycontents".equals(strPermission))
            return PdfWriter.ALLOW_MODIFY_CONTENTS;
        else if ("modifycontents".equals(strPermission))
            return PdfWriter.ALLOW_MODIFY_CONTENTS;
        else if ("allowcopy".equals(strPermission))
            return PdfWriter.ALLOW_COPY;
        else if ("copy".equals(strPermission))
            return PdfWriter.ALLOW_COPY;
        else if ("copycontent".equals(strPermission))
            return PdfWriter.ALLOW_COPY;
        else if ("allowprinting".equals(strPermission))
            return PdfWriter.ALLOW_PRINTING;
        else if ("printing".equals(strPermission))
            return PdfWriter.ALLOW_PRINTING;
        else if ("allowscreenreaders".equals(strPermission))
            return PdfWriter.ALLOW_SCREENREADERS;
        else if ("screenreaders".equals(strPermission))
            return PdfWriter.ALLOW_SCREENREADERS;

        else
            throw new ApplicationException("invalid permission [" + strPermission
                    + "], valid permission values are [AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations, AllowFillIn, AllowScreenReaders, AllowAssembly, AllowDegradedPrinting]");
    }

    private static int add(int permissions, int permission) {
        if (permission == 0 || (permissions & permission) > 0)
            return permissions;
        return permissions + permission;
    }

    /**
     * @param docs
     * @param os
     * @param removePages if true, pages defined in PDFDocument will be removed, otherwise all other pages will be removed
     * @param version 
     * @throws PageException 
     * @throws IOException 
     * @throws DocumentException 
     */
    public static void concat(PDFDocument[] docs, OutputStream os, boolean keepBookmark, boolean removePages,
            boolean stopOnError, char version) throws PageException, IOException, DocumentException {
        Document document = null;
        PdfCopy writer = null;
        PdfReader reader;
        Set pages;
        boolean isInit = false;
        PdfImportedPage page;
        try {
            int pageOffset = 0;
            ArrayList master = new ArrayList();

            for (int i = 0; i < docs.length; i++) {
                // we create a reader for a certain document
                pages = docs[i].getPages();
                try {
                    reader = docs[i].getPdfReader();
                } catch (Throwable t) {
                    if (!stopOnError)
                        continue;
                    throw Caster.toPageException(t);
                }
                reader.consolidateNamedDestinations();

                // we retrieve the total number of pages
                int n = reader.getNumberOfPages();
                List bookmarks = keepBookmark ? SimpleBookmark.getBookmark(reader) : null;
                if (bookmarks != null) {
                    removeBookmarks(bookmarks, pages, removePages);
                    if (pageOffset != 0)
                        SimpleBookmark.shiftPageNumbers(bookmarks, pageOffset, null);
                    master.addAll(bookmarks);
                }

                if (!isInit) {
                    isInit = true;
                    document = new Document(reader.getPageSizeWithRotation(1));
                    writer = new PdfCopy(document, os);

                    if (version != 0)
                        writer.setPdfVersion(version);

                    document.open();
                }

                for (int y = 1; y <= n; y++) {
                    if (pages != null && removePages == pages.contains(Integer.valueOf(y))) {
                        continue;
                    }
                    pageOffset++;
                    page = writer.getImportedPage(reader, y);
                    writer.addPage(page);
                }
                PRAcroForm form = reader.getAcroForm();
                if (form != null)
                    writer.copyAcroForm(reader);
            }
            if (master.size() > 0)
                writer.setOutlines(master);

        } finally {
            IOUtil.closeEL(document);
        }
    }

    private static void removeBookmarks(List bookmarks, Set pages, boolean removePages) {
        int size = bookmarks.size();
        for (int i = size - 1; i >= 0; i--) {
            if (removeBookmarks((Map) bookmarks.get(i), pages, removePages))
                bookmarks.remove(i);
        }
    }

    private static boolean removeBookmarks(Map bookmark, Set pages, boolean removePages) {
        List kids = (List) bookmark.get("Kids");
        if (kids != null)
            removeBookmarks(kids, pages, removePages);
        Integer page = Caster.toInteger(
                lucee.runtime.type.util.ListUtil.first((String) bookmark.get("Page"), " ", true),
                Constants.INTEGER_MINUS_ONE);
        return removePages == (pages != null && pages.contains(page));
    }

    public static Set parsePageDefinition(String strPages) throws PageException {
        if (StringUtil.isEmpty(strPages))
            return null;
        HashSet<Integer> set = new HashSet<Integer>();
        parsePageDefinition(set, strPages);
        return set;
    }

    public static void parsePageDefinition(Set<Integer> pages, String strPages) throws PageException {
        if (StringUtil.isEmpty(strPages))
            return;
        String[] arr = lucee.runtime.type.util.ListUtil
                .toStringArrayTrim(lucee.runtime.type.util.ListUtil.listToArrayRemoveEmpty(strPages, ','));
        int index, from, to;
        for (int i = 0; i < arr.length; i++) {
            index = arr[i].indexOf('-');
            if (index == -1)
                pages.add(Caster.toInteger(arr[i].trim()));
            else {
                from = Caster.toIntValue(arr[i].substring(0, index).trim());
                to = Caster.toIntValue(arr[i].substring(index + 1).trim());
                for (int y = from; y <= to; y++) {
                    pages.add(Integer.valueOf(y));
                }
            }
        }
    }

    public static void encrypt(PDFDocument doc, OutputStream os, String newUserPassword, String newOwnerPassword,
            int permissions, int encryption) throws ApplicationException, DocumentException, IOException {
        byte[] user = newUserPassword == null ? null : newUserPassword.getBytes();
        byte[] owner = newOwnerPassword == null ? null : newOwnerPassword.getBytes();

        PdfReader pr = doc.getPdfReader();
        List bookmarks = SimpleBookmark.getBookmark(pr);
        int n = pr.getNumberOfPages();

        Document document = new Document(pr.getPageSizeWithRotation(1));
        PdfCopy writer = new PdfCopy(document, os);
        if (encryption != ENCRYPT_NONE)
            writer.setEncryption(user, owner, permissions, encryption);
        document.open();

        PdfImportedPage page;
        for (int i = 1; i <= n; i++) {
            page = writer.getImportedPage(pr, i);
            writer.addPage(page);
        }
        PRAcroForm form = pr.getAcroForm();
        if (form != null)
            writer.copyAcroForm(pr);
        if (bookmarks != null)
            writer.setOutlines(bookmarks);
        document.close();
    }

    public static HashMap generateGoToBookMark(String title, int page) {
        return generateGoToBookMark(title, page, 0, 731);
    }

    public static HashMap generateGoToBookMark(String title, int page, int x, int y) {
        HashMap map = new HashMap();
        map.put("Title", title);
        map.put("Action", "GoTo");
        map.put("Page", page + " XYZ " + x + " " + y + " null");

        return map;
    }

    public static void setChildBookmarks(Map parent, List children) {
        Object kids = parent.get("Kids");
        if (kids instanceof List) {
            ((List) kids).addAll(children);
        } else
            parent.put("Kids", children);
    }

    public static PdfReader toPdfReader(PageContext pc, Object value, String password)
            throws IOException, PageException {
        if (value instanceof PdfReader)
            return (PdfReader) value;
        if (value instanceof PDFDocument)
            return ((PDFDocument) value).getPdfReader();
        if (Decision.isBinary(value)) {
            if (password != null)
                return new PdfReader(Caster.toBinary(value), password.getBytes());
            return new PdfReader(Caster.toBinary(value));
        }
        if (value instanceof Resource) {
            if (password != null)
                return new PdfReader(IOUtil.toBytes((Resource) value), password.getBytes());
            return new PdfReader(IOUtil.toBytes((Resource) value));
        }
        if (value instanceof String) {
            if (password != null)
                return new PdfReader(IOUtil.toBytes(Caster.toResource(pc, value, true)), password.getBytes());
            return new PdfReader(IOUtil.toBytes((Resource) value));
        }
        throw new CasterException(value, PdfReader.class);
    }

    /*public static void main(String[] args) throws IOException {
           
           
           
       PdfReader pr = new PdfReader("/Users/mic/Projects/Lucee/webroot/jm/test/tags/pdf/Parallels.pdf");
       List bm = SimpleBookmark.getBookmark(pr);
       print.out(bm);
       ByteArrayOutputStream os = new ByteArrayOutputStream();
       try {
     SimpleBookmark.exportToXML(bm, os, "UTF-8",false);
       }
       finally {
     IOUtil.closeEL(os);
       }
       print.out("*********************************");
       print.out(IOUtil.toString(os.toByteArray(), "UTF-8"));
    }*/

    public static Image toImage(byte[] input, int page) throws PageException, IOException {
        return PDF2Image.getInstance().toImage(input, page);
    }

    public static void writeImages(byte[] input, Set pages, Resource outputDirectory, String prefix, String format,
            int scale, boolean overwrite, boolean goodQuality, boolean transparent)
            throws PageException, IOException {
        PDF2Image.getInstance().writeImages(input, pages, outputDirectory, prefix, format, scale, overwrite,
                goodQuality, transparent);
    }

    public static Object extractText(PDFDocument doc, Set<Integer> pageNumbers)
            throws IOException, CryptographyException, InvalidPasswordException {
        PDDocument pdDoc = doc.toPDDocument();
        //PDPageNode pages = pdDoc.getDocumentCatalog().getPages();
        //pages.
        //pdDoc.getDocumentCatalog().

        /*Iterator<Integer> it = pageNumbers.iterator();
        int p;
        while(it.hasNext()){
           p=it.next().intValue();
            
           pdDoc.getDocumentCatalog().getPages()
        }
        */

        //print.o(pages);

        //pdDoc.

        //PDFTextStripperByArea  stripper = new PDFTextStripperByArea();
        //PDFHighlighter  stripper = new PDFHighlighter();
        PDFText2HTML stripper = new PDFText2HTML();
        //PDFTextStripper stripper = new PDFTextStripper();
        StringWriter writer = new StringWriter();
        stripper.writeText(pdDoc, writer);

        return writer.toString();
    }
}