001/* 002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Thibaud Arguillere 018 * Miguel Nixo 019 */ 020package org.nuxeo.ecm.platform.pdf; 021 022import org.apache.commons.lang.StringUtils; 023import org.apache.pdfbox.exceptions.COSVisitorException; 024import org.apache.pdfbox.exceptions.CryptographyException; 025import org.apache.pdfbox.pdmodel.PDDocument; 026import org.apache.pdfbox.pdmodel.PDDocumentInformation; 027import org.apache.pdfbox.pdmodel.encryption.BadSecurityHandlerException; 028import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial; 029import org.nuxeo.ecm.core.api.Blob; 030import org.nuxeo.ecm.core.api.Blobs; 031import org.nuxeo.ecm.core.api.NuxeoException; 032import org.nuxeo.ecm.core.api.impl.blob.FileBlob; 033 034import java.io.File; 035import java.io.IOException; 036 037/** 038 * Grouping miscellaneous utilities in this class. 039 * 040 * @since 8.10 041 */ 042public class PDFUtils { 043 044 public static final String DEFAULT_BLOB_XPATH = "file:content"; 045 046 public static int[] hex255ToRGB(String inHex) { 047 int[] result = { 0, 0, 0 }; 048 if (inHex != null) { 049 inHex = inHex.toLowerCase().replace("#", "").replace("0x", ""); 050 if (inHex.length() >= 6) { 051 for (int i = 0; i < 3; i++) { 052 result[i] = Integer.parseInt(inHex.substring(i * 2, i * 2 + 2), 16); 053 } 054 } 055 } 056 return result; 057 } 058 059 /** 060 * This is just a shortcut. We often load() and openProtection(). 061 * 062 * @param inBlob Input Blob. 063 * @param inPwd Input password. 064 * @throws NuxeoException 065 */ 066 public static PDDocument load(Blob inBlob, String inPwd) throws NuxeoException { 067 PDDocument pdfDoc; 068 try { 069 pdfDoc = PDDocument.load(inBlob.getStream()); 070 if (pdfDoc.isEncrypted()) { 071 pdfDoc.openProtection(new StandardDecryptionMaterial(inPwd)); 072 } 073 } catch (IOException e) { 074 throw new NuxeoException("Failed to load the PDF", e); 075 } catch (BadSecurityHandlerException | CryptographyException e) { 076 throw new NuxeoException("Failed to decrypt the PDF", e); 077 } 078 return pdfDoc; 079 } 080 081 /** 082 * Create a temporary PDF file and return a FileBlob built from this file. 083 * <p> 084 * Mainly a utility used just by this plug-in actually. 085 * 086 * @param inPdfDoc Input PDF document. 087 * @return FileBlob 088 * @throws IOException 089 * @throws COSVisitorException 090 */ 091 public static FileBlob saveInTempFile(PDDocument inPdfDoc) throws IOException, COSVisitorException { 092 return saveInTempFile(inPdfDoc, null); 093 } 094 095 public static FileBlob saveInTempFile(PDDocument inPdfDoc, String inFileName) throws IOException, 096 COSVisitorException { 097 Blob result = Blobs.createBlobWithExtension(".pdf"); 098 File resultFile = result.getFile(); 099 inPdfDoc.save(result.getFile()); 100 result.setMimeType("application/pdf"); 101 if (StringUtils.isNotBlank(inFileName)) { 102 result.setFilename(inFileName); 103 } 104 FileBlob fb = new FileBlob(resultFile); 105 fb.setMimeType("application/pdf"); 106 return fb; 107 } 108 109 /** 110 * Convenience method: If a parameter is null or "", it is not modified. 111 * 112 * @param inPdfDoc Input PDF document. 113 * @param inTitle Title of the PDF document. 114 * @param inSubject Subject of the PDF document. 115 * @param inAuthor Author of the PDF document. 116 */ 117 public static void setInfos(PDDocument inPdfDoc, String inTitle, String inSubject, String inAuthor) { 118 if (inTitle != null && inTitle.isEmpty()) { 119 inTitle = null; 120 } 121 if (inSubject != null && inSubject.isEmpty()) { 122 inSubject = null; 123 } 124 if (inAuthor != null && inAuthor.isEmpty()) { 125 inAuthor = null; 126 } 127 if (inTitle != null || inAuthor != null || inSubject != null) { 128 PDDocumentInformation docInfo = inPdfDoc.getDocumentInformation(); 129 if (inTitle != null) { 130 docInfo.setTitle(inTitle); 131 } 132 if (inSubject != null) { 133 docInfo.setSubject(inSubject); 134 } 135 if (inAuthor != null) { 136 docInfo.setAuthor(inAuthor); 137 } 138 inPdfDoc.setDocumentInformation(docInfo); 139 } 140 } 141 142 public static String checkXPath(String inXPath) { 143 if (StringUtils.isBlank(inXPath)) { 144 inXPath = DEFAULT_BLOB_XPATH; 145 } 146 return inXPath; 147 } 148 149 public static void closeSilently(PDDocument... inPdfDocs) { 150 for (PDDocument doc : inPdfDocs) { 151 if (doc != null) { 152 try { 153 doc.close(); 154 } catch (IOException e) { 155 // Ignore 156 } 157 } 158 } 159 } 160 161}