org.h819.commons.file.MyPDFUtilss.java Source code

Java tutorial

Introduction

Here is the source code for org.h819.commons.file.MyPDFUtilss.java

Source

package org.h819.commons.file;

import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.exceptions.BadPasswordException;
import com.itextpdf.text.io.FileChannelRandomAccessSource;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.PdfImageObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.h819.commons.MyConstants;
import org.h819.commons.MyExecUtils;
import org.h819.commons.exe.ExecParameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.List;

/**
 * @author H819
 * @version V1.0
 * @Title: PDFBaseUtils.java
 * @Description: TODO(pdf?)
 * @date 2015-3-1
 */

//http://tutorials.jenkov.com/java-itext/index.html

//html->pdf
//http://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-creating-pdf-documents-with-wkhtmltopdf/
//http://wkhtmltopdf.org/
/*
 *  pdf 
 *
 * ========== ??? ==========
 *
 * 1. pdf ?????
 *
 * 2. ?????
 *
 * 3. ???????
 *
 * ?????
 *
 * ========== ? ==========
 *
 * 1. pdf  pdf 
 *
 * pdf ???? iso 
 *
 * pdf  pdf (security ) ??
 *
 * (adobe reader ???).
 *
 * ???? pdf ? pdf ??
 *
 * pdf ???????(???)
 *
 *  pdf ? pdf  pdf ? pdf ???
 *
 *  pdf ??
 *
 * pdf ??????????????
 *
 * 2.  pdf 
 *
 * ?? pdf  pdf ?? pdf ???
 *
 * ????????????? pdf 
 *
 * ???? pdf  ??? pdf ????
 *
 * pdf
 *
 * 
 *
 *  java ???????
 *
 * ???
 *
 * :
 *
 * (1). icepdf(4.0  ?)ice pdf ??? pdf
 *
 * ??
 *
 * (2) pdf-renderer https://pdf-renderer.dev.java.net/,
 *
 * ??()
 *
 * (3) adobe ?(2001 ???)
 * http://www.adobe.com/products/acrviewer/acrvdnld.html?name=Accept#java
 *
 * ()
 *
 * http://big.faceless.org/products/pdfviewer/
 *
 * http://www.jpedal.org/
 *
 * http://www.qoppa.com/jpvindex.html(???)
 *
 * google  api ??
 *
 * ============================= ? java ????
 *
 * itext,
 *
 * ?pdf-renderer,qoppa pdf viewer,icepdf viewer
 *
 *
 *  pdf  adobe reader ?
 *
 * ========== pdf  ==========
 *
 * ? pdf ? pdf ?
 *
 * pdf?pdf???
 *
 * ??pdf????? pdf ???
 *
 * ????pdf creater or viwer 
 *
 * ?????
 *
 * pdf-renderer ??
 *
 *
 * ==========  itext  ==========
 *
 * 1. ??;
 *
 * 2. ??;(??)
 *
 * 3. ?????;
 *
 * 4. servlet ?????
 *
 * 5. ????
 *
 * "?""?" pdf "?????"?
 *
 * ?? F8  Ctrl+Shift+S ???
 *
 * ? adobe reader ???adobe 
 *
 * google "Parameters for Opening PDF Files" ?
 *
 * ??
 *
 * ==========  itext  ==========
 *
 * 1.  itext ? pdf (userpassword)(ownerpassword)?
 *
 * ? itext ???? ownerpassword ?? ownerpassword ??
 *
 * ??????
 *
 * 
 *
 * ?????
 *
 * ??????
 *
 * ?????????
 *
 * (?5 ??? decryptPdf . ???)
 *
 * 2. ???
 *
 * ????????????
 *
 * ( 1 )
 *
 * ========== pdf ? ==========
 *
 * 1. ????????????????????
 *
 * 2. ????????????
 *
 * 3. ????? java ??
 *
 * pdf ??? http://superleo.javaeye.com/blog/2838484
 *
 * === ? java 
 *
 * 1. pdf -> swf ?? swf ?
 *
 * http://nlslzf.javaeye.com/blog/395518 http://www.javaeye.com/topic/538361
 *
 * javaeye ? swftools,pdf2swf,flexpaper
 *
 * ?:
 *
 * http://flashpdfviewer.com/ //
 *
 * http://www.qoppa.com/pdfviewer/demo/jpvapplets.html
 *
 * http://flexpaper.devaldi.com/
 *
 * http://www.artofsolving.com/opensource
 */

/*
 * ?
 *
 * bcprov.jar
 *
 * bcmail.jar
 *
 * itext 
 *
 *
 * getPdfReader  PdfReader?itext 5.3.5 
 *
 */

public class MyPDFUtilss {

    // ?? countPages() ???????
    private static StringBuffer encryptPdfNamesTemp;

    // ?? countPages() ???????
    private static int numberOfPagesOfDirectory;

    private static Logger logger = LoggerFactory.getLogger(MyPDFUtilss.class);

