diff --git a/pom.xml b/pom.xml index cd4918b97235b64f269d59c5525aa9373933617c..ea9b2bdb5333816c49ec899752f0c9437c8ce356 100644 --- a/pom.xml +++ b/pom.xml @@ -1920,7 +1920,7 @@ <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> - <version>1.8.15</version> + <version>2.0.12</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> @@ -1928,15 +1928,20 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.apache.pdfbox</groupId> + <artifactId>xmpbox</artifactId> + <version>2.0.12</version> + </dependency> <dependency> <groupId>org.bouncycastle</groupId> - <artifactId>bcmail-jdk15</artifactId> - <version>1.46</version> + <artifactId>bcmail-jdk15on</artifactId> + <version>1.60</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> - <artifactId>bcprov-jdk15</artifactId> - <version>1.46</version> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.60</version> </dependency> <dependency> <groupId>org.scribe</groupId> diff --git a/src/main/java/org/olat/core/commons/services/image/ImageUtils.java b/src/main/java/org/olat/core/commons/services/image/ImageUtils.java index f9e571103b0e1be79f9238cdf5d247fc29132171..9651cd99c6a2ea39b74b5fa47e7ff2b94d07c2ab 100644 --- a/src/main/java/org/olat/core/commons/services/image/ImageUtils.java +++ b/src/main/java/org/olat/core/commons/services/image/ImageUtils.java @@ -21,7 +21,6 @@ package org.olat.core.commons.services.image; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; @@ -31,7 +30,6 @@ import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; -import org.apache.commons.io.IOUtils; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.FileUtils; @@ -48,13 +46,10 @@ public class ImageUtils { public static Size getImageSize(File image) { - InputStream in = null; - try { + try(InputStream in = new FileInputStream(image)) { String suffix = FileUtils.getFileSuffix(image.getName()); - in = new FileInputStream(image); return getImageSize(suffix, in); - } catch (FileNotFoundException e) { - IOUtils.closeQuietly(in); + } catch (IOException e) { return null; } } @@ -65,8 +60,7 @@ public class ImageUtils { Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffix); if (iter.hasNext()) { ImageReader reader = iter.next(); - try { - ImageInputStream stream = new MemoryCacheImageInputStream(in); + try(ImageInputStream stream = new MemoryCacheImageInputStream(in)) { reader.setInput(stream); int imageIndex = reader.getMinIndex(); @@ -76,7 +70,6 @@ public class ImageUtils { } catch (IOException e) { log.error(e.getMessage()); } finally { - IOUtils.closeQuietly(in); reader.dispose(); } } else { diff --git a/src/main/java/org/olat/core/commons/services/image/spi/ImageHelperImpl.java b/src/main/java/org/olat/core/commons/services/image/spi/ImageHelperImpl.java index a238bd03b4484a4f7ed227088b5ece17d886cd57..ce69329deaac89108e39cf5a0981fc15092c0fe5 100644 --- a/src/main/java/org/olat/core/commons/services/image/spi/ImageHelperImpl.java +++ b/src/main/java/org/olat/core/commons/services/image/spi/ImageHelperImpl.java @@ -37,7 +37,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; -import java.util.List; import javax.imageio.IIOImage; import javax.imageio.ImageIO; @@ -55,10 +54,11 @@ import javax.imageio.stream.MemoryCacheImageOutputStream; import org.apache.commons.io.IOUtils; import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException; +import org.apache.pdfbox.rendering.ImageType; +import org.apache.pdfbox.rendering.PDFRenderer; import org.olat.core.commons.services.image.Crop; import org.olat.core.commons.services.image.Size; -import org.olat.core.commons.services.thumbnail.CannotGenerateThumbnailException; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.FileUtils; @@ -81,40 +81,29 @@ public class ImageHelperImpl extends AbstractImageHelper { private static final String OUTPUT_FORMAT = "jpeg"; - @Override - public Size thumbnailPDF(VFSLeaf pdfFile, VFSLeaf thumbnailFile, int maxWidth, int maxHeight) { - InputStream in = null; + public Size thumbnailPDF(VFSLeaf pdfFile, VFSLeaf thumbnailFile, int maxWidth, int maxHeight) { PDDocument document = null; - try { + try(InputStream in = pdfFile.getInputStream()) { WorkThreadInformations.setInfoFiles(null, pdfFile); WorkThreadInformations.set("Generate thumbnail VFSLeaf=" + pdfFile); - in = pdfFile.getInputStream(); + document = PDDocument.load(in); - if (document.isEncrypted()) { - try { - document.decrypt(""); - } catch (Exception e) { - log.info("PDF document is encrypted: " + pdfFile); - throw new CannotGenerateThumbnailException("PDF document is encrypted: " + pdfFile); - } - } - List pages = document.getDocumentCatalog().getAllPages(); - PDPage page = (PDPage) pages.get(0); - BufferedImage image = page.convertToImage(BufferedImage.TYPE_INT_BGR, 72); + PDFRenderer pdfRenderer = new PDFRenderer(document); + BufferedImage image = pdfRenderer.renderImageWithDPI(0, 72, ImageType.RGB); Size size = scaleImage(image, thumbnailFile, maxWidth, maxHeight); if(size != null) { return size; } return null; - } catch (CannotGenerateThumbnailException e) { + } catch(InvalidPasswordException e) { + log.warn("Unable to decrypt. Unable to create image from pdf file.", e); return null; } catch (Exception e) { log.warn("Unable to create image from pdf file.", e); return null; } finally { WorkThreadInformations.unset(); - FileUtils.closeSafely(in); if (document != null) { try { document.close(); @@ -262,14 +251,13 @@ public class ImageHelperImpl extends AbstractImageHelper { } private Size scaleImage(BufferedImage image, VFSLeaf scaledImage, int maxWidth, int maxHeight) { - OutputStream bos = null; - try { + try(OutputStream bos = new BufferedOutputStream(scaledImage.getOutputStream(false))) { if (image == null) { // happens with faulty Java implementation, e.g. on MacOSX Java 10, or // unsupported image format return null; } - bos = new BufferedOutputStream(scaledImage.getOutputStream(false)); + Size scaledSize = calcScaledSize(image, maxWidth, maxHeight); if(writeTo(scaleTo(image, scaledSize), bos, scaledSize, getImageFormat(scaledImage))) { return scaledSize; @@ -277,8 +265,6 @@ public class ImageHelperImpl extends AbstractImageHelper { return null; } catch (Exception e) { return null; - } finally { - FileUtils.closeSafely(bos); } } diff --git a/src/main/java/org/olat/core/util/pdf/PdfDocument.java b/src/main/java/org/olat/core/util/pdf/PdfDocument.java index 6112bfc64445e5278d52abd641cdd0b2dbfb71c8..9ca38a526dee393342c626f9c0e1b939d84dccac 100644 --- a/src/main/java/org/olat/core/util/pdf/PdfDocument.java +++ b/src/main/java/org/olat/core/util/pdf/PdfDocument.java @@ -19,28 +19,33 @@ */ package org.olat.core.util.pdf; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Locale; import javax.xml.transform.TransformerException; -import org.apache.jempbox.xmp.XMPMetadata; -import org.apache.jempbox.xmp.XMPSchemaBasic; -import org.apache.jempbox.xmp.XMPSchemaDublinCore; -import org.apache.jempbox.xmp.XMPSchemaPDF; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentCatalog; import org.apache.pdfbox.pdmodel.PDDocumentInformation; import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode; +import org.apache.pdfbox.pdmodel.PDPageTree; import org.apache.pdfbox.pdmodel.common.PDMetadata; import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDFont; import org.apache.pdfbox.pdmodel.font.PDType1Font; +import org.apache.xmpbox.XMPMetadata; +import org.apache.xmpbox.schema.AdobePDFSchema; +import org.apache.xmpbox.schema.DublinCoreSchema; +import org.apache.xmpbox.schema.XMPBasicSchema; +import org.apache.xmpbox.xml.XmpSerializer; import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; @@ -69,7 +74,7 @@ public class PdfDocument { protected float currentY; protected String printDate; - public PdfDocument(Locale locale) throws IOException { + public PdfDocument(Locale locale) { document = new PDDocument(); printDate = Formatter.getInstance(locale).formatDate(new Date()); } @@ -79,11 +84,11 @@ public class PdfDocument { } public PDPage addPage() throws IOException { - return addPage(PDPage.PAGE_SIZE_A4); + return addPage(PDRectangle.A4); } public PDPage addPageLandscape() throws IOException { - return addPage(new PDRectangle(PDPage.PAGE_SIZE_A4.getHeight(), PDPage.PAGE_SIZE_A4.getWidth())); + return addPage(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); } public PDPage addPage(PDRectangle size) throws IOException { @@ -96,7 +101,7 @@ public class PdfDocument { currentPage = page; currentContentStream = new PDPageContentStream(document, currentPage); - PDRectangle mediabox = currentPage.findMediaBox(); + PDRectangle mediabox = currentPage.getMediaBox(); width = mediabox.getWidth() - 2 * marginLeftRight; currentY = mediabox.getUpperRightY() - marginTopBottom; return page; @@ -112,8 +117,8 @@ public class PdfDocument { throws IOException { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(marginLeftRight, currentY); - currentContentStream.drawString(text); + currentContentStream.newLineAtOffset(marginLeftRight, currentY); + currentContentStream.showText(text); currentContentStream.endText(); float leading = lineHeightFactory * fontSize; @@ -131,7 +136,7 @@ public class PdfDocument { PDFont textFont = bold ? fontBold : font; - List<String> lines = new ArrayList<String>(); + List<String> lines = new ArrayList<>(); int lastSpace = -1; while (text.length() > 0) { int spaceIndex = text.indexOf(' ', lastSpace + 1); @@ -156,10 +161,10 @@ public class PdfDocument { currentContentStream.beginText(); currentContentStream.setFont(textFont, fontSize); - currentContentStream.moveTextPositionByAmount(marginLeftRight, currentY); + currentContentStream.newLineAtOffset(marginLeftRight, currentY); for (String line: lines) { - currentContentStream.drawString(line); - currentContentStream.moveTextPositionByAmount(0, -leading); + currentContentStream.showText(line); + currentContentStream.newLineAtOffset(0, -leading); currentY -= leading; } currentContentStream.endText(); @@ -173,7 +178,9 @@ public class PdfDocument { public void drawLine(float xStart, float yStart, float xEnd, float yEnd, float lineWidth) throws IOException { currentContentStream.setLineWidth(lineWidth); - currentContentStream.drawLine(xStart, yStart, xEnd, yEnd); + currentContentStream.moveTo(xStart, yStart); + currentContentStream.lineTo(xEnd, yEnd); + currentContentStream.stroke(); } public void drawTextAtMovedPositionByAmount(String text, float fontSize, float textx, float texty) @@ -182,8 +189,8 @@ public class PdfDocument { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, texty); - currentContentStream.drawString(text); + currentContentStream.newLineAtOffset(textx, texty); + currentContentStream.showText(text); currentContentStream.endText(); } @@ -200,37 +207,45 @@ public class PdfDocument { info.setTitle(title); info.setSubject(subject); - XMPMetadata metadata = new XMPMetadata(); - XMPSchemaPDF pdfSchema = metadata.addPDFSchema(); + XMPMetadata metadata = XMPMetadata.createXMPMetadata(); + AdobePDFSchema pdfSchema = metadata.createAndAddAdobePDFSchema(); pdfSchema.setProducer("OpenOLAT"); - XMPSchemaBasic basicSchema = metadata.addBasicSchema(); + XMPBasicSchema basicSchema = metadata.createAndAddXMPBasicSchema(); basicSchema.setModifyDate(date); basicSchema.setCreateDate(date); basicSchema.setCreatorTool("OpenOLAT"); basicSchema.setMetadataDate(date); - XMPSchemaDublinCore dcSchema = metadata.addDublinCoreSchema(); + DublinCoreSchema dcSchema = metadata.createAndAddDublinCoreSchema(); dcSchema.setTitle(title); dcSchema.addCreator(author); dcSchema.setDescription(subject); PDMetadata metadataStream = new PDMetadata(document); - metadataStream.importXMPMetadata(metadata); + + // Create and return XMP data structure in XML format + try(ByteArrayOutputStream xmpOutputStream = new ByteArrayOutputStream()) { + new XmpSerializer().serialize(metadata, xmpOutputStream, true); + metadataStream.importXMPMetadata(xmpOutputStream.toByteArray()); + } catch(IOException e) { + e.printStackTrace(); + } + catalog.setMetadata(metadataStream); } public void addPageNumbers() throws IOException { float footerFontSize = 10.0f; - @SuppressWarnings("unchecked") - List<PDPage> allPages = document.getDocumentCatalog().getAllPages(); - int numOfPages = allPages.size(); - for( int i=0; i<allPages.size(); i++ ) { - PDPage page = allPages.get( i ); - PDRectangle pageSize = page.findMediaBox(); + PDPageTree pageTree = document.getPages(); + int i = 0; + int numOfPages = pageTree.getCount(); + for(Iterator<PDPage> pageIt=pageTree.iterator(); pageIt.hasNext(); ) { + PDPage page = pageIt.next(); + PDRectangle pageSize = page.getMediaBox(); - String text = (i+1) + " / " + numOfPages; + String text = (++i) + " / " + numOfPages; float stringWidth = getStringWidth(text, footerFontSize); // calculate to center of the page float pageWidth = pageSize.getWidth(); @@ -238,19 +253,19 @@ public class PdfDocument { double y = (marginTopBottom / 2.0f); // append the content to the existing stream - PDPageContentStream contentStream = new PDPageContentStream(document, page, true, true,true); + PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true,true); contentStream.beginText(); // set font and font size contentStream.setFont( font, footerFontSize ); contentStream.setTextTranslation(x, y); - contentStream.drawString(text); + contentStream.showText(text); contentStream.endText(); //set current date contentStream.beginText(); contentStream.setFont(font, footerFontSize ); contentStream.setTextTranslation(marginLeftRight, y); - contentStream.drawString(printDate); + contentStream.showText(printDate); contentStream.endText(); contentStream.close(); diff --git a/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java b/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java index 0a15d7c4c29a7e0521583a1b88ce8fc1028f0136..c8c03652b1cd82a1d766093ddc08fb16c6f4a6ab 100644 --- a/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java +++ b/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java @@ -256,7 +256,7 @@ public class CertificatePDFFormWorker { field.setValue(value); } - field.setReadonly(true); + field.setReadOnly(true); field.setNoExport(true); } } diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java index 577dc3093eaca50aaa3dc31e1c0b459eb393b2a6..f97ecce8003d4f996be538e6c9edccec65ca4e18 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java @@ -31,7 +31,6 @@ import java.util.Set; import javax.xml.transform.TransformerException; -import org.apache.pdfbox.exceptions.COSVisitorException; import org.olat.NewControllerFactory; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityModule; @@ -623,7 +622,7 @@ public class CheckListAssessmentController extends FormBasicController implement pdfExport.setGroupName(groupName); pdfExport.create(checkboxList, model.getObjects()); ureq.getDispatchResult().setResultingMediaResource(pdfExport); - } catch (IOException | COSVisitorException | TransformerException e) { + } catch (IOException | TransformerException e) { logError("", e); } } @@ -639,7 +638,7 @@ public class CheckListAssessmentController extends FormBasicController implement pdfExport.setCourseTitle(course.getCourseTitle()); pdfExport.create(checkboxList, model.getObjects()); ureq.getDispatchResult().setResultingMediaResource(pdfExport); - } catch (IOException | COSVisitorException | TransformerException e) { + } catch (IOException | TransformerException e) { logError("", e); } } diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxPDFExport.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxPDFExport.java index 25d14f78585ac6daa647dba4523b0b51b6fcdcaa..7c2956a8e493d8a773c2e01f4a06197b18157ffc 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxPDFExport.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxPDFExport.java @@ -26,7 +26,7 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.TransformerException; -import org.apache.pdfbox.exceptions.COSVisitorException; +import org.apache.pdfbox.util.Matrix; import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.translator.Translator; import org.olat.core.id.UserConstants; @@ -54,11 +54,11 @@ public class CheckboxPDFExport extends PdfDocument implements MediaResource { private String groupName; private String author; private final Translator translator; - private int firstNameIndex, lastNameIndex, institutionalUserIdentifierIndex; + private int firstNameIndex; + private int lastNameIndex; + private int institutionalUserIdentifierIndex; - - public CheckboxPDFExport(String filename, Translator translator, List<UserPropertyHandler> userPropertyHandlers) - throws IOException { + public CheckboxPDFExport(String filename, Translator translator, List<UserPropertyHandler> userPropertyHandlers) { super(translator.getLocale()); marginTopBottom = 62.0f; @@ -152,7 +152,7 @@ public class CheckboxPDFExport extends PdfDocument implements MediaResource { hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(filename)); hres.setHeader("Content-Description",StringHelper.urlEncodeUTF8(filename)); document.save(hres.getOutputStream()); - } catch (COSVisitorException | IOException e) { + } catch (IOException e) { log.error("", e); } } @@ -167,7 +167,7 @@ public class CheckboxPDFExport extends PdfDocument implements MediaResource { } public void create(CheckboxList checkboxList, List<CheckListAssessmentRow> rows) - throws IOException, COSVisitorException, TransformerException { + throws IOException, TransformerException { addPage(); addMetadata(courseNodeTitle, courseTitle, author); @@ -348,13 +348,13 @@ public class CheckboxPDFExport extends PdfDocument implements MediaResource { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); if (h == 0 || (h == lastColIndex)) { - currentContentStream.moveTextPositionByAmount(textx, texty - headerHeight + cellMargin); + currentContentStream.newLineAtOffset(textx, texty - headerHeight + cellMargin); textx += nameMaxSizeWithMargin; } else { - currentContentStream.setTextRotation(3 * (Math.PI / 2), textx + cellMargin, texty - cellMargin); + currentContentStream.setTextMatrix(Matrix.getRotateInstance(3 * (Math.PI / 2), textx + cellMargin, texty - cellMargin)); textx += colWidth; } - currentContentStream.drawString(text); + currentContentStream.showText(text); currentContentStream.endText(); } @@ -380,16 +380,16 @@ public class CheckboxPDFExport extends PdfDocument implements MediaResource { String textLine = texts[k]; currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, lineTexty); - currentContentStream.drawString(textLine); + currentContentStream.newLineAtOffset(textx, lineTexty); + currentContentStream.showText(textLine); currentContentStream.endText(); lineTexty -= (lineHeightFactory * fontSize); } } else { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, texty); - currentContentStream.drawString(text); + currentContentStream.newLineAtOffset(textx, texty); + currentContentStream.showText(text); currentContentStream.endText(); } } diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckedPDFExport.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckedPDFExport.java index a9604f46d525b0214e63e1ddcd2551842946ca9b..1624f6349cfcd15120a8fb6bcd319d6326e57a51 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckedPDFExport.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckedPDFExport.java @@ -27,7 +27,6 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.TransformerException; -import org.apache.pdfbox.exceptions.COSVisitorException; import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.translator.Translator; import org.olat.core.id.UserConstants; @@ -57,7 +56,9 @@ public class CheckedPDFExport extends PdfDocument implements MediaResource { private final boolean withScore; private final Translator translator; private final List<UserPropertyHandler> userPropertyHandlers; - private int firstNameIndex, lastNameIndex, institutionalUserIdentifierIndex; + private int firstNameIndex; + private int lastNameIndex; + private int institutionalUserIdentifierIndex; private int numOfCols = 0; @@ -162,7 +163,7 @@ public class CheckedPDFExport extends PdfDocument implements MediaResource { hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(filename)); hres.setHeader("Content-Description",StringHelper.urlEncodeUTF8(filename)); document.save(hres.getOutputStream()); - } catch (COSVisitorException | IOException e) { + } catch (IOException e) { log.error("", e); } } @@ -177,7 +178,7 @@ public class CheckedPDFExport extends PdfDocument implements MediaResource { } public void create(CheckboxList checkboxList, List<CheckListAssessmentRow> rows) - throws IOException, COSVisitorException, TransformerException { + throws IOException, TransformerException { addMetadata(courseNodeTitle, courseTitle, author); int i=0; @@ -189,7 +190,7 @@ public class CheckedPDFExport extends PdfDocument implements MediaResource { } private void create(Checkbox checkbox, int checkboxIndex, List<CheckListAssessmentRow> rows) - throws IOException, COSVisitorException, TransformerException { + throws IOException { addPage(); if(StringHelper.containsNonWhitespace(courseTitle)) { @@ -313,8 +314,8 @@ public class CheckedPDFExport extends PdfDocument implements MediaResource { } currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, texty - headerHeight + cellMargin); - currentContentStream.drawString(text); + currentContentStream.newLineAtOffset(textx, texty - headerHeight + cellMargin); + currentContentStream.showText(text); currentContentStream.endText(); textx += colWidth; } diff --git a/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java b/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java index a0968652a7159ba03fdac1d22cce1046285eb44f..7b37f059b422ea1ccc76ed86bb3799b2c0aeb5ea 100644 --- a/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java +++ b/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java @@ -23,16 +23,19 @@ import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.TransformerException; -import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.PDPageTree; +import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode; import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; +import org.apache.pdfbox.util.Matrix; import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -131,7 +134,7 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(filename)); hres.setHeader("Content-Description",StringHelper.urlEncodeUTF8(filename)); document.save(hres.getOutputStream()); - } catch (COSVisitorException | IOException e) { + } catch (IOException e) { log.error("", e); } } @@ -186,42 +189,42 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource public void addPageNumbers() throws IOException { float footerFontSize = 10.0f; - @SuppressWarnings("unchecked") - List<PDPage> allPages = document.getDocumentCatalog().getAllPages(); - int numOfPages = allPages.size(); - for( int i=0; i<allPages.size(); i++ ) { - PDPage page = allPages.get( i ); - PDRectangle pageSize = page.findMediaBox(); + PDPageTree pageTree = document.getPages(); + int numOfPages = pageTree.getCount(); + int i = 0; + for(Iterator<PDPage> pageIt=pageTree.iterator(); pageIt.hasNext(); ) { + PDPage page = pageIt.next(); + PDRectangle pageSize = page.getMediaBox(); - String text = (i+1) + " / " + numOfPages; + String text = (++i) + " / " + numOfPages; float stringWidth = getStringWidth(text, footerFontSize); // calculate to center of the page float pageWidth = pageSize.getWidth(); - double x = (pageWidth - stringWidth) / 2.0f; - double y = (marginTopBottom / 2.0f); + float x = (pageWidth - stringWidth) / 2.0f; + float y = (marginTopBottom / 2.0f); // append the content to the existing stream - PDPageContentStream contentStream = new PDPageContentStream(document, page, true, true,true); + PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true,true); // set warning contentStream.beginText(); contentStream.setFont(font, footerFontSize ); - contentStream.setTextTranslation(marginLeftRight, y + 14); - contentStream.drawString(translator.translate("rollcall.coach.hint")); + contentStream.setTextMatrix(Matrix.getTranslateInstance(marginLeftRight, y + 14)); + contentStream.showText(translator.translate("rollcall.coach.hint")); contentStream.endText(); contentStream.beginText(); // set font and font size contentStream.setFont(font, footerFontSize ); - contentStream.setTextTranslation(x, y); - contentStream.drawString(text); + contentStream.setTextMatrix(Matrix.getTranslateInstance(x, y)); + contentStream.showText(text); contentStream.endText(); //set current date contentStream.beginText(); contentStream.setFont(font, footerFontSize ); - contentStream.setTextTranslation(marginLeftRight, y); - contentStream.drawString(printDate); + contentStream.setTextMatrix(Matrix.getTranslateInstance(marginLeftRight, y)); + contentStream.showText(printDate); contentStream.endText(); contentStream.close(); @@ -369,16 +372,16 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource currentContentStream.beginText(); currentContentStream.setFont(fontBold, fontSize); - currentContentStream.moveTextPositionByAmount(headerX, headerY); - currentContentStream.drawString(translator.translate("pdf.table.header.participants")); + currentContentStream.newLineAtOffset(headerX, headerY); + currentContentStream.showText(translator.translate("pdf.table.header.participants")); currentContentStream.endText(); headerX += nameMaxSizeWithMargin; for(int i=0; i<numOfLectures; i++) { currentContentStream.beginText(); currentContentStream.setFont(fontBold, fontSize); - currentContentStream.moveTextPositionByAmount(headerX, headerY); - currentContentStream.drawString(Integer.toString(i+1)); + currentContentStream.newLineAtOffset(headerX, headerY); + currentContentStream.showText(Integer.toString(i+1)); currentContentStream.endText(); headerX += lectureColWidth; } @@ -386,24 +389,24 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource headerX += cellMargin; currentContentStream.beginText(); currentContentStream.setFont(fontBold, fontSize); - currentContentStream.moveTextPositionByAmount(headerX, headerY); - currentContentStream.drawString(translator.translate("pdf.table.header.all")); + currentContentStream.newLineAtOffset(headerX, headerY); + currentContentStream.showText(translator.translate("pdf.table.header.all")); currentContentStream.endText(); headerX += allColWidth; if(authorizedAbsenceEnabled) { currentContentStream.beginText(); currentContentStream.setFont(fontBold, fontSize); - currentContentStream.moveTextPositionByAmount(headerX, headerY); - currentContentStream.drawString(translator.translate("pdf.table.header.authorised")); + currentContentStream.newLineAtOffset(headerX, headerY); + currentContentStream.showText(translator.translate("pdf.table.header.authorised")); currentContentStream.endText(); headerX += authorisedColWidth; } currentContentStream.beginText(); currentContentStream.setFont(fontBold, fontSize); - currentContentStream.moveTextPositionByAmount(headerX, headerY); - currentContentStream.drawString(translator.translate("pdf.table.header.comment")); + currentContentStream.newLineAtOffset(headerX, headerY); + currentContentStream.showText(translator.translate("pdf.table.header.comment")); currentContentStream.endText(); } @@ -423,16 +426,16 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource String textLine = texts[k]; currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, lineTexty); - currentContentStream.drawString(textLine); + currentContentStream.newLineAtOffset(textx, lineTexty); + currentContentStream.showText(textLine); currentContentStream.endText(); lineTexty -= (lineHeightFactory * fontSize); } } else { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, texty); - currentContentStream.drawString(text); + currentContentStream.newLineAtOffset(textx, texty); + currentContentStream.showText(text); currentContentStream.endText(); } @@ -453,8 +456,8 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource if(absences[j]) { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(boxx + 2f, texty); - currentContentStream.drawString("x"); + currentContentStream.newLineAtOffset(boxx + 2f, texty); + currentContentStream.showText("x"); currentContentStream.endText(); } all &= absences[j]; @@ -472,8 +475,8 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource if(all) { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(startBoxx + 2f, texty); - currentContentStream.drawString("x"); + currentContentStream.newLineAtOffset(startBoxx + 2f, texty); + currentContentStream.showText("x"); currentContentStream.endText(); } boxx += allColWidth; @@ -489,8 +492,8 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource if(content[i].isAuthorised()) { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(startBoxx + 2f, texty); - currentContentStream.drawString("x"); + currentContentStream.newLineAtOffset(startBoxx + 2f, texty); + currentContentStream.showText("x"); currentContentStream.endText(); } boxx += authorisedColWidth; @@ -510,14 +513,14 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource } currentContentStream.beginText(); currentContentStream.setFont(font, fontSize - 2); - currentContentStream.moveTextPositionByAmount(boxx + 2f, texty); - currentContentStream.drawString(comment); + currentContentStream.newLineAtOffset(boxx + 2f, texty); + currentContentStream.showText(comment); currentContentStream.endText(); } else { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(boxx + 2f, texty); - currentContentStream.drawString(comment); + currentContentStream.newLineAtOffset(boxx + 2f, texty); + currentContentStream.showText(comment); currentContentStream.endText(); } } diff --git a/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockSignaturePDFExport.java b/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockSignaturePDFExport.java index 1c016020714751e9bf5ab1adc8b7ce084a037137..054184b49a7874ac800e92a40d18569a66142a4d 100644 --- a/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockSignaturePDFExport.java +++ b/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockSignaturePDFExport.java @@ -26,7 +26,6 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.TransformerException; -import org.apache.pdfbox.exceptions.COSVisitorException; import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -116,7 +115,7 @@ public class LecturesBlockSignaturePDFExport extends PdfDocument implements Medi hres.setHeader("Content-Disposition","attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(filename)); hres.setHeader("Content-Description",StringHelper.urlEncodeUTF8(filename)); document.save(hres.getOutputStream()); - } catch (COSVisitorException | IOException e) { + } catch (IOException e) { log.error("", e); } } @@ -262,14 +261,14 @@ public class LecturesBlockSignaturePDFExport extends PdfDocument implements Medi { currentContentStream.beginText(); currentContentStream.setFont(fontBold, fontSize); - currentContentStream.moveTextPositionByAmount(textx, texty - rowHeight + (2 * cellMargin)); - currentContentStream.drawString(translator.translate("pdf.table.header.participants")); + currentContentStream.newLineAtOffset(textx, texty - rowHeight + (2 * cellMargin)); + currentContentStream.showText(translator.translate("pdf.table.header.participants")); currentContentStream.endText(); currentContentStream.beginText(); currentContentStream.setFont(fontBold, fontSize); - currentContentStream.moveTextPositionByAmount(textx + nameMaxSizeWithMargin, texty - rowHeight + (2 * cellMargin)); - currentContentStream.drawString(translator.translate("pdf.table.header.signature")); + currentContentStream.newLineAtOffset(textx + nameMaxSizeWithMargin, texty - rowHeight + (2 * cellMargin)); + currentContentStream.showText(translator.translate("pdf.table.header.signature")); currentContentStream.endText(); } @@ -289,16 +288,16 @@ public class LecturesBlockSignaturePDFExport extends PdfDocument implements Medi String textLine = texts[k]; currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, lineTexty); - currentContentStream.drawString(textLine); + currentContentStream.newLineAtOffset(textx, lineTexty); + currentContentStream.showText(textLine); currentContentStream.endText(); lineTexty -= (lineHeightFactory * fontSize); } } else { currentContentStream.beginText(); currentContentStream.setFont(font, fontSize); - currentContentStream.moveTextPositionByAmount(textx, texty); - currentContentStream.drawString(text); + currentContentStream.newLineAtOffset(textx, texty); + currentContentStream.showText(text); currentContentStream.endText(); } texty -= rowHeights[i]; diff --git a/src/main/java/org/olat/search/service/document/file/PdfDocument.java b/src/main/java/org/olat/search/service/document/file/PdfDocument.java index ad174712e2305a6697c96949e592bb25e8cdb6b5..c29478a0a8ee7f748ccebafebbf186754bfd6344 100644 --- a/src/main/java/org/olat/search/service/document/file/PdfDocument.java +++ b/src/main/java/org/olat/search/service/document/file/PdfDocument.java @@ -50,7 +50,7 @@ public class PdfDocument extends FileDocument { private static final long serialVersionUID = 6432923202585881794L; private static final OLog log = Tracing.createLoggerFor(PdfDocument.class); - public final static String FILE_TYPE = "type.file.pdf"; + public static final String FILE_TYPE = "type.file.pdf"; private boolean externalIndexer; private String pdfTextBufferPath; diff --git a/src/main/java/org/olat/search/service/document/file/pdf/PdfBoxExtractor.java b/src/main/java/org/olat/search/service/document/file/pdf/PdfBoxExtractor.java index 82d7b3b507fbebb201f21f379becec2bc4ee9276..82e9f0c4810e84517d8b639d713582b0a7a14f67 100644 --- a/src/main/java/org/olat/search/service/document/file/pdf/PdfBoxExtractor.java +++ b/src/main/java/org/olat/search/service/document/file/pdf/PdfBoxExtractor.java @@ -25,7 +25,7 @@ import java.io.FileWriter; import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.util.PDFTextStripper; +import org.apache.pdfbox.text.PDFTextStripper; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; @@ -66,22 +66,9 @@ public class PdfBoxExtractor implements PdfExtractor { private FileContent extractTextFromPdf(VFSLeaf leaf) throws IOException, DocumentAccessException { if (log.isDebug()) log.debug("readContent from pdf starts..."); - PDDocument document = null; - BufferedInputStream bis = null; - try { - bis = new BufferedInputStream(leaf.getInputStream()); - document = PDDocument.load(bis); - if (document.isEncrypted()) { - try { - document.decrypt(""); - } catch (Exception e) { - log.warn("PDF is encrypted. Can not read content file=" + leaf.getName()); - LimitedContentWriter writer = new LimitedContentWriter(128, FileDocumentFactory.getMaxFileSize()); - writer.append(leaf.getName()); - writer.close(); - return new FileContent(leaf.getName(), writer.toString()); - } - } + + try(BufferedInputStream bis = new BufferedInputStream(leaf.getInputStream()); + PDDocument document = PDDocument.load(bis)) { String title = getTitle(document); if (log.isDebug()) log.debug("readContent PDDocument loaded"); PDFTextStripper stripper = new PDFTextStripper(); @@ -89,13 +76,19 @@ public class PdfBoxExtractor implements PdfExtractor { stripper.writeText(document, writer); writer.close(); return new FileContent(title, writer.toString()); - } finally { - if (document != null) { - document.close(); - } - if (bis != null) { - bis.close(); - } + } catch(Exception e) { + log.warn("Can not read content file=" + leaf.getName()); + return createWithFilename(leaf) ; + } + } + + private FileContent createWithFilename(VFSLeaf leaf) { + try(LimitedContentWriter writer = new LimitedContentWriter(128, FileDocumentFactory.getMaxFileSize())) { + writer.append(leaf.getName()); + return new FileContent(leaf.getName(), writer.toString()); + } catch(Exception e) { + log.error("", e); + return null; } }