From 6b7b61344aed4d8b3f1922732795ae018503d4b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jari-Matti=20M=C3=A4kel=C3=A4?= <jmjmak@utu.fi>
Date: Mon, 1 Jul 2024 16:11:39 +0300
Subject: [PATCH] Update deployment and package versions

---
 .gitlab-ci.yml                                |  14 ++-
 README.md                                     |  18 +++-
 bench/bench.R                                 |   2 +-
 ci_settings.xml                               |  16 +++
 pdfbox-benchmark/pom.xml                      |  21 +++-
 .../utu/tech/pdfbox/benchmark/MemoryUse.java  |   4 +-
 .../fi/utu/tech/pdfbox/benchmark/MyBench.java |   7 +-
 .../tech/pdfbox/bencmark}/presentation.pdf    | Bin
 pdfbox-gui/pom.xml                            |  63 +++---------
 .../java/fi/utu/tech/pdfbox/gui/Main.java     |  92 +++++++++++++++++-
 .../java/fi/utu/tech/pdfbox/gui/MainApp.java  |  90 -----------------
 pdfbox-gui/src/main/java/module-info.java     |   1 -
 .../utu/tech/pdfbox/gui}/presentation.pdf     | Bin
 pdfbox-wrapper/pom.xml                        |   4 +-
 .../utu/tech/pdfbox/controls/DocumentView.kt  |   6 +-
 .../tech/pdfbox/document/CachedDocument.kt    |   4 +-
 .../fi/utu/tech/pdfbox/document/DataSource.kt |  14 ++-
 .../fi/utu/tech/pdfbox/document/Document.kt   |  24 ++---
 .../tech/pdfbox/document/FolderDocument.kt    |  20 ++--
 .../utu/tech/pdfbox/document/PDFDocument.kt   |  24 ++---
 .../java/fi/utu/tech/pdfbox/document/Page.kt  |   2 +-
 .../fi/utu/tech/pdfbox/document/PageData.kt   |   6 +-
 .../utu/tech/pdfbox/document/RenderedPage.kt  |   6 +-
 .../utu/tech/pdfbox/utils/DirectExecutor.kt   |   3 +-
 .../java/fi/utu/tech/pdfbox/utils/Future.kt   |   3 +-
 .../java/fi/utu/tech/pdfbox/utils/LRUCache.kt |   8 +-
 pdfbox-wrapper/src/main/java/module-info.java |   1 -
 pom.xml                                       |  36 +++----
 28 files changed, 256 insertions(+), 233 deletions(-)
 create mode 100644 ci_settings.xml
 rename pdfbox-benchmark/src/main/resources/{ => fi/utu/tech/pdfbox/bencmark}/presentation.pdf (100%)
 delete mode 100644 pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/MainApp.java
 rename pdfbox-gui/src/main/resources/{ => fi/utu/tech/pdfbox/gui}/presentation.pdf (100%)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2430ca6..85c680f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: maven:latest
+image: maven:3.9.6-eclipse-temurin-22
 
 variables:
   # This will supress any download for dependencies and plugins or upload messages which would clutter the console log.
@@ -14,6 +14,11 @@ cache:
   paths:
     - .m2/repository
 
+stages:
+  - build
+  - test
+  - deploy
+
 build:
   stage: build
   script:
@@ -23,3 +28,10 @@ test:
   stage: test
   script:
     - mvn test
+
+deploy:
+  stage: deploy
+  rules:
+    - if: $CI_COMMIT_TAG
+  script:
+    - mvn deploy -s ci_settings.xml
diff --git a/README.md b/README.md
index a91bb66..d17f28e 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ additionally provides a simple LRU cache.
 
 Note: Possibly inefficient for large (1000+ pages)
 and complex documents, because the document is
-reparsed after each non-cached page request.
+parsed again after each non-cached page request.
 
 ## Classes
 
@@ -39,6 +39,7 @@ helper classes
 
 ## Setup
 
+Project repository
 ```xml
 <repositories>
     <repository>
@@ -47,16 +48,29 @@ helper classes
         <url>https://ftdev.utu.fi/maven2</url>
     </repository>
 </repositories>
+```
+
+Project dependency:
 
+```xml
 <dependencies>
     <dependency>
         <groupId>fi.utu.tech</groupId>
         <artifactId>pdfbox-wrapper</artifactId>
-        <version>1.0.0</version>
+        <version>1.1.0</version>
     </dependency>
 </dependencies>
 ```
 
