List of usage examples for org.apache.pdfbox.pdmodel PDDocument getDocumentCatalog
public PDDocumentCatalog getDocumentCatalog()
From source file:com.ecmkit.service.convert.impl.PDFToImage.java
License:Apache License
private static void changeCropBoxes(PDDocument document, float a, float b, float c, float d) { List pages = document.getDocumentCatalog().getAllPages(); for (int i = 0; i < pages.size(); i++) { System.out.println("resizing page"); PDPage page = (PDPage) pages.get(i); PDRectangle rectangle = new PDRectangle(); rectangle.setLowerLeftX(a);/* w ww. jav a 2s.c om*/ rectangle.setLowerLeftY(b); rectangle.setUpperRightX(c); rectangle.setUpperRightY(d); page.setMediaBox(rectangle); page.setCropBox(rectangle); } }
From source file:com.fangxin365.core.utils.PDFMerger.java
License:Apache License
/** * append all pages from source to destination. * /*w ww .java2s.c o m*/ * @param destination * the document to receive the pages * @param source * the document originating the new pages * * @throws IOException * If there is an error accessing data from either document. */ public void appendDocument(PDDocument destination, PDDocument source) throws IOException { if (destination.isEncrypted()) { System.out.println("Error: destination PDF is encrypted, can't append encrypted PDF documents."); } if (source.isEncrypted()) { System.out.println("Error: source PDF is encrypted, can't append encrypted PDF documents."); } PDDocumentInformation destInfo = destination.getDocumentInformation(); PDDocumentInformation srcInfo = source.getDocumentInformation(); destInfo.getDictionary().mergeInto(srcInfo.getDictionary()); PDDocumentCatalog destCatalog = destination.getDocumentCatalog(); PDDocumentCatalog srcCatalog = source.getDocumentCatalog(); // use the highest version number for the resulting pdf float destVersion = destination.getDocument().getVersion(); float srcVersion = source.getDocument().getVersion(); if (destVersion < srcVersion) { destination.getDocument().setVersion(srcVersion); } if (destCatalog.getOpenAction() == null) { destCatalog.setOpenAction(srcCatalog.getOpenAction()); } // maybe there are some shared resources for all pages COSDictionary srcPages = (COSDictionary) srcCatalog.getCOSDictionary().getDictionaryObject(COSName.PAGES); COSDictionary srcResources = (COSDictionary) srcPages.getDictionaryObject(COSName.RESOURCES); COSDictionary destPages = (COSDictionary) destCatalog.getCOSDictionary().getDictionaryObject(COSName.PAGES); COSDictionary destResources = (COSDictionary) destPages.getDictionaryObject(COSName.RESOURCES); if (srcResources != null) { if (destResources != null) { destResources.mergeInto(srcResources); } else { destPages.setItem(COSName.RESOURCES, srcResources); } } PDFCloneUtility cloner = new PDFCloneUtility(destination); try { PDAcroForm destAcroForm = destCatalog.getAcroForm(); PDAcroForm srcAcroForm = srcCatalog.getAcroForm(); if (destAcroForm == null) { cloner.cloneForNewDocument(srcAcroForm); destCatalog.setAcroForm(srcAcroForm); } else { if (srcAcroForm != null) { mergeAcroForm(cloner, destAcroForm, srcAcroForm); } } } catch (Exception e) { // if we are not ignoring exceptions, we'll re-throw this if (!ignoreAcroFormErrors) { throw (IOException) e; } } COSArray destThreads = (COSArray) destCatalog.getCOSDictionary().getDictionaryObject(COSName.THREADS); COSArray srcThreads = (COSArray) cloner .cloneForNewDocument(destCatalog.getCOSDictionary().getDictionaryObject(COSName.THREADS)); if (destThreads == null) { destCatalog.getCOSDictionary().setItem(COSName.THREADS, srcThreads); } else { destThreads.addAll(srcThreads); } PDDocumentNameDictionary destNames = destCatalog.getNames(); PDDocumentNameDictionary srcNames = srcCatalog.getNames(); if (srcNames != null) { if (destNames == null) { destCatalog.getCOSDictionary().setItem(COSName.NAMES, cloner.cloneForNewDocument(srcNames)); } else { cloner.cloneMerge(srcNames, destNames); } } PDDocumentOutline destOutline = destCatalog.getDocumentOutline(); PDDocumentOutline srcOutline = srcCatalog.getDocumentOutline(); if (srcOutline != null) { if (destOutline == null) { PDDocumentOutline cloned = new PDDocumentOutline( (COSDictionary) cloner.cloneForNewDocument(srcOutline)); destCatalog.setDocumentOutline(cloned); } else { PDOutlineItem first = srcOutline.getFirstChild(); if (first != null) { PDOutlineItem clonedFirst = new PDOutlineItem( (COSDictionary) cloner.cloneForNewDocument(first)); destOutline.appendChild(clonedFirst); } } } String destPageMode = destCatalog.getPageMode(); String srcPageMode = srcCatalog.getPageMode(); if (destPageMode == null) { destCatalog.setPageMode(srcPageMode); } COSDictionary destLabels = (COSDictionary) destCatalog.getCOSDictionary() .getDictionaryObject(COSName.PAGE_LABELS); COSDictionary srcLabels = (COSDictionary) srcCatalog.getCOSDictionary() .getDictionaryObject(COSName.PAGE_LABELS); if (srcLabels != null) { int destPageCount = destination.getNumberOfPages(); COSArray destNums = null; if (destLabels == null) { destLabels = new COSDictionary(); destNums = new COSArray(); destLabels.setItem(COSName.NUMS, destNums); destCatalog.getCOSDictionary().setItem(COSName.PAGE_LABELS, destLabels); } else { destNums = (COSArray) destLabels.getDictionaryObject(COSName.NUMS); } COSArray srcNums = (COSArray) srcLabels.getDictionaryObject(COSName.NUMS); if (srcNums != null) { for (int i = 0; i < srcNums.size(); i += 2) { COSNumber labelIndex = (COSNumber) srcNums.getObject(i); long labelIndexValue = labelIndex.intValue(); destNums.add(COSInteger.get(labelIndexValue + destPageCount)); destNums.add(cloner.cloneForNewDocument(srcNums.getObject(i + 1))); } } } COSStream destMetadata = (COSStream) destCatalog.getCOSDictionary().getDictionaryObject(COSName.METADATA); COSStream srcMetadata = (COSStream) srcCatalog.getCOSDictionary().getDictionaryObject(COSName.METADATA); if (destMetadata == null && srcMetadata != null) { PDStream newStream = new PDStream(destination, srcMetadata.getUnfilteredStream(), false); newStream.getStream().mergeInto(srcMetadata); newStream.addCompression(); destCatalog.getCOSDictionary().setItem(COSName.METADATA, newStream); } // finally append the pages @SuppressWarnings("unchecked") List<PDPage> pages = srcCatalog.getAllPages(); Iterator<PDPage> pageIter = pages.iterator(); while (pageIter.hasNext()) { PDPage page = pageIter.next(); PDPage newPage = new PDPage((COSDictionary) cloner.cloneForNewDocument(page.getCOSDictionary())); newPage.setCropBox(page.findCropBox()); newPage.setMediaBox(page.findMediaBox()); newPage.setRotation(page.findRotation()); destination.addPage(newPage); } }
From source file:com.formkiq.core.service.generator.pdfbox.PdfEditorServiceImpl.java
License:Apache License
/** * Do Partial PDF Save. This save works when updating Signature fields. * @param docBytes byte[]//from w w w. j a v a 2 s.c o m * @param archive {@link ArchiveDTO} * @param output {@link WorkflowOutputPdfForm} * @throws IOException IOException */ private void doSignaturePdfSave(final byte[] docBytes, final ArchiveDTO archive, final WorkflowOutputPdfForm output) throws IOException { boolean signed = false; List<SignatureOptions> signatureOptions = new ArrayList<>(); PDDocument doc = loadPDF(docBytes); try { PDDocumentCatalog docCatalog = doc.getDocumentCatalog(); PDAcroForm pdform = docCatalog.getAcroForm(); for (WorkflowOutputFormField ofield : output.getFields()) { Optional<FormJSON> form = findForm(archive, ofield); Optional<FormJSONField> field = findFormField(form, ofield); if (form.isPresent() && field.isPresent()) { String value = field.get().getValue(); PDField pfield = pdform.getField(ofield.getDocumentfieldname()); if (pfield != null && pfield instanceof PDSignatureField) { byte[] bs = form.get().getAssetData().get(value); if (bs != null) { try { InputStream is = new ByteArrayInputStream(bs); signatureOptions.add(setValue(doc, (PDSignatureField) pfield, is)); signed = true; } catch (IllegalStateException e) { LOG.log(Level.WARNING, "unable to set signature", e); } } } } } if (signed) { ByteArrayOutputStream bs = new ByteArrayOutputStream(); doc.saveIncremental(bs); bs.close(); String pdfname = output.getName(); archive.addPDF(pdfname + ".pdf", bs.toByteArray()); } for (SignatureOptions sigOption : signatureOptions) { IOUtils.closeQuietly(sigOption); } } finally { doc.close(); } }
From source file:com.formkiq.core.service.generator.pdfbox.PdfEditorServiceImpl.java
License:Apache License
/** * Do Full PDF Save. This save works when updating the values of fields. * @param docBytes byte[]//from w ww . j a v a2s . co m * @param archive {@link ArchiveDTO} * @param output {@link WorkflowOutputPdfForm} * @return boolean - whether signature fields are found * @throws IOException IOException */ private boolean dofullPDFSave(final byte[] docBytes, final ArchiveDTO archive, final WorkflowOutputPdfForm output) throws IOException { boolean hasSignatures = false; PDDocument doc = loadPDF(docBytes); try { PDDocumentCatalog docCatalog = doc.getDocumentCatalog(); PDAcroForm pdform = docCatalog.getAcroForm(); for (WorkflowOutputFormField ofield : output.getFields()) { Optional<FormJSON> form = findForm(archive, ofield); Optional<FormJSONField> field = findFormField(form, ofield); if (form.isPresent() && field.isPresent()) { PDField pdfield = pdform.getField(ofield.getDocumentfieldname()); if (pdfield != null) { if (pdfield instanceof PDSignatureField) { hasSignatures = true; } else { String value = field.get().getValue(); List<String> values = field.get().getValues(); if (!isEmpty(values)) { for (String val : values) { pdfield.setValue(extractLabelAndValue(val).getRight()); } } else if (!isEmpty(value)) { value = extractLabelAndValue(value).getRight(); pdfield.setValue(value); } } } } } ByteArrayOutputStream bs = new ByteArrayOutputStream(); doc.save(bs); bs.close(); String pdfname = output.getName(); archive.addPDF(pdfname + ".pdf", bs.toByteArray()); return hasSignatures; } finally { doc.close(); } }
From source file:com.formkiq.core.service.generator.pdfbox.PdfEditorServiceImpl.java
License:Apache License
/** * Sets value of {@link PDSignatureField}. * @param doc {@link PDDocument}//from www . ja v a 2s . co m * @param field {@link PDSignatureField} * @param signatureInputStream {@link InputStream} * @return {@link SignatureOptions} * @throws IOException IOException */ private SignatureOptions setValue(final PDDocument doc, final PDSignatureField field, final InputStream signatureInputStream) throws IOException { int accessPermissions = SigUtils.getMDPPermission(doc); if (accessPermissions == 1) { throw new IllegalStateException("No changes to the document are " + "permitted due to DocMDP transform parameters " + "dictionary"); } // retrieve signature dictionary PDSignature signature = field.getSignature(); if (signature == null) { signature = new PDSignature(); // after solving PDFBOX-3524 - signatureField.setValue(signature) // until then: field.getCOSObject().setItem(COSName.V, signature); } else { throw new IllegalStateException( "The signature field " + field.getFullyQualifiedName() + " is already signed."); } // Optional: certify // can be done only if version is at least 1.5 and if not already set // doing this on a PDF/A-1b file fails validation by Adobe // preflight (PDFBOX-3821) // PDF/A-1b requires PDF version 1.4 max, so don't increase the version // on such files. final float version = 1.5f; if (doc.getVersion() >= version && accessPermissions == 0) { SigUtils.setMDPPermission(doc, signature, 2); } PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm(); if (acroForm != null && acroForm.getNeedAppearances()) { // PDFBOX-3738 NeedAppearances true results in visible signature // becoming invisible // with Adobe Reader if (acroForm.getFields().isEmpty()) { // we can safely delete it if there are no fields acroForm.getCOSObject().removeItem(COSName.NEED_APPEARANCES); // note that if you've set MDP permissions, the removal of this // item // may result in Adobe Reader claiming that the document has // been changed. // and/or that field content won't be displayed properly. // ==> decide what you prefer and adjust your code accordingly. } } // default filter signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // subfilter for basic and PAdES Part 2 signatures signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); PDVisibleSignDesigner visibleSignDesigner = new PDVisibleSignDesigner(signatureInputStream); PDVisibleSigProperties visibleSigProps = new PDVisibleSigProperties(); visibleSigProps // .signerName(name) // TODO add.. // .signerLocation(location) // TODO add. // .signatureReason(reason) // .preferredSize(preferredSize) // .page(0) // TODO fix .visualSignEnabled(true).setPdVisibleSignature(visibleSignDesigner); visibleSigProps.buildSignature(); signature.setName(visibleSigProps.getSignerName()); signature.setLocation(visibleSigProps.getSignerLocation()); signature.setReason(visibleSigProps.getSignatureReason()); // the signing date, needed for valid signature signature.setSignDate(Calendar.getInstance()); SignatureOptions sigOptions = new SignatureOptions(); sigOptions.setVisualSignature(visibleSigProps.getVisibleSignature()); sigOptions.setPage(visibleSigProps.getPage() - 1); doc.addSignature(signature, this, sigOptions); return sigOptions; }
From source file:com.formkiq.core.service.generator.pdfbox.PdfEditorServiceImpl.java
License:Apache License
@Override public Pair<FormJSON, List<WorkflowOutputFormField>> getOutputFormFields(final String filename, final byte[] data) throws IOException { List<WorkflowOutputFormField> wofields = new ArrayList<>(); PDDocument doc = loadPDF(data); try {/* w ww . jav a2 s .com*/ Map<COSDictionary, Integer> obMap = getCOSDictionaryToPageNumberMap(doc); Map<Integer, List<PDField>> pdMap = getPDFields(doc, obMap); Map<Integer, List<PdfTextField>> textsMap = getTextMap(doc); PDPageTree pages = doc.getDocumentCatalog().getPages(); FormJSON form = buildFormJSON(doc, textsMap.get(Integer.valueOf(0))); for (int i = 0; i < pages.getCount(); i++) { PDPage page = pages.get(i); Integer pageNum = Integer.valueOf(i); List<PDField> fields = pdMap.getOrDefault(pageNum, emptyList()); List<PdfTextField> texts = getTextForPage(textsMap, pageNum); List<PDRectangle> lineRects = getPageLinePaths(pages.get(i)); Map<PDField, FormJSONField> fieldMap = buildFormSection(form, page, fields, texts, lineRects); List<WorkflowOutputFormField> outfields = createFieldOutputs(form, fields, fieldMap); wofields.addAll(outfields); } return Pair.of(form, wofields); } finally { doc.close(); } }
From source file:com.formkiq.core.service.generator.pdfbox.PdfEditorServiceImpl.java
License:Apache License
/** * Take {@link PDField} objects from {@link PDDocument} * and create {@link PDField} from them. * * @param doc {@link PDDocument}//from www . ja v a2s . c o m * @param objMap {@link Map} of {@link COSDictionary} and Page Number * @return {@link Map} of {@link PDField} by page number * @throws IOException IOException */ private Map<Integer, List<PDField>> getPDFields(final PDDocument doc, final Map<COSDictionary, Integer> objMap) throws IOException { PDDocumentCatalog dc = doc.getDocumentCatalog(); PDAcroForm pdform = dc.getAcroForm(); Map<Integer, List<PDField>> map = new HashMap<>(); for (PDField field : pdform.getFields()) { if (field instanceof PDPushButton) { LOG.log(Level.FINE, "skip addFieldToPageMap='" + field.getFullyQualifiedName() + "',class=" + field.getClass().getName()); continue; } addFieldToPageMap(objMap, field, map); } for (Map.Entry<Integer, List<PDField>> e : map.entrySet()) { Collections.sort(e.getValue(), new PDFieldComparator()); } return map; }
From source file:com.formkiq.core.service.generator.pdfbox.SigUtils.java
License:Apache License
/** * Get the access permissions granted for this document in the DocMDP * transform parameters dictionary. Details are described in the table * "Entries in the DocMDP transform parameters dictionary" in the PDF * specification./*from www .j av a 2s. c o m*/ * * @param doc * document. * @return the permission value. 0 means no DocMDP transform parameters * dictionary exists. Other return values are 1, 2 or 3. 2 is also * returned if the DocMDP transform parameters dictionary is found * but did not contain a /P entry, or if the value is outside the * valid range. */ public static int getMDPPermission(final PDDocument doc) { final int maxPerm = 3; COSBase base = doc.getDocumentCatalog().getCOSObject().getDictionaryObject(COSName.PERMS); if (base instanceof COSDictionary) { COSDictionary permsDict = (COSDictionary) base; base = permsDict.getDictionaryObject(COSName.DOCMDP); if (base instanceof COSDictionary) { COSDictionary signatureDict = (COSDictionary) base; base = signatureDict.getDictionaryObject("Reference"); if (base instanceof COSArray) { COSArray refArray = (COSArray) base; for (int i = 0; i < refArray.size(); ++i) { base = refArray.getObject(i); if (base instanceof COSDictionary) { COSDictionary sigRefDict = (COSDictionary) base; if (COSName.DOCMDP.equals(sigRefDict.getDictionaryObject("TransformMethod"))) { base = sigRefDict.getDictionaryObject("TransformParams"); if (base instanceof COSDictionary) { COSDictionary dict = (COSDictionary) base; int accessPermissions = dict.getInt(COSName.P, 2); if (accessPermissions < 1 || accessPermissions > maxPerm) { accessPermissions = 2; } return accessPermissions; } } } } } } } return 0; }
From source file:com.formkiq.core.service.generator.pdfbox.SigUtils.java
License:Apache License
/** * Set the access permissions granted for this document in the DocMDP * transform parameters dictionary. Details are described in the table * "Entries in the DocMDP transform parameters dictionary" in the PDF * specification./*from w w w.j a v a2s .c o m*/ * * @param doc * The document. * @param signature * The signature object. * @param accessPermissions * The permission value (1, 2 or 3). */ public static void setMDPPermission(final PDDocument doc, final PDSignature signature, final int accessPermissions) { COSDictionary sigDict = signature.getCOSObject(); // DocMDP specific stuff COSDictionary transformParameters = new COSDictionary(); transformParameters.setItem(COSName.TYPE, COSName.getPDFName("TransformParams")); transformParameters.setInt(COSName.P, accessPermissions); transformParameters.setName(COSName.V, "1.2"); transformParameters.setNeedToBeUpdated(true); COSDictionary referenceDict = new COSDictionary(); referenceDict.setItem(COSName.TYPE, COSName.getPDFName("SigRef")); referenceDict.setItem("TransformMethod", COSName.DOCMDP); referenceDict.setItem("DigestMethod", COSName.getPDFName("SHA1")); referenceDict.setItem("TransformParams", transformParameters); referenceDict.setNeedToBeUpdated(true); COSArray referenceArray = new COSArray(); referenceArray.add(referenceDict); sigDict.setItem("Reference", referenceArray); referenceArray.setNeedToBeUpdated(true); // Catalog COSDictionary catalogDict = doc.getDocumentCatalog().getCOSObject(); COSDictionary permsDict = new COSDictionary(); catalogDict.setItem(COSName.PERMS, permsDict); permsDict.setItem(COSName.DOCMDP, signature); catalogDict.setNeedToBeUpdated(true); permsDict.setNeedToBeUpdated(true); }
From source file:com.formkiq.web.WorkflowAddControllerIntegrationTest.java
License:Apache License
/** * testCreateWorkflow11().//from www . j a v a2s .c om * fillout and generate and sign fillable PDF * @throws Exception Exception */ @Test public void testCreateWorkflow11() throws Exception { // given String pdfname = "sample-form2.pdf"; byte[] data = Resources.getResourceAsBytes("/" + pdfname); ArchiveDTO archive = buildArchiveDTO(pdfname); this.pdfEditorService.generate(archive, pdfname, data); String token = login(); String folder = createFolder(token, getDefaultEmail()); addFileToFolder(token, folder, archive); // when login(getDefaultEmail()); getDriver().navigate().to(getDefaultHostAndPort() + "/user/dashboard"); waitForJSandJQueryToLoad(); assertEquals("FormKiQ Server - Dashboard", getTitle()); findElementBy(By.className("add_0")).click(); // then (verify on correct page) assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl()); assertEquals(SAMPLE_FORM_2_HTML_TITLE, getTitle()); fillSampleForm2(); // when (submit) submitByName("_eventId_next", "Next"); // then verify summary assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl()); assertEquals("FormKiQ Server - Signature", getTitle()); assertEquals(1, findElements(getBy("button", "data-fieldid", "55")).size()); assertEquals(0, getDriver().findElements(getBy("img", "data-fieldid", "55")).size()); // when (go back submitByName("_eventId_prev", "Previous"); // then assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e1", getDriver().getCurrentUrl()); assertEquals(SAMPLE_FORM_2_HTML_TITLE, getTitle()); // when findElementBy(By.name("1")).sendKeys("Smith123"); submitByName("_eventId_next", "Next"); // then assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e2", getDriver().getCurrentUrl()); assertEquals("FormKiQ Server - Signature", getTitle()); // when (signature) click(By.className("button-sig")); JavascriptExecutor jsExecutor = (JavascriptExecutor) getDriver(); jsExecutor.executeScript("signaturemetadata('555','999');"); // then getWait().until(ExpectedConditions.visibilityOfElementLocated(By.id("form-modal"))); // when click(By.className("form-modal-close-button")); // then getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("form-modal"))); // when (signature) click(By.className("button-sig")); // then fillSignature("55"); // when click(By.className("form-modal-update-button")); // then getWait().until(ExpectedConditions.invisibilityOfElementLocated(By.id("form-modal"))); assertEquals(0, getDriver().findElements(getBy("button", "data-fieldid", "55")).size()); assertEquals(1, findElements(getBy("img", "data-fieldid", "55")).size()); // when submitByName("_eventId_next", " Submit", TIMEOUT * 2); // then complete page assertEquals(getDefaultHostAndPort() + "/flow/workflow?execution=s1e3", getDriver().getCurrentUrl()); assertEquals("FormKiQ Server - sample-form2.pdf Complete", getTitle()); Workflow workflow = archive.getWorkflow(); Pair<Workflow, Map<String, byte[]>> pwf = verifyFolderFileList(token, folder, workflow, "ACTIVE", "sample-form2.pdf"); workflow = pwf.getLeft(); Map<String, byte[]> map = pwf.getRight(); assertEquals(getDefaultHostAndPort() + "/api/folders/files/" + folder + "/" + workflow.getUUID() + ".pdf", findElementBy(By.id("pdflink")).getAttribute("href")); assertEquals(SAMPLE_FORM2 + ".pdf", map.keySet().stream().filter(s -> s.endsWith(".pdf")).collect(Collectors.joining(", "))); assertEquals(1, map.keySet().stream().filter(s -> s.endsWith(".pdf")).count()); assertEquals(1, map.keySet().stream().filter(s -> s.endsWith(".signature")).count()); FormJSON f1 = this.jsonService.readValue(map.get(workflow.getSteps().get(1) + ".form"), FormJSON.class); assertTrue(f1.getAssetData().containsKey(f1.getSections().get(0).getFields().get(0).getValue())); assertEquals("555", findValueByKey(f1, "latitude").get().getValue()); assertEquals("999", findValueByKey(f1, "longitude").get().getValue()); assertEquals("0:0:0:0:0:0:0:1", findValueByKey(f1, "ipaddress").get().getValue()); assertEquals("", findValueByKey(f1, "xforwardedfor").get().getValue()); assertNotNull(this.jsonService.stringToDate(findValueByKey(f1, "inserteddate").get().getValue())); byte[] pdf = map.get(SAMPLE_FORM2 + ".pdf"); PDDocument document = PDDocument.load(pdf); try { PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm(); assertEquals("SmithSmith123", acroForm.getField("lastName").getValueAsString()); assertEquals("John", acroForm.getField("firstName").getValueAsString()); assertEquals(1, document.getSignatureDictionaries().size()); } finally { document.close(); } // TODO verify audit }