use of org.apache.pdfbox.pdmodel.common.COSArrayList in project pdfbox by apache.
the class PDDocument method addSignature.
/**
* This will add a signature to the document. If the 0-based page number in the options
* parameter is smaller than 0 or larger than max, the nearest valid page number will be used
* (i.e. 0 or max) and no exception will be thrown.
*
* @param sigObject is the PDSignatureField model
* @param signatureInterface is an interface which provides signing capabilities
* @param options signature options
* @throws IOException if there is an error creating required fields
*/
public void addSignature(PDSignature sigObject, SignatureInterface signatureInterface, SignatureOptions options) throws IOException {
// Reserve content
// We need to reserve some space for the signature. Some signatures including
// big certificate chain and we need enough space to store it.
int preferredSignatureSize = options.getPreferredSignatureSize();
if (preferredSignatureSize > 0) {
sigObject.setContents(new byte[preferredSignatureSize]);
} else {
sigObject.setContents(new byte[SignatureOptions.DEFAULT_SIGNATURE_SIZE]);
}
// Reserve ByteRange, will be overwritten in COSWriter
sigObject.setByteRange(RESERVE_BYTE_RANGE);
signInterface = signatureInterface;
// Create SignatureForm for signature and append it to the document
// Get the first valid page
int pageCount = getNumberOfPages();
if (pageCount == 0) {
throw new IllegalStateException("Cannot sign an empty document");
}
int startIndex = Math.min(Math.max(options.getPage(), 0), pageCount - 1);
PDPage page = getPage(startIndex);
// Get the AcroForm from the Root-Dictionary and append the annotation
PDDocumentCatalog catalog = getDocumentCatalog();
PDAcroForm acroForm = catalog.getAcroForm();
catalog.getCOSObject().setNeedToBeUpdated(true);
if (acroForm == null) {
acroForm = new PDAcroForm(this);
catalog.setAcroForm(acroForm);
} else {
acroForm.getCOSObject().setNeedToBeUpdated(true);
}
PDSignatureField signatureField = null;
if (!(acroForm.getCOSObject().getDictionaryObject(COSName.FIELDS) instanceof COSArray)) {
acroForm.getCOSObject().setItem(COSName.FIELDS, new COSArray());
} else {
COSArray fieldArray = (COSArray) acroForm.getCOSObject().getDictionaryObject(COSName.FIELDS);
fieldArray.setNeedToBeUpdated(true);
signatureField = findSignatureField(acroForm.getFieldIterator(), sigObject);
}
if (signatureField == null) {
signatureField = new PDSignatureField(acroForm);
// append the signature object
signatureField.setValue(sigObject);
// backward linking
signatureField.getWidgets().get(0).setPage(page);
} else {
sigObject.getCOSObject().setNeedToBeUpdated(true);
}
// TODO This "overwrites" the settings of the original signature field which might not be intended by the user
// better make it configurable (not all users need/want PDF/A but their own setting):
// to conform PDF/A-1 requirement:
// The /F key's Print flag bit shall be set to 1 and
// its Hidden, Invisible and NoView flag bits shall be set to 0
signatureField.getWidgets().get(0).setPrinted(true);
// Set the AcroForm Fields
List<PDField> acroFormFields = acroForm.getFields();
acroForm.getCOSObject().setDirect(true);
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
boolean checkFields = checkSignatureField(acroForm.getFieldIterator(), signatureField);
if (checkFields) {
signatureField.getCOSObject().setNeedToBeUpdated(true);
} else {
acroFormFields.add(signatureField);
}
// Get the object from the visual signature
COSDocument visualSignature = options.getVisualSignature();
// Distinction of case for visual and non-visual signature
if (visualSignature == null) {
prepareNonVisibleSignature(signatureField);
return;
}
prepareVisibleSignature(signatureField, acroForm, visualSignature);
// Create Annotation / Field for signature
List<PDAnnotation> annotations = page.getAnnotations();
// Make /Annots a direct object to avoid problem if it is an existing indirect object:
// it would not be updated in incremental save, and if we'd set the /Annots array "to be updated"
// while keeping it indirect, Adobe Reader would claim that the document had been modified.
page.setAnnotations(annotations);
// take care that page and acroforms do not share the same array (if so, we don't need to add it twice)
if (!(annotations instanceof COSArrayList && acroFormFields instanceof COSArrayList && ((COSArrayList<?>) annotations).toList().equals(((COSArrayList<?>) acroFormFields).toList()) && checkFields)) {
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
// use check to prevent the annotation widget from appearing twice
if (checkSignatureAnnotation(annotations, widget)) {
widget.getCOSObject().setNeedToBeUpdated(true);
} else {
annotations.add(widget);
}
}
page.getCOSObject().setNeedToBeUpdated(true);
}
use of org.apache.pdfbox.pdmodel.common.COSArrayList in project pdfbox by apache.
the class PDDocumentCatalog method getThreads.
/**
* Returns the document's article threads.
*/
public List<PDThread> getThreads() {
COSArray array = (COSArray) root.getDictionaryObject(COSName.THREADS);
if (array == null) {
array = new COSArray();
root.setItem(COSName.THREADS, array);
}
List<PDThread> pdObjects = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
pdObjects.add(new PDThread((COSDictionary) array.getObject(i)));
}
return new COSArrayList<>(pdObjects, array);
}
use of org.apache.pdfbox.pdmodel.common.COSArrayList in project pdfbox by apache.
the class FDFDictionary method getPages.
/**
* This will get the list of FDF Pages. This will return a list of FDFPage objects.
*
* @return A list of FDF pages.
*/
public List<FDFPage> getPages() {
List<FDFPage> retval = null;
COSArray pageArray = (COSArray) fdf.getDictionaryObject(COSName.PAGES);
if (pageArray != null) {
List<FDFPage> pages = new ArrayList<>();
for (int i = 0; i < pageArray.size(); i++) {
pages.add(new FDFPage((COSDictionary) pageArray.get(i)));
}
retval = new COSArrayList<>(pages, pageArray);
}
return retval;
}
use of org.apache.pdfbox.pdmodel.common.COSArrayList in project pdfbox by apache.
the class FDFField method getOptions.
/**
* This will return a list of options for a choice field. The value in the list will be 1 of 2 types.
* java.lang.String or FDFOptionElement.
*
* @return A list of all options.
*/
public List<Object> getOptions() {
List<Object> retval = null;
COSArray array = (COSArray) field.getDictionaryObject(COSName.OPT);
if (array != null) {
List<Object> objects = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
COSBase next = array.getObject(i);
if (next instanceof COSString) {
objects.add(((COSString) next).getString());
} else {
COSArray value = (COSArray) next;
objects.add(new FDFOptionElement(value));
}
}
retval = new COSArrayList<>(objects, array);
}
return retval;
}
use of org.apache.pdfbox.pdmodel.common.COSArrayList in project pdfbox by apache.
the class FDFPage method getTemplates.
/**
* This will get a list of FDFTemplage objects that describe the named pages that serve as templates.
*
* @return A list of templates.
*/
public List<FDFTemplate> getTemplates() {
List<FDFTemplate> retval = null;
COSArray array = (COSArray) page.getDictionaryObject(COSName.TEMPLATES);
if (array != null) {
List<FDFTemplate> objects = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
objects.add(new FDFTemplate((COSDictionary) array.getObject(i)));
}
retval = new COSArrayList<>(objects, array);
}
return retval;
}
Aggregations