    /*
      * === ??
     *
     * 1? iTextAsian.jar (? iTextAsian.jar)
     * BaseFont.createFont("STSong-Light",UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
     *
     * ? getChineseFont()
     *
     * 2?Windows(TrueType)
     * BaseFont.createFont("C:/WINDOWS/Fonts/SIMYOU.TTF",
     * BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
     *
     * 3??(ClassPath)
     * BaseFont.createFont("/SIMYOU.TTF",BaseFont.IDENTITY_H,
     * BaseFont.NOT_EMBEDDED);
     *
     *
     * === ?
     *
     * itext ?????
     *
     * over.setColorFill(Color.LIGHT_GRAY)  ?
     *
     * === getOverContent(),getUnderContent() 
     *
     * getOverContent()  pdf ()
     *
     * getUnderContent()
     *
     * itext??? pdf ??? pdf (Content)????
     *
     * ( word ? pdf )  Content  Content()
     * ??
     *
     *  pdf???? pdf itext ???? Content()
     *  ??
     *
     *  getOverContent()  Content ? Content??
     *
     * ?"?"  ??? setColorFill(Color.LIGHT_GRAY)??
     *
     * ??????
     *
     * === 
     *
     * ???""? ?"?" ?
     */

    /**
     * ??
     */
    private MyPDFUtilss() {

    }

    /**
     * ??
     *
     * @param srcPdf         ?
     * @param destPdf        
     * @param waterMarkImage ?
     */
    public static void addWaterMarkFile(File srcPdf, File destPdf, File waterMarkImage)
            throws IOException, DocumentException {
        addWaterMarkFile(srcPdf, destPdf, null, waterMarkImage);
    }

    /**
     * ?
     *
     * @param srcPdfFileDirectory  ?
     * @param descPdfFileDirectory 
     * @param waterMarkImage       ?
     */
    public static void addWaterMarkDerictory(File srcPdfFileDirectory, File descPdfFileDirectory,
            File waterMarkImage) throws IOException, DocumentException {

        if (descPdfFileDirectory.getAbsolutePath().contains(srcPdfFileDirectory.getAbsolutePath()))
            throw new IOException("?");

        if (!isEnoughtSpace(srcPdfFileDirectory, descPdfFileDirectory))
            return;

        for (File file : srcPdfFileDirectory.listFiles()) {
            String path = descPdfFileDirectory.getAbsolutePath() + File.separator + file.getName();
            if (file.isFile()) {
                addWaterMarkFile(file, Paths.get(path).toFile(), null, waterMarkImage);
            } else if (file.isDirectory())
                addWaterMarkDerictory(file, Paths.get(path).toFile(), waterMarkImage);
            else
                return;

        }
    }

    /**
     * ??
     *
     * @param srcPdf        ?
     * @param destPdf       
     * @param waterMarkText ?
     */
    public static void addWaterMarkFile(File srcPdf, File destPdf, String waterMarkText)
            throws IOException, DocumentException {
        addWaterMarkFile(srcPdf, destPdf, waterMarkText, null);
    }

    /**
     * ?
     *
     * @param srcPdfFileDirectory  ?
     * @param descPdfFileDirectory 
     * @param waterMarkText        ?
     */
    public static void addWaterMarkDerictory(File srcPdfFileDirectory, File descPdfFileDirectory,
            String waterMarkText) throws IOException, DocumentException {

        if (descPdfFileDirectory.getAbsolutePath().contains(srcPdfFileDirectory.getAbsolutePath()))
            throw new IOException("?");

        if (!isEnoughtSpace(srcPdfFileDirectory, descPdfFileDirectory))
            return;

        for (File file : srcPdfFileDirectory.listFiles()) {
            String path = descPdfFileDirectory.getAbsolutePath() + File.separator + file.getName();
            if (file.isFile()) {
                addWaterMarkFile(file, Paths.get(path).toFile(), waterMarkText);
            } else if (file.isDirectory())
                addWaterMarkDerictory(file, Paths.get(path).toFile(), waterMarkText);
            else
                return;

        }

    }

