From ee9277cb68ce97fee9dc788a38f83ec40cab3c7e Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Thu, 19 Nov 2015 08:51:11 +0100 Subject: mutlithreading GC problem fixed, visual signature options finalizing, would destroy resource buffer, which are used during save incremental update Conflicts: pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java --- .../lib/impl/signing/pdfbox/PADESPDFBOXSigner.java | 219 ++++++++------------- 1 file changed, 82 insertions(+), 137 deletions(-) (limited to 'pdf-as-pdfbox') diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java index b0de9c3d..8556ae9f 100644 --- a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java +++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java @@ -23,8 +23,6 @@ ******************************************************************************/ package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; -import iaik.x509.X509Certificate; - import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; @@ -36,17 +34,15 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Calendar; -import java.util.Iterator; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSBase; import org.apache.pdfbox.cos.COSDictionary; +import org.apache.pdfbox.cos.COSDocument; import org.apache.pdfbox.cos.COSInteger; import org.apache.pdfbox.cos.COSName; -import org.apache.pdfbox.cos.COSObject; -import org.apache.pdfbox.cos.COSStream; import org.apache.pdfbox.cos.COSString; import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.exceptions.SignatureException; @@ -103,18 +99,19 @@ import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; import at.knowcenter.wag.egov.egiz.pdf.TablePos; import at.knowcenter.wag.egov.egiz.table.Table; +import iaik.x509.X509Certificate; public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { private static final Logger logger = LoggerFactory .getLogger(PADESPDFBOXSigner.class); - + public void signPDF(PDFObject genericPdfObject, RequestedSignature requestedSignature, PDFASSignatureInterface genericSigner) throws PdfAsException { String fisTmpFile = null; - PDFAsVisualSignatureProperties properties = null; + PDFAsVisualSignatureProperties properties=null; if (!(genericPdfObject instanceof PDFBOXObject)) { // tODO: @@ -132,6 +129,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { TempFileHelper helper = pdfObject.getStatus().getTempFileHelper(); PDDocument doc = null; + SignatureOptions options = new SignatureOptions(); + COSDocument visualSignatureDocumentGuard = null; try { fisTmpFile = helper.getStaticFilename(); @@ -149,7 +148,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { } doc = pdfObject.getDocument(); - + SignaturePlaceholderData signaturePlaceholderData = PlaceholderFilter .checkPlaceholderSignature(pdfObject.getStatus(), pdfObject.getStatus().getSettings()); @@ -163,8 +162,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { logger.debug("Placeholder Profile set to: " + signaturePlaceholderData.getProfile()); requestedSignature - .setSignatureProfileID(signaturePlaceholderData - .getProfile()); + .setSignatureProfileID(signaturePlaceholderData + .getProfile()); } tablePos = signaturePlaceholderData.getTablePos(); @@ -209,7 +208,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { // signature.setSignDate(signer.getSigningDate()); signer.setPDSignature(signature); - SignatureOptions options = new SignatureOptions(); + options.setPreferedSignatureSize(0x1000); // Is visible Signature @@ -324,8 +323,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { requestedSignature.setSignaturePosition(position); - properties = new PDFAsVisualSignatureProperties(pdfObject - .getStatus().getSettings(), pdfObject, + properties = new PDFAsVisualSignatureProperties( + pdfObject.getStatus().getSettings(), pdfObject, (PdfBoxVisualObject) visualObject, positioningInstruction, signatureProfileSettings); @@ -359,7 +358,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { logger.info("Placeholder name: " + signaturePlaceholderData - .getPlaceholderName()); + .getPlaceholderName()); COSDictionary xobjectsDictionary = (COSDictionary) page .findResources().getCOSDictionary() .getDictionaryObject(COSName.XOBJECT); @@ -367,10 +366,10 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { .getPlaceholderName(), img); xobjectsDictionary.setNeedToBeUpdate(true); page.findResources().getCOSObject() - .setNeedToBeUpdate(true); + .setNeedToBeUpdate(true); logger.info("Placeholder name: " + signaturePlaceholderData - .getPlaceholderName()); + .getPlaceholderName()); } finally { IOUtils.closeQuietly(is); } @@ -380,51 +379,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { PDDocumentCatalog root = doc.getDocumentCatalog(); COSBase base = root.getCOSDictionary().getItem( COSName.OUTPUT_INTENTS); - - boolean sRGBFound = false; - - /* - if (base != null) { - if (base instanceof COSArray) { - List outputIntents = root - .getOutputIntent(); - Iterator outputIterator = outputIntents - .iterator(); - while (outputIterator.hasNext()) { - PDOutputIntent ouputIntent = outputIterator - .next(); - if ("sRGB IEC61966-2.1".equals(ouputIntent - .getInfo())) { - sRGBFound = true; - break; - } - } - } else if (base instanceof COSObject && ((COSObject)base).getObject() instanceof COSArray) { - COSArray array = (COSArray)((COSObject)base).getObject(); - Iterator cosIterator = array.iterator(); - while(cosIterator.hasNext()) { - COSBase oiBase = cosIterator.next(); - PDOutputIntent oi = new PDOutputIntent((COSDictionary) oiBase); - if ("sRGB IEC61966-2.1".equals(oi - .getInfo())) { - sRGBFound = true; - break; - } - } - } else { - try { - PDOutputIntent oi = new PDOutputIntent((COSDictionary) base); - if ("sRGB IEC61966-2.1".equals(oi - .getInfo())) { - sRGBFound = true; - } - } catch(Throwable e){ - logger.warn("Failed to check existing Output Intent in PDF-A document"); - } - } - }*/ - - if (!sRGBFound) { + if (base == null) { InputStream colorProfile = null; try { colorProfile = PDDocumentCatalog.class @@ -437,26 +392,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { oi.setOutputCondition("sRGB IEC61966-2.1"); oi.setOutputConditionIdentifier("sRGB IEC61966-2.1"); oi.setRegistryName("http://www.color.org"); - List intents = new ArrayList(); - intents.add(oi); - root.setOutputIntents(intents); - /*if (base != null) { - if (base instanceof COSObject && ((COSObject)base).getObject() instanceof COSArray) { - COSArray array = (COSArray)((COSObject)base).getObject(); - array.clear(); - array.add(oi); - array.setNeedToBeUpdate(true); - } else if (!(base instanceof COSArray)) { - // Need to convert Output Intent from base object to array - //PDOutputIntent existingOI = new PDOutputIntent((COSDictionary)base); - COSArray array = new COSArray(); - //array.add(existingOI); - array.add(oi); - root.getCOSDictionary().setItem(COSName.OUTPUT_INTENTS, array); - } - } else { - root.addOutputIntent(oi); - }*/ + + root.addOutputIntent(oi); root.getCOSObject().setNeedToBeUpdate(true); logger.info("added Output Intent"); } catch (Throwable e) { @@ -470,9 +407,13 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { } } + + options.setPage(positioningInstruction.getPage()); options.setVisualSignature(properties.getVisibleSignature()); } + + visualSignatureDocumentGuard = options.getVisualSignature(); doc.addSignature(signature, signer, options); @@ -489,18 +430,18 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { PDAcroForm acroFormm = doc.getDocumentCatalog().getAcroForm(); - // PDStructureTreeRoot pdstRoot = - // doc.getDocumentCatalog().getStructureTreeRoot(); - // COSDictionary dic = - // doc.getDocumentCatalog().getCOSDictionary(); - // PDStructureElement el = new PDStructureElement("Widget", - // pdstRoot); + // PDStructureTreeRoot pdstRoot = doc.getDocumentCatalog().getStructureTreeRoot(); + // COSDictionary dic = doc.getDocumentCatalog().getCOSDictionary(); + // PDStructureElement el = new PDStructureElement("Widget", pdstRoot); + + PDSignatureField signatureField = null; if (acroFormm != null) { @SuppressWarnings("unchecked") List fields = acroFormm.getFields(); + if (fields != null) { for (PDField pdField : fields) { if (pdField != null) { @@ -509,7 +450,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { if (tmpSigField.getSignature() != null && tmpSigField.getSignature() - .getDictionary() != null) { + .getDictionary() != null) { if (tmpSigField .getSignature() .getDictionary() @@ -527,12 +468,11 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { } if (signatureField != null) { - signatureField.setPartialName(sigFieldName); + signatureField.setPartialName(sigFieldName); } - if (properties != null) { - signatureField.setAlternateFieldName(properties - .getAlternativeTableCaption()); - } else { + if(properties!=null){ + signatureField.setAlternateFieldName(properties.getAlternativeTableCaption()); + }else{ signatureField.setAlternateFieldName(sigFieldName); } } else { @@ -541,37 +481,35 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { // PDF-UA logger.info("Adding pdf/ua content."); - try { + try{ PDDocumentCatalog root = doc.getDocumentCatalog(); PDStructureTreeRoot treeRoot = root.getStructureTreeRoot(); - + if(treeRoot != null) { logger.info("Tree Root: {}", treeRoot.toString()); List kids = treeRoot.getKids(); - if (kids == null) { + if(kids==null){ logger.info("No kid-elements in structure tree Root, maybe not PDF/UA document"); } PDStructureElement docElement = null; - for (Object k : kids) { - if (k instanceof PDStructureElement) { - docElement = (PDStructureElement) k; + for(Object k: kids){ + if(k instanceof PDStructureElement){ + docElement=(PDStructureElement) k; break; - // if(((PDStructureElement) - // k).getStructureType().equals("Document")){ - // docElement=(PDStructureElement) k; - // } + // if(((PDStructureElement) k).getStructureType().equals("Document")){ + // docElement=(PDStructureElement) k; + // } } } PDStructureElement sigBlock = new PDStructureElement( "Form", docElement); - // create object dictionary and add as child element - COSDictionary objectdic = new COSDictionary(); + //create object dictionary and add as child element + COSDictionary objectdic= new COSDictionary(); objectdic.setName("Type", "OBJR"); - objectdic.setItem("Pg", signatureField.getWidget() - .getPage()); + objectdic.setItem("Pg", signatureField.getWidget().getPage()); objectdic.setItem("Obj", signatureField.getWidget()); List l = new ArrayList(); @@ -582,10 +520,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { sigBlock.setParent(docElement); docElement.appendKid(sigBlock); - // Create and add Attribute dictionary to mitigate PAC - // warning - COSDictionary sigBlockDic = (COSDictionary) sigBlock - .getCOSObject(); + //Create and add Attribute dictionary to mitigate PAC warning + COSDictionary sigBlockDic = (COSDictionary) sigBlock.getCOSObject(); COSDictionary sub = new COSDictionary(); sub.setName("O", "Layout"); @@ -593,31 +529,30 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { sigBlockDic.setItem(COSName.A, sub); sigBlockDic.setNeedToBeUpdate(true); - // Modify number tree + + //Modify number tree PDNumberTreeNode ntn = treeRoot.getParentTree(); - if (ntn == null) { + if(ntn==null){ ntn = new PDNumberTreeNode(objectdic, null); logger.info("No number-tree-node found!"); } - COSDictionary ntndic = ntn.getCOSDictionary(); - COSArray ntndicnumbersarray = (COSArray) ntndic - .getDictionaryObject(COSName.NUMS); + COSDictionary ntndic=ntn.getCOSDictionary(); + COSArray ntndicnumbersarray = (COSArray)ntndic.getDictionaryObject(COSName.NUMS); int arrindex = ntndicnumbersarray.size(); - int treeindex = arrindex / 2; + int treeindex = arrindex/2; ntndicnumbersarray.add(arrindex, COSInteger.get(treeindex)); - ntndicnumbersarray.add(arrindex + 1, - sigBlock.getCOSObject()); + ntndicnumbersarray.add(arrindex+1, sigBlock.getCOSObject()); treeRoot.setParentTree(ntn); - treeRoot.setParentTreeNextKey(treeindex + 1); + treeRoot.setParentTreeNextKey(treeindex+1); - // setStructureParent - PDAnnotationWidget widg = signatureField.getWidget(); + //setStructureParent + PDAnnotationWidget widg=signatureField.getWidget(); widg.setStructParent(treeindex); - // add the Tabs /S Element for Tabbing through annots + //add the Tabs /S Element for Tabbing through annots PDPage p = signatureField.getWidget().getPage(); p.getCOSDictionary().setName("Tabs", "S"); p.getCOSObject().setNeedToBeUpdate(true); @@ -628,11 +563,12 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { objectdic.getCOSObject().setNeedToBeUpdate(true); docElement.getCOSObject().setNeedToBeUpdate(true); - } catch (Throwable e) { - if (signatureProfileSettings.isPDFUA() == true) { + } + }catch(Throwable e){ + if (signatureProfileSettings.isPDFUA()==true){ logger.error("Could not create PDF-UA conform document!"); throw new PdfAsException("error.pdf.sig.pdfua.1", e); - } else { + }else{ logger.info("Could not create PDF-UA conform signature"); } } @@ -682,11 +618,17 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { try { tmpFileIs = new FileInputStream(new File(fisTmpFile)); - - doc.saveIncremental(tmpFileIs, tmpOutputStream); + synchronized (doc) { + doc.saveIncremental(tmpFileIs, tmpOutputStream); + } tmpFileIs.close(); } finally { IOUtils.closeQuietly(tmpFileIs); + if(options != null) { + if(options.getVisualSignature() != null) { + options.getVisualSignature().close(); + } + } } tmpOutputStream.flush(); tmpOutputStream.close(); @@ -729,7 +671,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { } } - if (fisTmpFile != null) { + if(fisTmpFile != null) { helper.deleteFile(fisTmpFile); } logger.debug("Signature done!"); @@ -778,7 +720,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { public Image generateVisibleSignaturePreview(SignParameter parameter, java.security.cert.X509Certificate cert, int resolution, OperationStatus status, RequestedSignature requestedSignature) - throws PDFASError { + throws PDFASError { try { PDFBOXObject pdfObject = (PDFBOXObject) status.getPdfObject(); @@ -834,12 +776,15 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( pdfObject.getStatus().getSettings(), pdfObject, - (PdfBoxVisualObject) visualObject, positioningInstruction, + (PdfBoxVisualObject) visualObject, positioningInstruction, signatureProfileSettings); properties.buildSignature(); - PDDocument visualDoc = PDDocument.load(properties + PDDocument visualDoc; + synchronized (PDDocument.class) { + visualDoc = PDDocument.load(properties .getVisibleSignature()); + } // PDPageable pageable = new PDPageable(visualDoc); List pages = new ArrayList(); visualDoc.getDocumentCatalog().getPages().getAllKids(pages); @@ -862,11 +807,11 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { graphics.drawImage(outputImage, 0, 0, cutOut.getWidth(), cutOut .getHeight(), (int) (1 * factor), (int) (outputImage - .getHeight() - ((position.getHeight() + 1) * factor)), - (int) ((1 + position.getWidth()) * factor), - (int) (outputImage.getHeight() - - ((position.getHeight() + 1) * factor) + (position - .getHeight() * factor)), null); + .getHeight() - ((position.getHeight() + 1) * factor)), + (int) ((1 + position.getWidth()) * factor), + (int) (outputImage.getHeight() + - ((position.getHeight() + 1) * factor) + (position + .getHeight() * factor)), null); return cutOut; } catch (PdfAsException e) { logger.warn("PDF-AS Exception", e); -- cgit v1.2.3