From 4b0a06b8bae5a8f5f3a97541bc26ff64002dce46 Mon Sep 17 00:00:00 2001 From: Andrei Isvoran Date: Thu, 8 Feb 2024 10:11:08 +0100 Subject: [PATCH] RED-8359 - Migrate to gradle --- .gitignore | 8 + .gitlab-ci.yml | 3 +- build.gradle.kts | 102 +++++++++ config/checkstyle/checkstyle.xml | 39 ++++ config/pmd/pmd.xml | 20 ++ config/pmd/test_pmd.xml | 22 ++ gradle.properties.kts | 1 + pom.xml | 94 --------- settings.gradle.kts | 1 + .../red/pdftronlogic/commons/Converter.java | 7 +- .../pdftronlogic/commons/ElementFeatures.java | 1 + .../commons/ImageHashFactory.java | 17 +- .../InvisibleElementRemovalService.java | 197 +++++++++--------- .../commons/MarkedContentStack.java | 18 +- .../commons/OCGWatermarkRemovalService.java | 34 ++- .../commons/PdfTextExtraction.java | 24 +-- .../commons/WatermarkRemovalService.java | 73 +++---- .../InvisibleElementRemovalServiceTest.java | 1 + .../commons/WatermarkRemovalServiceTest.java | 1 + 19 files changed, 377 insertions(+), 286 deletions(-) create mode 100644 build.gradle.kts create mode 100644 config/checkstyle/checkstyle.xml create mode 100644 config/pmd/pmd.xml create mode 100644 config/pmd/test_pmd.xml create mode 100644 gradle.properties.kts delete mode 100644 pom.xml create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore index 050831a..e9bca93 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,11 @@ **/classpath-data.json **/dependencies-and-licenses-overview.txt git.tag + +gradle.properties +gradlew +gradlew.bat +gradle/ + +**/.gradle +**/build diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b85809e..aa3b5b4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,5 @@ include: - project: 'gitlab/gitlab' ref: 'main' - file: 'ci-templates/maven_deps.yml' + file: 'ci-templates/gradle_java.yml' + diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..571816e --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,102 @@ +plugins { + `java-library` + `maven-publish` + `kotlin-dsl` + pmd + checkstyle + jacoco + id("io.freefair.lombok") version "8.4" + id("org.sonarqube") version "4.0.0.2929" +} + +repositories { + mavenLocal() + maven { + url = uri("https://pdftron.com/maven/release") + } + maven { + url = uri("https://nexus.knecon.com/repository/gindev/"); + credentials { + username = providers.gradleProperty("mavenUser").getOrNull(); + password = providers.gradleProperty("mavenPassword").getOrNull(); + } + } + mavenCentral() +} + +dependencies { + api("org.projectlombok:lombok:1.18.30") + api("org.springframework.boot:spring-boot-configuration-processor:3.2.2") + api("com.google.guava:guava:33.0.0-jre") + api("com.pdftron:PDFNet:10.3.0") + testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") + testImplementation("org.assertj:assertj-core:3.24.2") + testImplementation("org.mockito:mockito-core:5.2.0") + testImplementation("org.apache.logging.log4j:log4j-slf4j2-impl:2.22.1") + compileOnly("org.slf4j:slf4j-api:2.0.11") +} + +group = "com.iqser.red.commons" +description = "pdftron-logic-commons" +java.sourceCompatibility = JavaVersion.VERSION_17 +java.targetCompatibility = JavaVersion.VERSION_17 + +publishing { + publications { + create(name) { + from(components["java"]) + } + } + repositories { + maven { + url = uri("https://nexus.knecon.com/repository/red-platform-releases/") + credentials { + username = providers.gradleProperty("mavenUser").getOrNull(); + password = providers.gradleProperty("mavenPassword").getOrNull(); + } + } + } +} + +pmd { + isConsoleOutput = true +} + +tasks.pmdMain { + pmd.ruleSetFiles = files("${rootDir}/config/pmd/pmd.xml") +} + +tasks.pmdTest { + pmd.ruleSetFiles = files("${rootDir}/config/pmd/test_pmd.xml") +} + +tasks.named("test") { + useJUnitPlatform() + reports { + junitXml.outputLocation.set(layout.buildDirectory.dir("reports/junit")) + } +} + +sonarqube { + properties { + property("sonar.login", providers.gradleProperty("sonarToken").getOrNull()) + property("sonar.host.url", "https://sonarqube.knecon.com") + } +} + +tasks.test { + finalizedBy(tasks.jacocoTestReport) +} + +tasks.jacocoTestReport { + dependsOn(tasks.test) + reports { + xml.required.set(true) + csv.required.set(false) + html.outputLocation.set(layout.buildDirectory.dir("jacocoHtml")) + } +} + +java { + withJavadocJar() +} \ No newline at end of file diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 0000000..8faaf13 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/pmd/pmd.xml b/config/pmd/pmd.xml new file mode 100644 index 0000000..7537e1c --- /dev/null +++ b/config/pmd/pmd.xml @@ -0,0 +1,20 @@ + + + + + Knecon ruleset checks the code for bad stuff + + + + + + + + + + + + diff --git a/config/pmd/test_pmd.xml b/config/pmd/test_pmd.xml new file mode 100644 index 0000000..be4aa92 --- /dev/null +++ b/config/pmd/test_pmd.xml @@ -0,0 +1,22 @@ + + + + + Knecon test ruleset checks the code for bad stuff + + + + + + + + + + + + + + diff --git a/gradle.properties.kts b/gradle.properties.kts new file mode 100644 index 0000000..f2b849c --- /dev/null +++ b/gradle.properties.kts @@ -0,0 +1 @@ +version = 2.0-SNAPSHOT \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 818ae13..0000000 --- a/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - platform-dependency - com.iqser.red - 2.2.0 - - - 4.0.0 - - - UTF-8 - - - pdftron-logic-commons - com.iqser.red.commons - 2.0-SNAPSHOT - - - - - org.slf4j - slf4j-api - provided - - - org.apache.logging.log4j - log4j-slf4j2-impl - 2.20.0 - test - - - com.google.guava - guava - - - - com.pdftron - PDFNet - 10.3.0 - provided - - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - org.jacoco - jacoco-maven-plugin - - - prepare-agent - - prepare-agent - - - - report - - report - - - - - - - - - - - - pdftron - PDFNet Maven - https://pdftron.com/maven/release - - - - diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..beaf7ec --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "pdftron-logic-commons" diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/Converter.java b/src/main/java/com/iqser/red/pdftronlogic/commons/Converter.java index a485152..4a29b5b 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/Converter.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/Converter.java @@ -62,10 +62,9 @@ public class Converter { @SneakyThrows public static Color convertColor(ColorSpace colorSpace, ColorPt colorPt) { - ColorPt rgbColor = colorSpace.convert2RGB(colorPt); - Color color = new Color((float) rgbColor.get(0), (float) rgbColor.get(1), (float) rgbColor.get(2)); - rgbColor.destroy(); - return color; + try (ColorPt rgbColor = colorSpace.convert2RGB(colorPt)) { + return new Color((float) rgbColor.get(0), (float) rgbColor.get(1), (float) rgbColor.get(2)); + } } diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/ElementFeatures.java b/src/main/java/com/iqser/red/pdftronlogic/commons/ElementFeatures.java index 718c4ea..3ef3ec7 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/ElementFeatures.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/ElementFeatures.java @@ -103,6 +103,7 @@ public class ElementFeatures { @Getter @SuperBuilder @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) + @SuppressWarnings("PMD") public static class Text extends ElementFeatures { String text; diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/ImageHashFactory.java b/src/main/java/com/iqser/red/pdftronlogic/commons/ImageHashFactory.java index 308b5ed..5d3682f 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/ImageHashFactory.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/ImageHashFactory.java @@ -35,17 +35,16 @@ public class ImageHashFactory { @SneakyThrows private byte[] getBytesOfImage(com.pdftron.pdf.Image inputImage) { // 0 because the memory filter determines the size - var memFilter = new MemoryFilter(0, false); - var filterWriter = new FilterWriter(memFilter); + try(var memFilter = new MemoryFilter(0, false); + var filterWriter = new FilterWriter(memFilter)) { - inputImage.export(filterWriter); - filterWriter.flushAll(); - byte[] res = memFilter.getBuffer(); + inputImage.export(filterWriter); + filterWriter.flushAll(); + byte[] res = memFilter.getBuffer(); - memFilter.flushAll(); - memFilter.destroy(); - filterWriter.destroy(); - return res; + memFilter.flushAll(); + return res; + } } diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalService.java b/src/main/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalService.java index 13f66e8..ae60168 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalService.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalService.java @@ -151,39 +151,36 @@ public class InvisibleElementRemovalService { private void execute(PDFDoc pdfDoc, boolean delta, boolean removePaths, Set markedContentToIgnore) { log.info("Start removing invisible Elements"); - ElementWriter writer = new ElementWriter(); - ElementReader reader = new ElementReader(); - Set visitedXObjIds = new TreeSet<>(); + try(ElementWriter writer = new ElementWriter(); + ElementReader reader = new ElementReader()) { + Set visitedXObjIds = new TreeSet<>(); - for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { + for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { - Page page = iterator.next(); + Page page = iterator.next(); - visitedXObjIds.add(page.getSDFObj().getObjNum()); + visitedXObjIds.add(page.getSDFObj().getObjNum()); - InvisibleElementRemovalContext context = InvisibleElementRemovalContext.builder() - .reader(reader) - .clippingPathStack(new ClippingPathStack(page.getMediaBox())) - .markedContentStack(new MarkedContentStack()) - .removePaths(removePaths) - .delta(delta) - .overlappedElements(new ArrayList<>()) - .visibleElements(new ArrayList<>()) - .visitedXObjIds(visitedXObjIds) - .markedContentToIgnore(markedContentToIgnore) - .build(); + InvisibleElementRemovalContext context = InvisibleElementRemovalContext.builder() + .reader(reader) + .clippingPathStack(new ClippingPathStack(page.getMediaBox())) + .markedContentStack(new MarkedContentStack()) + .removePaths(removePaths) + .delta(delta) + .overlappedElements(new ArrayList<>()) + .visibleElements(new ArrayList<>()) + .visitedXObjIds(visitedXObjIds) + .markedContentToIgnore(markedContentToIgnore) + .build(); - removeClippedElementsAndInvisibleTextAndRememberOverlappedElements(page, writer, context); + removeClippedElementsAndInvisibleTextAndRememberOverlappedElements(page, writer, context); - context.visitedXObjIds().clear(); - context.markedContentStack().clear(); - - removeOverlappedElements(page, writer, context); + context.visitedXObjIds().clear(); + context.markedContentStack().clear(); + removeOverlappedElements(page, writer, context); + } } - writer.destroy(); - reader.destroy(); - log.info("Finished removing invisible Elements"); } @@ -239,68 +236,70 @@ public class InvisibleElementRemovalService { private void processImages(Element imageElement, ElementWriter writer, InvisibleElementRemovalContext context) throws PDFNetException { - Rect rect = imageElement.getBBox(); + try(Rect rect = imageElement.getBBox()) { - if (rect == null) { - return; - } + if (rect == null) { + return; + } - boolean inClippingPath = context.clippingPathStack().almostIntersects(rect.getX1(), rect.getY1(), rect.getWidth(), rect.getHeight()); + boolean inClippingPath = context.clippingPathStack().almostIntersects(rect.getX1(), rect.getY1(), rect.getWidth(), rect.getHeight()); - if (!context.delta() && inClippingPath) { - context.visibleElements().add(ElementFeatureFactory.extractFeatures(imageElement)); - } + if (!context.delta() && inClippingPath) { + context.visibleElements().add(ElementFeatureFactory.extractFeatures(imageElement)); + } - if (context.delta() ^ inClippingPath) { - writer.writeElement(imageElement); + if (context.delta() ^ inClippingPath) { + writer.writeElement(imageElement); + } } } private void processText(Element textElement, ElementWriter writer, InvisibleElementRemovalContext context) throws PDFNetException { - Rect textBBox = textElement.getBBox(); + try(Rect textBBox = textElement.getBBox()) { - if (textBBox == null) { - writer.writeElement(textElement); - return; - } - - GState gState = textElement.getGState(); - - boolean inClippingPath = context.clippingPathStack().almostIntersects(textBBox.getX1(), textBBox.getY1(), textBBox.getWidth(), textBBox.getHeight()); - - boolean isTextVisible = isTextRenderedVisibly(gState, textBBox, context); - - if (inClippingPath && isTextVisible) { - context.visibleElements().add(ElementFeatureFactory.extractFeatures(textElement)); - } - if (!context.delta()) { - if (inClippingPath && isTextVisible) { + if (textBBox == null) { writer.writeElement(textElement); - } else if (textElement.hasTextMatrix()) { + return; + } + + GState gState = textElement.getGState(); + + boolean inClippingPath = context.clippingPathStack().almostIntersects(textBBox.getX1(), textBBox.getY1(), textBBox.getWidth(), textBBox.getHeight()); + + boolean isTextVisible = isTextRenderedVisibly(gState, textBBox, context); + + if (inClippingPath && isTextVisible) { + context.visibleElements().add(ElementFeatureFactory.extractFeatures(textElement)); + } + if (!context.delta()) { + if (inClippingPath && isTextVisible) { + writer.writeElement(textElement); + } else if (textElement.hasTextMatrix()) { /* PDFTron Element with type "text" refers to a Tj command. If a Tm command is just above it in the pdf file, PDFTron will join the two commands and treat them as one Element. hasTextMatrix() checks for this case specifically. Also, Tm changes the position for a whole BT/ET segment, possibly containing multiple Tj commands. Therefore, the position of a following Tj is affected by not writing the first Element. This is why, we write only the Tm command: */ - writer.writeGStateChanges(textElement); - } - } else { - if (!inClippingPath) { - gState.setFillColorSpace(ColorSpace.createDeviceRGB()); - // red for elements removed by clipping path - gState.setFillColor(new ColorPt(1, 0, 0)); - writer.writeElement(textElement); - } - if (!isTextVisible) { - gState.setFillColorSpace(ColorSpace.createDeviceRGB()); - // blue for elements removed due to transparency or not rendered or same color as background - gState.setFillColor(new ColorPt(0, 0, 1)); - gState.setTextRenderMode(GState.e_fill_text); - gState.setFillOpacity(1); - writer.writeElement(textElement); + writer.writeGStateChanges(textElement); + } + } else { + if (!inClippingPath) { + gState.setFillColorSpace(ColorSpace.createDeviceRGB()); + // red for elements removed by clipping path + gState.setFillColor(new ColorPt(1, 0, 0)); + writer.writeElement(textElement); + } + if (!isTextVisible) { + gState.setFillColorSpace(ColorSpace.createDeviceRGB()); + // blue for elements removed due to transparency or not rendered or same color as background + gState.setFillColor(new ColorPt(0, 0, 1)); + gState.setTextRenderMode(GState.e_fill_text); + gState.setFillOpacity(1); + writer.writeElement(textElement); + } } } } @@ -315,20 +314,20 @@ public class InvisibleElementRemovalService { context.visitedXObjIds().add(formObj.getObjNum()); // writer needs to be newly initialized when entering a new content stream // see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest) - ElementWriter formWriter = new ElementWriter(); - context.clippingPathStack().enterNewGState(); - context.clippingPathStack().intersectClippingPath(new GeneralPath(Converter.toRectangle2D(formElement.getBBox()))); - context.reader().formBegin(); - formWriter.begin(formObj); + try(ElementWriter formWriter = new ElementWriter()) { + context.clippingPathStack().enterNewGState(); + context.clippingPathStack().intersectClippingPath(new GeneralPath(Converter.toRectangle2D(formElement.getBBox()))); + context.reader().formBegin(); + formWriter.begin(formObj); - context.reader().clearChangeList(); - formWriter.setDefaultGState(context.reader()); + context.reader().clearChangeList(); + formWriter.setDefaultGState(context.reader()); - processElements(formWriter, context); - formWriter.end(); - formWriter.destroy(); - context.reader().end(); - context.clippingPathStack().leaveGState(); + processElements(formWriter, context); + formWriter.end(); + context.reader().end(); + context.clippingPathStack().leaveGState(); + } } } @@ -481,17 +480,17 @@ public class InvisibleElementRemovalService { context.visitedXObjIds().add(formObj.getObjNum()); // writer needs to be newly initialized when entering a new content stream // see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest) - ElementWriter formWriter = new ElementWriter(); - context.reader().formBegin(); - formWriter.begin(formObj); + try(ElementWriter formWriter = new ElementWriter()) { + context.reader().formBegin(); + formWriter.begin(formObj); - context.reader().clearChangeList(); - formWriter.setDefaultGState(context.reader()); + context.reader().clearChangeList(); + formWriter.setDefaultGState(context.reader()); - processOverlappedElements(formWriter, context); - formWriter.end(); - formWriter.destroy(); - context.reader().end(); + processOverlappedElements(formWriter, context); + formWriter.end(); + context.reader().end(); + } } } @@ -582,18 +581,16 @@ public class InvisibleElementRemovalService { @SneakyThrows private void drawBBox(ElementWriter writer, Rectangle2D r, String hexcolor) { - ColorPt colorPt = new ColorPt(Integer.valueOf(hexcolor.substring(1, 3), 16) / 255d, + try(ColorPt colorPt = new ColorPt(Integer.valueOf(hexcolor.substring(1, 3), 16) / 255d, Integer.valueOf(hexcolor.substring(3, 5), 16) / 255d, Integer.valueOf(hexcolor.substring(5, 7), 16) / 255d); - ElementBuilder eb = new ElementBuilder(); - Element rect = eb.createRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - rect.setPathStroke(true); - rect.getGState().setStrokeColorSpace(ColorSpace.createDeviceRGB()); - rect.getGState().setStrokeColor(colorPt); - writer.writePlacedElement(rect); - - colorPt.destroy(); - eb.destroy(); + ElementBuilder eb = new ElementBuilder()) { + Element rect = eb.createRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + rect.setPathStroke(true); + rect.getGState().setStrokeColorSpace(ColorSpace.createDeviceRGB()); + rect.getGState().setStrokeColor(colorPt); + writer.writePlacedElement(rect); + } } diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/MarkedContentStack.java b/src/main/java/com/iqser/red/pdftronlogic/commons/MarkedContentStack.java index 20747fb..d38caa2 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/MarkedContentStack.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/MarkedContentStack.java @@ -7,33 +7,33 @@ import java.util.Set; public class MarkedContentStack { - Deque markedContentStack = new LinkedList<>(); + Deque stack = new LinkedList<>(); public void enterMarkedContent(String name) { - markedContentStack.push(new MarkedContent(name)); + stack.push(new MarkedContent(name)); } public void leaveMarkedContent() { - markedContentStack.pop(); + stack.pop(); } public String currentMarkedContent() { - if (markedContentStack.isEmpty()) { + if (stack.isEmpty()) { return ""; } - return markedContentStack.peek().name(); + return stack.peek().name(); } public boolean currentMarkedContentContains(String name) { - Iterator markedContentIterator = markedContentStack.descendingIterator(); + Iterator markedContentIterator = stack.descendingIterator(); while (markedContentIterator.hasNext()) { var markedContent = markedContentIterator.next(); if (markedContent.name().equals(name)) { @@ -46,10 +46,10 @@ public class MarkedContentStack { public boolean currentMarkedContentContainsAny(Set names) { - if (markedContentStack.isEmpty()) { + if (stack.isEmpty()) { return false; } - Iterator markedContentIterator = markedContentStack.descendingIterator(); + Iterator markedContentIterator = stack.descendingIterator(); while (markedContentIterator.hasNext()) { var markedContent = markedContentIterator.next(); if (names.contains(markedContent.name())) { @@ -62,7 +62,7 @@ public class MarkedContentStack { public void clear() { - markedContentStack.clear(); + stack.clear(); } diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/OCGWatermarkRemovalService.java b/src/main/java/com/iqser/red/pdftronlogic/commons/OCGWatermarkRemovalService.java index 9a655f0..6e70023 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/OCGWatermarkRemovalService.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/OCGWatermarkRemovalService.java @@ -43,18 +43,16 @@ public class OCGWatermarkRemovalService { @SneakyThrows private void removeOCGWatermarks(PDFDoc pdfDoc) { - ElementReader reader = new ElementReader(); - ElementWriter writer = new ElementWriter(); - Set visitedXObjIds = new TreeSet<>(); + try(ElementReader reader = new ElementReader(); + ElementWriter writer = new ElementWriter()) { + Set visitedXObjIds = new TreeSet<>(); - for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { + for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { - Page page = iterator.next(); - writeAllElementsExceptWatermarks(page, reader, writer, visitedXObjIds); + Page page = iterator.next(); + writeAllElementsExceptWatermarks(page, reader, writer, visitedXObjIds); + } } - - reader.destroy(); - writer.destroy(); } @@ -124,17 +122,17 @@ public class OCGWatermarkRemovalService { visitedXObjIds.add(element.getXObject().getObjNum()); // writer needs to be newly initialized when entering a new content stream // see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest) - ElementWriter formWriter = new ElementWriter(); - reader.formBegin(); - formWriter.begin(element.getXObject()); + try(ElementWriter formWriter = new ElementWriter()) { + reader.formBegin(); + formWriter.begin(element.getXObject()); - reader.clearChangeList(); - formWriter.setDefaultGState(reader); + reader.clearChangeList(); + formWriter.setDefaultGState(reader); - processElements(page, reader, formWriter, visitedXObjIds); - formWriter.end(); - formWriter.destroy(); - reader.end(); + processElements(page, reader, formWriter, visitedXObjIds); + formWriter.end(); + reader.end(); + } } } diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/PdfTextExtraction.java b/src/main/java/com/iqser/red/pdftronlogic/commons/PdfTextExtraction.java index bb6a762..77a4aca 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/PdfTextExtraction.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/PdfTextExtraction.java @@ -16,20 +16,20 @@ import lombok.experimental.UtilityClass; @UtilityClass public class PdfTextExtraction { - private static String execute(PDFDoc pdfDoc) throws IOException, PDFNetException{ - TextExtractor extractor = new TextExtractor(); - List texts = new ArrayList<>(); + private static String execute(PDFDoc pdfDoc) throws PDFNetException{ + try(TextExtractor extractor = new TextExtractor()) { + List texts = new ArrayList<>(); - PageIterator iterator = pdfDoc.getPageIterator(); - while (iterator.hasNext()) { - Page page = iterator.next(); - extractor.begin(page); - texts.add(extractor.getAsText()); + PageIterator iterator = pdfDoc.getPageIterator(); + while (iterator.hasNext()) { + Page page = iterator.next(); + extractor.begin(page); + texts.add(extractor.getAsText()); + } + + pdfDoc.close(); + return String.join("\n", texts); } - - extractor.destroy(); - pdfDoc.close(); - return String.join("\n", texts); } public static String extractAllTextFromDocument(InputStream fileStream) throws IOException, PDFNetException { diff --git a/src/main/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalService.java b/src/main/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalService.java index 45694ac..34e6cbe 100644 --- a/src/main/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalService.java +++ b/src/main/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalService.java @@ -93,27 +93,26 @@ public class WatermarkRemovalService { Map> formObjectsAndImagesForPages = new HashMap<>(); Set visitedXObjIds = new TreeSet<>(); - ElementReader reader = new ElementReader(); + try(ElementReader reader = new ElementReader()) { - for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { + for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { - Page page = iterator.next(); + Page page = iterator.next(); - double minAreaCoveringFromPage = AREA_THRESHOLD * page.getPageHeight() * page.getPageWidth(); + double minAreaCoveringFromPage = AREA_THRESHOLD * page.getPageHeight() * page.getPageWidth(); - LinkedList elementFeaturesLinkedList = new LinkedList<>(); + LinkedList elementFeaturesLinkedList = new LinkedList<>(); - reader.begin(page); - for (Element element = reader.next(); element != null; element = reader.next()) { - processElement(element, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringFromPage, page); + reader.begin(page); + for (Element element = reader.next(); element != null; element = reader.next()) { + processElement(element, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringFromPage, page); + } + + formObjectsAndImagesForPages.put(page.getSDFObj().getObjNum(), elementFeaturesLinkedList); } - formObjectsAndImagesForPages.put(page.getSDFObj().getObjNum(), elementFeaturesLinkedList); + return formObjectsAndImagesForPages; } - - reader.destroy(); - - return formObjectsAndImagesForPages; } @@ -220,13 +219,13 @@ public class WatermarkRemovalService { } if (visitedXObjIds.add(element.getXObject().getObjNum())) { - ElementReader xObjectReader = new ElementReader(); - xObjectReader.begin(element.getXObject()); - for (Element element1 = xObjectReader.next(); element1 != null; element1 = xObjectReader.next()) { - processElement(element1, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringPage, page); + try(ElementReader xObjectReader = new ElementReader()) { + xObjectReader.begin(element.getXObject()); + for (Element element1 = xObjectReader.next(); element1 != null; element1 = xObjectReader.next()) { + processElement(element1, visitedXObjIds, elementFeaturesLinkedList, formObjectsOccuringMoreThanOnceOnAPage, minAreaCoveringPage, page); + } + elementFeaturesLinkedList.add(ElementFeatureFactory.extractFeatures(element)); } - elementFeaturesLinkedList.add(ElementFeatureFactory.extractFeatures(element)); - xObjectReader.destroy(); } else { elementFeaturesLinkedList.add(ElementFeatureFactory.extractFeatures(element)); } @@ -256,21 +255,17 @@ public class WatermarkRemovalService { @SneakyThrows private void removeAllWatermarks(PDFDoc pdfDoc, List watermarksElementFeaturesList) { - ElementReader reader = new ElementReader(); - ElementWriter writer = new ElementWriter(); - Set visitedXObjIds = new TreeSet<>(); + try(ElementReader reader = new ElementReader(); + ElementWriter writer = new ElementWriter()) { + Set visitedXObjIds = new TreeSet<>(); - for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { + for (PageIterator iterator = pdfDoc.getPageIterator(); iterator.hasNext(); ) { - Page page = iterator.next(); - - writeAllElementsExceptWatermarks(page, reader, writer, watermarksElementFeaturesList, visitedXObjIds); + Page page = iterator.next(); + writeAllElementsExceptWatermarks(page, reader, writer, watermarksElementFeaturesList, visitedXObjIds); + } } - - reader.destroy(); - writer.destroy(); - } @@ -390,17 +385,17 @@ public class WatermarkRemovalService { visitedXObjIds.add(element.getXObject().getObjNum()); // writer needs to be newly initialized when entering a new content stream // see ElementEditTest in PDFTron (https://www.pdftron.com/documentation/samples/android/java/ElementEditTest) - ElementWriter formWriter = new ElementWriter(); - reader.formBegin(); - formWriter.begin(element.getXObject()); + try(ElementWriter formWriter = new ElementWriter()) { + reader.formBegin(); + formWriter.begin(element.getXObject()); - reader.clearChangeList(); - formWriter.setDefaultGState(reader); + reader.clearChangeList(); + formWriter.setDefaultGState(reader); - processElements(page, reader, formWriter, watermarksElementFeaturesList, visitedXObjIds); - formWriter.end(); - formWriter.destroy(); - reader.end(); + processElements(page, reader, formWriter, watermarksElementFeaturesList, visitedXObjIds); + formWriter.end(); + reader.end(); + } } } diff --git a/src/test/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalServiceTest.java b/src/test/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalServiceTest.java index 135385b..760d14b 100644 --- a/src/test/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalServiceTest.java +++ b/src/test/java/com/iqser/red/pdftronlogic/commons/InvisibleElementRemovalServiceTest.java @@ -13,6 +13,7 @@ import com.pdftron.pdf.PDFNet; import lombok.SneakyThrows; +@SuppressWarnings("PMD") class InvisibleElementRemovalServiceTest { InvisibleElementRemovalService invisibleElementRemovalService; diff --git a/src/test/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalServiceTest.java b/src/test/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalServiceTest.java index 6755ab1..2f94a3e 100644 --- a/src/test/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalServiceTest.java +++ b/src/test/java/com/iqser/red/pdftronlogic/commons/WatermarkRemovalServiceTest.java @@ -13,6 +13,7 @@ import com.pdftron.pdf.PDFNet; import lombok.SneakyThrows; @Disabled +@SuppressWarnings("PMD") class WatermarkRemovalServiceTest { @SneakyThrows