diff options
Diffstat (limited to 'pdf-as-lib/src')
17 files changed, 895 insertions, 636 deletions
| diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java index 3fdfb576..7946f966 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java @@ -26,7 +26,6 @@ package at.gv.egiz.pdfas.lib.impl;  import java.io.ByteArrayInputStream;  import java.io.ByteArrayOutputStream;  import java.io.File; -import java.io.FileOutputStream;  import java.io.IOException;  import java.io.OutputStream;  import java.util.ArrayList; @@ -39,7 +38,6 @@ import org.apache.pdfbox.cos.COSDictionary;  import org.apache.pdfbox.cos.COSName;  import org.apache.pdfbox.cos.COSString;  import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.encryption.AccessPermission;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; @@ -49,7 +47,6 @@ import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsValidationException;  import at.gv.egiz.pdfas.common.settings.ISettings;  import at.gv.egiz.pdfas.common.settings.Settings; -import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings;  import at.gv.egiz.pdfas.common.utils.PDFUtils;  import at.gv.egiz.pdfas.lib.api.Configuration;  import at.gv.egiz.pdfas.lib.api.IConfigurationConstants; @@ -60,27 +57,14 @@ import at.gv.egiz.pdfas.lib.api.sign.SignResult;  import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter;  import at.gv.egiz.pdfas.lib.api.verify.VerifyResult;  import at.gv.egiz.pdfas.lib.impl.configuration.ConfigurationImpl; -import at.gv.egiz.pdfas.lib.impl.configuration.PlaceholderConfiguration; -import at.gv.egiz.pdfas.lib.impl.configuration.SignatureProfileConfiguration; -import at.gv.egiz.pdfas.lib.impl.placeholder.SignaturePlaceholderData; -import at.gv.egiz.pdfas.lib.impl.placeholder.SignaturePlaceholderExtractor; -import at.gv.egiz.pdfas.lib.impl.positioning.Positioning;  import at.gv.egiz.pdfas.lib.impl.signing.IPdfSigner;  import at.gv.egiz.pdfas.lib.impl.signing.PdfSignerFactory;  import at.gv.egiz.pdfas.lib.impl.signing.pdfbox.PdfboxSignerWrapper;  import at.gv.egiz.pdfas.lib.impl.signing.sig_interface.SignatureDataExtractor; -import at.gv.egiz.pdfas.lib.impl.stamping.IPDFStamper; -import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; -import at.gv.egiz.pdfas.lib.impl.stamping.StamperFactory; -import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory;  import at.gv.egiz.pdfas.lib.impl.status.OperationStatus;  import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature;  import at.gv.egiz.pdfas.lib.impl.verify.IVerifyFilter;  import at.gv.egiz.pdfas.lib.impl.verify.VerifierDispatcher; -import at.knowcenter.wag.egov.egiz.pdf.PDFUtilities; -import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; -import at.knowcenter.wag.egov.egiz.pdf.TablePos; -import at.knowcenter.wag.egov.egiz.table.Table;  public class PdfAsImpl implements PdfAs, IConfigurationConstants { @@ -158,8 +142,8 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {  			ISettings settings = (ISettings) parameter.getConfiguration();  			OperationStatus status = new OperationStatus(settings, parameter); -			PlaceholderConfiguration placeholderConfiguration = status -					.getPlaceholderConfiguration(); +			//PlaceholderConfiguration placeholderConfiguration = status +			//		.getPlaceholderConfiguration();  			RequestedSignature requestedSignature = new RequestedSignature(  					status); @@ -184,7 +168,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {  			status.getPdfObject().setOriginalDocument(  					parameter.getDataSource().getByteData()); -			this.stampPdf(status); +			//this.stampPdf(status);  			// Create signature  			IPdfSigner signer = PdfSignerFactory.createPdfSigner(); @@ -371,7 +355,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {  						status.getSignParamter().getDataSource().getByteData());  				// STAMPER! -				stampPdf(status); +				//stampPdf(status);  				request.setNeedCertificate(false);  				status.setSigningDate(Calendar.getInstance()); @@ -450,159 +434,6 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {  		}  	} -	private boolean checkPlaceholderSignature(OperationStatus status) -			throws PdfAsException, IOException { -		if (status.getPlaceholderConfiguration().isGlobalPlaceholderEnabled()) { -			SignaturePlaceholderData signaturePlaceholderData = SignaturePlaceholderExtractor -					.extract(new ByteArrayInputStream(status.getPdfObject() -							.getOriginalDocument()), null, 1); - -			if (signaturePlaceholderData != null) { -				RequestedSignature requestedSignature = status -						.getRequestedSignature(); - -				if (signaturePlaceholderData.getProfile() != null) { -					requestedSignature -							.setSignatureProfileID(signaturePlaceholderData -									.getProfile()); -				} - -				String signatureProfileID = requestedSignature -						.getSignatureProfileID(); - -				TablePos tablePos = signaturePlaceholderData.getTablePos(); - -				SignatureProfileSettings signatureProfileSettings = TableFactory -						.createProfile(signatureProfileID, settings); - -				Table main = TableFactory.createSigTable( -						signatureProfileSettings, MAIN, settings, -						requestedSignature); - -				IPDFStamper stamper = StamperFactory -						.createDefaultStamper(settings); -				IPDFVisualObject visualObject = stamper.createVisualPDFObject( -						status.getPdfObject(), main); - -				PDDocument originalDocument = PDDocument -						.load(new ByteArrayInputStream(status.getPdfObject() -								.getOriginalDocument())); - -				PositioningInstruction positioningInstruction = Positioning -						.determineTablePositioning(tablePos, "", -								originalDocument, visualObject, false); - -				// ================================================================ -				// StampingStage (visual) -> stamp logical signature block to -				// location (itext) - -				byte[] incrementalUpdate = stamper.writeVisualObject( -						visualObject, positioningInstruction, status -								.getPdfObject().getOriginalDocument(), -						signaturePlaceholderData.getPlaceholderName()); - -				SignaturePositionImpl position = new SignaturePositionImpl(); -				position.setX(positioningInstruction.getX()); -				position.setY(positioningInstruction.getY()); -				position.setPage(positioningInstruction.getPage()); -				position.setHeight(visualObject.getHeight()); -				position.setWidth(visualObject.getWidth()); - -				requestedSignature.setSignaturePosition(position); - -				status.getPdfObject().setStampedDocument(incrementalUpdate); -				return true; -			} -		} -		return false; -	} - -	private void stampPdf(OperationStatus status) throws PdfAsException, -			IOException { - -		RequestedSignature requestedSignature = status.getRequestedSignature(); -		String signatureProfileID = requestedSignature.getSignatureProfileID(); -		SignatureProfileConfiguration signatureProfileConfiguration = status -				.getSignatureProfileConfiguration(signatureProfileID); - -		if (checkPlaceholderSignature(status)) { -			logger.info("Placeholder found for Signature"); -			return; -		} - -		if (requestedSignature.isVisual() && false) { -			logger.info("Creating visual siganture block"); -			// ================================================================ -			// SignBlockCreationStage (visual) -> create visual signature -			// block (logicaly) -			SignatureProfileSettings signatureProfileSettings = TableFactory -					.createProfile(signatureProfileID, settings); - -			Table main = TableFactory.createSigTable(signatureProfileSettings, -					MAIN, settings, requestedSignature); - -			IPDFStamper stamper = StamperFactory.createDefaultStamper(settings); -			IPDFVisualObject visualObject = stamper.createVisualPDFObject( -					status.getPdfObject(), main); - -			// ================================================================ -			// PositioningStage (visual) -> find position or use fixed -			// position - -			String posString = status.getSignParamter().getSignaturePosition(); - -			if (posString == null) { -				posString = signatureProfileConfiguration -						.getDefaultPositioning(); -			} - -			logger.debug("using Positioning: " + posString); - -			boolean legacy32Position = signatureProfileConfiguration -					.getLegacy32Positioning(); - -			TablePos tablePos = null; - -			if (posString == null) { -				tablePos = new TablePos(); -			} else { -				tablePos = new TablePos(posString); -			} - -			PDDocument originalDocument = PDDocument -					.load(new ByteArrayInputStream(status.getPdfObject() -							.getOriginalDocument())); - -			PositioningInstruction positioningInstruction = Positioning -					.determineTablePositioning(tablePos, "", originalDocument, -							visualObject, legacy32Position); - -			// ================================================================ -			// StampingStage (visual) -> stamp logical signature block to -			// location (itext) - -			byte[] incrementalUpdate = stamper.writeVisualObject(visualObject, -					positioningInstruction, status.getPdfObject() -							.getOriginalDocument(), null); - -			SignaturePositionImpl position = new SignaturePositionImpl(); -			position.setX(positioningInstruction.getX()); -			position.setY(positioningInstruction.getY()); -			position.setPage(positioningInstruction.getPage()); -			position.setHeight(visualObject.getHeight()); -			position.setWidth(visualObject.getWidth()); - -			requestedSignature.setSignaturePosition(position); - -			status.getPdfObject().setStampedDocument(incrementalUpdate); -		} else { -			logger.info("No visual siganture block"); -			// Stamped Object is equal to original -			status.getPdfObject().setStampedDocument( -					status.getPdfObject().getOriginalDocument()); -		} -	} -  	private SignResult createSignResult(OperationStatus status)  			throws IOException {  		// ================================================================ diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/PlaceholderFilter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/PlaceholderFilter.java new file mode 100644 index 00000000..a4d2c7aa --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/PlaceholderFilter.java @@ -0,0 +1,69 @@ +package at.gv.egiz.pdfas.lib.impl.placeholder; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.common.settings.ISettings; +import at.gv.egiz.pdfas.lib.api.IConfigurationConstants; +import at.gv.egiz.pdfas.lib.impl.status.OperationStatus; + +public class PlaceholderFilter implements IConfigurationConstants { +	 +	public static SignaturePlaceholderData checkPlaceholderSignature( +			OperationStatus status, ISettings settings) +			throws PdfAsException, IOException { +		 +		if (status.getPlaceholderConfiguration().isGlobalPlaceholderEnabled()) { +			SignaturePlaceholderData signaturePlaceholderData = SignaturePlaceholderExtractor +					.extract(new ByteArrayInputStream(status.getPdfObject() +							.getOriginalDocument()), null, 1); + +			return signaturePlaceholderData; +			/* +			if (signaturePlaceholderData != null) { +				RequestedSignature requestedSignature = status +						.getRequestedSignature(); + +				if (signaturePlaceholderData.getProfile() != null) { +					requestedSignature +							.setSignatureProfileID(signaturePlaceholderData +									.getProfile()); +				} + +				//String signatureProfileID = requestedSignature +				//		.getSignatureProfileID(); + +				TablePos tablePos = signaturePlaceholderData.getTablePos(); + +				return tablePos; +				 +				*/ +				/* +				SignatureProfileSettings signatureProfileSettings = TableFactory +						.createProfile(signatureProfileID, settings); + +				Table main = TableFactory.createSigTable( +						signatureProfileSettings, MAIN, settings, +						requestedSignature); + +				IPDFStamper stamper = StamperFactory +						.createDefaultStamper(settings); +				 +				IPDFVisualObject visualObject = stamper.createVisualPDFObject( +						status.getPdfObject(), main); + +				PDDocument originalDocument = PDDocument +						.load(new ByteArrayInputStream(status.getPdfObject() +								.getOriginalDocument())); + +				PositioningInstruction positioningInstruction = Positioning +						.determineTablePositioning(tablePos, "", +								originalDocument, visualObject, false); +				 +				return positioningInstruction;*/ +			//} +		} +		return null; +	} +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java index 651c2e49..767887b3 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java @@ -29,12 +29,21 @@ import java.io.File;  import java.io.FileInputStream;  import java.io.FileOutputStream;  import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList;  import java.util.Calendar; +import java.util.List; +import org.apache.pdfbox.cos.COSDictionary;  import org.apache.pdfbox.cos.COSName;  import org.apache.pdfbox.exceptions.COSVisitorException;  import org.apache.pdfbox.exceptions.SignatureException;  import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDDocumentCatalog; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageNode; +import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent; +import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;  import org.slf4j.Logger; @@ -45,111 +54,275 @@ import at.gv.egiz.pdfas.common.messages.MessageResolver;  import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings;  import at.gv.egiz.pdfas.common.utils.StreamUtils;  import at.gv.egiz.pdfas.common.utils.TempFileHelper; +import at.gv.egiz.pdfas.lib.api.IConfigurationConstants; +import at.gv.egiz.pdfas.lib.impl.SignaturePositionImpl; +import at.gv.egiz.pdfas.lib.impl.configuration.SignatureProfileConfiguration; +import at.gv.egiz.pdfas.lib.impl.placeholder.PlaceholderFilter; +import at.gv.egiz.pdfas.lib.impl.placeholder.SignaturePlaceholderData; +import at.gv.egiz.pdfas.lib.impl.positioning.Positioning;  import at.gv.egiz.pdfas.lib.impl.signing.IPdfSigner;  import at.gv.egiz.pdfas.lib.impl.signing.sig_interface.PDFASSignatureInterface; +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFStamper; +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; +import at.gv.egiz.pdfas.lib.impl.stamping.StamperFactory;  import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory;  import at.gv.egiz.pdfas.lib.impl.stamping.ValueResolver;  import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox.PDFAsVisualSignatureProperties; +import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox.PdfBoxVisualObject;  import at.gv.egiz.pdfas.lib.impl.status.PDFObject;  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; -public class PADESPDFBOXSigner implements IPdfSigner { +public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { -    private static final Logger logger = LoggerFactory.getLogger(PADESPDFBOXSigner.class); +	private static final Logger logger = LoggerFactory +			.getLogger(PADESPDFBOXSigner.class); -    public void signPDF(PDFObject pdfObject, RequestedSignature requestedSignature,  -    		PDFASSignatureInterface signer) -            throws PdfAsException { -        String fisTmpFile = null; -         -        TempFileHelper helper = pdfObject.getStatus().getTempFileHelper(); -         -        try { -            fisTmpFile = helper.getStaticFilename(); +	public void signPDF(PDFObject pdfObject, +			RequestedSignature requestedSignature, +			PDFASSignatureInterface signer) throws PdfAsException { +		String fisTmpFile = null; -            // write to temporary file -            FileOutputStream fos = new FileOutputStream(new File(fisTmpFile)); -            fos.write(pdfObject.getStampedDocument()); +		TempFileHelper helper = pdfObject.getStatus().getTempFileHelper(); +		try { +			fisTmpFile = helper.getStaticFilename(); -            FileInputStream fis = new FileInputStream(new File(fisTmpFile)); +			// write to temporary file +			FileOutputStream fos = new FileOutputStream(new File(fisTmpFile)); +			fos.write(pdfObject.getOriginalDocument()); -            PDDocument doc = PDDocument.load( -                    new ByteArrayInputStream(pdfObject.getStampedDocument())); +			FileInputStream fis = new FileInputStream(new File(fisTmpFile)); -            PDSignature signature = new PDSignature(); -            signature.setFilter(COSName.getPDFName(signer.getPDFFilter())); // default filter -            signature.setSubFilter(COSName.getPDFName(signer.getPDFSubFilter())); +			PDDocument doc = PDDocument.load(new ByteArrayInputStream(pdfObject +					.getOriginalDocument())); -            SignatureProfileSettings signatureProfileSettings = TableFactory -					.createProfile(requestedSignature.getSignatureProfileID(),  +			PDSignature signature = new PDSignature(); +			signature.setFilter(COSName.getPDFName(signer.getPDFFilter())); // default +																			// filter +			signature +					.setSubFilter(COSName.getPDFName(signer.getPDFSubFilter())); + +			SignatureProfileSettings signatureProfileSettings = TableFactory +					.createProfile(requestedSignature.getSignatureProfileID(),  							pdfObject.getStatus().getSettings()); -             -            ValueResolver resolver = new ValueResolver(); -            String signerName = resolver.resolve("SIG_SUBJECT", signatureProfileSettings.getValue("SIG_SUBJECT"),  -            		signatureProfileSettings, requestedSignature); -             -            signature.setName(signerName); -            signature.setSignDate(Calendar.getInstance()); -            String signerReason = signatureProfileSettings.getSigningReason(); -             -            if(signerReason == null) { -            	signerReason = "PAdES Signature"; -            } -             -            signature.setReason(signerReason); -            logger.debug("Signing reason: " + signerReason); - -            logger.debug("Signing @ " + signer.getSigningDate().getTime().toString()); -            // the signing date, needed for valid signature -            //signature.setSignDate(signer.getSigningDate()); - -            signer.setPDSignature(signature); -            SignatureOptions options = new SignatureOptions(); -             -            // FOR DEVELOPING: Call custom visual signature creation -            PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( -            		pdfObject.getStatus().getSettings(), pdfObject); -            properties.buildSignature(); -             -            ByteArrayOutputStream sigbos = new ByteArrayOutputStream(); -            sigbos.write(StreamUtils.inputStreamToByteArray(properties.getVisibleSignature())); -            sigbos.close(); -             -            FileOutputStream fos2 = new FileOutputStream("/tmp/apsig.pdf"); -            fos2.write(sigbos.toByteArray()); -            fos2.close(); -             -            options.setVisualSignature(new ByteArrayInputStream(sigbos.toByteArray())); -             -            doc.addSignature(signature, signer, options); - -            // pdfbox patched (FIS -> IS) -            doc.saveIncremental(fis, fos); -            fis.close(); -            fos.close(); - -            fis = new FileInputStream(new File(fisTmpFile)); - -            // write to resulting output stream -            ByteArrayOutputStream bos = new ByteArrayOutputStream(); -            bos.write(StreamUtils.inputStreamToByteArray(fis)); -            fis.close(); -            bos.close(); - -            pdfObject.setSignedDocument(bos.toByteArray()); - -            helper.deleteFile(fisTmpFile); - -        } catch (IOException e) { -            logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); -            throw new PdfAsException("error.pdf.sig.01", e); -        } catch(SignatureException e) { -            logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); -            throw new PdfAsException("error.pdf.sig.01", e); -        } catch (COSVisitorException e) { -            logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); -            throw new PdfAsException("error.pdf.sig.01", e); -        } -    } + +			ValueResolver resolver = new ValueResolver(); +			String signerName = resolver.resolve("SIG_SUBJECT", +					signatureProfileSettings.getValue("SIG_SUBJECT"), +					signatureProfileSettings, requestedSignature); + +			signature.setName(signerName); +			signature.setSignDate(Calendar.getInstance()); +			String signerReason = signatureProfileSettings.getSigningReason(); + +			if (signerReason == null) { +				signerReason = "PAdES Signature"; +			} + +			signature.setReason(signerReason); +			logger.debug("Signing reason: " + signerReason); + +			logger.debug("Signing @ " +					+ signer.getSigningDate().getTime().toString()); +			// the signing date, needed for valid signature +			// signature.setSignDate(signer.getSigningDate()); + +			signer.setPDSignature(signature); +			SignatureOptions options = new SignatureOptions(); + +			// Is visible Signature +			if (requestedSignature.isVisual()) { +				logger.info("Creating visual siganture block"); + +				SignatureProfileConfiguration signatureProfileConfiguration = pdfObject +						.getStatus().getSignatureProfileConfiguration( +								requestedSignature.getSignatureProfileID()); + +				SignaturePlaceholderData signaturePlaceholderData = PlaceholderFilter +						.checkPlaceholderSignature(pdfObject.getStatus(), +								pdfObject.getStatus().getSettings()); + +				TablePos tablePos = null; + +				if (signaturePlaceholderData != null) { +					// Placeholder found! + +					if (signaturePlaceholderData.getProfile() != null) { +						requestedSignature +								.setSignatureProfileID(signaturePlaceholderData +										.getProfile()); +					} + +					tablePos = signaturePlaceholderData.getTablePos(); +				} + +				if (tablePos == null) { +					// ================================================================ +					// PositioningStage (visual) -> find position or use fixed +					// position + +					String posString = pdfObject.getStatus().getSignParamter() +							.getSignaturePosition(); + +					if (posString == null) { +						posString = signatureProfileConfiguration +								.getDefaultPositioning(); +					} + +					logger.debug("using Positioning: " + posString); + +					if (posString == null) { +						tablePos = new TablePos(); +					} else { +						tablePos = new TablePos(posString); +					} +				} +				boolean legacy32Position = signatureProfileConfiguration +						.getLegacy32Positioning(); + +				// create Table describtion +				Table main = TableFactory.createSigTable( +						signatureProfileSettings, MAIN, pdfObject.getStatus() +								.getSettings(), requestedSignature); + +				IPDFStamper stamper = StamperFactory +						.createDefaultStamper(pdfObject.getStatus() +								.getSettings()); + +				IPDFVisualObject visualObject = stamper.createVisualPDFObject( +						pdfObject, main); + +				PDDocument originalDocument = PDDocument +						.load(new ByteArrayInputStream(pdfObject.getStatus() +								.getPdfObject().getOriginalDocument())); + +				PositioningInstruction positioningInstruction = Positioning +						.determineTablePositioning(tablePos, "", +								originalDocument, visualObject, +								legacy32Position); + +				SignaturePositionImpl position = new SignaturePositionImpl(); +				position.setX(positioningInstruction.getX()); +				position.setY(positioningInstruction.getY()); +				position.setPage(positioningInstruction.getPage()); +				position.setHeight(visualObject.getHeight()); +				position.setWidth(visualObject.getWidth()); + +				requestedSignature.setSignaturePosition(position); + +				PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( +						pdfObject.getStatus().getSettings(), pdfObject, +						(PdfBoxVisualObject) visualObject, +						positioningInstruction); + +				properties.buildSignature(); + +				ByteArrayOutputStream sigbos = new ByteArrayOutputStream(); +				sigbos.write(StreamUtils.inputStreamToByteArray(properties +						.getVisibleSignature())); +				sigbos.close(); + +				FileOutputStream fos2 = new FileOutputStream("/tmp/apsig.pdf"); +				fos2.write(sigbos.toByteArray()); +				fos2.close(); + +				if (signaturePlaceholderData != null) { +					// Placeholder found! +					// replace placeholder +					InputStream is = PADESPDFBOXSigner.class +							.getResourceAsStream("/placeholder/empty.jpg"); +					PDJpeg img = new PDJpeg(doc, is); +					img.getCOSObject().setNeedToBeUpdate(true); + +					PDDocumentCatalog root = doc.getDocumentCatalog(); +					PDPageNode rootPages = root.getPages(); +					List<PDPage> kids = new ArrayList<PDPage>(); +					rootPages.getAllKids(kids); +					int pageNumber = positioningInstruction.getPage(); +					rootPages.getAllKids(kids); +					PDPage page = kids.get(pageNumber); +					 +					logger.info("Placeholder name: " + signaturePlaceholderData.getPlaceholderName()); +					COSDictionary xobjectsDictionary = (COSDictionary) page.findResources().getCOSDictionary() +							.getDictionaryObject(COSName.XOBJECT); +					xobjectsDictionary.setItem(signaturePlaceholderData.getPlaceholderName(), img); +					xobjectsDictionary.setNeedToBeUpdate(true); +					page.findResources().getCOSObject().setNeedToBeUpdate(true); +					logger.info("Placeholder name: " + signaturePlaceholderData.getPlaceholderName()); +				} + +				if (positioningInstruction.isMakeNewPage()) { +					int last = doc.getNumberOfPages() - 1; +					PDDocumentCatalog root = doc.getDocumentCatalog(); +					PDPageNode rootPages = root.getPages(); +					List<PDPage> kids = new ArrayList<PDPage>(); +					rootPages.getAllKids(kids); +					PDPage lastPage = kids.get(last); +					rootPages.getCOSObject().setNeedToBeUpdate(true); +					PDPage p = new PDPage(lastPage.findMediaBox()); + +					doc.addPage(p); +				} + +				if (signatureProfileSettings.isPDFA()) { +					PDDocumentCatalog root = doc.getDocumentCatalog(); +					InputStream colorProfile = PDDocumentCatalog.class +							.getResourceAsStream("/icm/sRGB Color Space Profile.icm"); +					try { +						PDOutputIntent oi = new PDOutputIntent(doc, +								colorProfile); +						oi.setInfo("sRGB IEC61966-2.1"); +						oi.setOutputCondition("sRGB IEC61966-2.1"); +						oi.setOutputConditionIdentifier("sRGB IEC61966-2.1"); +						oi.setRegistryName("http://www.color.org"); + +						root.addOutputIntent(oi); +						root.getCOSObject().setNeedToBeUpdate(true); +						logger.info("added Output Intent"); +					} catch (Throwable e) { +						e.printStackTrace(); +						throw new PdfAsException("Failed to add Output Intent", +								e); +					} +				} + +				options.setPreferedSignatureSize(0x1000); +				options.setPage(positioningInstruction.getPage()); +				options.setVisualSignature(new ByteArrayInputStream(sigbos +						.toByteArray())); +			} + +			doc.addSignature(signature, signer, options); + +			// pdfbox patched (FIS -> IS) +			doc.saveIncremental(fis, fos); +			fis.close(); +			fos.close(); + +			fis = new FileInputStream(new File(fisTmpFile)); + +			// write to resulting output stream +			ByteArrayOutputStream bos = new ByteArrayOutputStream(); +			bos.write(StreamUtils.inputStreamToByteArray(fis)); +			fis.close(); +			bos.close(); + +			pdfObject.setSignedDocument(bos.toByteArray()); + +			helper.deleteFile(fisTmpFile); + +		} catch (IOException e) { +			logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); +			throw new PdfAsException("error.pdf.sig.01", e); +		} catch (SignatureException e) { +			logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); +			throw new PdfAsException("error.pdf.sig.01", e); +		} catch (COSVisitorException e) { +			logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); +			throw new PdfAsException("error.pdf.sig.01", e); +		} +	}  } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IPDFStamper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IPDFStamper.java index 6de356ed..22e20767 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IPDFStamper.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IPDFStamper.java @@ -23,6 +23,8 @@   ******************************************************************************/  package at.gv.egiz.pdfas.lib.impl.stamping; +import java.io.IOException; +  import at.gv.egiz.pdfas.common.exceptions.PdfAsException;  import at.gv.egiz.pdfas.common.settings.ISettings;  import at.gv.egiz.pdfas.lib.impl.status.PDFObject; @@ -30,7 +32,7 @@ import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;  import at.knowcenter.wag.egov.egiz.table.Table;  public interface IPDFStamper { -    public IPDFVisualObject createVisualPDFObject(PDFObject pdf, Table table); +    public IPDFVisualObject createVisualPDFObject(PDFObject pdf, Table table) throws IOException;      public byte[] writeVisualObject(IPDFVisualObject visualObject, PositioningInstruction positioningInstruction,                                      byte[] pdfData, String placeholderName) throws PdfAsException; diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/StamperFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/StamperFactory.java index 05bccc89..42dee32d 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/StamperFactory.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/StamperFactory.java @@ -28,7 +28,8 @@ import at.gv.egiz.pdfas.common.settings.ISettings;  public class StamperFactory { -	public static final String DEFAULT_STAMPER_CLASS = "at.gv.egiz.pdfas.stmp.itext.ITextStamper"; +	//public static final String DEFAULT_STAMPER_CLASS = "at.gv.egiz.pdfas.stmp.itext.ITextStamper"; +	public static final String DEFAULT_STAMPER_CLASS = "at.gv.egiz.pdfas.lib.impl.stamping.pdfbox.PdfBoxStamper";  	public static IPDFStamper createDefaultStamper(ISettings settings) throws PdfAsException {  		try { diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java index 058b08b0..e7582137 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java @@ -1,12 +1,10 @@  package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; -import java.awt.geom.AffineTransform;  import java.io.ByteArrayInputStream;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; -import org.apache.pdfbox.cos.COSDocument;  import org.apache.pdfbox.exceptions.COSVisitorException;  import org.apache.pdfbox.pdmodel.PDDocument;  import org.apache.pdfbox.pdmodel.PDPage; @@ -14,10 +12,8 @@ import org.apache.pdfbox.pdmodel.PDResources;  import org.apache.pdfbox.pdmodel.common.PDRectangle;  import org.apache.pdfbox.pdmodel.common.PDStream;  import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateBuilder;  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateCreator;  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateStructure; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;  import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;  import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;  import org.slf4j.Logger; @@ -66,7 +62,7 @@ public class PDFAsTemplateCreator extends PDFTemplateCreator {          // create AffineTransform          this.pdfBuilder.createAffineTransform(properties.getAffineTransformParams()); -        AffineTransform transform = pdfStructure.getAffineTransform(); +        //AffineTransform transform = pdfStructure.getAffineTransform();          // rectangle, formatter, image. /AcroForm/DR/XObject contains that form          this.pdfBuilder.createSignatureRectangle(pdSignatureField, properties); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java index 49d7b4bd..8da6d149 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java @@ -1,16 +1,15 @@  package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox;  import java.awt.Color; -import java.awt.Image;  import java.awt.geom.AffineTransform;  import java.awt.image.BufferedImage;  import java.io.File; -import java.io.FileInputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.OutputStream;  import java.util.ArrayList;  import java.util.HashMap; +import java.util.Iterator;  import java.util.List;  import java.util.Map; @@ -19,13 +18,13 @@ import javax.imageio.ImageIO;  import org.apache.pdfbox.cos.COSArray;  import org.apache.pdfbox.cos.COSDictionary;  import org.apache.pdfbox.cos.COSName; -import org.apache.pdfbox.cos.COSStream;  import org.apache.pdfbox.pdmodel.PDDocument;  import org.apache.pdfbox.pdmodel.PDPage;  import org.apache.pdfbox.pdmodel.PDResources;  import org.apache.pdfbox.pdmodel.common.PDRectangle;  import org.apache.pdfbox.pdmodel.common.PDStream;  import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDFont;  import org.apache.pdfbox.pdmodel.font.PDType1Font;  import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;  import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm; @@ -45,7 +44,6 @@ import at.gv.egiz.pdfas.common.settings.ISettings;  import at.gv.egiz.pdfas.lib.test.mains.TestPDFBoxTable;  import at.knowcenter.wag.egov.egiz.table.Entry;  import at.knowcenter.wag.egov.egiz.table.Style; -import at.knowcenter.wag.egov.egiz.table.Table;  public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { @@ -53,14 +51,16 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  			.getLogger(TestPDFBoxTable.class);  	private void drawTable(PDPage page, PDPageContentStream contentStream, -			float x, float y, PDFBoxTable abstractTable, PDDocument doc, boolean subtable) -			throws IOException, PdfAsException { +			float x, float y, PDFBoxTable abstractTable, PDDocument doc, +			boolean subtable) throws IOException, PdfAsException {  		final int rows = abstractTable.getRowCount();  		final int cols = abstractTable.getColCount();  		float[] colsSizes = abstractTable.getColsRelativeWith();  		int max_cols = abstractTable.getColCount();  		float padding = abstractTable.getPadding(); +		float fontSize = PDFBoxFont.defaultFontSize; +		PDFont textFont = PDFBoxFont.defaultFont;  		if (colsSizes == null) {  			colsSizes = new float[max_cols];  			// set the column ratio for all columns to 1 @@ -71,11 +71,13 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  		logger.info("Drawing Table:");  		abstractTable.dumpTable(); -		 -		contentStream.setNonStrokingColor(Color.blue); -		contentStream.fillRect(x, y, abstractTable.getWidth(), abstractTable.getHeight()); -		contentStream.setNonStrokingColor(Color.BLACK); -		 + +		if(abstractTable.getBGColor() != null) { +			contentStream.setNonStrokingColor(abstractTable.getBGColor()); +			contentStream.fillRect(x, y, abstractTable.getWidth(), +				abstractTable.getHeight()); +			contentStream.setNonStrokingColor(Color.BLACK); +		}  		float total = 0;  		for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { @@ -91,15 +93,16 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  			logger.info("Col: " + cols_idx + " : " + colsSizes[cols_idx]);  		} -		contentStream.setLineWidth(0.1f); +		float border = abstractTable.style.getBorder(); +		contentStream.setLineWidth(border);  		float tableHeight = abstractTable.getHeight();  		float tableWidth = abstractTable.getWidth();  		final float colWidth = tableWidth / (float) cols; -		// TODO: check boarder width -		if (1 != 0) { -			 +		// draw if boarder > 0 +		if (border != 0) { +  			// draw the rows  			float nexty = y + tableHeight;  			for (int i = 0; i <= rows; i++) { @@ -109,7 +112,7 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  				if (i < abstractTable.getRowHeights().length) {  					nexty -= abstractTable.getRowHeights()[i] + padding * 2;  				} -				if(subtable && i+1 == abstractTable.getRowHeights().length) { +				if (subtable && i + 1 == abstractTable.getRowHeights().length) {  					nexty -= padding;  				}  			} @@ -118,14 +121,17 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  			float nextx = x;  			float ypos = y;  			float yheight = y + abstractTable.getHeight(); -			if(subtable) { +			if (subtable) {  				ypos -= padding;  				yheight = y + abstractTable.getHeight();  			}  			for (int i = 0; i <= cols; i++) { -				logger.info("COL LINE: {} {} {} {}", nextx, ypos, nextx, yheight); -				contentStream.drawLine(nextx, ypos, nextx, +				if(subtable && i == cols) { +					continue; +				} +				logger.info("COL LINE: {} {} {} {}", nextx, ypos, nextx,  						yheight); +				contentStream.drawLine(nextx, ypos, nextx, yheight);  				if (i < colsSizes.length) {  					nextx += (colsSizes != null) ? colsSizes[i] : colWidth;  				} @@ -135,24 +141,43 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  		float textx = x + padding;  		float texty = y + tableHeight;  		for (int i = 0; i < abstractTable.getRowCount(); i++) { -			ArrayList row = abstractTable.getRow(i); +			ArrayList<Entry> row = abstractTable.getRow(i);  			for (int j = 0; j < row.size(); j++) {  				Entry cell = (Entry) row.get(j);  				if (cell.getType() == Entry.TYPE_CAPTION  						|| cell.getType() == Entry.TYPE_VALUE) { + +					if (cell.getType() == Entry.TYPE_CAPTION) { +						textFont = abstractTable.getFont().getFont(doc); +						fontSize = abstractTable.getFont().getFontSize(); +					} else if (cell.getType() == Entry.TYPE_VALUE) { +						textFont = abstractTable.getValueFont().getFont(doc); +						fontSize = abstractTable.getValueFont().getFontSize(); +					} +  					String text = (String) cell.getValue(); -					float fontsize = 5.f; -					float ttexty = texty - padding - fontsize; -					COSName name = COSName.getPDFName("ANDI_TAG!"); -					contentStream.beginMarkedContentSequence(COSName.ALT, name); +					float ttexty = texty - padding - fontSize; +					// COSName name = COSName.getPDFName("ANDI_TAG!"); +					// contentStream.beginMarkedContentSequence(COSName.ALT, +					// name); +					String fontName = textFont.equals(PDType1Font.COURIER) ? "COURIER" : "HELVETICA"; +					  					contentStream.beginText(); +					 +					if(innerFormResources.getFonts().containsValue(textFont)) { +						String fontID = getFontID(textFont); +						logger.info("Using Font: " + fontID); +						contentStream.appendRawCommands("/" + fontID + " " + fontSize + " Tf\n"); +					} else { +						contentStream.setFont(textFont, fontSize); +					}  					logger.info("Writing: " + textx + " : " + ttexty + " = " -							+ text); +							+ text + " as " + cell.getType() + " w "  + fontName);  					contentStream.moveTextPositionByAmount(textx, ttexty);  					if (text.contains("\n")) {  						String[] lines = text.split("\n"); -						contentStream.appendRawCommands(fontsize + " TL\n"); +						contentStream.appendRawCommands(fontSize + " TL\n");  						for (int k = 0; k < lines.length; k++) {  							contentStream.drawString(lines[k]);  							if (k < lines.length - 1) { @@ -163,67 +188,87 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  						contentStream.drawString(text);  					}  					contentStream.endText(); -					contentStream.endMarkedContentSequence(); +					// contentStream.endMarkedContentSequence();  				} else if (cell.getType() == Entry.TYPE_IMAGE) {  					String img_ref = (String) cell.getValue(); -					if(!images.containsKey(img_ref)) { +					if (!images.containsKey(img_ref)) {  						logger.error("Image not prepared! : " + img_ref); -						throw new PdfAsException("Image not prepared! : " + img_ref); +						throw new PdfAsException("Image not prepared! : " +								+ img_ref);  					}  					ImageObject image = images.get(img_ref);  					PDXObjectImage pdImage = image.getImage();  					// text = "Row :" + i + "COL: " + j; -					COSName name = COSName.getPDFName("ANDI_TAG!"); -					contentStream.beginMarkedContentSequence(COSName.ALT, name); -					 +					// COSName name = COSName.getPDFName("ANDI_TAG!"); +					// contentStream.beginMarkedContentSequence(COSName.ALT, +					// name); +  					float imgy = texty; -					if(cell.getStyle().getImageVAlign() != null &&  -							cell.getStyle().getImageVAlign().equals(Style.TOP)) { +					if (cell.getStyle().getImageVAlign() != null +							&& cell.getStyle().getImageVAlign() +									.equals(Style.TOP)) {  						imgy = texty - padding - image.getSize(); -					} else if(cell.getStyle().getImageVAlign() != null &&  -							cell.getStyle().getImageVAlign().equals(Style.BOTTOM)) { +					} else if (cell.getStyle().getImageVAlign() != null +							&& cell.getStyle().getImageVAlign() +									.equals(Style.BOTTOM)) {  						// Should allready be at bottom ... -						imgy = texty - abstractTable.getRowHeights()[i] + padding; +						imgy = texty - abstractTable.getRowHeights()[i] +								+ padding;  					} else {  						// default to middle -						imgy = texty - padding - abstractTable.getRowHeights()[i] / 2; +						imgy = texty - padding +								- abstractTable.getRowHeights()[i] / 2;  						imgy = imgy - image.getSize() / 2;  					}  					logger.info("Image: " + textx + " : " + imgy); -					contentStream.drawXObject(pdImage, textx, imgy,  +					contentStream.drawXObject(pdImage, textx, imgy,  							image.getSize(), image.getSize()); -					contentStream.endMarkedContentSequence(); -					 +					// contentStream.endMarkedContentSequence(); +  				} else if (cell.getType() == Entry.TYPE_TABLE) { -					float tableY = texty - abstractTable.getRowHeights()[i]  - padding; +					float tableY = texty - abstractTable.getRowHeights()[i] +							- padding;  					float tableX = textx; -					//texty = texty - padding; +					// texty = texty - padding;  					tableX = textx - padding;  					PDFBoxTable tbl_value = (PDFBoxTable) cell.getValue(); -					logger.info("Table: " + tableX + " : " + tableY ); -					drawTable(page, contentStream, tableX, tableY, tbl_value, doc, true); +					logger.info("Table: " + tableX + " : " + tableY); +					drawTable(page, contentStream, tableX, tableY, tbl_value, +							doc, true);  				}  				textx += (colsSizes != null) ? colsSizes[j] : colWidth;  			} -			//if (i + 1 < abstractTable.getRowHeights().length) { -				logger.info("Row {} from {} - {} - {} = {}", i, texty,  -						abstractTable.getRowHeights()[i], padding * 2,  -						texty - (abstractTable.getRowHeights()[i] + padding * 2)); -				texty -= abstractTable.getRowHeights()[i] + padding * 2; -				//texty = texty - abstractTable.getRowHeights()[i + 1] - padding -				//		* 2; -				//texty = texty - abstractTable.getRowHeights()[i] - padding -				//		* 2; -			//} +			// if (i + 1 < abstractTable.getRowHeights().length) { +			logger.info("Row {} from {} - {} - {} = {}", i, texty, +					abstractTable.getRowHeights()[i], padding * 2, texty +							- (abstractTable.getRowHeights()[i] + padding * 2)); +			texty -= abstractTable.getRowHeights()[i] + padding * 2; +			// texty = texty - abstractTable.getRowHeights()[i + 1] - padding +			// * 2; +			// texty = texty - abstractTable.getRowHeights()[i] - padding +			// * 2; +			// }  			textx = x + padding;  		}  	}  	private PDFAsVisualSignatureProperties properties;  	private ISettings settings; +	private List<PDFont> addedFonts = new ArrayList<PDFont>();  	private PDResources innerFormResources;  	private Map<String, ImageObject> images = new HashMap<String, ImageObject>(); +	private String getFontID(PDFont font) { +		Iterator<java.util.Map.Entry<String, PDFont>> it = innerFormResources.getFonts().entrySet().iterator(); +		while(it.hasNext()) { +			java.util.Map.Entry<String, PDFont> entry = it.next(); +			if(entry.getValue().equals(font)) { +				return entry.getKey(); +			} +		} +		return ""; +	} +	  	public PDFAsVisualSignatureBuilder(  			PDFAsVisualSignatureProperties properties, ISettings settings) {  		this.properties = properties; @@ -250,99 +295,114 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  		getStructure().setTemplate(template);  	} -	@Override -	public void createInnerFormStream(PDDocument template) { -		try { -			float[] colsSizes = properties.getMainTable().getColsRelativeWith(); -			int max_cols = properties.getMainTable().getColCount(); -			float padding = properties.getMainTable().getPadding(); -			if (colsSizes == null) { -				colsSizes = new float[max_cols]; -				// set the column ratio for all columns to 1 -				for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { -					colsSizes[cols_idx] = 1; -				} +	private void readTableResources(PDFBoxTable table, PDDocument template) throws PdfAsException, IOException { + +		float[] colsSizes = table.getColsRelativeWith(); +		int max_cols = table.getColCount(); +		float padding = table.getPadding(); +		if (colsSizes == null) { +			colsSizes = new float[max_cols]; +			// set the column ratio for all columns to 1 +			for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { +				colsSizes[cols_idx] = 1;  			} +		} -			logger.info("TOTAL Width: " + properties.getMainTable().getWidth()); +		logger.info("TOTAL Width: " + table.getWidth()); -			float total = 0; +		float total = 0; -			for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { -				total += colsSizes[cols_idx]; -			} +		for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { +			total += colsSizes[cols_idx]; +		} -			for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { -				colsSizes[cols_idx] = (colsSizes[cols_idx] / total) -						* properties.getMainTable().getWidth(); -			} +		for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { +			colsSizes[cols_idx] = (colsSizes[cols_idx] / total) +					* table.getWidth(); +		} -			for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { -				logger.info("Col: " + cols_idx + " : " + colsSizes[cols_idx]); -			} -			 -			// Hint we have to create all PDXObjectImages before creating the -			// PDPageContentStream -			// only PDFbox developers know why ... -			innerFormResources = new PDResources(); -			for (int i = 0; i < properties.getMainTable().getRowCount(); i++) { -				ArrayList row = properties.getMainTable().getRow(i); -				for (int j = 0; j < row.size(); j++) { -					Entry cell = (Entry) row.get(j); -					if (cell.getType() == Entry.TYPE_IMAGE) { -						String img_ref = (String) cell.getValue(); -						if (!images.containsKey(img_ref)) { -							File img_file = new File(img_ref); -							if (!img_file.isAbsolute()) { -								logger.debug("Image file declaration is relative. Prepending path of resources directory."); -								logger.debug("Image Location: " -										+ settings.getWorkingDirectory() -										+ File.separator + img_ref); -								img_file = new File( -										settings.getWorkingDirectory() -												+ File.separator + img_ref); -							} else { -								logger.debug("Image file declaration is absolute. Skipping file relocation."); -							} +		for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { +			logger.info("Col: " + cols_idx + " : " + colsSizes[cols_idx]); +		} -							if (!img_file.exists()) { -								logger.debug("Image file \"" -										+ img_file.getCanonicalPath() -										+ "\" doesn't exist."); -								throw new PdfAsException("error.pdf.stamp.04"); -							} +		/*if(!addedFonts.contains(table.getFont().getFont(null))) { +			PDFont font = table.getFont().getFont(template); +			addedFonts.add(font); +			innerFormResources.addFont(font); +		} +		 +		if(!addedFonts.contains(table.getValueFont().getFont(null))) { +			PDFont font = table.getValueFont().getFont(template); +			addedFonts.add(font); +			innerFormResources.addFont(font); +		}*/ +		 +		for (int i = 0; i < table.getRowCount(); i++) { +			ArrayList<Entry> row = table.getRow(i); +			for (int j = 0; j < row.size(); j++) { +				Entry cell = (Entry) row.get(j); +				if (cell.getType() == Entry.TYPE_IMAGE) { +					String img_ref = (String) cell.getValue(); +					if (!images.containsKey(img_ref)) { +						File img_file = new File(img_ref); +						if (!img_file.isAbsolute()) { +							logger.debug("Image file declaration is relative. Prepending path of resources directory."); +							logger.debug("Image Location: " +									+ settings.getWorkingDirectory() +									+ File.separator + img_ref); +							img_file = new File(settings.getWorkingDirectory() +									+ File.separator + img_ref); +						} else { +							logger.debug("Image file declaration is absolute. Skipping file relocation."); +						} -							BufferedImage img = null; -							try { -								img = ImageIO.read(img_file); -							} catch (IOException e) { -								throw new PdfAsException("error.pdf.stamp.04", -										e); -							} -							 -							float width = colsSizes[j]; -							 -							int size = (int)Math.floor((double)width); -							size -= 2*padding; -							logger.debug("Scaling image to: " + size); -							 -							PDXObjectImage pdImage = new PDJpeg(template, -									img); -							ImageObject image = new ImageObject(pdImage, size); -							images.put(img_ref, image); -							innerFormResources.addXObject(pdImage, "Im"); +						if (!img_file.exists()) { +							logger.debug("Image file \"" +									+ img_file.getCanonicalPath() +									+ "\" doesn't exist."); +							throw new PdfAsException("error.pdf.stamp.04"); +						} + +						BufferedImage img = null; +						try { +							img = ImageIO.read(img_file); +						} catch (IOException e) { +							throw new PdfAsException("error.pdf.stamp.04", e);  						} + +						float width = colsSizes[j]; + +						int size = (int) Math.floor((double) width); +						size -= 2 * padding; +						logger.debug("Scaling image to: " + size); + +						PDXObjectImage pdImage = new PDJpeg(template, img); +						ImageObject image = new ImageObject(pdImage, size); +						images.put(img_ref, image); +						innerFormResources.addXObject(pdImage, "Im");  					} +				} else if(cell.getType() == Entry.TYPE_TABLE) {  +					PDFBoxTable tbl_value = (PDFBoxTable) cell.getValue(); +					readTableResources(tbl_value, template);  				}  			} -			 -			//innerFormResources.getCOSObject().setDirect(true); -			// TODO create Fonts caption and Value -			innerFormResources.addFont(PDType1Font.COURIER); +		} +	} + +	@Override +	public void createInnerFormStream(PDDocument template) { +		try { +			// Hint we have to create all PDXObjectImages before creating the +			// PDPageContentStream +			// only PDFbox developers know why ... +			innerFormResources = new PDResources(); +			getStructure().getPage().setResources(innerFormResources); +			readTableResources(properties.getMainTable(), template); +			  			PDPageContentStream stream = new PDPageContentStream(template,  					getStructure().getPage()); -			stream.setFont(PDType1Font.COURIER, 5); +			//stream.setFont(PDType1Font.COURIER, 5);  			drawTable(getStructure().getPage(), stream, 1, 1,  					properties.getMainTable(), template, false); @@ -619,24 +679,6 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {  		os.close();  	} -	public void appendCosStreamCommands(OutputStream os, COSStream stream) -			throws IOException { -		// stream.getScratchFile(); -		byte[] data = new byte[1024]; -		long i = 0; -		long pos = stream.getScratchFile().getPosition(); -		stream.getScratchFile().seek(0); -		while (i < stream.getScratchFile().length()) { -			int read = stream.getScratchFile().read(data, 0, data.length); -			i += read; -			os.write(data, 0, read); -		} -		// /byte[] data = -		// StreamUtils.inputStreamToByteArray(stream.getFilteredStream()); -		// os.write(data); -		os.close(); -	} -  	public void createVisualSignature(PDDocument template) {  		this.getStructure().setVisualSignature(template.getDocument());  		logger.info("Visible signature has been created"); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java index f9e63a48..bd516100 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java @@ -49,9 +49,9 @@ public class PDFAsVisualSignatureDesigner {  	 *             - If we can't read, flush, or can't close stream  	 */  	public PDFAsVisualSignatureDesigner(PDDocument doc, int page, -			PDFAsVisualSignatureProperties properties) throws IOException { +			PDFAsVisualSignatureProperties properties, boolean newpage) throws IOException {  		this.properties = properties; -		calculatePageSize(doc, page); +		calculatePageSize(doc, page, newpage);  	}  	/** @@ -60,19 +60,25 @@ public class PDFAsVisualSignatureDesigner {  	 * @param document  	 * @param page  	 */ -	private void calculatePageSize(PDDocument document, int page) { +	private void calculatePageSize(PDDocument document, int page, boolean newpage) {  		if (page < 1) {  			throw new IllegalArgumentException("First page of pdf is 1, not "  					+ page);  		} - +		  		List<?> pages = document.getDocumentCatalog().getAllPages(); -		PDPage firstPage = (PDPage) pages.get(page - 1); -		PDRectangle mediaBox = firstPage.findMediaBox(); -		this.pageHeight(mediaBox.getHeight()); -		this.pageWidth = mediaBox.getWidth(); - +		if(newpage) { +			PDPage lastPage = (PDPage) pages.get(pages.size()-1); +			PDRectangle mediaBox = lastPage.findMediaBox(); +			this.pageHeight(mediaBox.getHeight()); +			this.pageWidth = mediaBox.getWidth(); +		} else { +			PDPage firstPage = (PDPage) pages.get(page - 1); +			PDRectangle mediaBox = firstPage.findMediaBox(); +			this.pageHeight(mediaBox.getHeight()); +			this.pageWidth = mediaBox.getWidth(); +		}  		float x = this.pageWidth;  		float y = 0;  		this.pageWidth = this.pageWidth + y; diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java index 24ef3881..05cce46d 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java @@ -1,26 +1,16 @@  package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; -import iaik.x509.X509Certificate; -  import java.io.ByteArrayInputStream; -import java.io.FileInputStream;  import java.io.IOException;  import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.font.PDFont; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateBuilder; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateCreator;  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import at.gv.egiz.pdfas.common.settings.ISettings; -import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; -import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory;  import at.gv.egiz.pdfas.lib.impl.status.PDFObject; -import at.gv.egiz.pdfas.lib.test.mains.CertificateHolderRequest; -import at.knowcenter.wag.egov.egiz.table.Table; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;  public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties { @@ -29,40 +19,25 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties {  	private ISettings settings;  	private PDFBoxTable main; -	private PDFont tableFont;  	private PDFAsVisualSignatureDesigner designer; -	public PDFAsVisualSignatureProperties(ISettings settings, PDFObject object) { +	public PDFAsVisualSignatureProperties(ISettings settings, PDFObject object,  +			PdfBoxVisualObject visObj, PositioningInstruction pos) {  		this.settings = settings;  		try { -			SignatureProfileSettings profileSettings = TableFactory -					.createProfile(object.getStatus().getRequestedSignature().getSignatureProfileID(),  -							settings); -			//float width = object.getStatus().getRequestedSignature().getSignaturePosition().getWidth(); -			object.getStatus().getRequestedSignature().getCertificate(); -			X509Certificate cert = object.getStatus().getRequestedSignature().getCertificate(); - -			CertificateHolderRequest request = new CertificateHolderRequest( -					cert); - -			Table mainTable = TableFactory.createSigTable(profileSettings, "main", -					settings, request); -			 -			main = new PDFBoxTable(mainTable, null, 230.f); -			 -			//tableFont = PDFont. +			main = visObj.getTable(); -			//main.setWidth(100);  		} catch (Throwable e) {  			e.printStackTrace();  		}  		try {  			PDDocument origDoc = PDDocument.load(new ByteArrayInputStream( -					object.getStampedDocument())); +					object.getOriginalDocument())); -			designer = new PDFAsVisualSignatureDesigner(origDoc, 1, this); -			designer.coordinates(100, 100); +			designer = new PDFAsVisualSignatureDesigner(origDoc, pos.getPage(), this, pos.isMakeNewPage()); +			float posy = designer.getPageHeight() - pos.getY(); +			designer.coordinates(pos.getX(), posy);  			float[] form_rect = new float[] {0,0, main.getWidth() + 2, main.getHeight() + 2};  			logger.info("AP Rect: {} {} {} {}", form_rect[0], form_rect[1], form_rect[2], form_rect[3]);  			designer.formaterRectangleParams(form_rect); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java new file mode 100644 index 00000000..62aaf5a8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxFont.java @@ -0,0 +1,146 @@ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont; +import org.apache.pdfbox.pdmodel.font.PDType1Font; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.settings.ISettings; + +public class PDFBoxFont { +	 +	private static final Logger logger = LoggerFactory +			.getLogger(PDFBoxFont.class); +	 +	private static final String HELVETICA = "HELVETICA"; +	private static final String COURIER = "COURIER"; +	private static final String TIMES_ROMAN = "TIMES_ROMAN"; +	private static final String BOLD = "BOLD"; +	private static final String NORMAL = "NORMAL"; +	private static final String ITALIC = "ITALIC"; +	private static final String SEP = ":"; +	 +	public static PDFont defaultFont = PDType1Font.HELVETICA; +	public static float defaultFontSize = 8; +	 +	private static Map<String, PDFont> fontStyleMap = new HashMap<String, PDFont>(); +	 +	static { +		fontStyleMap.put(HELVETICA+SEP+NORMAL, PDType1Font.HELVETICA); +		fontStyleMap.put(HELVETICA+SEP+BOLD, PDType1Font.HELVETICA_BOLD); +		 +		fontStyleMap.put(COURIER+SEP+NORMAL, PDType1Font.COURIER); +		fontStyleMap.put(COURIER+SEP+BOLD, PDType1Font.COURIER_BOLD); +		 +		fontStyleMap.put(TIMES_ROMAN+SEP+NORMAL, PDType1Font.TIMES_ROMAN); +		fontStyleMap.put(TIMES_ROMAN+SEP+BOLD, PDType1Font.TIMES_BOLD); +		fontStyleMap.put(TIMES_ROMAN+SEP+ITALIC, PDType1Font.TIMES_ITALIC); +	} +	 +	public static void showBuildinFonts() { +		Iterator<String> it = fontStyleMap.keySet().iterator(); +		logger.info("Available Fonts:"); +		while(it.hasNext()) { +			logger.info(it.next()); +		} +	} +	 +	PDFont font; +	PDFont cachedfont = null; +	float fontSize; +	String fontDesc; +	String ttfFontDesc; +	PDDocument doc; +	ISettings settings; +	 +	private PDFont generateTTF(String fonttype, PDDocument doc) throws IOException { +		boolean cacheNow = false; +		if(doc == null) { +			if(this.doc == null) { +				this.doc = new PDDocument(); +			} +			doc = this.doc; +		} else { +			cacheNow = true; +		} +		ttfFontDesc = fonttype; +		String fontName = fonttype.replaceFirst("TTF:", ""); +		 +		logger.debug("Instantiating font."); +        String fontPath = this.settings.getWorkingDirectory()  + File.separator + "fonts" + File.separator + fontName; +        logger.debug("Instantiating \"" + fontPath + "\"."); + +        if(cacheNow) { +        	cachedfont = PDTrueTypeFont.loadTTF(doc, fontPath); +        	return cachedfont; +        } else { +        	return PDTrueTypeFont.loadTTF(doc, fontPath); +        } +	} +	 +	private PDFont generateFont(String fonttype, String fontder) throws IOException { +		if(fonttype.startsWith("TTF:")) { +			// Load TTF Font +			return generateTTF(fonttype, null); +		} else { +			if(fontder == null) { +				fontder = NORMAL; +			} +			 +			String fontDesc = fonttype + SEP + fontder; +			PDFont font = fontStyleMap.get(fontDesc); +			if(font == null) { +				showBuildinFonts(); +				throw new IOException("Invalid font descriptor"); +			} +			return font; +		} +	} +	 +	private void setFont(String desc) throws IOException { +		String[] fontArr = desc.split(","); +		 +		if(fontArr.length == 3) { +			font = generateFont(fontArr[0], fontArr[2]); +			fontSize = Integer.parseInt(fontArr[1]); +		} else if(fontArr.length == 2 && fontArr[0].startsWith("TTF:")) { +			font = generateFont(fontArr[0], null); +			fontSize = Integer.parseInt(fontArr[1]); +		} else { +			logger.warn("Using default font because: {} is not a valid font descriptor.", desc); +			this.font = defaultFont; +			this.fontSize = defaultFontSize; +		} +		 +	} + +	public PDFBoxFont(String fontDesc, ISettings settings) throws IOException { +		this.settings = settings; +		this.fontDesc = fontDesc; +		logger.info("Creating Font: " + fontDesc); +		this.setFont(fontDesc); +	} +	 +	public PDFont getFont(PDDocument doc) throws IOException { +		if(cachedfont != null) { +			return cachedfont; +		} +		if(font instanceof PDTrueTypeFont && doc != null) { +			return generateTTF(ttfFontDesc, doc); +		} else { +			return font; +		} +	} +	 +	public float getFontSize() { +		return fontSize; +	} +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java index 6555b82d..2ef653d8 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFBoxTable.java @@ -1,5 +1,6 @@  package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; +import java.awt.Color;  import java.io.IOException;  import java.util.ArrayList;  import java.util.List; @@ -9,6 +10,7 @@ import org.apache.pdfbox.pdmodel.font.PDType1Font;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.settings.ISettings;  import at.knowcenter.wag.egov.egiz.table.Entry;  import at.knowcenter.wag.egov.egiz.table.Style;  import at.knowcenter.wag.egov.egiz.table.Table; @@ -20,15 +22,16 @@ public class PDFBoxTable {  	Table table;  	Style style; -	PDFont font; -	PDFont valueFont; +	PDFBoxFont font; +	PDFBoxFont valueFont; +	ISettings settings;  	float padding;  	int positionX = 0;  	int positionY = 0;  	float tableWidth;  	float tableHeight; -	float fontSize; +	Color bgColor;  	float[] rowHeights;  	float[] colWidths; @@ -50,17 +53,26 @@ public class PDFBoxTable {  		}  		String fontString = style.getFont(); -		font = PDType1Font.COURIER;  		String vfontString = style.getValueFont(); -		valueFont = font; +		if (parent != null && style == parent.style) { +			font = parent.getFont(); +			valueFont = parent.getValueFont(); +		} else { + +			font = new PDFBoxFont(fontString, settings); + +			valueFont = new PDFBoxFont(vfontString, settings); +		}  		padding = style.getPadding(); -		fontSize = 5f; + +		bgColor = style.getBgColor();  	} -	public PDFBoxTable(Table abstractTable, PDFBoxTable parent, float fixSize) -			throws IOException { +	public PDFBoxTable(Table abstractTable, PDFBoxTable parent, float fixSize, +			ISettings settings) throws IOException { +		this.settings = settings;  		initializeStyle(abstractTable, parent);  		float[] relativSizes = abstractTable.getColsRelativeWith();  		colWidths = new float[relativSizes.length]; @@ -80,8 +92,9 @@ public class PDFBoxTable {  		calculateHeightsBasedOnWidths();  	} -	public PDFBoxTable(Table abstractTable, PDFBoxTable parent) -			throws IOException { +	public PDFBoxTable(Table abstractTable, PDFBoxTable parent, +			ISettings settings) throws IOException { +		this.settings = settings;  		initializeStyle(abstractTable, parent);  		this.calculateWidthHeight();  	} @@ -95,7 +108,7 @@ public class PDFBoxTable {  		}  		for (int i = 0; i < rows; i++) { -			ArrayList row = (ArrayList) this.table.getRows().get(i); +			ArrayList<Entry> row = this.table.getRows().get(i);  			for (int j = 0; j < row.size(); j++) {  				Entry cell = (Entry) row.get(j); @@ -132,7 +145,7 @@ public class PDFBoxTable {  		}  		for (int i = 0; i < rows; i++) { -			ArrayList row = (ArrayList) this.table.getRows().get(i); +			ArrayList<Entry> row = this.table.getRows().get(i);  			for (int j = 0; j < row.size(); j++) {  				Entry cell = (Entry) row.get(j);  				float cellWidth = getCellWidth(cell); @@ -180,13 +193,19 @@ public class PDFBoxTable {  			isValue = false;  		case Entry.TYPE_VALUE:  			PDFont c = null; +			float fontSize;  			String string = (String) cell.getValue();  			if (isValue) { -				c = valueFont; +				c = valueFont.getFont(null); +				fontSize = valueFont.getFontSize();  			} else { -				c = font; +				c = font.getFont(null); +				fontSize = font.getFontSize(); +			} +			if (string == null) { +				string = ""; +				cell.setValue(string);  			} -  			if (string.contains("\n")) {  				float maxWidth = 0;  				String[] lines = string.split("\n"); @@ -205,7 +224,8 @@ public class PDFBoxTable {  		case Entry.TYPE_TABLE:  			PDFBoxTable pdfBoxTable = null;  			if (cell.getValue() instanceof Table) { -				pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this); +				pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this, +						this.settings);  				cell.setValue(pdfBoxTable);  			} else if (cell.getValue() instanceof PDFBoxTable) {  				pdfBoxTable = (PDFBoxTable) cell.getValue(); @@ -243,17 +263,49 @@ public class PDFBoxTable {  			if (lineBreaks.length > 1) {  				for (int j = 0; j < lineBreaks.length; j++) {  					String subword = lineBreaks[j]; -					//if (cLine + subword.length() > maxline) { -						lines.add(cLineValue.trim()); -						cLineValue = ""; -						cLine = 0; -					//} +					// if (cLine + subword.length() > maxline) { +					lines.add(cLineValue.trim()); +					cLineValue = ""; +					cLine = 0; +					// }  					cLineValue += subword + " ";  					cLine += subword.length();  				}  			} else { -				if (cLine + word.length() > maxline &&  -						cLineValue.length() != 0) { +				if (cLine + word.length() > maxline && cLineValue.length() != 0) { +					lines.add(cLineValue.trim()); +					cLineValue = ""; +					cLine = 0; +				} +				cLineValue += word + " "; +				cLine += word.length(); +			} +		} +		lines.add(cLineValue.trim()); +		return lines.toArray(new String[0]); +	} +	 +	private String[] breakString(String value, PDFont f, float maxwidth) throws IOException { +		String[] words = value.split(" "); +		List<String> lines = new ArrayList<String>(); +		int cLine = 0; +		String cLineValue = ""; +		for (int i = 0; i < words.length; i++) { +			String word = words[i]; +			String[] lineBreaks = word.split("\n"); +			if (lineBreaks.length > 1) { +				for (int j = 0; j < lineBreaks.length; j++) { +					String subword = lineBreaks[j]; +					// if (cLine + subword.length() > maxline) { +					lines.add(cLineValue.trim()); +					cLineValue = ""; +					cLine = 0; +					// } +					cLineValue += subword + " "; +					cLine += subword.length(); +				} +			} else { +				if (f.getStringWidth(cLineValue + word) > maxwidth && cLineValue.length() != 0) {  					lines.add(cLineValue.trim());  					cLineValue = "";  					cLine = 0; @@ -273,23 +325,31 @@ public class PDFBoxTable {  			isValue = false;  		case Entry.TYPE_VALUE:  			PDFont c = null; +			float fontSize;  			String string = (String) cell.getValue();  			if (isValue) { -				c = valueFont; +				c = valueFont.getFont(null); +				fontSize = valueFont.getFontSize();  			} else { -				c = font; +				c = font.getFont(null); +				fontSize = font.getFontSize();  			} -			float fwidth = c.getFontDescriptor().getFontBoundingBox() -					.getWidth() -					/ 1000 * fontSize; +			float fwidth; +			if (c instanceof PDType1Font) { +				fwidth = c.getFontDescriptor().getFontBoundingBox().getWidth() +						/ 1000 * fontSize; +			} else { +				fwidth = c.getFontDescriptor().getMaxWidth(); +			} +			logger.debug("Font Width: {}", fwidth);  			int maxcharcount = (int) ((width - padding * 2) / fwidth) - 1; -			logger.info("Max {} chars per line!", maxcharcount); +			logger.debug("Max {} chars per line!", maxcharcount);  			float fheight = c.getFontDescriptor().getFontBoundingBox()  					.getHeight()  					/ 1000 * fontSize; - +			  			String[] lines = breakString(string, maxcharcount);  			cell.setValue(concatLines(lines));  			return fheight * lines.length; @@ -299,10 +359,14 @@ public class PDFBoxTable {  			PDFBoxTable pdfBoxTable = null;  			if (cell.getValue() instanceof Table) {  				pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this, -						width - padding); +						width - padding, this.settings);  				cell.setValue(pdfBoxTable);  			} else if (cell.getValue() instanceof PDFBoxTable) { +				// recreate here beacuse of fixed width!  				pdfBoxTable = (PDFBoxTable) cell.getValue(); +				pdfBoxTable = new PDFBoxTable(pdfBoxTable.table, this, width +						- padding, this.settings); +				cell.setValue(pdfBoxTable);  			} else {  				throw new IOException("Failed to build PDFBox Table");  			} @@ -320,11 +384,14 @@ public class PDFBoxTable {  			isValue = false;  		case Entry.TYPE_VALUE:  			PDFont c = null; +			float fontSize;  			String string = (String) cell.getValue();  			if (isValue) { -				c = valueFont; +				c = valueFont.getFont(null); +				fontSize = valueFont.getFontSize();  			} else { -				c = font; +				c = font.getFont(null); +				fontSize = font.getFontSize();  			}  			float fheight = c.getFontDescriptor().getFontBoundingBox()  					.getHeight() @@ -341,7 +408,8 @@ public class PDFBoxTable {  		case Entry.TYPE_TABLE:  			PDFBoxTable pdfBoxTable = null;  			if (cell.getValue() instanceof Table) { -				pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this); +				pdfBoxTable = new PDFBoxTable((Table) cell.getValue(), this, +						this.settings);  				cell.setValue(pdfBoxTable);  			} else if (cell.getValue() instanceof PDFBoxTable) {  				pdfBoxTable = (PDFBoxTable) cell.getValue(); @@ -394,7 +462,8 @@ public class PDFBoxTable {  	public void dumpTable() {  		logger.info("=====================================================================");  		logger.info("Information about: " + this.table.getName()); -		logger.info("\tDimensions: {} x {} (W x H)", this.tableWidth, this.tableHeight); +		logger.info("\tDimensions: {} x {} (W x H)", this.tableWidth, +				this.tableHeight);  		logger.info("\tPadding: {}", padding);  		logger.info("\t================================");  		logger.info("\tRow Heights:"); @@ -408,8 +477,24 @@ public class PDFBoxTable {  		}  		logger.info("=====================================================================");  	} -	 -	public ArrayList getRow(int i) { -		return (ArrayList) this.table.getRows().get(i); + +	public Table getOrigTable() { +		return this.table; +	} + +	public ArrayList<Entry> getRow(int i) { +		return this.table.getRows().get(i); +	} + +	public PDFBoxFont getFont() { +		return font; +	} + +	public PDFBoxFont getValueFont() { +		return valueFont; +	} + +	public Color getBGColor() { +		return this.bgColor;  	}  } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java index 559c8c9b..1bd4fed5 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java @@ -1,13 +1,9 @@  package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; -import java.io.InputStream; +import java.io.IOException; -import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.common.PDRectangle;  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateBuilder; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateStructure;  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigBuilder; -import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; @@ -29,109 +25,13 @@ public class PdfBoxStamper implements IPDFStamper {  		this.pdfBuilder = new PDVisibleSigBuilder();  	} -	/* -	private InputStream renderTable(Table abstractTable) throws PdfAsException -    { -		logger.info("pdf building has been started"); -        PDFTemplateStructure pdfStructure = pdfBuilder.getStructure(); -        //pdfStructure.setIm -        // we create array of [Text, ImageB, ImageC, ImageI] -        this.pdfBuilder.createProcSetArray(); -          -        //create page -        this.pdfBuilder.createPage(properties); -        PDPage page = pdfStructure.getPage(); - -        //create template -        this.pdfBuilder.createTemplate(page); -        PDDocument template = pdfStructure.getTemplate(); -         -        //create /AcroForm -        this.pdfBuilder.createAcroForm(template); -        PDAcroForm acroForm = pdfStructure.getAcroForm(); - -        // AcroForm contains singature fields -        this.pdfBuilder.createSignatureField(acroForm); -        PDSignatureField pdSignatureField = pdfStructure.getSignatureField(); -         -        // create signature -        this.pdfBuilder.createSignature(pdSignatureField, page, properties.getSignatureFieldName()); -        -        // that is /AcroForm/DR entry -        this.pdfBuilder.createAcroFormDictionary(acroForm, pdSignatureField); -         -        // create AffineTransform -        this.pdfBuilder.createAffineTransform(properties.getAffineTransformParams()); -        AffineTransform transform = pdfStructure.getAffineTransform(); -        -        // rectangle, formatter, image. /AcroForm/DR/XObject contains that form -        this.pdfBuilder.createSignatureRectangle(pdSignatureField, properties); -        this.pdfBuilder.createFormaterRectangle(properties.getFormaterRectangleParams()); -        PDRectangle formater = pdfStructure.getFormaterRectangle(); -        this.pdfBuilder.createSignatureImage(template, properties.getImage()); - -        // create form stream, form and  resource.  -        this.pdfBuilder.createHolderFormStream(template); -        PDStream holderFormStream = pdfStructure.getHolderFormStream(); -        this.pdfBuilder.createHolderFormResources(); -        PDResources holderFormResources = pdfStructure.getHolderFormResources(); -        this.pdfBuilder.createHolderForm(holderFormResources, holderFormStream, formater); -         -        // that is /AP entry the appearance dictionary. -        this.pdfBuilder.createAppearanceDictionary(pdfStructure.getHolderForm(), pdSignatureField); -         -        // inner formstream, form and resource (hlder form containts inner form) -        this.pdfBuilder.createInnerFormStream(template); -        this.pdfBuilder.createInnerFormResource(); -        PDResources innerFormResource = pdfStructure.getInnerFormResources(); -        this.pdfBuilder.createInnerForm(innerFormResource, pdfStructure.getInnterFormStream(), formater); -        PDFormXObject innerForm = pdfStructure.getInnerForm(); -        -        // inner form must be in the holder form as we wrote -        this.pdfBuilder.insertInnerFormToHolerResources(innerForm, holderFormResources); -         -        //  Image form is in this structure: /AcroForm/DR/FRM0/Resources/XObject/n0 -        this.pdfBuilder.createImageFormStream(template); -        PDStream imageFormStream = pdfStructure.getImageFormStream(); -        this.pdfBuilder.createImageFormResources(); -        PDResources imageFormResources = pdfStructure.getImageFormResources(); -        this.pdfBuilder.createImageForm(imageFormResources, innerFormResource, imageFormStream, formater, transform, -                pdfStructure.getImage()); -        -        // now inject procSetArray -        this.pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, imageFormResources, holderFormResources, -                pdfStructure.getProcSet()); - -        String imgFormName = pdfStructure.getImageFormName(); -        String imgName = pdfStructure.getImageName(); -        String innerFormName = pdfStructure.getInnerFormName(); - -        // now create Streams of AP -        this.pdfBuilder.injectAppearanceStreams(holderFormStream, imageFormStream, imageFormStream, imgFormName, -                imgName, innerFormName, properties); -        this.pdfBuilder.createVisualSignature(template); -        this.pdfBuilder.createWidgetDictionary(pdSignatureField, holderFormResources); -         -        ByteArrayInputStream in = pdfStructure.getTemplateAppearanceStream(); -        logger.info("stream returning started, size= " + in.available()); -         -        // we must close the document -        template.close(); -         -        // return result of the stream  -        return in; -    } -	*/ -	 -	public IPDFVisualObject createVisualPDFObject(PDFObject pdf, Table table) { -		 -		return null; +	public IPDFVisualObject createVisualPDFObject(PDFObject pdf, Table table) throws IOException { +		return new PdfBoxVisualObject(table, pdf.getStatus().getSettings());  	}  	public byte[] writeVisualObject(IPDFVisualObject visualObject,  			PositioningInstruction positioningInstruction, byte[] pdfData,  			String placeholderName) throws PdfAsException { -		// TODO Auto-generated method stub  		return null;  	} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java index 25028073..c10a5f68 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java @@ -1,46 +1,74 @@  package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; +import java.io.IOException; + +import at.gv.egiz.pdfas.common.settings.ISettings;  import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; +import at.knowcenter.wag.egov.egiz.table.Table;  public class PdfBoxVisualObject implements IPDFVisualObject { -	public void setWidth(float width) { +	private Table abstractTable; +	private PDFBoxTable table; +	private float width; +	private float x; +	private float y; +	private int page; +	private ISettings settings; +	public PdfBoxVisualObject(Table table, ISettings settings) +			throws IOException { +		this.abstractTable = table; +		this.table = new PDFBoxTable(table, null, settings); +		this.settings = settings; +	} + +	public void setWidth(float width) { +		this.width = width;  	}  	public void fixWidth() { -		// TODO Auto-generated method stub -		 +		try { +			table = new PDFBoxTable(abstractTable, null, this.width,  settings); +		} catch (IOException e) { +			// should not occur +			e.printStackTrace(); +		}  	}  	public float getHeight() { -		// TODO Auto-generated method stub -		return 0; +		return table.getHeight();  	}  	public float getWidth() { -		// TODO Auto-generated method stub -		return 0; +		return table.getWidth();  	}  	public void setXPos(float x) { -		// TODO Auto-generated method stub -		 +		this.x = x;  	} -	public void setYPos(float x) { -		// TODO Auto-generated method stub -		 +	public void setYPos(float y) { +		this.y = y;  	} +	 +	public float getX() { +        return x; +    } + +    public float getY() { +        return y; +    }  	public int getPage() { -		// TODO Auto-generated method stub -		return 0; +		return page;  	}  	public void setPage(int page) { -		// TODO Auto-generated method stub -		 +		this.page = page;  	} +	public PDFBoxTable getTable() { +		return this.table; +	}  } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java index 514d0fa3..b402d0d2 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java @@ -28,7 +28,6 @@ public class PDFObject {  	private OperationStatus status;  	private byte[] originalDocument; -	private byte[] stampedDocument;  	private byte[] signedDocument;  	public PDFObject(OperationStatus operationStatus) { @@ -43,14 +42,6 @@ public class PDFObject {  		this.originalDocument = originalDocument;  	} -	public byte[] getStampedDocument() { -		return stampedDocument; -	} - -	public void setStampedDocument(byte[] stampedDocument) { -		this.stampedDocument = stampedDocument; -	} -  	public byte[] getSignedDocument() {  		return signedDocument;  	} diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java index de471e11..72bdfc4d 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java @@ -78,7 +78,7 @@ public class Table implements Serializable    /**     * The row definitions.     */ -  private Map rows_ = new HashMap(); +  private Map<String, ArrayList<Entry>> rows_ = new HashMap<String, ArrayList<Entry>>();    /**     * The table width. @@ -192,12 +192,12 @@ public class Table implements Serializable     *      * @return Returns the sorted (by row number) table rows.     */ -  public ArrayList getRows() +  public ArrayList<ArrayList<Entry>> getRows()    { -    ArrayList rows = new ArrayList(); +    ArrayList<ArrayList<Entry>> rows = new ArrayList<ArrayList<Entry>>();      for (int row_idx = 1; row_idx <= rows_.size(); row_idx++)      { -      ArrayList row = (ArrayList) rows_.get("" + row_idx); +      ArrayList<Entry> row = (ArrayList<Entry>) rows_.get("" + row_idx);        rows.add(row);      }      return rows; @@ -213,7 +213,7 @@ public class Table implements Serializable     * @param row     *          the entry list to store     */ -  public void addRow(String rowNumber, ArrayList row) +  public void addRow(String rowNumber, ArrayList<Entry> row)    {      rows_.put(rowNumber, row);      if (row.size() > maxCols_) @@ -230,10 +230,10 @@ public class Table implements Serializable      String the_string = "\n#### TABLE " + name_ + " BEGIN #####";      the_string += " Width:" + width_ + " max cols:" + maxCols_ + " cols:" + colsRelativeWith_;      the_string += "\nStyle:" + style_; -    ArrayList rows = getRows(); +    ArrayList<ArrayList<Entry>> rows = getRows();      for (int row_idx = 0; row_idx < rows.size(); row_idx++)      { -      ArrayList row = (ArrayList) rows.get(row_idx); +      ArrayList<Entry> row = rows.get(row_idx);        String row_prefix = "\n ++ ROW " + row_idx + " ++ ";        for (int entry_idx = 0; entry_idx < row.size(); entry_idx++)        { diff --git a/pdf-as-lib/src/main/resources/icm/sRGB Color Space Profile.icm b/pdf-as-lib/src/main/resources/icm/sRGB Color Space Profile.icmBinary files differ new file mode 100644 index 00000000..7f9d18d0 --- /dev/null +++ b/pdf-as-lib/src/main/resources/icm/sRGB Color Space Profile.icm diff --git a/pdf-as-lib/src/main/resources/icm/sRGB Color Space Profile.icm.LICENSE.txt b/pdf-as-lib/src/main/resources/icm/sRGB Color Space Profile.icm.LICENSE.txt new file mode 100644 index 00000000..9b817e33 --- /dev/null +++ b/pdf-as-lib/src/main/resources/icm/sRGB Color Space Profile.icm.LICENSE.txt @@ -0,0 +1,14 @@ +Obtained from: http://www.srgb.com/usingsrgb.html + +The file "sRGB Color Space Profile.icm" is: +Copyright (c) 1998 Hewlett-Packard Company + +To anyone who acknowledges that the file "sRGB Color Space Profile.icm"  +is provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY: +permission to use, copy and distribute this file for any purpose is hereby  +granted without fee, provided that the file is not changed including the HP  +copyright notice tag, and that the name of Hewlett-Packard Company not be  +used in advertising or publicity pertaining to distribution of the software  +without specific, written prior permission.  Hewlett-Packard Company makes  +no representations about the suitability of this software for any purpose. + | 