    /**
     * ??
     *
     * @param srcPdf         ?
     * @param destPdf        
     * @param waterMarkText  ?
     * @param waterMarkImage ?
     */
    public static void addWaterMarkFile(File srcPdf, File destPdf, String waterMarkText, File waterMarkImage)
            throws IOException, DocumentException {

        if (waterMarkText == null && waterMarkImage == null)
            throw new FileNotFoundException(waterMarkText + " " + waterMarkImage + " all null.");

        if (srcPdf == null || !srcPdf.exists() || !srcPdf.isFile())
            throw new FileNotFoundException("pdf file :  '" + srcPdf + "' does not exsit.");

        if (!FilenameUtils.getExtension(srcPdf.getAbsolutePath()).toLowerCase().equals("pdf"))
            return;

        if (waterMarkImage != null) {
            if (!waterMarkImage.exists() || !waterMarkImage.isFile())
                throw new FileNotFoundException("img file :  '" + srcPdf + "' does not exsit.");

            if (!FilenameUtils.getExtension(waterMarkImage.getAbsolutePath()).toLowerCase().equals("png"))
                throw new FileNotFoundException("image file '" + srcPdf
                        + "'  not png.(???? pdf )");
        }

        PdfReader reader = getPdfReader(srcPdf);

        int n = reader.getNumberOfPages();
        PdfStamper stamper = getPdfStamper(srcPdf, destPdf);

        //
        //        HashMap<String, String> moreInfo = new HashMap<String, String>();
        //        moreInfo.put("Author", "H819 create");
        //        moreInfo.put("Producer", "H819 Producer");
        //        Key = CreationDate, Value = D:20070425182920
        //        Key = Producer, Value = TH-OCR 2000 (C++/Win32)
        //        Key = Author, Value = TH-OCR 2000
        //        Key = Creator, Value = TH-OCR PDF Writer

        // stamp.setMoreInfo(moreInfo);

        // text
        Phrase text = null;
        if (waterMarkText != null) {
            //
            Font bfont = getPdfFont();
            bfont.setSize(35);
            bfont.setColor(new BaseColor(192, 192, 192));
            text = new Phrase(waterMarkText, bfont);
        }
        // image watermark
        Image img = null;
        float w = 0;
        float h = 0;
        if (waterMarkImage != null) {
            img = Image.getInstance(waterMarkImage.getAbsolutePath());
            w = img.getScaledWidth();
            h = img.getScaledHeight();
            //  img.
            img.setRotationDegrees(45);

        }

        // transparency
        PdfGState gs1 = new PdfGState();
        gs1.setFillOpacity(0.5f);
        // properties
        PdfContentByte over;
        Rectangle pageSize;
        float x, y;
        // loop over every page
        for (int i = 1; i <= n; i++) {
            pageSize = reader.getPageSizeWithRotation(i);
            x = (pageSize.getLeft() + pageSize.getRight()) / 2;
            y = (pageSize.getTop() + pageSize.getBottom()) / 2;
            //  pdf pdf ???
            over = stamper.getOverContent(i);
            // ?
            // over = stamp.getUnderContent(i);
            // ?? over.beginText(); over.endText(); ?
            // ,?,:????
            over.saveState(); //??
            over.setGState(gs1);

            if (waterMarkText != null && waterMarkImage != null) { // 
                if (i % 2 == 1) {
                    ColumnText.showTextAligned(over, Element.ALIGN_CENTER, text, x, y, 45);
                } else
                    over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
            } else if (waterMarkText != null) { //?

                ColumnText.showTextAligned(over, Element.ALIGN_CENTER, text, x, y, 45);
                //?? ,?, :?????
                // ...

            } else { //?
                over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
            }

            over.restoreState();//???
        }

        stamper.close();
        reader.close();

    }

    /**
     * ? pdf ??
     *
     * @param srcPdfFile  the original PDF
     * @param descPdfFile the resulting PDF
     * @throws java.io.IOException
     * @throws DocumentException
     */
    public static void compressPdf(File srcPdfFile, File descPdfFile) throws IOException, DocumentException {

        if (srcPdfFile == null || !srcPdfFile.exists())
            throw new IOException("src pdf file '" + srcPdfFile + "' does not exsit.");

        PdfReader reader = getPdfReader(srcPdfFile);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(descPdfFile.getAbsoluteFile()),
                PdfWriter.VERSION_1_7);

