public void write()

in pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/COSWriter.java [1483:1596]


    public void write(PDDocument doc, SignatureInterface signInterface) throws IOException
    {
        pdDocument = doc;
        COSDocument cosDoc = pdDocument.getDocument();
        COSDictionary trailer = cosDoc.getTrailer();
        if (incrementalUpdate)
        {
            trailer.toIncrement().exclude(trailer).forEach(base -> {
                objectsToWrite.add(base);
                if (base instanceof COSObject)
                {
                    actualsAdded.add(((COSObject) base).getObject());
                }
                else
                {
                    actualsAdded.add(base);
                }
            });
        }
        signatureInterface = signInterface;
        number = pdDocument.getDocument().getHighestXRefObjectNumber();
        if (incrementalUpdate)
        {
            prepareIncrement();
        }
        long idTime = pdDocument.getDocumentId() == null ? System.currentTimeMillis()
                : pdDocument.getDocumentId();

        // if the document says we should remove encryption, then we shouldn't encrypt
        if (doc.isAllSecurityToBeRemoved())
        {
            willEncrypt = false;
            // also need to get rid of the "Encrypt" in the trailer so readers 
            // don't try to decrypt a document which is not encrypted
            trailer.removeItem(COSName.ENCRYPT);
        }
        else
        {
            if (pdDocument.getEncryption() != null)
            {
                if (!incrementalUpdate)
                {
                    SecurityHandler<? extends ProtectionPolicy> securityHandler =
                            pdDocument.getEncryption().getSecurityHandler();
                    if (!securityHandler.hasProtectionPolicy())
                    {
                        throw new IllegalStateException("PDF contains an encryption dictionary, please remove it with "
                                + "setAllSecurityToBeRemoved() or set a protection policy with protect()");
                    }
                    securityHandler.prepareDocumentForEncryption(pdDocument);
                }
                willEncrypt = true;
            }
            else
            {
                willEncrypt = false;
            }
        }

        COSArray idArray;
        boolean missingID = true;
        COSBase base = trailer.getDictionaryObject(COSName.ID);
        if (base instanceof COSArray)
        {
            idArray = (COSArray) base;
            if (idArray.size() == 2)
            {
                missingID = false;
            }
        }
        else
        {
            idArray = new COSArray();
        }
        if( missingID || incrementalUpdate)
        {
            MessageDigest sha256;
            try
            {
                sha256 = MessageDigest.getInstance("SHA-256");
            }
            catch (NoSuchAlgorithmException e)
            {
                // should never happen
                throw new RuntimeException(e);
            }

            // algorithm says to use time/path/size/values in doc to generate the id.
            // we don't have path or size, so do the best we can
            sha256.update(Long.toString(idTime).getBytes(StandardCharsets.ISO_8859_1));

            COSDictionary info = trailer.getCOSDictionary(COSName.INFO);
            if( info != null )
            {
                for (COSBase cosBase : info.getValues())
                {
                    sha256.update(cosBase.toString().getBytes(StandardCharsets.ISO_8859_1));
                }
            }
            // reuse origin documentID if available as first value
            COSString firstID = missingID ? new COSString(sha256.digest()) : (COSString) idArray.get(0);
            // it's ok to use the same ID for the second part if the ID is created for the first time
            COSString secondID = missingID ? firstID : new COSString(sha256.digest());
            idArray = new COSArray();
            idArray.add( firstID );
            idArray.add( secondID );
            trailer.setItem(COSName.ID, idArray);
        }
        cosDoc.accept(this);
        if (!incrementalUpdate)
        {
            cosDoc.setHighestXRefObjectNumber(number);
        }
    }