@Override
    protected void endDocument(PDDocument pdf) throws IOException {
        try {
            // Extract text for any bookmarks:
            if (config.isExtractBookmarksText()) {
                extractBookmarkText();
            }

            try {
                extractEmbeddedDocuments(pdf);
            } catch (IOException e) {
                handleCatchableIOE(e);
            }

            try {
                extractIncrementalUpdates();
            } catch (IOException e) {
                handleCatchableIOE(e);
            }

            extractXMPXFA(pdf, metadata, context);

            //extract acroform data at end of doc
            if (config.isExtractAcroFormContent() == true) {
                try {
                    extractAcroForm(pdf);
                } catch (IOException e) {
                    handleCatchableIOE(e);
                }
            }
            PDDocumentCatalogAdditionalActions additionalActions =
                    pdf.getDocumentCatalog().getActions();
            handleDestinationOrAction(additionalActions.getDP(),
                    ActionTrigger.AFTER_DOCUMENT_PRINT);
            handleDestinationOrAction(additionalActions.getDS(), ActionTrigger.AFTER_DOCUMENT_SAVE);
            handleDestinationOrAction(additionalActions.getWC(),
                    ActionTrigger.BEFORE_DOCUMENT_CLOSE);
            handleDestinationOrAction(additionalActions.getWP(),
                    ActionTrigger.BEFORE_DOCUMENT_PRINT);
            handleDestinationOrAction(additionalActions.getWS(),
                    ActionTrigger.BEFORE_DOCUMENT_SAVE);
            //now record annotationtypes and subtypes
            for (String annotationType : annotationTypes) {
                metadata.add(PDF.ANNOTATION_TYPES, annotationType);
            }
            for (String annotationSubtype : annotationSubtypes) {
                metadata.add(PDF.ANNOTATION_SUBTYPES, annotationSubtype);
            }

            for (String trigger : triggers) {
                metadata.add(PDF.ACTION_TRIGGERS, trigger);
            }

            for (String actionType : actionTypes) {
                metadata.add(PDF.ACTION_TYPES, actionType);
            }
            xhtml.endDocument();
        } catch (TikaException | SAXException e) {
            throw new IOException("Unable to end a document", e);
        }
        if (fontNames.size() > 0) {
            for (String fontName : fontNames) {
                metadata.add(Font.FONT_NAME, fontName);
            }
        }
        metadata.set(PDF.TOTAL_UNMAPPED_UNICODE_CHARS, totalUnmappedUnicodeCharacters);
        if (totalCharacters > 0) {
            metadata.set(PDF.OVERALL_PERCENTAGE_UNMAPPED_UNICODE_CHARS,
                    (float) totalUnmappedUnicodeCharacters / (float) totalCharacters);
        }
        metadata.set(PDF.CONTAINS_DAMAGED_FONT, containsDamagedFont);
        metadata.set(PDF.CONTAINS_NON_EMBEDDED_FONT, containsNonEmbeddedFont);
        metadata.set(PDF.NUM_3D_ANNOTATIONS, num3DAnnotations);
    }
Format used for signature dates
TODO Make this thread-safe
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java