From db52e4d66d60184d53a27ba4d6772461daacc03d Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 22 Mar 2013 08:57:51 +0000 Subject: Maintenance update (bugfixes, new features, cleanup...) Refer to /dok/RELEASE_NOTES-3.3.txt for further information. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/pdf-as/trunk@931 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../java/at/gv/egiz/pdfas/utils/PDFASUtils.java | 268 +++++++++++++++++---- 1 file changed, 219 insertions(+), 49 deletions(-) (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java') diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java index 7f09dfc..a2332dd 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java @@ -30,63 +30,233 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.pdfbox.pdmodel.PDDocument; +import at.gv.egiz.pdfas.api.io.DataSource; import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import com.lowagie.text.Document; +import com.lowagie.text.pdf.BadPasswordException; import com.lowagie.text.pdf.PdfReader; /** - * @author tknall + * Collection of useful utilities. */ public class PDFASUtils { -//23.11.2010 changed by exthex - added checkDocumentPermissions(PDDocument doc) - - private PDFASUtils() { - } - - /** - * Verifies that a document could be opened with full permissions. - * @param pdfReader The PdfReader - * @throws PDFDocumentException Thrown if document has not been opened with full permissions. - */ - public static void checkReaderPermissions(PdfReader pdfReader) throws PDFDocumentException { - if (pdfReader.isEncrypted()) { - throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted."); - } - if (!pdfReader.isOpenedWithFullPermissions()) { - throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected."); - } - } - - public static boolean toFile(byte[] data, File file) throws IOException { - return PDFASUtils.toFile(new ByteArrayInputStream(data), file); - } - - public static boolean toFile(InputStream inputStream, File file) throws IOException { - boolean result = false; - BufferedOutputStream bufferedOutputStream = null; - try { - bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file)); - ConfigUtils.writeInputStreamToOutputStream(inputStream, bufferedOutputStream); - } finally { - if (bufferedOutputStream != null) { - try { - bufferedOutputStream.close(); - result = true; - } catch (IOException e) { - result = false; - } - } - } - return result; - } - - public static void checkDocumentPermissions(PDDocument doc) throws PDFDocumentException { - if (doc.isEncrypted()) { - throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted."); - } - } - + + private static Log log = LogFactory.getLog(PDFASUtils.class); + + /** + * The configuration key for PDF/A support. + */ + public static final String CFG_KEY_PDFA = "SIG_PDFA1B_VALID"; + + private PDFASUtils() { + } + + /** + * Verifies that a document could be opened with full permissions. + * + * @param pdfReader + * The PdfReader. + * @throws PDFDocumentException + * Thrown if document has not been opened with full permissions. + */ + private static void checkReaderPermissions(PdfReader pdfReader) throws PDFDocumentException { + if (pdfReader.isEncrypted()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted."); + } + if (!pdfReader.isOpenedWithFullPermissions()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected."); + } + } + + /** + * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the + * document a pdf reader is returned. + * + * @param dataSource + * The document data source. + * @throws PDFDocumentException + * Thrown if the document could not be opened with full permissions. + */ + public static PdfReader createPdfReaderCheckingPermissions(DataSource dataSource) throws PDFDocumentException { + return createPdfReaderCheckingPermissions(dataSource.createInputStream()); + } + + /** + * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the + * document a pdf reader is returned. + * + * @param dataSource + * The document data source. + * @throws PDFDocumentException + * Thrown if the document could not be opened with full permissions. + */ + public static PdfReader createPdfReaderCheckingPermissions(at.gv.egiz.pdfas.framework.input.DataSource dataSource) + throws PDFDocumentException { + return createPdfReaderCheckingPermissions(dataSource.createInputStream()); + } + + /** + * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the + * document a pdf reader is returned. + * + * @param inputStream + * The document data input stream. + * @throws PDFDocumentException + * Thrown if the document could not be opened with full permissions. + */ + public static PdfReader createPdfReaderCheckingPermissions(InputStream inputStream) throws PDFDocumentException { + PdfReader reader = null; + try { + // try to parse document + // If fully encrypted, PdfReader will fail; + // It should throw a BadPasswordException, but unfortunately does not (throws an IOException instead, + // internally catching BadPAsswordException; see comments below). + reader = new PdfReader(inputStream); + checkReaderPermissions(reader); + return reader; + } catch (BadPasswordException e) { + // will never be reached with itext-2.1.5-rev3628-pdfas:v1.1 + // just added for later versions... (see comments below) + // itext-2.1.5-rev3628-pdfas:v1.2 correctly throws BadPasswordException + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected."); + } catch (PDFDocumentException e) { + throw e; + } catch (Exception e) { + final String EX_MSG_FOR_ENCRYPTED_DOCUMENT = "Bad user Password"; + // Inspecting the exception message seems to be the only way when using itext-2.1.5-rev3628-pdfas:v1.1: + // itext neither externally throws a BadPasswordException nor passed the cause..., + // later versions do! + // String "Bad user Password" is set in com.lowagie.text.pdf.BadPasswordException so this approach will + // work as long as the underlying itext library is not beeing updated. + if (StringUtils.containsIgnoreCase(e.getMessage(), EX_MSG_FOR_ENCRYPTED_DOCUMENT)) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected."); + } + throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "Unable to parse document."); + } finally { + IOUtils.closeQuietly(inputStream); + closeQuietly(reader); + } + } + + /** + * Quietly closes a pdf reader. + * + * @param reader + * The reader. + */ + public static void closeQuietly(PdfReader reader) { + if (reader != null) { + try { + reader.close(); + } catch (Throwable e) { + // ignore + } + } + } + + /** + * Quietly closes a pdf document. + * + * @param pdDocument + * The pdf document. + */ + public static void closeQuietly(PDDocument pdDocument) { + if (pdDocument != null) { + try { + pdDocument.close(); + } catch (Throwable e) { + // ignore + } + } + } + + /** + * Quietly closes a pdf document. + * + * @param pdDocument + * The pdf document. + */ + public static void closeQuietly(org.pdfbox.pdmodel.PDDocument pdDocument) { + if (pdDocument != null) { + try { + pdDocument.close(); + } catch (Throwable e) { + // ignore + } + } + } + + /** + * Quietly closes a pdf document. + * + * @param pdDocument + * The pdf document. + */ + public static void closeQuietly(Document doc) { + if (doc != null) { + try { + doc.close(); + } catch (Throwable e) { + // ignore + } + } + } + + public static boolean toFile(byte[] data, File file) throws IOException { + return PDFASUtils.toFile(new ByteArrayInputStream(data), file); + } + + public static boolean toFile(InputStream inputStream, File file) throws IOException { + boolean result = false; + BufferedOutputStream bufferedOutputStream = null; + try { + bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file)); + ConfigUtils.writeInputStreamToOutputStream(inputStream, bufferedOutputStream); + } finally { + if (bufferedOutputStream != null) { + try { + bufferedOutputStream.close(); + result = true; + } catch (IOException e) { + result = false; + } + } + } + return result; + } + + /** + * Returns {@code true} if the given {@code profileId} is PDF/A-1b enabled, {@code false} if not. + * + * @param profileId + * The signature profile. + * @return {@code true} if the given {@code profileId} is PDF/A-1b enabled, {@code false} if not. + */ + public static boolean isPdfAEnabled(String profileId) { + if (profileId == null) { + throw new NullPointerException("Profile identifier must not be null."); + } + if (StringUtils.isEmpty(profileId)) { + throw new IllegalArgumentException("Profile identifier must not be empty."); + } + try { + String pdfa = SettingsReader.getInstance().getSetting("sig_obj." + profileId + ".key." + CFG_KEY_PDFA, + "default." + CFG_KEY_PDFA, "false"); + return BooleanUtils.toBoolean(pdfa); + } catch (Exception e) { + log.error("Unable to read settings for PDF/A functionality.", e); + return false; + } + } + } -- cgit v1.2.3