        stamper.getWriter().setCompressionLevel(9);
        int total = reader.getNumberOfPages() + 1;
        for (int i = 1; i < total; i++) {
            reader.setPageContent(i, reader.getPageContent(i));
        }
        stamper.setFullCompression();
        stamper.close();
        reader.close();
    }

    /**
     *  pdf ? pdf
     *
     * @param srcPdf      the original PDF
     * @param destPdf     the resulting PDF
     * @param imageFactor The multiplication factor for the image (?  imageFacto =0.5f)
     * @throws IOException
     * @throws DocumentException
     */
    public static void compressPdf(File srcPdf, File destPdf, float imageFactor)
            throws IOException, DocumentException {

        PdfReader reader = new PdfReader(srcPdf.getAbsolutePath());
        int n = reader.getXrefSize();
        PdfObject object;
        PRStream stream;
        // Look for image and manipulate image stream
        for (int i = 0; i < n; i++) {
            object = reader.getPdfObject(i);
            if (object == null || !object.isStream())
                continue;
            stream = (PRStream) object;
            if (!PdfName.IMAGE.equals(stream.getAsName(PdfName.SUBTYPE)))
                continue;
            if (!PdfName.DCTDECODE.equals(stream.getAsName(PdfName.FILTER)))
                continue;
            PdfImageObject image = new PdfImageObject(stream);
            BufferedImage bi = image.getBufferedImage();
            if (bi == null)
                continue;
            int width = (int) (bi.getWidth() * imageFactor);
            int height = (int) (bi.getHeight() * imageFactor);
            if (width <= 0 || height <= 0)
                continue;
            BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            AffineTransform at = AffineTransform.getScaleInstance(imageFactor, imageFactor);
            Graphics2D g = img.createGraphics();
            g.drawRenderedImage(bi, at);
            ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();
            ImageIO.write(img, "JPG", imgBytes);
            stream.clear();
            stream.setData(imgBytes.toByteArray(), false, PRStream.NO_COMPRESSION);
            stream.put(PdfName.TYPE, PdfName.XOBJECT);
            stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
            stream.put(PdfName.FILTER, PdfName.DCTDECODE);
            stream.put(PdfName.WIDTH, new PdfNumber(width));
            stream.put(PdfName.HEIGHT, new PdfNumber(height));
            stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
            stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
        }
        reader.removeUnusedObjects();
        // Save altered PDF
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destPdf.getAbsolutePath()));
        stamper.setFullCompression();
        stamper.close();
        reader.close();
    }

    /**
     * ?pdf
     *
     * @param srcPdfFile  the original PDF
     * @param descPdfFile the resulting PDF
     * @throws java.io.IOException
     * @throws DocumentException
     */
    public static void decompressPdf(File srcPdfFile, File descPdfFile) throws IOException, DocumentException {

        if (srcPdfFile == null || !srcPdfFile.exists())
            throw new IOException("src pdf file '" + srcPdfFile + "' does not exsit.");

        PdfReader reader = getPdfReader(srcPdfFile);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(descPdfFile.getAbsoluteFile()));
        stamper.getWriter().setCompressionLevel(PdfStream.NO_COMPRESSION);
        int total = reader.getNumberOfPages() + 1;
        for (int i = 1; i < total; i++) {
            reader.setPageContent(i, reader.getPageContent(i));
        }
        stamper.close();
        reader.close();

    }

    /**
     * ??? pdf ???
     *
     * @param srcPdfFileDirectory   pdf . ??
     * @param descPdfFileDirectory ?????
     * @param badDirectory         ?? pdf 
     * @throws java.io.IOException
     */
    public static void decryptDirectory(File srcPdfFileDirectory, File descPdfFileDirectory, File badDirectory)
            throws IOException {

        if (descPdfFileDirectory.getAbsolutePath().contains(srcPdfFileDirectory.getAbsolutePath()))
            throw new IOException("?");

        if (!isEnoughtSpace(srcPdfFileDirectory, descPdfFileDirectory))
            return;

        for (File file : srcPdfFileDirectory.listFiles()) {
            String path = descPdfFileDirectory.getAbsolutePath() + File.separator + file.getName();
            if (file.isFile()) {
                decryptFile(file, Paths.get(path).toFile(), badDirectory);
            } else if (file.isDirectory())
                decryptDirectory(file, Paths.get(path).toFile(), badDirectory);
            else
                return;

        }
    }

    /**
     * ??? pdf 
     * windows 
     * "PDF Password Remover v4.0" ??
     *
     * @param srcPdf        pdf 
     * @param descPdf      ? pdf 
     * @param badDirectory ?? pdf 
     * @throws java.io.IOException
     */

    public static void decryptFile(File srcPdf, File descPdf, File badDirectory) {

        String extension = FilenameUtils.getExtension(srcPdf.getAbsolutePath());

        if (!extension.equalsIgnoreCase("pdf"))
            return;
        // ??? 0 ?
        if (FileUtils.sizeOf(srcPdf) == 0) {
            logger.info("{} size =0 ,copy to {}", srcPdf.getAbsoluteFile(), badDirectory.getAbsoluteFile());
            MyFileUtils.copyFileToDirectory(srcPdf, badDirectory);
            return;
        }

        try {

            PdfReader reader = getPdfReader(srcPdf);
            if (!reader.isEncrypted()) {// ?
                FileUtils.copyFile(srcPdf, descPdf);
                logger.info("not encrypted,copy {} to {} ", srcPdf.getAbsolutePath(), descPdf.getAbsoluteFile());
                return;
            }

            List<ExecParameter> list = new ArrayList<>();
            list.add(new ExecParameter("-i", srcPdf.getAbsolutePath())); // ? key  value
            list.add(new ExecParameter("-o", descPdf.getAbsolutePath()));
            //            list.add(new ExecParameter("-u", ""));
            //            list.add(new ExecParameter("-w", ""));
            MyExecUtils.exec(Paths.get(getPdfPdfdecryptExec()), list, 1);
            logger.info("encrypted {} to {}", srcPdf.getAbsolutePath(), descPdf.getAbsolutePath());
            // ??
            reader.close();

        } catch (BadPasswordException e) {
            // ???
            logger.info("{} has user password ,copy to {}", srcPdf.getAbsoluteFile(),
                    badDirectory.getAbsoluteFile());
            MyFileUtils.copyFileToDirectory(srcPdf, badDirectory);
            e.printStackTrace();
            return;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * pdf  owner ? user (owner  user ??)
     * <p>
     *  pdf  ???
     * <p>
     *  pdf ????,?pdf 
     *
     * @param srcPdf        ?
     * @param descPdf       
     * @param ownerPassword ??.
     * @throws java.io.IOException
     * @throws DocumentException
     */
    public static void decryptFile(File srcPdf, File descPdf, String ownerPassword)
            throws IOException, DocumentException {

        PdfReader reader = getPdfReader(srcPdf, ownerPassword);
        PdfStamper stamper = getPdfStamper(srcPdf, descPdf);
        stamper.close();
        reader.close();

    }

    /**
     *  pdf 
     *
     * @param srcPdfFile        ?
     * @param descPdfFile       
     * @param userPassword      ?? ,null ?
     * @param ownerPassword     ?? ,null ?
     * @param allow_HideMenubar ????
     * @param allow_HideToolbar ??
     * @param allow_printing    ???
     * @param allow_copy        ???
     * @throws java.io.IOException
     * @throws DocumentException
     */
    public static void encryptPdf(File srcPdfFile, File descPdfFile, String userPassword, String ownerPassword,
            boolean allow_HideMenubar, boolean allow_HideToolbar, boolean allow_printing, boolean allow_copy)
            throws IOException {

        if (srcPdfFile == null || !srcPdfFile.exists())
            throw new IOException("src pdf file '" + srcPdfFile + "' does not exsit.");

        byte[] USER = null;
        byte[] OWNER = null;

        /** User password. */
        if (userPassword != null)
            USER = userPassword.getBytes();
        /** Owner password. */
        if (ownerPassword != null)
            OWNER = ownerPassword.getBytes();

        try {

            PdfReader reader = getPdfReader(srcPdfFile);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(descPdfFile.getAbsoluteFile()));

            // 
            // ???? PdfWriter.setViewerPreferences   addViewerPreference
            // ? api ??? addViewerPreference ?
            // ???"|"()?, ? PdfWriter.HideWindowUI
            // ???, ??

            // ( addViewerPreference )
            stamper.getWriter().addViewerPreference(PdfName.CENTERWINDOW, PdfBoolean.PDFTRUE);
            stamper.getWriter().addViewerPreference(PdfName.DISPLAYDOCTITLE, PdfBoolean.PDFTRUE);
            stamper.getWriter().addViewerPreference(PdfName.FITWINDOW, PdfBoolean.PDFTRUE);
            // writer.addViewerPreference(PdfName.HIDEWINDOWUI,
            // PdfBoolean.PDFTRUE);

            if (!allow_HideToolbar)
                stamper.getWriter().addViewerPreference(PdfName.HIDETOOLBAR, PdfBoolean.PDFTRUE);

            if (!allow_HideMenubar)
                stamper.getWriter().addViewerPreference(PdfName.HIDEMENUBAR, PdfBoolean.PDFTRUE);

            //  allow 
            if (allow_printing && allow_copy)
                stamper.setEncryption(USER, OWNER, PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY, true);

            else if (allow_printing)
                stamper.setEncryption(USER, OWNER, PdfWriter.ALLOW_PRINTING, true);

            else if (allow_copy)
                stamper.setEncryption(USER, OWNER, PdfWriter.ALLOW_COPY, true);

            else
                stamper.setEncryption(USER, OWNER, 0, true);

            stamper.close();

            logger.info(srcPdfFile.getAbsoluteFile() + " encrypt finished.");

        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * ??
     *
     * @param srcPdfFileDir 
     * @throws java.io.IOException
     */
    public static void findEcryptPdf(File srcPdfFileDir) throws IOException {

        encryptPdfNamesTemp = new StringBuffer();

        testEcryptPdf(srcPdfFileDir);

        if (encryptPdfNamesTemp.length() == 0)
            FileUtils.writeStringToFile(new File(srcPdfFileDir.getParent() + File.separator + "ecrypt.txt"),
                    "");
        else
            FileUtils.writeStringToFile(new File(srcPdfFileDir.getParent() + File.separator + "ecrypt.txt"),
                    encryptPdfNamesTemp.toString());

        logger.info(" finished!");

    }

    /**
     * pdf?
     *
     * @param srcPdfFileDir 
     * @return
     * @throws IOException
     */
    public static int getNumberOfPages(File srcPdfFileDir) throws IOException {

        numberOfPagesOfDirectory = 0; //?????????
        countNumberOfPagesOfDir(srcPdfFileDir);
        return numberOfPagesOfDirectory;
    }

    /**
     * ???
     *
     * @param srcPdfFileDir
     * @param descPdfFileDir
     * @return
     */
    private static boolean isEnoughtSpace(File srcPdfFileDir, File descPdfFileDir) {

        if (!srcPdfFileDir.exists() && !srcPdfFileDir.isDirectory()) {
            logger.info(srcPdfFileDir.getAbsolutePath() + " not exist.");
            return false;
        }

        try {
            FileUtils.forceMkdir(descPdfFileDir);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // ??

        // 
        long prefixDiskFreeSize = descPdfFileDir.getFreeSpace();
        // ??
        long srcSize = FileUtils.sizeOfDirectory(srcPdfFileDir);

        // logger.info(descPdfFileDir.getAbsolutePath() + " "
        // + prefixDiskFreeSize / 1000000.00 + " M");
        // logger.info(srcPdfFileDir.getAbsolutePath() + " ? :" + srcSize
        // / 1000000.00 + " M");

        if (prefixDiskFreeSize < srcSize) {
            logger.info(FilenameUtils.getPrefix(descPdfFileDir.getAbsolutePath()) + " has not enoght disk size .");
            return false;
        }

        return true;

    }

    /**
     * ?
     * <p>
     * ? iText in Action 2nd EditionChapter 6: Working with existing PDFs
     * Concatenate
     * </p>
     *
     * @param files  ?
     * @param result ??
     * @throws DocumentException
     * @throws java.io.IOException
     */
    public static void merge(File[] files, File result) throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2

        /**
         * PdfCopy  PdfSmartCopy 
         *
         * PdfCopy???
         *
         * PdfSmartCopy??????
         */
        //
        // PdfCopy copy = new PdfCopy(document, new FileOutputStream(result));
        PdfSmartCopy copy = new PdfSmartCopy(document, new FileOutputStream(result));
        // step 3
        document.open();
        // step 4
        PdfReader reader;
        int n;
        // loop over the documents you want to concatenate
        for (int i = 0; i < files.length; i++) {
            reader = getPdfReader(files[i]);
            // loop over the pages in that document
            n = reader.getNumberOfPages();
            for (int page = 0; page < n;) {
                copy.addPage(copy.getImportedPage(reader, ++page));
            }
            copy.freeReader(reader);
        }
        // step 5
        document.close();
    }

    /**
     * http://www.javabeat.net/javascript-in-pdf-documents-using-itext/
     * http://www.javabeat.net/javascript-communication-between-html-and-pdf-in-itext/
     *  PDF  field  javaScript
     * <p>
     * pdf ? javaScript?????
     * <p>
     * javaScript ?? filed  filed javaScript ???
     * <p>
     * ?? javaScript 
     * <p>
     *  itext  reader.getJavaScript()? pdf  JavaScript??(adobe pro
     * ????)
     * <p>
     * ??? field ??
     *
     * @param srcPdfFileDir   ?
     * @param descPdfFileDir  
     * @param removeFieldName  javaScript ???
     * @throws java.io.IOException
     */
    public static void removeFieldJavaScript(File srcPdfFileDir, File descPdfFileDir, String removeFieldName)
            throws IOException {

        if (!srcPdfFileDir.isDirectory()) {
            logger.info("srcPdfFileDir is not a Directory: " + srcPdfFileDir.getAbsolutePath());
            return;
        }

        File listFiles[] = srcPdfFileDir.listFiles();

        if (listFiles.length == 0) {
            logger.info("srcPdfFileDir has not file. " + srcPdfFileDir.getAbsolutePath());
            return;
        }

        FileUtils.forceMkdir(descPdfFileDir);

        // ??

        // 
        long prefixDiskFreeSize = descPdfFileDir.getFreeSpace();
        // ??
        long srcSize = FileUtils.sizeOf(srcPdfFileDir);

        logger.info(descPdfFileDir.getAbsolutePath() + " " + prefixDiskFreeSize / 1000000.00
                + " M");
        logger.info(srcPdfFileDir.getAbsolutePath() + " ? :" + srcSize / 1000000.00 + " M");

        if (prefixDiskFreeSize < srcSize) {

            logger.info(FilenameUtils.getPrefix(descPdfFileDir.getAbsolutePath()) + " has not enoght disk size .");

            return;
        }

        // logger.info(descPdfFileDir.getAbsolutePath());

        for (File f : listFiles) {
            String fileName = f.getName();
            String extensiion = FilenameUtils.getExtension(fileName).toLowerCase();

            PdfReader reader = null;

            PdfStamper stamper = null;

            if (f.isFile()) {
                if (extensiion.equals("pdf")) {

                    reader = getPdfReader(f);

                    File fileDesc = new File(descPdfFileDir.getAbsolutePath() + File.separator + fileName);

                    try {
                        stamper = new PdfStamper(reader, FileUtils.openOutputStream(fileDesc));

                        /**
                         * ???
                         * **/
                        // reader.removeFields();

                        /**
                         * ??? javaScript ?
                         * **/
                        AcroFields form = stamper.getAcroFields();
                        form.removeField(removeFieldName);

                        stamper.close();
                        reader.close();

                    } catch (DocumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                } else
                    continue;

            } // end if f.isFile

            else if (f.isDirectory()) {
                removeFieldJavaScript(f, new File(descPdfFileDir.getAbsolutePath() + File.separator + fileName),
                        removeFieldName);
            } // end if f.isDirectory
            else
                continue;

        } // end for

        logger.info("finished !");
    }

    /**
     * ?pdf???
     * <p>
     *  javaScript ???? javaScript ?
     * </p>
     *
     * @param srcPdfFileDir  ?
     * @param descPdfFileDir 
     * @param startDate      ? "2011,01,01"
     * @param alerDays       ???
     * @param expiredDays    ?????
     * @throws java.io.IOException
     */
    public static void setExpireDateWithJavaScript(File srcPdfFileDir, File descPdfFileDir, String startDate,
            int alerDays, int expiredDays) throws IOException {

        // ??
        if (alerDays >= expiredDays) {
            logger.info(" ' ' " + alerDays + "  '' " + expiredDays);
            return;
        }

        // ??? ?
        if (StringUtils.countMatches(startDate, ",") != 2) {
            logger.info(startDate + " ??  '2011,01,01' ?");
            return;
        }

        if (!isEnoughtSpace(srcPdfFileDir, descPdfFileDir))
            return;

        File listFiles[] = srcPdfFileDir.listFiles();

        if (listFiles.length == 0) {
            logger.info("srcPdfFileDir has not file. " + srcPdfFileDir.getAbsolutePath());
            return;
        }

        // ??
        // String[] resources = new String[]{"/pdfexpiration.js"};
        File resPath = MyFileUtils.copyResourceFileFromJarLibToTmpDir("/pdfexpiration.js"); //????
        // ?
        String jsStr = FileUtils.readFileToString(resPath);

        /** ? js ? */
        // ?
        jsStr = StringUtils.replace(jsStr, "2011,01,01", startDate);
        // ?
        jsStr = StringUtils.replace(jsStr, "alertDays = 355", "alertDays = " + Integer.toString(alerDays));
        // ?
        jsStr = StringUtils.replace(jsStr, "expiredDays = 365", "expiredDays = " + Integer.toString(expiredDays));

        System.out.println(jsStr);

        // logger.info(descPdfFileDir.getAbsolutePath());

        for (File f : listFiles) {
            String fileName = f.getName();
            String extensiion = FilenameUtils.getExtension(fileName).toLowerCase();

            if (f.isFile()) {
                if (extensiion.equals("pdf")) {

                    PdfReader reader = getPdfReader(f);

                    File fileDesc = new File(descPdfFileDir.getAbsolutePath() + File.separator + fileName);

                    try {
                        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(fileDesc));
                        // Get the writer (to add actions and annotations)
                        PdfWriter writer = stamper.getWriter();
                        PdfAction action = PdfAction.javaScript(jsStr, writer, true);
                        //  javaScript ?
                        stamper.setPageAction(PdfWriter.PAGE_OPEN, action, 1);
                        // Close the stamper
                        stamper.close();
                        reader.close();

                        logger.info(fileDesc.getAbsolutePath() + " ? !");

                    } catch (DocumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                } else
                    continue;

            } // end if f.isFile

            else if (f.isDirectory()) {
                setExpireDateWithJavaScript(f,
                        new File(descPdfFileDir.getAbsolutePath() + File.separator + fileName), startDate, alerDays,
                        expiredDays);
            } // end if f.isDirectory
            else
                continue;

        } // end for
    }

    /**
     * 
     * <p/>
     * <p>
     * ? iText in Action 2nd EditionChapter 6: Working with existing PDFs
     * SelectPages
     * </p>
     *
     * @param src       ?
     * @param desc      
     * @param beginPage 
     * @param endPage   ?
     * @throws java.io.IOException
     * @throws DocumentException
     */
    public static void splitToPages(File src, File desc, int beginPage, int endPage)
            throws IOException, DocumentException {

        PdfReader reader = getPdfReader(src);
        // reader.selectPages("4-8");
        reader.selectPages(Integer.toString(beginPage) + "-" + Integer.toString(endPage));
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(desc));
        stamper.close();
    }

    /**
     * ??? findEcryptPdf()
     *
     * @param srcPdfFileDir 
     * @throws java.io.IOException
     */
    private static void testEcryptPdf(File srcPdfFileDir) throws IOException {

        encryptPdfNamesTemp = new StringBuffer();

        if (!srcPdfFileDir.isDirectory()) {
            logger.info("srcPdfFileDir is not a Directory: " + srcPdfFileDir.getAbsolutePath());
            return;
        }

        File listFiles[] = srcPdfFileDir.listFiles();

        if (listFiles.length == 0) {
            logger.info("srcPdfFileDir has not file. " + srcPdfFileDir.getAbsolutePath());
            return;
        }

        // logger.info(descPdfFileDir.getAbsolutePath());

        for (File f : listFiles) {
            String fileName = f.getName();
            String extensiion = FilenameUtils.getExtension(fileName).toLowerCase();

            if (f.isFile()) {

                if (extensiion.equals("pdf")) {

                    // ??? 0  40 M 
                    if (FileUtils.sizeOf(f) == 0 || FileUtils.sizeOf(f) > 40 * 1000000) {

                        encryptPdfNamesTemp.append("size > 40M :" + f.getAbsolutePath() + "\n");
                        continue;
                    }

                    PdfReader reader = null;
                    try {
                        reader = getPdfReader(f);
                    } catch (BadPasswordException e) {
                        // ??
                        e.printStackTrace();
                        encryptPdfNamesTemp.append("can not open :" + f.getAbsolutePath() + "\n");
                        continue;
                    } catch (Exception e2) {

                        encryptPdfNamesTemp.append("other exception :" + f.getAbsolutePath() + "\n");
                        e2.printStackTrace();
                        continue;

                    }
                    // logger.info("fileDesc name :" + fileDesc.getAbsolutePath());

                    if (reader.isEncrypted()) {// 
                        encryptPdfNamesTemp.append("encrypted :" + f.getAbsolutePath() + "\n");
                        reader.close();
                        continue;
                    } else {
                        logger.info("not encrypted :" + f.getAbsoluteFile());
                        reader.close();
                        continue;
                    }

                } // end if f.isFile
                else
                    continue;
            } else if (f.isDirectory()) {
                testEcryptPdf(f);
            } // end if f.isDirectory
            else
                continue;

        } // end for

    }

    /**
     * ?
     *
     * @param srcPdf
     * @param destPdf
     * @return
     * @throws IOException
     * @throws DocumentException
     */

    public static PdfStamper getPdfStamper(File srcPdf, File destPdf) throws IOException, DocumentException {
        return new PdfStamper(getPdfReader(srcPdf), new FileOutputStream(destPdf), PdfWriter.VERSION_1_7);
    }

    // http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/js_api_reference.pdf
    // adobe  javaScript ?

    /**
     *  PdfReader ? pdf  pdf ???
     *
     * @param pdfFile ? pdf 
     * @return PdfReader 
     * @throws IOException
     */
    public static PdfReader getPdfReader(File pdfFile) throws IOException {

        Document.plainRandomAccess = true;
        FileInputStream fileStream = new FileInputStream(pdfFile);
        return new PdfReader(
                new RandomAccessFileOrArray(new FileChannelRandomAccessSource(fileStream.getChannel())), null);

    }

    /**
     *  PdfReader ? pdf  pdf ??
     *
     * @param pdfFile       ? pdf 
     * @param ownerPassword ?
     * @return
     * @throws IOException
     */
    public static PdfReader getPdfReader(File pdfFile, String ownerPassword) throws IOException {

        FileInputStream fileStream = new FileInputStream(pdfFile);

        if (ownerPassword == null)
            return getPdfReader(pdfFile);

        return new PdfReader(
                new RandomAccessFileOrArray(new FileChannelRandomAccessSource(fileStream.getChannel())),
                ownerPassword.getBytes());
    }

    /**
     *  STCAIYUN.TTF?? jar? classpath
     * ? pdf ??? pdf ?
     * ??????
     *
     * @return
     * @throws IOException
     */
    private static Font getPdfFont() {

        //
        String fontName = "/STCAIYUN.TTF";
        String fontPath = SystemUtils.getJavaIoTmpDir() + File.separator + MyConstants.JarTempDir + File.separator
                + fontName;

        //?????
        if (!Files.exists(Paths.get(fontPath))) {
            MyFileUtils.copyResourceFileFromJarLibToTmpDir(fontName);
        }
        return FontFactory.getFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
    }

    /**
     * ? iTextAsian.jar
     * itext 5.5.9 ???
     *
     * @return
     */
    @Deprecated
    private static Font getChineseFont() {
        Font fontChinese = null;
        try {
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            fontChinese = new Font(bfChinese, 12, Font.NORMAL);
        } catch (DocumentException de) {
            System.err.println(de.getMessage());
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        }
        return fontChinese;
    }

    /**
     * pdf??? getPageCount()
     *
     * @param srcPDFFileDir 
     * @return
     * @throws IOException
     */
    private static void countNumberOfPagesOfDir(File srcPDFFileDir) throws IOException {

        if (srcPDFFileDir == null || !srcPDFFileDir.isDirectory())
            throw new FileNotFoundException(srcPDFFileDir + "'is null or dose not exist.");

        Collection<File> listPDFs = FileUtils.listFiles(srcPDFFileDir, null, true);
        for (File f : listPDFs) {

            // 
            if (f.isDirectory())
                countNumberOfPagesOfDir(f);

            if (!FilenameUtils.getExtension(f.getName().toUpperCase()).equals("PDF"))
                continue;
            // System.out.println(f.getPath());
            // we create a reader for a certain document
            PdfReader reader = getPdfReader(f);
            // we retrieve the total number of pages
            // 
            if (reader.isEncrypted())
                continue;

            numberOfPagesOfDirectory = numberOfPagesOfDirectory + reader.getNumberOfPages();

        }
    }

    /**
     * pdfdecrypt.exe 
     *
     * @return
     * @throws IOException
     */
    private static String getPdfPdfdecryptExec() {

        //?????
        String exec1 = "/pdfdecrypt.exe";
        String exec2 = "/license.dat";

        String tempPath = SystemUtils.getJavaIoTmpDir() + File.separator + MyConstants.JarTempDir + File.separator;

        String exec1Path = tempPath + exec1;
        String exec2Path = tempPath + exec2;

        //?????
        if (!Files.exists(Paths.get(exec1Path)))
            MyFileUtils.copyResourceFileFromJarLibToTmpDir(exec1);

        if (!Files.exists(Paths.get(exec2Path)))
            MyFileUtils.copyResourceFileFromJarLibToTmpDir(exec2);

        return exec1Path;
    }

}