+Module imports
+
+```java
+module demo {
+  requires transitive javafx.controls;
+  requires fi.utu.tech.pdfbox;
+}
+```
+
 ## Example
 
 ```kotlin
diff --git a/bench/bench.R b/bench/bench.R
index 0b4ba16..6d8e36d 100755
--- a/bench/bench.R
+++ b/bench/bench.R
@@ -12,7 +12,7 @@ runBenchmarks = any(is.element(args, "generate"))
 # generates the result file with t threads, results the data frame
 benchRun = function(n, t) {
   if (runBenchmarks) {
-    cmd = paste("java -jar pdfbox-benchmark/target/pdfbox-benchmark-1.0.2.jar", opts, "-t", t, "-rff", n)
+    cmd = paste("java -jar pdfbox-benchmark/target/pdfbox-benchmark-1.1.0.jar", opts, "-t", t, "-rff", n)
     print(cmd)
     system(cmd)
   }
diff --git a/ci_settings.xml b/ci_settings.xml
new file mode 100644
index 0000000..59c8c27
--- /dev/null
+++ b/ci_settings.xml
@@ -0,0 +1,16 @@
+<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+  <servers>
+    <server>
+      <id>gitlab-maven</id>
+      <configuration>
+        <httpHeaders>
+          <property>
+            <name>Job-Token</name>
+            <value>${env.CI_JOB_TOKEN}</value>
+          </property>
+        </httpHeaders>
+      </configuration>
+    </server>
+  </servers>
+</settings>
diff --git a/pdfbox-benchmark/pom.xml b/pdfbox-benchmark/pom.xml
index e18d8e6..4d61a69 100644
--- a/pdfbox-benchmark/pom.xml
+++ b/pdfbox-benchmark/pom.xml
@@ -2,18 +2,18 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <artifactId>pdfbox-benchmark</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>1.1.0</version>
     <packaging>jar</packaging>
 
     <properties>
         <project.mainclass>org.openjdk.jmh.Main</project.mainclass>
-        <jmh.version>1.23</jmh.version>
+        <jmh.version>1.37</jmh.version>
     </properties>
 
     <parent>
         <groupId>fi.utu.tech</groupId>
         <artifactId>pdfbox-suite</artifactId>
-        <version>1.0.2</version>
+        <version>1.1.0</version>
     </parent>
 
     <dependencies>
@@ -36,7 +36,13 @@
         <dependency>
             <groupId>com.github.jbellis</groupId>
             <artifactId>jamm</artifactId>
-            <version>0.3.3</version>
+            <version>0.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>pdfbox</artifactId>
+            <version>3.0.2</version>
+            <scope>compile</scope>
         </dependency>
     </dependencies>
 
@@ -104,4 +110,11 @@
 
         </plugins>
     </build>
+    <repositories>
+        <repository>
+            <id>maven_central</id>
+            <name>Maven Central</name>
+            <url>https://repo.maven.apache.org/maven2/</url>
+        </repository>
+    </repositories>
 </project>
diff --git a/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MemoryUse.java b/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MemoryUse.java
index 18a17f5..bb4e490 100644
--- a/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MemoryUse.java
+++ b/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MemoryUse.java
@@ -5,7 +5,7 @@ import org.github.jamm.MemoryMeter;
 import java.io.IOException;
 
 public class MemoryUse {
-    static final MemoryMeter meter = new MemoryMeter();
+    static final MemoryMeter meter = MemoryMeter.builder().build();
 
     static void analyze(Object o) {
         try {
@@ -13,7 +13,7 @@ public class MemoryUse {
             System.out.println("Measuring the contents of [" + o.getClass().getCanonicalName() + "]");
             System.out.println("Shallow memory consumption: " + m + " bytes.");
             System.out.println("Deep    memory consumption: " + m2 + " bytes.");
-            System.out.println("Number of child objects   : " + meter.countChildren(o));
+            //System.out.println("Number of child objects   : " + meter.countChildren(o));
         } catch (IllegalStateException e) {
             System.err.println();
             System.err.println("If you are starting the app from an IDE, remember to");
diff --git a/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MyBench.java b/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MyBench.java
index a458cba..bebc975 100644
--- a/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MyBench.java
+++ b/pdfbox-benchmark/src/main/java/fi/utu/tech/pdfbox/benchmark/MyBench.java
@@ -1,5 +1,6 @@
 package fi.utu.tech.pdfbox.benchmark;
 
+import org.apache.pdfbox.Loader;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
@@ -12,7 +13,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 
 public class MyBench {
-    static final byte[] file = readBytes("/presentation.pdf");
+    static final byte[] file = readBytes("presentation.pdf");
 
     static final int width = 1920;
     static final int height = 1080;
@@ -29,7 +30,7 @@ public class MyBench {
     static public ArrayList<BufferedImage> renderIterator() throws IOException {
         ArrayList<BufferedImage> images = new ArrayList<>();
 
-        try (PDDocument document = PDDocument.load(file)) {
+        try (PDDocument document = Loader.loadPDF(file)) {
             PDFRenderer pdfRenderer = new PDFRenderer(document);
             int pageCounter = 0;
             for (PDPage page : document.getPages()) {
@@ -55,7 +56,7 @@ public class MyBench {
     static public ArrayList<BufferedImage> renderSeparately() throws IOException {
         ArrayList<BufferedImage> images = new ArrayList<>();
 
-        try (PDDocument document = PDDocument.load(file)) {
+        try (PDDocument document = Loader.loadPDF(file)) {
             PDFRenderer pdfRenderer = new PDFRenderer(document);
             int pageCounter = 0;
             for (int i = 0; i < document.getNumberOfPages(); i++) {
diff --git a/pdfbox-benchmark/src/main/resources/presentation.pdf b/pdfbox-benchmark/src/main/resources/fi/utu/tech/pdfbox/bencmark/presentation.pdf
similarity index 100%
rename from pdfbox-benchmark/src/main/resources/presentation.pdf
rename to pdfbox-benchmark/src/main/resources/fi/utu/tech/pdfbox/bencmark/presentation.pdf
diff --git a/pdfbox-gui/pom.xml b/pdfbox-gui/pom.xml
index 770590b..6718319 100644
--- a/pdfbox-gui/pom.xml
+++ b/pdfbox-gui/pom.xml
@@ -2,17 +2,19 @@
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <artifactId>pdfbox-gui</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>1.1.0</version>
     <packaging>jar</packaging>
 
     <properties>
         <project.mainclass>fi.utu.tech.pdfbox.gui.Main</project.mainclass>
+        <project.mainmodule>fi.utu.tech.pdfbox.gui</project.mainmodule>
+        <project.launcher>pdfbox</project.launcher>
     </properties>
 
     <parent>
         <groupId>fi.utu.tech</groupId>
         <artifactId>pdfbox-suite</artifactId>
-        <version>1.0.2</version>
+        <version>1.1.0</version>
     </parent>
 
     <dependencies>
@@ -35,56 +37,17 @@
 
     <build>
         <plugins>
-            <!-- Make a 'fat' jar, that is, jar that contains all its dependencies and runs as is.
-                 See: https://stackoverflow.com/a/57691362 -->
             <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-shade-plugin</artifactId>
-                <version>3.2.4</version>
-                <executions>
-                    <execution>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>shade</goal>
-                        </goals>
-                        <configuration>
-                            <createDependencyReducedPom>false</createDependencyReducedPom>
-                            <filters>
-                                <filter>
-                                    <artifact>*:*</artifact>
-                                    <excludes>
-                                        <exclude>module-info.class</exclude>
-                                        <exclude>META-INF/*.SF</exclude>
-                                        <exclude>META-INF/*.DSA</exclude>
-                                        <exclude>META-INF/*.RSA</exclude>
-                                    </excludes>
-                                </filter>
-                            </filters>
-                            <transformers>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
-                                    <mainClass>${project.mainclass}</mainClass>
-                                </transformer>
-                            </transformers>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <!-- Run this app with exec:java -->
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <version>3.0.0</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>java</goal>
-                        </goals>
-                    </execution>
-                </executions>
+                <groupId>org.openjfx</groupId>
+                <artifactId>javafx-maven-plugin</artifactId>
+                <version>0.0.8</version>
                 <configuration>
-                    <skip>false</skip>
-                    <mainClass>${project.mainclass}</mainClass>
+                    <mainClass>${project.mainmodule}/${project.mainclass}</mainClass>
+                    <stripDebug>true</stripDebug>
+                    <compress>2</compress>
+                    <noHeaderFiles>true</noHeaderFiles>
+                    <noManPages>true</noManPages>
+                    <launcher>${project.launcher}</launcher>
                 </configuration>
             </plugin>
         </plugins>
diff --git a/pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/Main.java b/pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/Main.java
index 2e82e65..79bfd7a 100644
--- a/pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/Main.java
+++ b/pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/Main.java
@@ -1,7 +1,95 @@
 package fi.utu.tech.pdfbox.gui;
 
-public class Main {
+import fi.utu.tech.pdfbox.controls.DocumentView;
+import fi.utu.tech.pdfbox.document.*;
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.beans.binding.Bindings;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.FlowPane;
+import javafx.stage.FileChooser;
+import javafx.stage.Screen;
+import javafx.stage.Stage;
+
+import java.io.File;
+import java.util.function.Consumer;
+
+public class Main extends Application {
+    final DocumentView view = new DocumentView();
+
+    void setDoc(DataSource src) {
+        view.getDocumentProperty().set(
+                new CachedDocument(new PDFDocument((int) view.getFitWidth() * 2, (int) view.getFitHeight() * 2, src, null), 3)
+        );
+    }
+
+    void openFile() {
+        singleFileDialog("Select PDF file", "PDF file", "pdf", false, f ->
+                setDoc(new FileSource(f))
+        );
+    }
+
+    public void singleFileDialog(String title, String type, String ext, boolean saveDialog, Consumer<File> handler) {
+        FileChooser chooser = new FileChooser();
+        chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(type + " (." + ext + ")", "*." + ext));
+        chooser.setTitle(title);
+        File selected;
+        if (saveDialog) {
+            selected = chooser.showSaveDialog(null);
+            if (selected == null) return;
+            String file = selected.getAbsolutePath();
+            if (!file.endsWith("." + ext))
+                file += "." + ext;
+            selected = new File(file);
+        } else {
+            selected = chooser.showOpenDialog(null);
+        }
+        if (selected == null) return;
+        handler.accept(selected);
+    }
+
+    @Override
+    public void start(Stage stage) {
+        var prev = new Button("Previous");
+        prev.setOnAction(e -> view.prev());
+
+        var next = new Button("Next");
+        next.setOnAction(e -> view.next());
+
+        var open = new Button("Open");
+        open.setOnAction(e -> openFile());
+
+        var exit = new Button("Exit");
+        exit.setOnAction(e -> Platform.exit());
+
+        var pages = new Label();
+        pages.textProperty().bind(Bindings.concat(
+                "Page ", view.getPageProperty(), " / ", view.getPageCountProperty()
+        ));
+
+        var pane = new BorderPane(view);
+        var controls = new FlowPane(prev, next, open, exit, pages);
+        pane.setBottom(controls);
+        view.fitWidthProperty().bind(pane.widthProperty());
+        view.fitHeightProperty().bind(pane.heightProperty().subtract(controls.heightProperty()));
+        view.setPreserveRatio(true);
+
+        stage.setTitle("PDF viewer");
+        stage.setScene(new Scene(pane));
+        var screen = Screen.getScreens().get(0).getBounds();
+        stage.setWidth(screen.getWidth() * 2 / 3);
+        stage.setHeight(screen.getHeight() * 2 / 3);
+        stage.show();
+
+        var loader = new ResourceSource("presentation.pdf") {
+        };
+        setDoc(loader);
+    }
+
     public static void main(String[] args) {
-        MainApp.launch(MainApp.class, args);
+        Main.launch(Main.class, args);
     }
 }
diff --git a/pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/MainApp.java b/pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/MainApp.java
deleted file mode 100644
index b832bb9..0000000
--- a/pdfbox-gui/src/main/java/fi/utu/tech/pdfbox/gui/MainApp.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package fi.utu.tech.pdfbox.gui;
-
-import fi.utu.tech.pdfbox.controls.DocumentView;
-import fi.utu.tech.pdfbox.document.*;
-import javafx.application.Application;
-import javafx.application.Platform;
-import javafx.beans.binding.Bindings;
-import javafx.scene.Scene;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.layout.BorderPane;
-import javafx.scene.layout.FlowPane;
-import javafx.stage.FileChooser;
-import javafx.stage.Screen;
-import javafx.stage.Stage;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.function.Consumer;
-
-public class MainApp extends Application {
-    DocumentView view = new DocumentView();
-
-    void setDoc(DataSource src) {
-        view.getDocumentProperty().set(
-                new CachedDocument(new PDFDocument((int) view.getFitWidth() * 2, (int) view.getFitHeight() * 2, src, null), 3)
-        );
-    }
-
-    void openFile() {
-        singleFileDialog("Select PDF file", "PDF file", "pdf", false, f ->
-                setDoc(new FileSource(f))
-        );
-    }
-
-    public void singleFileDialog(String title, String type, String ext, boolean saveDialog, Consumer<File> handler) {
-        FileChooser chooser = new FileChooser();
-        chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(type + " (." + ext + ")", "*." + ext));
-        chooser.setTitle(title);
-        File selected;
-        if (saveDialog) {
-            selected = chooser.showSaveDialog(null);
-            if (selected == null) return;
-            String file = selected.getAbsolutePath();
-            if (!file.endsWith("." + ext))
-                file += "." + ext;
-            selected = new File(file);
-        } else {
-            selected = chooser.showOpenDialog(null);
-        }
-        if (selected == null) return;
-        handler.accept(selected);
-    }
-
-    @Override
-    public void start(Stage stage) throws IOException {
-        var prev = new Button("Previous");
-        prev.setOnAction(e -> view.prev());
-
-        var next = new Button("Next");
-        next.setOnAction(e -> view.next());
-
-        var open = new Button("Open");
-        open.setOnAction(e -> openFile());
-
-        var exit = new Button("Exit");
-        exit.setOnAction(e -> Platform.exit());
-
-        var pages = new Label();
-        pages.textProperty().bind(Bindings.concat(
-                "Page ", view.getPageProperty(), " / ", view.getPageCountProperty()
-        ));
-
-        var pane = new BorderPane(view);
-        var controls = new FlowPane(prev, next, open, exit, pages);
-        pane.setBottom(controls);
-        view.fitWidthProperty().bind(pane.widthProperty());
-        view.fitHeightProperty().bind(pane.heightProperty().subtract(controls.heightProperty()));
-        view.setPreserveRatio(true);
-
-        stage.setTitle("PDF viewer");
-        stage.setScene(new Scene(pane));
-        var screen = Screen.getScreens().get(0).getBounds();
-        stage.setWidth(screen.getWidth() * 2 / 3);
-        stage.setHeight(screen.getHeight() * 2 / 3);
-        stage.show();
-
-        setDoc(new ResourceSource("/presentation.pdf"));
-    }
-}
diff --git a/pdfbox-gui/src/main/java/module-info.java b/pdfbox-gui/src/main/java/module-info.java
index 5e59602..2ad1b51 100644
--- a/pdfbox-gui/src/main/java/module-info.java
+++ b/pdfbox-gui/src/main/java/module-info.java
@@ -1,5 +1,4 @@
 module fi.utu.tech.pdfbox.gui {
-  requires transitive javafx.base;
   requires transitive javafx.controls;
   requires fi.utu.tech.pdfbox;
   exports fi.utu.tech.pdfbox.gui;
diff --git a/pdfbox-gui/src/main/resources/presentation.pdf b/pdfbox-gui/src/main/resources/fi/utu/tech/pdfbox/gui/presentation.pdf
similarity index 100%
rename from pdfbox-gui/src/main/resources/presentation.pdf
rename to pdfbox-gui/src/main/resources/fi/utu/tech/pdfbox/gui/presentation.pdf
diff --git a/pdfbox-wrapper/pom.xml b/pdfbox-wrapper/pom.xml
index 9c9e052..591c30f 100644
--- a/pdfbox-wrapper/pom.xml
+++ b/pdfbox-wrapper/pom.xml
@@ -2,13 +2,13 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <artifactId>pdfbox-wrapper</artifactId>
-    <version>1.0.2</version>
+    <version>1.1.0</version>
     <packaging>jar</packaging>
 
     <parent>
         <groupId>fi.utu.tech</groupId>
         <artifactId>pdfbox-suite</artifactId>
-        <version>1.0.2</version>
+        <version>1.1.0</version>
     </parent>
 
     <dependencies>
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/controls/DocumentView.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/controls/DocumentView.kt
index d0d0c66..a0b6cb4 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/controls/DocumentView.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/controls/DocumentView.kt
@@ -7,6 +7,8 @@ import javafx.beans.Observable
 import javafx.beans.property.SimpleIntegerProperty
 import javafx.beans.property.SimpleObjectProperty
 import javafx.scene.image.ImageView
+import kotlin.math.max
+import kotlin.math.min
 
 open class DocumentView : ImageView {
     val documentProperty = SimpleObjectProperty<Document>()
@@ -24,13 +26,13 @@ open class DocumentView : ImageView {
 
     fun next() {
         documentProperty.get()?.let {
-            pageProperty.set(Math.min(it.pageCount(), pageProperty.get() + 1))
+            pageProperty.set(min(it.pageCount(), pageProperty.get() + 1))
         }
     }
 
     fun prev() {
         documentProperty.get()?.let {
-            pageProperty.set(Math.max(0, pageProperty.get() - 1))
+            pageProperty.set(max(0, pageProperty.get() - 1))
         }
     }
 
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/CachedDocument.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/CachedDocument.kt
index 2780a3f..c27321b 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/CachedDocument.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/CachedDocument.kt
@@ -2,8 +2,8 @@ package fi.utu.tech.pdfbox.document
 
 import fi.utu.tech.pdfbox.utils.LRUCache
 
-class CachedDocument(val document: Document, cacheSize: Int) :
-        Document(document.requestWidth, document.requestWidth) {
+open class CachedDocument(val document: Document, cacheSize: Int) :
+    Document(document.requestWidth, document.requestWidth) {
     private val cache = LRUCache<Int, PageData>(cacheSize)
 
     override fun refresh() {
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/DataSource.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/DataSource.kt
index d692276..e3c915f 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/DataSource.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/DataSource.kt
@@ -1,6 +1,7 @@
 package fi.utu.tech.pdfbox.document
 
 import java.io.File
+import java.io.IOException
 import java.nio.file.Files
 import java.nio.file.Path
 import java.nio.file.Paths
@@ -9,14 +10,19 @@ abstract class DataSource {
     abstract fun load(): ByteArray
 }
 
-data class FileSource(val path: Path) : DataSource() {
+open class FileSource(val path: Path) : DataSource() {
     constructor(path: String) : this(Paths.get(path))
 
     constructor(file: File) : this(file.toPath())
 
-    override fun load() = Files.readAllBytes(path)!!
+    override fun load(): ByteArray = Files.readAllBytes(path)
 }
 
-data class ResourceSource(val path: String) : DataSource() {
-    override fun load() = javaClass.getResourceAsStream(path).readAllBytes()!!
+open class ResourceSource(val path: String) : DataSource() {
+    override fun load() = try {
+        javaClass.getResourceAsStream(path).readAllBytes()!!
+    }
+    catch (e: Exception) {
+        throw IOException("Java resource $path not found!")
+    }
 }
\ No newline at end of file
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Document.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Document.kt
index 27a1c08..562485e 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Document.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Document.kt
@@ -1,16 +1,16 @@
 package fi.utu.tech.pdfbox.document
 
 import javafx.embed.swing.SwingFXUtils
-import org.apache.pdfbox.pdmodel.PDDocument
+import org.apache.pdfbox.Loader
 import org.apache.pdfbox.rendering.ImageType
 import org.apache.pdfbox.rendering.PDFRenderer
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.Executor
 
 abstract class Document(
-        val requestWidth: Int,
-        val requestHeight: Int,
-        val executor: Executor? = null
+    val requestWidth: Int,
+    val requestHeight: Int,
+    val executor: Executor? = null
 ) {
     abstract fun documentData(pageIdx: Int): ByteArray
 
@@ -28,7 +28,7 @@ abstract class Document(
     // PDDocument.getPage docs recommend reusing the iterator for large (> 1000 pg) documents
     // presentations typically have < 100 pages
     // https://pdfbox.apache.org/docs/2.0.13/javadocs/org/apache/pdfbox/pdmodel/PDDocument.html
-    open fun renderNow(pageIdx: Int) = PDDocument.load(documentData(pageIdx)).use { document ->
+    open fun renderNow(pageIdx: Int) = Loader.loadPDF(documentData(pageIdx)).use { document ->
         val renderer = PDFRenderer(document)
 
         val renderedPageIdx = documentPage(pageIdx)
@@ -44,15 +44,15 @@ abstract class Document(
 
         val fxImage = SwingFXUtils.toFXImage(swingImage, null)
 
-        println("Requested: " + requestWidth + "x" + requestHeight)
-        println("Size:      " + widthPt + "x" + heightPt)
-        println("Got:       " + swingImage.width + "x" + swingImage.height)
-        println("Scale:     " + scale)
+        println("Requested: $requestWidth x $requestHeight")
+        println("Size:      $widthPt x $heightPt")
+        println("Got:       ${swingImage.width} x ${swingImage.height}")
+        println("Scale:     $scale")
 
         RenderedPage(
-                swingImage.width,
-                swingImage.height,
-                fxImage
+            swingImage.width,
+            swingImage.height,
+            fxImage
         )
     }
 
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/FolderDocument.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/FolderDocument.kt
index 177c98e..a87461e 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/FolderDocument.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/FolderDocument.kt
@@ -4,20 +4,19 @@ import java.io.IOException
 import java.nio.file.Files
 import java.nio.file.Path
 import java.nio.file.Paths
-import java.util.stream.Collectors
 
-class FolderDocument(
-        requestWidth: Int,
-        requestHeight: Int,
-        val rootPath: Path
+open class FolderDocument(
+    requestWidth: Int,
+    requestHeight: Int,
+    val rootPath: Path
 ) : Document(requestWidth, requestHeight) {
     constructor(
-            requestWidth: Int,
-            requestHeight: Int,
-            rootPath: String
+        requestWidth: Int,
+        requestHeight: Int,
+        rootPath: String
     ) : this(requestWidth, requestHeight, Paths.get(rootPath))
 
-    protected var directoryContents = readDirectory()
+    protected var directoryContents: List<Path> = readDirectory()
 
     override fun resize(width: Int, height: Int) = FolderDocument(width, height, rootPath)
 
@@ -26,7 +25,8 @@ class FolderDocument(
     }
 
     open fun readDirectory(): List<Path> =
-            Files.list(rootPath).collect(Collectors.toList()).filter { it.toString().toUpperCase().endsWith(".PDF") }.sortedBy { it.toString() }
+        Files.list(rootPath).toList().filter { "$it".toUpperCase().endsWith(".PDF") }
+            .sortedBy { it.toString() }
 
     override fun documentData(pageIdx: Int): ByteArray =
         Files.readAllBytes(directoryContents[pageIdx]) ?: throw IOException("Empty file")
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PDFDocument.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PDFDocument.kt
index f2289ef..eddda41 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PDFDocument.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PDFDocument.kt
@@ -1,26 +1,26 @@
 package fi.utu.tech.pdfbox.document
 
-import org.apache.pdfbox.pdmodel.PDDocument
+import org.apache.pdfbox.Loader
 import java.util.concurrent.Executor
 
-class PDFDocument(
-        requestWidth: Int,
-        requestHeight: Int,
-        private var documentData: ByteArray,
-        val source: DataSource? = null,
-        executor: Executor? = null
+open class PDFDocument(
+    requestWidth: Int,
+    requestHeight: Int,
+    private var documentData: ByteArray,
+    val source: DataSource? = null,
+    executor: Executor? = null
 ) : Document(requestWidth, requestHeight, executor) {
 
     protected var pageCount = parsePageCount()
 
     fun parsePageCount(): Int =
-            PDDocument.load(documentData).use { it.numberOfPages }
+        Loader.loadPDF(documentData).use { it.numberOfPages }
 
     constructor(
-            requestWidth: Int,
-            requestHeight: Int,
-            source: DataSource,
-            executor: Executor? = null
+        requestWidth: Int,
+        requestHeight: Int,
+        source: DataSource,
+        executor: Executor? = null
     ) : this(requestWidth, requestHeight, source.load(), source, executor)
 
     override fun refresh() {
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Page.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Page.kt
index af497bc..c7b296a 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Page.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/Page.kt
@@ -1,6 +1,6 @@
 package fi.utu.tech.pdfbox.document
 
-interface Page<X : Page<X>> : Comparable<X>{
+interface Page<X : Page<X>> : Comparable<X> {
     val pageNum: Int
 
     override fun compareTo(other: X) = pageNum.compareTo(other.pageNum)
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PageData.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PageData.kt
index 9ac1291..d23ad0a 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PageData.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/PageData.kt
@@ -3,7 +3,7 @@ package fi.utu.tech.pdfbox.document
 import java.util.concurrent.CompletableFuture
 
 data class PageData(
-        override val pageNum: Int,
-        val caption: String,
-        val rendered: CompletableFuture<RenderedPage>
+    override val pageNum: Int,
+    val caption: String,
+    val rendered: CompletableFuture<RenderedPage>
 ) : Page<PageData>
\ No newline at end of file
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/RenderedPage.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/RenderedPage.kt
index 285956a..c61ab76 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/RenderedPage.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/document/RenderedPage.kt
@@ -3,7 +3,7 @@ package fi.utu.tech.pdfbox.document
 import javafx.scene.image.WritableImage
 
 data class RenderedPage(
-        val width: Int,
-        val height: Int,
-        val image: WritableImage
+    val width: Int,
+    val height: Int,
+    val image: WritableImage
 )
\ No newline at end of file
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/DirectExecutor.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/DirectExecutor.kt
index ff61870..fe8f4ee 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/DirectExecutor.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/DirectExecutor.kt
@@ -7,9 +7,8 @@ import java.util.concurrent.ForkJoinPool
 // https://github.com/vjames19/kotlin-futures
 
 object DirectExecutor : Executor {
-    override fun execute(command: Runnable) {
+    override fun execute(command: Runnable) =
         command.run()
-    }
 }
 
 object ForkJoinExecutor : ExecutorService by ForkJoinPool.commonPool()
\ No newline at end of file
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/Future.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/Future.kt
index 04bfb82..c2dd85b 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/Future.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/Future.kt
@@ -1,5 +1,5 @@
 package fi.utu.tech.pdfbox.utils
-
+/*
 import java.util.*
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.Executor
@@ -133,3 +133,4 @@ object Future {
                 fr.zip(fa, executor) { r, a -> r.add(f(a)); r }
             }.map(executor) { it.toList() }
 }
+*/
\ No newline at end of file
diff --git a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/LRUCache.kt b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/LRUCache.kt
index 891b16a..2b60104 100644
--- a/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/LRUCache.kt
+++ b/pdfbox-wrapper/src/main/java/fi/utu/tech/pdfbox/utils/LRUCache.kt
@@ -21,10 +21,10 @@ class LRUCache<K, V>(val capacity: Int, private val onRemove: (V) -> Unit = { })
 
     //Recently accessed, hence move it to the tail
     operator fun get(key: K): V? =
-            if (queue.remove(key)) {
-                queue.add(key)
-                map[key]
-            } else null
+        if (queue.remove(key)) {
+            queue.add(key)
+            map[key]
+        } else null
 
     operator fun set(key: K, value: V) {
         val existing = map[key]
diff --git a/pdfbox-wrapper/src/main/java/module-info.java b/pdfbox-wrapper/src/main/java/module-info.java
index 44855b0..0e52727 100644
--- a/pdfbox-wrapper/src/main/java/module-info.java
+++ b/pdfbox-wrapper/src/main/java/module-info.java
@@ -1,7 +1,6 @@
 module fi.utu.tech.pdfbox {
     requires kotlin.stdlib;
     requires org.apache.pdfbox;
-    requires java.desktop;
     requires javafx.swing;
     requires transitive javafx.base;
     exports fi.utu.tech.pdfbox.document;
diff --git a/pom.xml b/pom.xml
index e50d0e7..4fbfd4f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,18 +1,17 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project>
     <modelVersion>4.0.0</modelVersion>
     <groupId>fi.utu.tech</groupId>
     <artifactId>pdfbox-suite</artifactId>
-    <version>1.0.2</version>
+    <version>1.1.0</version>
     <packaging>pom</packaging>
 
     <properties>
-        <jdk.version>11</jdk.version>
-        <kotlin.version>1.4.30</kotlin.version>
-        <javafx.version>15.0.1</javafx.version>
+        <jdk.version>17</jdk.version>
+        <kotlin.version>2.0.0</kotlin.version>
+        <javafx.version>22</javafx.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <pdfbox.version>2.0.22</pdfbox.version>
-        <pdfboxwrapper.version>1.0.2</pdfboxwrapper.version>
+        <pdfbox.version>3.0.2</pdfbox.version>
+        <pdfboxwrapper.version>1.1.0</pdfboxwrapper.version>
     </properties>
 
     <modules>
@@ -31,6 +30,11 @@
 
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.openjfx</groupId>
+                <artifactId>javafx-maven-plugin</artifactId>
+                <version>0.0.8</version>
+            </plugin>
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>exec-maven-plugin</artifactId>
@@ -85,19 +89,15 @@
                 </executions>
             </plugin>
         </plugins>
-        <extensions>
-            <extension>
-                <groupId>org.apache.maven.wagon</groupId>
-                <artifactId>wagon-ssh</artifactId>
-                <version>3.4.1</version>
-            </extension>
-        </extensions>
     </build>
     <distributionManagement>
         <repository>
-            <id>ftdev</id>
-            <name>UTU tech ftdev repository</name>
-            <url>scp://localhost:2222/var/www/maven2</url>
+            <id>gitlab-maven</id>
+            <url>${env.CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
         </repository>
+        <snapshotRepository>
+            <id>gitlab-maven</id>
+            <url>${env.CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+        </snapshotRepository>
     </distributionManagement>
 </project>
-- 
GitLab