From 9469d0aeb538cb94e27ecd64be1c98f5785fb45f Mon Sep 17 00:00:00 2001
From: Ryan Tang <84262952+ryantang247@users.noreply.github.com>
Date: Wed, 12 Mar 2025 15:58:32 +0800
Subject: [PATCH 01/12] Implemented undo and redo mechanism for drawing
signature (#3152)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Description of Changes
Please provide a summary of the changes, including:
Added undo and redo button for drawing signature, and provided
translation properties for the buttons
Closes
[#(2454)](https://github.com/Stirling-Tools/Stirling-PDF/issues/2454)
---
## Checklist
### General
- [✅](https://emojipedia.org/check-mark-button)I have read the
[Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [✅](https://emojipedia.org/check-mark-button) I have read the
[Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
-[✅](https://emojipedia.org/check-mark-button)I have read the [How to
add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [✅](https://emojipedia.org/check-mark-button) I have performed a
self-review of my own code
-[✅](https://emojipedia.org/check-mark-button) My changes generate no
new warnings
### UI Changes (if applicable)

### Testing (if applicable)
- [✅](https://emojipedia.org/check-mark-button) I have tested my changes
locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---
src/main/resources/messages_ar_AR.properties | 3 +-
src/main/resources/messages_az_AZ.properties | 3 +-
src/main/resources/messages_bg_BG.properties | 3 +-
src/main/resources/messages_ca_CA.properties | 3 +-
src/main/resources/messages_cs_CZ.properties | 3 +-
src/main/resources/messages_da_DK.properties | 3 +-
src/main/resources/messages_de_DE.properties | 3 +-
src/main/resources/messages_el_GR.properties | 3 +-
src/main/resources/messages_en_GB.properties | 3 +-
src/main/resources/messages_en_US.properties | 3 +-
src/main/resources/messages_es_ES.properties | 3 +-
src/main/resources/messages_eu_ES.properties | 3 +-
src/main/resources/messages_fa_IR.properties | 3 +-
src/main/resources/messages_fr_FR.properties | 3 +-
src/main/resources/messages_ga_IE.properties | 3 +-
src/main/resources/messages_hi_IN.properties | 3 +-
src/main/resources/messages_hr_HR.properties | 3 +-
src/main/resources/messages_hu_HU.properties | 3 +-
src/main/resources/messages_id_ID.properties | 3 +-
src/main/resources/messages_it_IT.properties | 3 +-
src/main/resources/messages_ja_JP.properties | 3 +-
src/main/resources/messages_ko_KR.properties | 3 +-
src/main/resources/messages_nl_NL.properties | 3 +-
src/main/resources/messages_no_NB.properties | 3 +-
src/main/resources/messages_pl_PL.properties | 3 +-
src/main/resources/messages_pt_BR.properties | 3 +-
src/main/resources/messages_pt_PT.properties | 3 +-
src/main/resources/messages_ro_RO.properties | 3 +-
src/main/resources/messages_ru_RU.properties | 3 +-
src/main/resources/messages_sk_SK.properties | 3 +-
src/main/resources/messages_sl_SI.properties | 3 +-
.../resources/messages_sr_LATN_RS.properties | 3 +-
src/main/resources/messages_sv_SE.properties | 3 +-
src/main/resources/messages_th_TH.properties | 3 +-
src/main/resources/messages_tr_TR.properties | 3 +-
src/main/resources/messages_uk_UA.properties | 3 +-
src/main/resources/messages_vi_VN.properties | 3 +-
src/main/resources/messages_zh_BO.properties | 3 +-
src/main/resources/messages_zh_CN.properties | 3 +-
src/main/resources/messages_zh_TW.properties | 3 +-
.../static/js/sign/signature-canvas.js | 38 +++++++++++++++++++
src/main/resources/templates/sign.html | 4 ++
42 files changed, 122 insertions(+), 40 deletions(-)
diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties
index a279ba794..037f398b2 100644
--- a/src/main/resources/messages_ar_AR.properties
+++ b/src/main/resources/messages_ar_AR.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=إصلاح
diff --git a/src/main/resources/messages_az_AZ.properties b/src/main/resources/messages_az_AZ.properties
index ae59b7c53..e46bdb51a 100644
--- a/src/main/resources/messages_az_AZ.properties
+++ b/src/main/resources/messages_az_AZ.properties
@@ -860,7 +860,8 @@ sign.last=Son səhifə
sign.next=Növbəti səhifə
sign.previous=Əvvəlki səhifə
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Bərpa Et
diff --git a/src/main/resources/messages_bg_BG.properties b/src/main/resources/messages_bg_BG.properties
index 09af7cbbf..df91050b0 100644
--- a/src/main/resources/messages_bg_BG.properties
+++ b/src/main/resources/messages_bg_BG.properties
@@ -860,7 +860,8 @@ sign.last=Последна страница
sign.next=Следваща страница
sign.previous=Предишна стараница
sign.maintainRatio=Превключване за поддържане на съотношението на страните
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Поправи
diff --git a/src/main/resources/messages_ca_CA.properties b/src/main/resources/messages_ca_CA.properties
index a7da336de..7f0b266ed 100644
--- a/src/main/resources/messages_ca_CA.properties
+++ b/src/main/resources/messages_ca_CA.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparar
diff --git a/src/main/resources/messages_cs_CZ.properties b/src/main/resources/messages_cs_CZ.properties
index ae5076197..1a3970f57 100644
--- a/src/main/resources/messages_cs_CZ.properties
+++ b/src/main/resources/messages_cs_CZ.properties
@@ -860,7 +860,8 @@ sign.last=Poslední stránka
sign.next=Další stránka
sign.previous=Předchozí stránka
sign.maintainRatio=Přepnout zachování poměru stran
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Opravit
diff --git a/src/main/resources/messages_da_DK.properties b/src/main/resources/messages_da_DK.properties
index de2a26dd5..4bf0f03a1 100644
--- a/src/main/resources/messages_da_DK.properties
+++ b/src/main/resources/messages_da_DK.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparér
diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties
index 401cff58f..6d73e5dca 100644
--- a/src/main/resources/messages_de_DE.properties
+++ b/src/main/resources/messages_de_DE.properties
@@ -860,7 +860,8 @@ sign.last=Letzte Seite
sign.next=Nächste Seite
sign.previous=Vorherige Seite
sign.maintainRatio=Seitenverhältnis beibehalten ein-/ausschalten
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparieren
diff --git a/src/main/resources/messages_el_GR.properties b/src/main/resources/messages_el_GR.properties
index 946585931..321bf7459 100644
--- a/src/main/resources/messages_el_GR.properties
+++ b/src/main/resources/messages_el_GR.properties
@@ -860,7 +860,8 @@ sign.last=Τελευταία σελίδα
sign.next=Επόμενη σελίδα
sign.previous=Προηγούμενη σελίδα
sign.maintainRatio=Εναλλαγή διατήρησης αναλογίας διαστάσεων
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Επιδιόρθωση
diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties
index 176a83707..aab945371 100644
--- a/src/main/resources/messages_en_GB.properties
+++ b/src/main/resources/messages_en_GB.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Repair
diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties
index 3a62c78e1..c5392d419 100644
--- a/src/main/resources/messages_en_US.properties
+++ b/src/main/resources/messages_en_US.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Repair
diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties
index e02031243..2e0cbc5a3 100644
--- a/src/main/resources/messages_es_ES.properties
+++ b/src/main/resources/messages_es_ES.properties
@@ -860,7 +860,8 @@ sign.last=Última página
sign.next=Siguiente página
sign.previous=Página anterior
sign.maintainRatio=Activar/desactivar la relación de aspecto
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparar
diff --git a/src/main/resources/messages_eu_ES.properties b/src/main/resources/messages_eu_ES.properties
index 00647f829..e468adec6 100644
--- a/src/main/resources/messages_eu_ES.properties
+++ b/src/main/resources/messages_eu_ES.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Konpondu
diff --git a/src/main/resources/messages_fa_IR.properties b/src/main/resources/messages_fa_IR.properties
index 035d9f0dd..bb8af5449 100644
--- a/src/main/resources/messages_fa_IR.properties
+++ b/src/main/resources/messages_fa_IR.properties
@@ -860,7 +860,8 @@ sign.last=صفحه آخر
sign.next=صفحه بعدی
sign.previous=صفحه قبلی
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=تعمیر
diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties
index 268598181..ac6a78b27 100644
--- a/src/main/resources/messages_fr_FR.properties
+++ b/src/main/resources/messages_fr_FR.properties
@@ -860,7 +860,8 @@ sign.last=Dernière page
sign.next=Page suivante
sign.previous=Page précédente
sign.maintainRatio=Conserver les proportions
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Réparer
diff --git a/src/main/resources/messages_ga_IE.properties b/src/main/resources/messages_ga_IE.properties
index aef7de862..dc0346cdb 100644
--- a/src/main/resources/messages_ga_IE.properties
+++ b/src/main/resources/messages_ga_IE.properties
@@ -860,7 +860,8 @@ sign.last=An leathanach deiridh
sign.next=An chéad leathanach eile
sign.previous=Leathanach roimhe seo
sign.maintainRatio=Scoránaigh, coinnigh an cóimheas gné
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Deisiúchán
diff --git a/src/main/resources/messages_hi_IN.properties b/src/main/resources/messages_hi_IN.properties
index 5baa3a2c3..b9d2b7ccd 100644
--- a/src/main/resources/messages_hi_IN.properties
+++ b/src/main/resources/messages_hi_IN.properties
@@ -860,7 +860,8 @@ sign.last=अंतिम पृष्ठ
sign.next=अगला पृष्ठ
sign.previous=पिछला पृष्ठ
sign.maintainRatio=आनुपातिक अनुपात बनाए रखें टॉगल करें
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=मरम्मत
diff --git a/src/main/resources/messages_hr_HR.properties b/src/main/resources/messages_hr_HR.properties
index 5751fc9bb..49b9da7bf 100644
--- a/src/main/resources/messages_hr_HR.properties
+++ b/src/main/resources/messages_hr_HR.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Popravi
diff --git a/src/main/resources/messages_hu_HU.properties b/src/main/resources/messages_hu_HU.properties
index ea365b0c8..a64e15ec0 100644
--- a/src/main/resources/messages_hu_HU.properties
+++ b/src/main/resources/messages_hu_HU.properties
@@ -860,7 +860,8 @@ sign.last=Utolsó oldal
sign.next=Következő oldal
sign.previous=Előző oldal
sign.maintainRatio=Képarány fenntartása váltása
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Javítás
diff --git a/src/main/resources/messages_id_ID.properties b/src/main/resources/messages_id_ID.properties
index 1348fb955..2c6e65b36 100644
--- a/src/main/resources/messages_id_ID.properties
+++ b/src/main/resources/messages_id_ID.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Perbaiki
diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties
index a97228139..400b1137f 100644
--- a/src/main/resources/messages_it_IT.properties
+++ b/src/main/resources/messages_it_IT.properties
@@ -860,7 +860,8 @@ sign.last=Ultima pagina
sign.next=Prossima pagina
sign.previous=Pagina precedente
sign.maintainRatio=Attiva il mantenimento delle proporzioni
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Ripara
diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties
index d0b66ea60..79ad40c19 100644
--- a/src/main/resources/messages_ja_JP.properties
+++ b/src/main/resources/messages_ja_JP.properties
@@ -860,7 +860,8 @@ sign.last=最後のページ
sign.next=次のページ
sign.previous=前のページ
sign.maintainRatio=アスペクト比を維持を切替え
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=修復
diff --git a/src/main/resources/messages_ko_KR.properties b/src/main/resources/messages_ko_KR.properties
index 0b4368e96..00e8da564 100644
--- a/src/main/resources/messages_ko_KR.properties
+++ b/src/main/resources/messages_ko_KR.properties
@@ -860,7 +860,8 @@ sign.last=마지막 페이지
sign.next=다음 페이지
sign.previous=이전 페이지
sign.maintainRatio=종횡비 유지 토글
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=복구
diff --git a/src/main/resources/messages_nl_NL.properties b/src/main/resources/messages_nl_NL.properties
index 47428ac9c..21514896b 100644
--- a/src/main/resources/messages_nl_NL.properties
+++ b/src/main/resources/messages_nl_NL.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Repareren
diff --git a/src/main/resources/messages_no_NB.properties b/src/main/resources/messages_no_NB.properties
index d33daaa47..b2a22a183 100644
--- a/src/main/resources/messages_no_NB.properties
+++ b/src/main/resources/messages_no_NB.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparer
diff --git a/src/main/resources/messages_pl_PL.properties b/src/main/resources/messages_pl_PL.properties
index 7fec27796..506bec173 100644
--- a/src/main/resources/messages_pl_PL.properties
+++ b/src/main/resources/messages_pl_PL.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Napraw
diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties
index 06bc23128..f66dc54a1 100644
--- a/src/main/resources/messages_pt_BR.properties
+++ b/src/main/resources/messages_pt_BR.properties
@@ -860,7 +860,8 @@ sign.last=Última página
sign.next=Próxima página
sign.previous=Página anterior
sign.maintainRatio=Habilitar manter proporção
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparar
diff --git a/src/main/resources/messages_pt_PT.properties b/src/main/resources/messages_pt_PT.properties
index 1f75a6e89..f83f36f65 100644
--- a/src/main/resources/messages_pt_PT.properties
+++ b/src/main/resources/messages_pt_PT.properties
@@ -860,7 +860,8 @@ sign.last=Última página
sign.next=Próxima página
sign.previous=Página anterior
sign.maintainRatio=Alternar manter proporção
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparar
diff --git a/src/main/resources/messages_ro_RO.properties b/src/main/resources/messages_ro_RO.properties
index 70ae27897..0685c95ac 100644
--- a/src/main/resources/messages_ro_RO.properties
+++ b/src/main/resources/messages_ro_RO.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Repară
diff --git a/src/main/resources/messages_ru_RU.properties b/src/main/resources/messages_ru_RU.properties
index fcb4413d5..1a9460bfc 100644
--- a/src/main/resources/messages_ru_RU.properties
+++ b/src/main/resources/messages_ru_RU.properties
@@ -860,7 +860,8 @@ sign.last=Последняя страница
sign.next=Следующая страница
sign.previous=Предыдущая страница
sign.maintainRatio=Переключить сохранение пропорций
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Восстановление
diff --git a/src/main/resources/messages_sk_SK.properties b/src/main/resources/messages_sk_SK.properties
index d7ea322ac..8e6dc085c 100644
--- a/src/main/resources/messages_sk_SK.properties
+++ b/src/main/resources/messages_sk_SK.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Opraviť
diff --git a/src/main/resources/messages_sl_SI.properties b/src/main/resources/messages_sl_SI.properties
index 870066c9c..b30b6db76 100644
--- a/src/main/resources/messages_sl_SI.properties
+++ b/src/main/resources/messages_sl_SI.properties
@@ -860,7 +860,8 @@ sign.last=Zadnja stran
sign.next=Naslednja stran
sign.previous=Prejšnja stran
sign.maintainRatio=Preklopi ohranjanje razmerja stranic
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Popravilo
diff --git a/src/main/resources/messages_sr_LATN_RS.properties b/src/main/resources/messages_sr_LATN_RS.properties
index e2db8ef6d..0a0cdfbb6 100644
--- a/src/main/resources/messages_sr_LATN_RS.properties
+++ b/src/main/resources/messages_sr_LATN_RS.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Popravi
diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties
index 21d19c2e1..6a5d6d715 100644
--- a/src/main/resources/messages_sv_SE.properties
+++ b/src/main/resources/messages_sv_SE.properties
@@ -860,7 +860,8 @@ sign.last=Sista sidan
sign.next=Nästa sida
sign.previous=Föregående sida
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Reparera
diff --git a/src/main/resources/messages_th_TH.properties b/src/main/resources/messages_th_TH.properties
index 0c4d4ff71..372f3c38e 100644
--- a/src/main/resources/messages_th_TH.properties
+++ b/src/main/resources/messages_th_TH.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=ซ่อมแซม
diff --git a/src/main/resources/messages_tr_TR.properties b/src/main/resources/messages_tr_TR.properties
index bee1c693a..adb9644df 100644
--- a/src/main/resources/messages_tr_TR.properties
+++ b/src/main/resources/messages_tr_TR.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Onar
diff --git a/src/main/resources/messages_uk_UA.properties b/src/main/resources/messages_uk_UA.properties
index f17f8a774..dcec7158a 100644
--- a/src/main/resources/messages_uk_UA.properties
+++ b/src/main/resources/messages_uk_UA.properties
@@ -860,7 +860,8 @@ sign.last=Остання сторінка
sign.next=Наступна сторінка
sign.previous=Попередня сторінка
sign.maintainRatio=Переключити збереження пропорцій
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Ремонт
diff --git a/src/main/resources/messages_vi_VN.properties b/src/main/resources/messages_vi_VN.properties
index 41daea0e3..8695969c6 100644
--- a/src/main/resources/messages_vi_VN.properties
+++ b/src/main/resources/messages_vi_VN.properties
@@ -860,7 +860,8 @@ sign.last=Last page
sign.next=Next page
sign.previous=Previous page
sign.maintainRatio=Toggle maintain aspect ratio
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=Sửa chữa
diff --git a/src/main/resources/messages_zh_BO.properties b/src/main/resources/messages_zh_BO.properties
index 41dc4335d..8e768c306 100644
--- a/src/main/resources/messages_zh_BO.properties
+++ b/src/main/resources/messages_zh_BO.properties
@@ -860,7 +860,8 @@ sign.last=ཤོག་ངོས་མཐའ་མ།
sign.next=ཤོག་ངོས་རྗེས་མ།
sign.previous=ཤོག་ངོས་སྔོན་མ།
sign.maintainRatio=བསྡུར་ཚད་རྒྱུན་འཁྱོངས་སྒོ་རྒྱག་པ།
-
+sign.undo=Undo
+sign.redo=Redo
#repair
repair.title=བཟོ་བཅོས།
diff --git a/src/main/resources/messages_zh_CN.properties b/src/main/resources/messages_zh_CN.properties
index 77c839f65..af60eabc9 100644
--- a/src/main/resources/messages_zh_CN.properties
+++ b/src/main/resources/messages_zh_CN.properties
@@ -860,7 +860,8 @@ sign.last=末页
sign.next=下一页
sign.previous=上一页
sign.maintainRatio=切换保持长宽比
-
+sign.undo=撤销
+sign.redo=重做
#repair
repair.title=修复
diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties
index e6485e7bc..6a4bd2ee2 100644
--- a/src/main/resources/messages_zh_TW.properties
+++ b/src/main/resources/messages_zh_TW.properties
@@ -860,7 +860,8 @@ sign.last=最後一頁
sign.next=下一頁
sign.previous=上一頁
sign.maintainRatio=切換維持長寬比
-
+sign.undo=撤销
+sign.redo=重做
#repair
repair.title=修復
diff --git a/src/main/resources/static/js/sign/signature-canvas.js b/src/main/resources/static/js/sign/signature-canvas.js
index 03052d9ce..bd06e8456 100644
--- a/src/main/resources/static/js/sign/signature-canvas.js
+++ b/src/main/resources/static/js/sign/signature-canvas.js
@@ -1,10 +1,48 @@
const signaturePadCanvas = document.getElementById('drawing-pad-canvas');
+const undoButton = document.getElementById("signature-undo-button");
+const redoButton = document.getElementById("signature-redo-button");
const signaturePad = new SignaturePad(signaturePadCanvas, {
minWidth: 1,
maxWidth: 2,
penColor: 'black',
});
+let undoData = [];
+
+signaturePad.addEventListener("endStroke", () => {
+ undoData = [];
+});
+
+window.addEventListener("keydown", (event) => {
+ switch (true) {
+ case event.key === "z" && event.ctrlKey:
+ undoButton.click();
+ break;
+ case event.key === "y" && event.ctrlKey:
+ redoButton.click();
+ break;
+ }
+});
+
+function undoDraw() {
+ const data = signaturePad.toData();
+
+ if (data && data.length > 0) {
+ const removed = data.pop();
+ undoData.push(removed);
+ signaturePad.fromData(data);
+ }
+}
+
+function redoDraw() {
+
+ if (undoData.length > 0) {
+ const data = signaturePad.toData();
+ data.push(undoData.pop());
+ signaturePad.fromData(data);
+ }
+}
+
function addDraggableFromPad() {
if (signaturePad.isEmpty()) return;
const startTime = Date.now();
diff --git a/src/main/resources/templates/sign.html b/src/main/resources/templates/sign.html
index 605737457..b0c66c27e 100644
--- a/src/main/resources/templates/sign.html
+++ b/src/main/resources/templates/sign.html
@@ -56,6 +56,10 @@
th:text="#{sign.clear}">
+
+
From d286cfa23d87fac1b2ea018e28c3d09ab30dd524 Mon Sep 17 00:00:00 2001
From: albanobattistella <34811668+albanobattistella@users.noreply.github.com>
Date: Wed, 12 Mar 2025 10:12:04 +0100
Subject: [PATCH 02/12] Update messages_it_IT.properties (#3166)
# Description of Changes
Please provide a summary of the changes, including:
- What was changed
- Why the change was made
- Any challenges encountered
Closes #(issue_number)
---
## Checklist
### General
- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---
src/main/resources/messages_it_IT.properties | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties
index 400b1137f..1ba2d0daf 100644
--- a/src/main/resources/messages_it_IT.properties
+++ b/src/main/resources/messages_it_IT.properties
@@ -860,8 +860,8 @@ sign.last=Ultima pagina
sign.next=Prossima pagina
sign.previous=Pagina precedente
sign.maintainRatio=Attiva il mantenimento delle proporzioni
-sign.undo=Undo
-sign.redo=Redo
+sign.undo=Annulla
+sign.redo=Rifare
#repair
repair.title=Ripara
From e4dbe7f9b04a6ad3b96cb3828c0e2deccf9dbfc9 Mon Sep 17 00:00:00 2001
From: Ludy
Date: Wed, 12 Mar 2025 13:13:44 +0100
Subject: [PATCH 03/12] Rename `CustomPDDocumentFactory` to
`CustomPDFDocumentFactory` across multiple controllers (#3163)
# Description of Changes
Please provide a summary of the changes, including:
- What was changed
- Why the change was made
- Any challenges encountered
Closes #(issue_number)
---
## Checklist
### General
- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---------
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
---
.../controller/api/AnalysisController.java | 6 ++--
.../SPDF/controller/api/CropController.java | 9 +++---
.../SPDF/controller/api/MergeController.java | 10 ++++---
.../api/MultiPageLayoutController.java | 9 +++---
.../api/PdfImageRemovalController.java | 9 +++---
.../controller/api/PdfOverlayController.java | 9 +++---
.../api/RearrangePagesPDFController.java | 15 ++++++----
.../controller/api/RotationController.java | 9 +++---
.../controller/api/ScalePagesController.java | 12 ++++----
.../controller/api/SplitPDFController.java | 11 ++++---
.../api/SplitPdfByChaptersController.java | 6 ++--
.../api/SplitPdfBySectionsController.java | 10 ++++---
.../api/SplitPdfBySizeController.java | 15 ++++++----
.../api/ToSinglePageController.java | 11 ++++---
.../api/converters/ConvertHtmlToPDF.java | 9 +++---
.../converters/ConvertImgPDFController.java | 14 +++++----
.../api/converters/ConvertMarkdownToPdf.java | 9 +++---
.../converters/ConvertOfficeController.java | 9 +++---
.../api/converters/ConvertPDFToOffice.java | 18 ++++++-----
.../api/converters/ConvertWebsiteToPDF.java | 9 +++---
.../api/converters/ExtractCSVController.java | 9 +++---
.../api/filters/FilterController.java | 6 ++--
.../api/misc/AutoRenameController.java | 9 +++---
.../api/misc/AutoSplitPdfController.java | 6 ++--
.../api/misc/BlankPageController.java | 10 ++++---
.../api/misc/CompressController.java | 24 +++++++++------
.../api/misc/DecompressPdfController.java | 6 ++--
.../api/misc/ExtractImageScansController.java | 11 ++++---
.../api/misc/ExtractImagesController.java | 10 ++++---
.../api/misc/FlattenController.java | 9 +++---
.../api/misc/MetadataController.java | 10 ++++---
.../controller/api/misc/OCRController.java | 10 ++++---
.../api/misc/OverlayImageController.java | 10 ++++---
.../api/misc/PageNumbersController.java | 9 +++---
.../controller/api/misc/RepairController.java | 10 ++++---
.../controller/api/misc/ShowJavascript.java | 6 ++--
.../controller/api/misc/StampController.java | 10 ++++---
.../api/security/CertSignController.java | 8 ++---
.../controller/api/security/GetInfoOnPDF.java | 6 ++--
.../api/security/PasswordController.java | 15 +++++-----
.../api/security/RedactController.java | 14 +++++----
.../security/RemoveCertSignController.java | 9 +++---
.../api/security/SanitizeController.java | 6 ++--
.../security/ValidateSignatureController.java | 9 +++---
.../api/security/WatermarkController.java | 10 ++++---
...ory.java => CustomPDFDocumentFactory.java} | 10 +++----
.../software/SPDF/utils/PdfUtils.java | 8 ++---
.../api/RearrangePagesPDFControllerTest.java | 30 ++++++++++---------
.../converters/ConvertWebsiteToPdfTest.java | 28 +++++++++--------
49 files changed, 301 insertions(+), 226 deletions(-)
rename src/main/java/stirling/software/SPDF/service/{CustomPDDocumentFactory.java => CustomPDFDocumentFactory.java} (98%)
diff --git a/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java
index 37941017e..2406e1168 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java
@@ -18,17 +18,17 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
@RestController
@RequestMapping("/api/v1/analysis")
@Tag(name = "Analysis", description = "Analysis APIs")
public class AnalysisController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public AnalysisController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public AnalysisController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/CropController.java b/src/main/java/stirling/software/SPDF/controller/api/CropController.java
index 68d252a47..68c3a44f3 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/CropController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/CropController.java
@@ -21,7 +21,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.general.CropPdfForm;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -29,10 +29,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class CropController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public CropController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public CropController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -40,7 +40,8 @@ public class CropController {
@Operation(
summary = "Crops a PDF document",
description =
- "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")
+ "This operation takes an input PDF file and crops it according to the given"
+ + " coordinates. Input:PDF Output:PDF Type:SISO")
public ResponseEntity cropPdf(@ModelAttribute CropPdfForm form) throws IOException {
PDDocument sourceDocument = pdfDocumentFactory.load(form);
diff --git a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java
index 8c63f817e..c95aff8fe 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java
@@ -33,7 +33,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.general.MergePdfsRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -43,10 +43,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class MergeController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public MergeController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public MergeController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -119,7 +119,9 @@ public class MergeController {
@Operation(
summary = "Merge multiple PDF files into one",
description =
- "This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided. Input:PDF Output:PDF Type:MISO")
+ "This endpoint merges multiple PDF files into a single PDF file. The merged"
+ + " file will contain all pages from the input files in the order they were"
+ + " provided. Input:PDF Output:PDF Type:MISO")
public ResponseEntity mergePdfs(@ModelAttribute MergePdfsRequest form)
throws IOException {
List filesToDelete = new ArrayList<>(); // List of temporary files to delete
diff --git a/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java b/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java
index 56d02a686..73bbe98a9 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/MultiPageLayoutController.java
@@ -24,7 +24,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.general.MergeMultiplePagesRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -32,10 +32,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class MultiPageLayoutController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public MultiPageLayoutController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public MultiPageLayoutController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -43,7 +43,8 @@ public class MultiPageLayoutController {
@Operation(
summary = "Merge multiple pages of a PDF document into a single page",
description =
- "This operation takes an input PDF file and the number of pages to merge into a single sheet in the output PDF file. Input:PDF Output:PDF Type:SISO")
+ "This operation takes an input PDF file and the number of pages to merge into a"
+ + " single sheet in the output PDF file. Input:PDF Output:PDF Type:SISO")
public ResponseEntity mergeMultiplePagesIntoOne(
@ModelAttribute MergeMultiplePagesRequest request) throws IOException {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java b/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java
index fdcb55a24..fce61d3e5 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/PdfImageRemovalController.java
@@ -15,7 +15,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.service.PdfImageRemovalService;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -31,7 +31,7 @@ public class PdfImageRemovalController {
// Service for removing images from PDFs
private final PdfImageRemovalService pdfImageRemovalService;
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
/**
* Constructor for dependency injection of PdfImageRemovalService.
@@ -41,7 +41,7 @@ public class PdfImageRemovalController {
@Autowired
public PdfImageRemovalController(
PdfImageRemovalService pdfImageRemovalService,
- CustomPDDocumentFactory pdfDocumentFactory) {
+ CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfImageRemovalService = pdfImageRemovalService;
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -61,7 +61,8 @@ public class PdfImageRemovalController {
@Operation(
summary = "Remove images from file to reduce the file size.",
description =
- "This endpoint remove images from file to reduce the file size.Input:PDF Output:PDF Type:MISO")
+ "This endpoint remove images from file to reduce the file size.Input:PDF"
+ + " Output:PDF Type:MISO")
public ResponseEntity removeImages(@ModelAttribute PDFFile file) throws IOException {
// Load the PDF document
PDDocument document = pdfDocumentFactory.load(file);
diff --git a/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java b/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java
index 7ff17ccb5..996ed45bb 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/PdfOverlayController.java
@@ -26,7 +26,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.general.OverlayPdfsRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -35,10 +35,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class PdfOverlayController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public PdfOverlayController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public PdfOverlayController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -46,7 +46,8 @@ public class PdfOverlayController {
@Operation(
summary = "Overlay PDF files in various modes",
description =
- "Overlay PDF files onto a base PDF with different modes: Sequential, Interleaved, or Fixed Repeat. Input:PDF Output:PDF Type:MIMO")
+ "Overlay PDF files onto a base PDF with different modes: Sequential,"
+ + " Interleaved, or Fixed Repeat. Input:PDF Output:PDF Type:MIMO")
public ResponseEntity overlayPdfs(@ModelAttribute OverlayPdfsRequest request)
throws IOException {
MultipartFile baseFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java
index 09f8afe9c..342d3cb8b 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java
@@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.SortTypes;
import stirling.software.SPDF.model.api.PDFWithPageNums;
import stirling.software.SPDF.model.api.general.RearrangePagesRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -34,10 +34,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class RearrangePagesPDFController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public RearrangePagesPDFController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public RearrangePagesPDFController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -45,7 +45,9 @@ public class RearrangePagesPDFController {
@Operation(
summary = "Remove pages from a PDF file",
description =
- "This endpoint removes specified pages from a given PDF file. Users can provide a comma-separated list of page numbers or ranges to delete. Input:PDF Output:PDF Type:SISO")
+ "This endpoint removes specified pages from a given PDF file. Users can provide"
+ + " a comma-separated list of page numbers or ranges to delete. Input:PDF"
+ + " Output:PDF Type:SISO")
public ResponseEntity deletePages(@ModelAttribute PDFWithPageNums request)
throws IOException {
@@ -242,7 +244,10 @@ public class RearrangePagesPDFController {
@Operation(
summary = "Rearrange pages in a PDF file",
description =
- "This endpoint rearranges pages in a given PDF file based on the specified page order or custom mode. Users can provide a page order as a comma-separated list of page numbers or page ranges, or a custom mode. Input:PDF Output:PDF")
+ "This endpoint rearranges pages in a given PDF file based on the specified page"
+ + " order or custom mode. Users can provide a page order as a"
+ + " comma-separated list of page numbers or page ranges, or a custom mode."
+ + " Input:PDF Output:PDF")
public ResponseEntity rearrangePages(@ModelAttribute RearrangePagesRequest request)
throws IOException {
MultipartFile pdfFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/RotationController.java b/src/main/java/stirling/software/SPDF/controller/api/RotationController.java
index 9ffc61b65..41891c7f5 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/RotationController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/RotationController.java
@@ -18,7 +18,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.general.RotatePDFRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -26,10 +26,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class RotationController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public RotationController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public RotationController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -37,7 +37,8 @@ public class RotationController {
@Operation(
summary = "Rotate a PDF file",
description =
- "This endpoint rotates a given PDF file by a specified angle. The angle must be a multiple of 90. Input:PDF Output:PDF Type:SISO")
+ "This endpoint rotates a given PDF file by a specified angle. The angle must be"
+ + " a multiple of 90. Input:PDF Output:PDF Type:SISO")
public ResponseEntity rotatePDF(@ModelAttribute RotatePDFRequest request)
throws IOException {
MultipartFile pdfFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java b/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java
index 5fb62cafc..48e3c0f44 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/ScalePagesController.java
@@ -25,7 +25,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.general.ScalePagesRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -33,10 +33,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class ScalePagesController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ScalePagesController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ScalePagesController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -44,7 +44,8 @@ public class ScalePagesController {
@Operation(
summary = "Change the size of a PDF page/document",
description =
- "This operation takes an input PDF file and the size to scale the pages to in the output PDF file. Input:PDF Output:PDF Type:SISO")
+ "This operation takes an input PDF file and the size to scale the pages to in"
+ + " the output PDF file. Input:PDF Output:PDF Type:SISO")
public ResponseEntity scalePages(@ModelAttribute ScalePagesRequest request)
throws IOException {
MultipartFile file = request.getFileInput();
@@ -123,7 +124,8 @@ public class ScalePagesController {
}
throw new IllegalArgumentException(
- "Invalid PDRectangle. It must be one of the following: A0, A1, A2, A3, A4, A5, A6, LETTER, LEGAL, KEEP");
+ "Invalid PDRectangle. It must be one of the following: A0, A1, A2, A3, A4, A5, A6,"
+ + " LETTER, LEGAL, KEEP");
}
private Map getSizeMap() {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java
index d0df4ced5..696482b63 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java
@@ -28,7 +28,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.PDFWithPageNums;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -37,10 +37,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class SplitPDFController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public SplitPDFController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public SplitPDFController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -48,7 +48,10 @@ public class SplitPDFController {
@Operation(
summary = "Split a PDF file into separate documents",
description =
- "This endpoint splits a given PDF file into separate documents based on the specified page numbers or ranges. Users can specify pages using individual numbers, ranges, or 'all' for every page. Input:PDF Output:PDF Type:SIMO")
+ "This endpoint splits a given PDF file into separate documents based on the"
+ + " specified page numbers or ranges. Users can specify pages using"
+ + " individual numbers, ranges, or 'all' for every page. Input:PDF"
+ + " Output:PDF Type:SIMO")
public ResponseEntity splitPdf(@ModelAttribute PDFWithPageNums request)
throws IOException {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java
index b774d3ced..698e2b50e 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfByChaptersController.java
@@ -33,7 +33,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.PdfMetadata;
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.service.PdfMetadataService;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -45,11 +45,11 @@ public class SplitPdfByChaptersController {
private final PdfMetadataService pdfMetadataService;
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
public SplitPdfByChaptersController(
- PdfMetadataService pdfMetadataService, CustomPDDocumentFactory pdfDocumentFactory) {
+ PdfMetadataService pdfMetadataService, CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfMetadataService = pdfMetadataService;
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java
index 2a692cbca..83f0cb0e9 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java
@@ -31,7 +31,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -39,10 +39,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class SplitPdfBySectionsController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public SplitPdfBySectionsController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public SplitPdfBySectionsController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -50,7 +50,9 @@ public class SplitPdfBySectionsController {
@Operation(
summary = "Split PDF pages into smaller sections",
description =
- "Split each page of a PDF into smaller sections based on the user's choice (halves, thirds, quarters, etc.), both vertically and horizontally. Input:PDF Output:ZIP-PDF Type:SISO")
+ "Split each page of a PDF into smaller sections based on the user's choice"
+ + " (halves, thirds, quarters, etc.), both vertically and horizontally."
+ + " Input:PDF Output:ZIP-PDF Type:SISO")
public ResponseEntity splitPdf(@ModelAttribute SplitPdfBySectionsRequest request)
throws Exception {
List splitDocumentsBoas = new ArrayList<>();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java
index ee73cbb89..4ec2bd361 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java
@@ -25,7 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -35,22 +35,25 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class SplitPdfBySizeController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public SplitPdfBySizeController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public SplitPdfBySizeController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
log.info(
"SplitPdfBySizeController initialized with pdfDocumentFactory: {}",
- pdfDocumentFactory);
+ pdfDocumentFactory.getClass().getSimpleName());
}
@PostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data")
@Operation(
summary = "Auto split PDF pages into separate documents based on size or count",
description =
- "split PDF into multiple paged documents based on size/count, ie if 20 pages and split into 5, it does 5 documents each 4 pages\r\n"
- + " if 10MB and each page is 1MB and you enter 2MB then 5 docs each 2MB (rounded so that it accepts 1.9MB but not 2.1MB) Input:PDF Output:ZIP-PDF Type:SISO")
+ "split PDF into multiple paged documents based on size/count, ie if 20 pages"
+ + " and split into 5, it does 5 documents each 4 pages\r\n"
+ + " if 10MB and each page is 1MB and you enter 2MB then 5 docs each 2MB"
+ + " (rounded so that it accepts 1.9MB but not 2.1MB) Input:PDF"
+ + " Output:ZIP-PDF Type:SISO")
public ResponseEntity autoSplitPdf(@ModelAttribute SplitPdfBySizeOrCountRequest request)
throws Exception {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java b/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java
index 00bdf827e..f6b0ed947 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/ToSinglePageController.java
@@ -21,7 +21,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -29,10 +29,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class ToSinglePageController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ToSinglePageController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ToSinglePageController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -40,7 +40,10 @@ public class ToSinglePageController {
@Operation(
summary = "Convert a multi-page PDF into a single long page PDF",
description =
- "This endpoint converts a multi-page PDF document into a single paged PDF document. The width of the single page will be same as the input's width, but the height will be the sum of all the pages' heights. Input:PDF Output:PDF Type:SISO")
+ "This endpoint converts a multi-page PDF document into a single paged PDF"
+ + " document. The width of the single page will be same as the input's"
+ + " width, but the height will be the sum of all the pages' heights."
+ + " Input:PDF Output:PDF Type:SISO")
public ResponseEntity pdfToSinglePage(@ModelAttribute PDFFile request)
throws IOException {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java
index cd68798bb..52b124e53 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java
@@ -15,7 +15,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.config.RuntimePathConfig;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.FileToPdf;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -24,7 +24,7 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@RequestMapping("/api/v1/convert")
public class ConvertHtmlToPDF {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
private final ApplicationProperties applicationProperties;
@@ -32,7 +32,7 @@ public class ConvertHtmlToPDF {
@Autowired
public ConvertHtmlToPDF(
- CustomPDDocumentFactory pdfDocumentFactory,
+ CustomPDFDocumentFactory pdfDocumentFactory,
ApplicationProperties applicationProperties,
RuntimePathConfig runtimePathConfig) {
this.pdfDocumentFactory = pdfDocumentFactory;
@@ -45,7 +45,8 @@ public class ConvertHtmlToPDF {
@Operation(
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
description =
- "This endpoint takes an HTML or ZIP file input and converts it to a PDF format. Input:HTML Output:PDF Type:SISO")
+ "This endpoint takes an HTML or ZIP file input and converts it to a PDF format."
+ + " Input:HTML Output:PDF Type:SISO")
public ResponseEntity HtmlToPdf(@ModelAttribute HTMLToPdfRequest request)
throws Exception {
MultipartFile fileInput = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java
index 103f6e1c8..2aa75f159 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java
@@ -33,7 +33,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.converters.ConvertToImageRequest;
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.*;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@@ -43,10 +43,10 @@ import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@Tag(name = "Convert", description = "Convert APIs")
public class ConvertImgPDFController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ConvertImgPDFController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ConvertImgPDFController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -54,7 +54,9 @@ public class ConvertImgPDFController {
@Operation(
summary = "Convert PDF to image(s)",
description =
- "This endpoint converts a PDF file to image(s) with the specified image format, color type, and DPI. Users can choose to get a single image or multiple images. Input:PDF Output:Image Type:SI-Conditional")
+ "This endpoint converts a PDF file to image(s) with the specified image format,"
+ + " color type, and DPI. Users can choose to get a single image or multiple"
+ + " images. Input:PDF Output:Image Type:SI-Conditional")
public ResponseEntity convertToImage(@ModelAttribute ConvertToImageRequest request)
throws NumberFormatException, Exception {
MultipartFile file = request.getFileInput();
@@ -208,7 +210,9 @@ public class ConvertImgPDFController {
@Operation(
summary = "Convert images to a PDF file",
description =
- "This endpoint converts one or more images to a PDF file. Users can specify whether to stretch the images to fit the PDF page, and whether to automatically rotate the images. Input:Image Output:PDF Type:MISO")
+ "This endpoint converts one or more images to a PDF file. Users can specify"
+ + " whether to stretch the images to fit the PDF page, and whether to"
+ + " automatically rotate the images. Input:Image Output:PDF Type:MISO")
public ResponseEntity convertToPdf(@ModelAttribute ConvertToPdfRequest request)
throws IOException {
MultipartFile[] file = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java
index 121539778..547d9c646 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java
@@ -25,7 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.config.RuntimePathConfig;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.GeneralFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.FileToPdf;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -34,14 +34,14 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@RequestMapping("/api/v1/convert")
public class ConvertMarkdownToPdf {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
private final ApplicationProperties applicationProperties;
private final RuntimePathConfig runtimePathConfig;
@Autowired
public ConvertMarkdownToPdf(
- CustomPDDocumentFactory pdfDocumentFactory,
+ CustomPDFDocumentFactory pdfDocumentFactory,
ApplicationProperties applicationProperties,
RuntimePathConfig runtimePathConfig) {
this.pdfDocumentFactory = pdfDocumentFactory;
@@ -54,7 +54,8 @@ public class ConvertMarkdownToPdf {
@Operation(
summary = "Convert a Markdown file to PDF",
description =
- "This endpoint takes a Markdown file input, converts it to HTML, and then to PDF format. Input:MARKDOWN Output:PDF Type:SISO")
+ "This endpoint takes a Markdown file input, converts it to HTML, and then to"
+ + " PDF format. Input:MARKDOWN Output:PDF Type:SISO")
public ResponseEntity markdownToPdf(@ModelAttribute GeneralFile request)
throws Exception {
MultipartFile fileInput = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java
index 4cdfd1bdf..46bf4c033 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertOfficeController.java
@@ -24,7 +24,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.config.RuntimePathConfig;
import stirling.software.SPDF.model.api.GeneralFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -34,12 +34,12 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@RequestMapping("/api/v1/convert")
public class ConvertOfficeController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
private final RuntimePathConfig runtimePathConfig;
@Autowired
public ConvertOfficeController(
- CustomPDDocumentFactory pdfDocumentFactory, RuntimePathConfig runtimePathConfig) {
+ CustomPDFDocumentFactory pdfDocumentFactory, RuntimePathConfig runtimePathConfig) {
this.pdfDocumentFactory = pdfDocumentFactory;
this.runtimePathConfig = runtimePathConfig;
}
@@ -93,7 +93,8 @@ public class ConvertOfficeController {
@Operation(
summary = "Convert a file to a PDF using LibreOffice",
description =
- "This endpoint converts a given file to a PDF using LibreOffice API Input:ANY Output:PDF Type:SISO")
+ "This endpoint converts a given file to a PDF using LibreOffice API Input:ANY"
+ + " Output:PDF Type:SISO")
public ResponseEntity processFileToPDF(@ModelAttribute GeneralFile request)
throws Exception {
MultipartFile inputFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java
index 39c808096..f603aa277 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java
@@ -21,7 +21,7 @@ import stirling.software.SPDF.model.api.PDFFile;
import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest;
import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest;
import stirling.software.SPDF.model.api.converters.PdfToWordRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.PDFToFile;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -30,10 +30,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Convert", description = "Convert APIs")
public class ConvertPDFToOffice {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ConvertPDFToOffice(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ConvertPDFToOffice(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -41,7 +41,8 @@ public class ConvertPDFToOffice {
@Operation(
summary = "Convert PDF to Presentation format",
description =
- "This endpoint converts a given PDF file to a Presentation format. Input:PDF Output:PPT Type:SISO")
+ "This endpoint converts a given PDF file to a Presentation format. Input:PDF"
+ + " Output:PPT Type:SISO")
public ResponseEntity processPdfToPresentation(
@ModelAttribute PdfToPresentationRequest request)
throws IOException, InterruptedException {
@@ -55,7 +56,8 @@ public class ConvertPDFToOffice {
@Operation(
summary = "Convert PDF to Text or RTF format",
description =
- "This endpoint converts a given PDF file to Text or RTF format. Input:PDF Output:TXT Type:SISO")
+ "This endpoint converts a given PDF file to Text or RTF format. Input:PDF"
+ + " Output:TXT Type:SISO")
public ResponseEntity processPdfToRTForTXT(
@ModelAttribute PdfToTextOrRTFRequest request)
throws IOException, InterruptedException {
@@ -82,7 +84,8 @@ public class ConvertPDFToOffice {
@Operation(
summary = "Convert PDF to Word document",
description =
- "This endpoint converts a given PDF file to a Word document format. Input:PDF Output:WORD Type:SISO")
+ "This endpoint converts a given PDF file to a Word document format. Input:PDF"
+ + " Output:WORD Type:SISO")
public ResponseEntity processPdfToWord(@ModelAttribute PdfToWordRequest request)
throws IOException, InterruptedException {
MultipartFile inputFile = request.getFileInput();
@@ -95,7 +98,8 @@ public class ConvertPDFToOffice {
@Operation(
summary = "Convert PDF to XML",
description =
- "This endpoint converts a PDF file to an XML file. Input:PDF Output:XML Type:SISO")
+ "This endpoint converts a PDF file to an XML file. Input:PDF Output:XML"
+ + " Type:SISO")
public ResponseEntity processPdfToXML(@ModelAttribute PDFFile request)
throws Exception {
MultipartFile inputFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java
index ebf9321aa..b762c0881 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java
@@ -21,7 +21,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.RuntimePathConfig;
import stirling.software.SPDF.model.api.converters.UrlToPdfRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@@ -33,12 +33,12 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@RequestMapping("/api/v1/convert")
public class ConvertWebsiteToPDF {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
private final RuntimePathConfig runtimePathConfig;
@Autowired
public ConvertWebsiteToPDF(
- CustomPDDocumentFactory pdfDocumentFactory, RuntimePathConfig runtimePathConfig) {
+ CustomPDFDocumentFactory pdfDocumentFactory, RuntimePathConfig runtimePathConfig) {
this.pdfDocumentFactory = pdfDocumentFactory;
this.runtimePathConfig = runtimePathConfig;
}
@@ -47,7 +47,8 @@ public class ConvertWebsiteToPDF {
@Operation(
summary = "Convert a URL to a PDF",
description =
- "This endpoint fetches content from a URL and converts it to a PDF format. Input:N/A Output:PDF Type:SISO")
+ "This endpoint fetches content from a URL and converts it to a PDF format."
+ + " Input:N/A Output:PDF Type:SISO")
public ResponseEntity urlToPdf(@ModelAttribute UrlToPdfRequest request)
throws IOException, InterruptedException {
String URL = request.getUrlInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java
index 359d353d7..06cc45094 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ExtractCSVController.java
@@ -30,7 +30,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.PDFWithPageNums;
import stirling.software.SPDF.pdf.FlexibleCSVWriter;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import technology.tabula.ObjectExtractor;
import technology.tabula.Page;
@@ -43,10 +43,10 @@ import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;
@Slf4j
public class ExtractCSVController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ExtractCSVController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ExtractCSVController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -54,7 +54,8 @@ public class ExtractCSVController {
@Operation(
summary = "Extracts a CSV document from a PDF",
description =
- "This operation takes an input PDF file and returns CSV file of whole page. Input:PDF Output:CSV Type:SISO")
+ "This operation takes an input PDF file and returns CSV file of whole page."
+ + " Input:PDF Output:CSV Type:SISO")
public ResponseEntity> pdfToCsv(@ModelAttribute PDFWithPageNums form) throws Exception {
String baseName = getBaseName(form.getFileInput().getOriginalFilename());
List csvEntries = new ArrayList<>();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java b/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java
index 66ac4cb8b..006598bd1 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/filters/FilterController.java
@@ -23,7 +23,7 @@ import stirling.software.SPDF.model.api.filter.ContainsTextRequest;
import stirling.software.SPDF.model.api.filter.FileSizeRequest;
import stirling.software.SPDF.model.api.filter.PageRotationRequest;
import stirling.software.SPDF.model.api.filter.PageSizeRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -32,10 +32,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Filter", description = "Filter APIs")
public class FilterController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public FilterController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public FilterController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java
index d3d2e91cc..1d71d94b7 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java
@@ -23,7 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.ExtractHeaderRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -35,10 +35,10 @@ public class AutoRenameController {
private static final float TITLE_FONT_SIZE_THRESHOLD = 20.0f;
private static final int LINE_LIMIT = 200;
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public AutoRenameController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public AutoRenameController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -46,7 +46,8 @@ public class AutoRenameController {
@Operation(
summary = "Extract header from PDF file",
description =
- "This endpoint accepts a PDF file and attempts to extract its title or header based on heuristics. Input:PDF Output:PDF Type:SISO")
+ "This endpoint accepts a PDF file and attempts to extract its title or header"
+ + " based on heuristics. Input:PDF Output:PDF Type:SISO")
public ResponseEntity extractHeader(@ModelAttribute ExtractHeaderRequest request)
throws Exception {
MultipartFile file = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java
index 16b021144..7a5c730fe 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java
@@ -35,7 +35,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.AutoSplitPdfRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -51,10 +51,10 @@ public class AutoSplitPdfController {
"https://github.com/Frooodle/Stirling-PDF",
"https://stirlingpdf.com"));
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public AutoSplitPdfController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public AutoSplitPdfController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java
index 0195382ea..c50c0a685 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java
@@ -30,7 +30,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.RemoveBlankPagesRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -40,10 +40,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class BlankPageController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public BlankPageController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public BlankPageController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -77,7 +77,9 @@ public class BlankPageController {
@Operation(
summary = "Remove blank pages from a PDF file",
description =
- "This endpoint removes blank pages from a given PDF file. Users can specify the threshold and white percentage to tune the detection of blank pages. Input:PDF Output:PDF Type:SISO")
+ "This endpoint removes blank pages from a given PDF file. Users can specify the"
+ + " threshold and white percentage to tune the detection of blank pages."
+ + " Input:PDF Output:PDF Type:SISO")
public ResponseEntity removeBlankPages(@ModelAttribute RemoveBlankPagesRequest request)
throws IOException, InterruptedException {
MultipartFile inputFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
index deb4e7aa0..54897f7c1 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
@@ -39,7 +39,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.OptimizePdfRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@@ -51,10 +51,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class CompressController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public CompressController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public CompressController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -63,7 +63,8 @@ public class CompressController {
byte[] fileBytes = Files.readAllBytes(pdfFile);
long originalFileSize = fileBytes.length;
log.info(
- "Starting image compression with scale factor: {} and JPEG quality: {} on file size: {}",
+ "Starting image compression with scale factor: {} and JPEG quality: {} on file"
+ + " size: {}",
scaleFactor,
jpegQuality,
GeneralUtils.formatBytes(originalFileSize));
@@ -140,7 +141,8 @@ public class CompressController {
// More aggressive for very large images
adjustedScaleFactor = Math.min(scaleFactor, 0.75);
log.info(
- "Page {}, Image {}: Very large image, using more aggressive scale: {}",
+ "Page {}, Image {}: Very large image, using more aggressive scale:"
+ + " {}",
pageNum + 1,
imageName,
adjustedScaleFactor);
@@ -288,7 +290,8 @@ public class CompressController {
if (imageBytes.length >= originalEncodedSize) {
log.info(
- "Page {}, Image {}: Compressed size {} not smaller than original {}, skipping replacement",
+ "Page {}, Image {}: Compressed size {} not smaller than original"
+ + " {}, skipping replacement",
pageNum + 1,
imageName,
GeneralUtils.formatBytes(imageBytes.length),
@@ -382,7 +385,8 @@ public class CompressController {
@Operation(
summary = "Optimize PDF file",
description =
- "This endpoint accepts a PDF file and optimizes it based on the provided parameters. Input:PDF Output:PDF Type:SISO")
+ "This endpoint accepts a PDF file and optimizes it based on the provided"
+ + " parameters. Input:PDF Output:PDF Type:SISO")
public ResponseEntity optimizePdf(@ModelAttribute OptimizePdfRequest request)
throws Exception {
MultipartFile inputFile = request.getFileInput();
@@ -493,7 +497,8 @@ public class CompressController {
if (newOptimizeLevel == optimizeLevel) {
if (autoMode) {
log.info(
- "Maximum optimization level reached without meeting target size.");
+ "Maximum optimization level reached without meeting target"
+ + " size.");
sizeMet = true;
}
} else {
@@ -512,7 +517,8 @@ public class CompressController {
// Check if optimized file is larger than the original
if (pdfBytes.length > inputFileSize) {
log.warn(
- "Optimized file is larger than the original. Returning the original file instead.");
+ "Optimized file is larger than the original. Returning the original file"
+ + " instead.");
finalFile = tempInputFile;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java
index 45767fc82..090b2b2e1 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/DecompressPdfController.java
@@ -25,7 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -34,10 +34,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class DecompressPdfController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public DecompressPdfController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public DecompressPdfController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java
index 7c4d9137f..fb27bf75a 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java
@@ -32,7 +32,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.CheckProgramInstall;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@@ -46,10 +46,10 @@ public class ExtractImageScansController {
private static final String REPLACEFIRST = "[.][^.]+$";
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ExtractImageScansController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ExtractImageScansController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -57,7 +57,10 @@ public class ExtractImageScansController {
@Operation(
summary = "Extract image scans from an input file",
description =
- "This endpoint extracts image scans from a given file based on certain parameters. Users can specify angle threshold, tolerance, minimum area, minimum contour area, and border size. Input:PDF Output:IMAGE/ZIP Type:SIMO")
+ "This endpoint extracts image scans from a given file based on certain"
+ + " parameters. Users can specify angle threshold, tolerance, minimum area,"
+ + " minimum contour area, and border size. Input:PDF Output:IMAGE/ZIP"
+ + " Type:SIMO")
public ResponseEntity extractImageScans(
@RequestBody(
description = "Form data containing file and extraction parameters",
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java
index 3010c1be6..af865f8f4 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImagesController.java
@@ -40,7 +40,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.PDFExtractImagesRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.ImageProcessingUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -50,10 +50,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class ExtractImagesController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ExtractImagesController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ExtractImagesController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -61,7 +61,9 @@ public class ExtractImagesController {
@Operation(
summary = "Extract images from a PDF file",
description =
- "This endpoint extracts images from a given PDF file and returns them in a zip file. Users can specify the output image format. Input:PDF Output:IMAGE/ZIP Type:SIMO")
+ "This endpoint extracts images from a given PDF file and returns them in a zip"
+ + " file. Users can specify the output image format. Input:PDF"
+ + " Output:IMAGE/ZIP Type:SIMO")
public ResponseEntity extractImages(@ModelAttribute PDFExtractImagesRequest request)
throws IOException, InterruptedException, ExecutionException {
MultipartFile file = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java
index 39991a1f6..8ddfa1657 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java
@@ -26,7 +26,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.FlattenRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -35,10 +35,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class FlattenController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public FlattenController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public FlattenController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -46,7 +46,8 @@ public class FlattenController {
@Operation(
summary = "Flatten PDF form fields or full page",
description =
- "Flattening just PDF form fields or converting each page to images to make text unselectable. Input:PDF, Output:PDF. Type:SISO")
+ "Flattening just PDF form fields or converting each page to images to make text"
+ + " unselectable. Input:PDF, Output:PDF. Type:SISO")
public ResponseEntity flatten(@ModelAttribute FlattenRequest request) throws Exception {
MultipartFile file = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java
index 66c1c8b66..4bca4988a 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/MetadataController.java
@@ -23,7 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.MetadataRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
import stirling.software.SPDF.utils.propertyeditor.StringToMapPropertyEditor;
@@ -33,10 +33,10 @@ import stirling.software.SPDF.utils.propertyeditor.StringToMapPropertyEditor;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class MetadataController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public MetadataController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public MetadataController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -59,7 +59,9 @@ public class MetadataController {
@Operation(
summary = "Update metadata of a PDF file",
description =
- "This endpoint allows you to update the metadata of a given PDF file. You can add, modify, or delete standard and custom metadata fields. Input:PDF Output:PDF Type:SISO")
+ "This endpoint allows you to update the metadata of a given PDF file. You can"
+ + " add, modify, or delete standard and custom metadata fields. Input:PDF"
+ + " Output:PDF Type:SISO")
public ResponseEntity metadata(@ModelAttribute MetadataRequest request)
throws IOException {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java
index 44fbb65b5..47d6d5b35 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java
@@ -33,7 +33,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.misc.ProcessPdfWithOcrRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
@RestController
@RequestMapping("/api/v1/misc")
@@ -43,11 +43,11 @@ public class OCRController {
private final ApplicationProperties applicationProperties;
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
public OCRController(
ApplicationProperties applicationProperties,
- CustomPDDocumentFactory pdfDocumentFactory) {
+ CustomPDFDocumentFactory pdfDocumentFactory) {
this.applicationProperties = applicationProperties;
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -70,7 +70,9 @@ public class OCRController {
@Operation(
summary = "Process PDF files with OCR using Tesseract",
description =
- "Takes a PDF file as input, performs OCR using specified languages and OCR type (skip-text/force-ocr), and returns the processed PDF. Input:PDF Output:PDF Type:SISO")
+ "Takes a PDF file as input, performs OCR using specified languages and OCR type"
+ + " (skip-text/force-ocr), and returns the processed PDF. Input:PDF"
+ + " Output:PDF Type:SISO")
public ResponseEntity processPdfWithOCR(
@ModelAttribute ProcessPdfWithOcrRequest request)
throws IOException, InterruptedException {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java
index 2814149e8..a953586fb 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java
@@ -18,7 +18,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.OverlayImageRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -28,10 +28,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class OverlayImageController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public OverlayImageController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public OverlayImageController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -39,7 +39,9 @@ public class OverlayImageController {
@Operation(
summary = "Overlay image onto a PDF file",
description =
- "This endpoint overlays an image onto a PDF file at the specified coordinates. The image can be overlaid on every page of the PDF if specified. Input:PDF/IMAGE Output:PDF Type:SISO")
+ "This endpoint overlays an image onto a PDF file at the specified coordinates."
+ + " The image can be overlaid on every page of the PDF if specified. "
+ + " Input:PDF/IMAGE Output:PDF Type:SISO")
public ResponseEntity overlayImage(@ModelAttribute OverlayImageRequest request) {
MultipartFile pdfFile = request.getFileInput();
MultipartFile imageFile = request.getImageFile();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java
index 17d1bbaa9..c66b55d73 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java
@@ -24,7 +24,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.misc.AddPageNumbersRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -33,10 +33,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class PageNumbersController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public PageNumbersController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public PageNumbersController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -44,7 +44,8 @@ public class PageNumbersController {
@Operation(
summary = "Add page numbers to a PDF document",
description =
- "This operation takes an input PDF file and adds page numbers to it. Input:PDF Output:PDF Type:SISO")
+ "This operation takes an input PDF file and adds page numbers to it. Input:PDF"
+ + " Output:PDF Type:SISO")
public ResponseEntity addPageNumbers(@ModelAttribute AddPageNumbersRequest request)
throws IOException {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java
index 374d0c53b..e75a2e20d 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java
@@ -19,7 +19,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -29,10 +29,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class RepairController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public RepairController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public RepairController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -40,7 +40,9 @@ public class RepairController {
@Operation(
summary = "Repair a PDF file",
description =
- "This endpoint repairs a given PDF file by running qpdf command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response. Input:PDF Output:PDF Type:SISO")
+ "This endpoint repairs a given PDF file by running qpdf command. The PDF is"
+ + " first saved to a temporary location, repaired, read back, and then"
+ + " returned as a response. Input:PDF Output:PDF Type:SISO")
public ResponseEntity repairPdf(@ModelAttribute PDFFile request)
throws IOException, InterruptedException {
MultipartFile inputFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java
index e38657cfe..ca5370b32 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java
@@ -20,7 +20,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -28,10 +28,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class ShowJavascript {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public ShowJavascript(CustomPDDocumentFactory pdfDocumentFactory) {
+ public ShowJavascript(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java
index 30a7540ee..e23635b82 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java
@@ -38,7 +38,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.misc.AddStampRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -46,10 +46,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class StampController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public StampController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public StampController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -57,7 +57,9 @@ public class StampController {
@Operation(
summary = "Add stamp to a PDF file",
description =
- "This endpoint adds a stamp to a given PDF file. Users can specify the stamp type (text or image), rotation, opacity, width spacer, and height spacer. Input:PDF Output:PDF Type:SISO")
+ "This endpoint adds a stamp to a given PDF file. Users can specify the stamp"
+ + " type (text or image), rotation, opacity, width spacer, and height"
+ + " spacer. Input:PDF Output:PDF Type:SISO")
public ResponseEntity addStamp(@ModelAttribute AddStampRequest request)
throws IOException, Exception {
MultipartFile pdfFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java
index cad762062..4a8981142 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java
@@ -68,7 +68,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -81,15 +81,15 @@ public class CertSignController {
Security.addProvider(new BouncyCastleProvider());
}
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public CertSignController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public CertSignController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
private static void sign(
- CustomPDDocumentFactory pdfDocumentFactory,
+ CustomPDFDocumentFactory pdfDocumentFactory,
MultipartFile input,
OutputStream output,
CreateSignature instance,
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java b/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java
index 026fd38a0..3452c3625 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java
@@ -62,7 +62,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -73,10 +73,10 @@ public class GetInfoOnPDF {
static ObjectMapper objectMapper = new ObjectMapper();
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public GetInfoOnPDF(CustomPDDocumentFactory pdfDocumentFactory) {
+ public GetInfoOnPDF(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java
index 6a89a0710..386e938b9 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java
@@ -19,7 +19,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.security.AddPasswordRequest;
import stirling.software.SPDF.model.api.security.PDFPasswordRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -27,10 +27,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Security", description = "Security APIs")
public class PasswordController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public PasswordController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public PasswordController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -38,8 +38,8 @@ public class PasswordController {
@Operation(
summary = "Remove password from a PDF file",
description =
- "This endpoint removes the password from a protected PDF file. Users need to provide the"
- + " existing password. Input:PDF Output:PDF Type:SISO")
+ "This endpoint removes the password from a protected PDF file. Users need to"
+ + " provide the existing password. Input:PDF Output:PDF Type:SISO")
public ResponseEntity removePassword(@ModelAttribute PDFPasswordRequest request)
throws IOException {
MultipartFile fileInput = request.getFileInput();
@@ -57,8 +57,9 @@ public class PasswordController {
@Operation(
summary = "Add password to a PDF file",
description =
- "This endpoint adds password protection to a PDF file. Users can specify a set of"
- + " permissions that should be applied to the file. Input:PDF Output:PDF")
+ "This endpoint adds password protection to a PDF file. Users can specify a set"
+ + " of permissions that should be applied to the file. Input:PDF"
+ + " Output:PDF")
public ResponseEntity addPassword(@ModelAttribute AddPasswordRequest request)
throws IOException {
MultipartFile fileInput = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java
index 5bffe68e1..deec98e4e 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java
@@ -35,7 +35,7 @@ import stirling.software.SPDF.model.api.security.ManualRedactPdfRequest;
import stirling.software.SPDF.model.api.security.RedactPdfRequest;
import stirling.software.SPDF.model.api.security.RedactionArea;
import stirling.software.SPDF.pdf.TextFinder;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -47,10 +47,10 @@ import stirling.software.SPDF.utils.propertyeditor.StringToArrayListPropertyEdit
@Tag(name = "Security", description = "Security APIs")
public class RedactController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public RedactController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public RedactController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -64,7 +64,9 @@ public class RedactController {
@Operation(
summary = "Redacts areas and pages in a PDF document",
description =
- "This operation takes an input PDF file with a list of areas, page number(s)/range(s)/function(s) to redact. Input:PDF, Output:PDF, Type:SISO")
+ "This operation takes an input PDF file with a list of areas, page"
+ + " number(s)/range(s)/function(s) to redact. Input:PDF, Output:PDF,"
+ + " Type:SISO")
public ResponseEntity redactPDF(@ModelAttribute ManualRedactPdfRequest request)
throws IOException {
MultipartFile file = request.getFileInput();
@@ -196,8 +198,8 @@ public class RedactController {
@Operation(
summary = "Redacts listOfText in a PDF document",
description =
- "This operation takes an input PDF file and redacts the provided listOfText. Input:PDF,"
- + " Output:PDF, Type:SISO")
+ "This operation takes an input PDF file and redacts the provided listOfText."
+ + " Input:PDF, Output:PDF, Type:SISO")
public ResponseEntity redactPdf(@ModelAttribute RedactPdfRequest request)
throws Exception {
MultipartFile file = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java
index 88ed9b13f..81c0bcfb1 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/RemoveCertSignController.java
@@ -21,7 +21,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -29,10 +29,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Security", description = "Security APIs")
public class RemoveCertSignController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public RemoveCertSignController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public RemoveCertSignController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -40,7 +40,8 @@ public class RemoveCertSignController {
@Operation(
summary = "Remove digital signature from PDF",
description =
- "This endpoint accepts a PDF file and returns the PDF file without the digital signature. Input:PDF, Output:PDF Type:SISO")
+ "This endpoint accepts a PDF file and returns the PDF file without the digital"
+ + " signature. Input:PDF, Output:PDF Type:SISO")
public ResponseEntity removeCertSignPDF(@ModelAttribute PDFFile request)
throws Exception {
MultipartFile pdf = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java
index e075559e6..e1959fc88 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java
@@ -25,7 +25,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.security.SanitizePdfRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -33,10 +33,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Security", description = "Security APIs")
public class SanitizeController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public SanitizeController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public SanitizeController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java b/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java
index 317c6424b..4b4da4bdd 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/ValidateSignatureController.java
@@ -35,19 +35,19 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.security.SignatureValidationRequest;
import stirling.software.SPDF.model.api.security.SignatureValidationResult;
import stirling.software.SPDF.service.CertificateValidationService;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
@RestController
@RequestMapping("/api/v1/security")
@Tag(name = "Security", description = "Security APIs")
public class ValidateSignatureController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
private final CertificateValidationService certValidationService;
@Autowired
public ValidateSignatureController(
- CustomPDDocumentFactory pdfDocumentFactory,
+ CustomPDFDocumentFactory pdfDocumentFactory,
CertificateValidationService certValidationService) {
this.pdfDocumentFactory = pdfDocumentFactory;
this.certValidationService = certValidationService;
@@ -56,7 +56,8 @@ public class ValidateSignatureController {
@Operation(
summary = "Validate PDF Digital Signature",
description =
- "Validates the digital signatures in a PDF file against default or custom certificates. Input:PDF Output:JSON Type:SISO")
+ "Validates the digital signatures in a PDF file against default or custom"
+ + " certificates. Input:PDF Output:JSON Type:SISO")
@PostMapping(value = "/validate-signature")
public ResponseEntity> validateSignature(
@ModelAttribute SignatureValidationRequest request) throws IOException {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java b/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java
index 3e1be8153..7ed8a5a04 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java
@@ -36,7 +36,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.security.AddWatermarkRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -45,10 +45,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Security", description = "Security APIs")
public class WatermarkController {
- private final CustomPDDocumentFactory pdfDocumentFactory;
+ private final CustomPDFDocumentFactory pdfDocumentFactory;
@Autowired
- public WatermarkController(CustomPDDocumentFactory pdfDocumentFactory) {
+ public WatermarkController(CustomPDFDocumentFactory pdfDocumentFactory) {
this.pdfDocumentFactory = pdfDocumentFactory;
}
@@ -56,7 +56,9 @@ public class WatermarkController {
@Operation(
summary = "Add watermark to a PDF file",
description =
- "This endpoint adds a watermark to a given PDF file. Users can specify the watermark type (text or image), rotation, opacity, width spacer, and height spacer. Input:PDF Output:PDF Type:SISO")
+ "This endpoint adds a watermark to a given PDF file. Users can specify the"
+ + " watermark type (text or image), rotation, opacity, width spacer, and"
+ + " height spacer. Input:PDF Output:PDF Type:SISO")
public ResponseEntity addWatermark(@ModelAttribute AddWatermarkRequest request)
throws IOException, Exception {
MultipartFile pdfFile = request.getFileInput();
diff --git a/src/main/java/stirling/software/SPDF/service/CustomPDDocumentFactory.java b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java
similarity index 98%
rename from src/main/java/stirling/software/SPDF/service/CustomPDDocumentFactory.java
rename to src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java
index 6963b522c..5aa6ee335 100644
--- a/src/main/java/stirling/software/SPDF/service/CustomPDDocumentFactory.java
+++ b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java
@@ -29,7 +29,7 @@ import stirling.software.SPDF.model.api.PDFFile;
*/
@Component
@Slf4j
-public class CustomPDDocumentFactory {
+public class CustomPDFDocumentFactory {
private final PdfMetadataService pdfMetadataService;
@@ -63,7 +63,7 @@ public class CustomPDDocumentFactory {
// Counter for tracking temporary resources
private static final AtomicLong tempCounter = new AtomicLong(0);
- public CustomPDDocumentFactory(PdfMetadataService pdfMetadataService) {
+ public CustomPDFDocumentFactory(PdfMetadataService pdfMetadataService) {
this.pdfMetadataService = pdfMetadataService;
}
@@ -168,8 +168,8 @@ public class CustomPDDocumentFactory {
private PDDocument loadAdaptively(Object source, long contentSize) throws IOException {
// Get the appropriate caching strategy
StreamCacheCreateFunction cacheFunction = getStreamCacheFunction(contentSize);
-
- //If small handle as bytes and remove original file
+
+ // If small handle as bytes and remove original file
if (contentSize <= SMALL_FILE_THRESHOLD && source instanceof File file) {
source = Files.readAllBytes(file.toPath());
file.delete();
@@ -192,7 +192,7 @@ public class CustomPDDocumentFactory {
throws IOException {
// Get the appropriate caching strategy
StreamCacheCreateFunction cacheFunction = getStreamCacheFunction(contentSize);
- //If small handle as bytes and remove original file
+ // If small handle as bytes and remove original file
if (contentSize <= SMALL_FILE_THRESHOLD && source instanceof File file) {
source = Files.readAllBytes(file.toPath());
file.delete();
diff --git a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java
index ad404660e..14c5c09d7 100644
--- a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java
+++ b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java
@@ -35,7 +35,7 @@ import io.github.pixee.security.Filenames;
import lombok.extern.slf4j.Slf4j;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
@Slf4j
public class PdfUtils {
@@ -127,7 +127,7 @@ public class PdfUtils {
}
public static byte[] convertFromPdf(
- CustomPDDocumentFactory pdfDocumentFactory,
+ CustomPDFDocumentFactory pdfDocumentFactory,
byte[] inputStream,
String imageType,
ImageType colorType,
@@ -315,7 +315,7 @@ public class PdfUtils {
String fitOption,
boolean autoRotate,
String colorType,
- CustomPDDocumentFactory pdfDocumentFactory)
+ CustomPDFDocumentFactory pdfDocumentFactory)
throws IOException {
try (PDDocument doc = pdfDocumentFactory.createNewDocument()) {
for (MultipartFile file : files) {
@@ -405,7 +405,7 @@ public class PdfUtils {
}
public static byte[] overlayImage(
- CustomPDDocumentFactory pdfDocumentFactory,
+ CustomPDFDocumentFactory pdfDocumentFactory,
byte[] pdfBytes,
byte[] imageBytes,
float x,
diff --git a/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java b/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java
index 6c6852866..2270d68f0 100644
--- a/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java
+++ b/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java
@@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.*;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import java.util.Arrays;
import java.util.List;
@@ -23,8 +23,7 @@ import org.junit.jupiter.api.BeforeEach;
class RearrangePagesPDFControllerTest {
- @Mock
- private CustomPDDocumentFactory mockPdfDocumentFactory;
+ @Mock private CustomPDFDocumentFactory mockPdfDocumentFactory;
private RearrangePagesPDFController sut;
@@ -81,21 +80,24 @@ class RearrangePagesPDFControllerTest {
*/
@ParameterizedTest
@CsvSource({
- "1, '0'",
- "2, '0,1'",
- "3, '0,2,1'",
- "4, '0,2,1,3'",
- "5, '0,3,1,4,2'",
- "6, '0,3,1,4,2,5'",
- "10, '0,5,1,6,2,7,3,8,4,9'",
- "50, '0,25,1,26,2,27,3,28,4,29,5,30,6,31,7,32,8,33,9,34,10,35," +
- "11,36,12,37,13,38,14,39,15,40,16,41,17,42,18,43,19,44,20,45,21,46," +
- "22,47,23,48,24,49'"
+ "1, '0'",
+ "2, '0,1'",
+ "3, '0,2,1'",
+ "4, '0,2,1,3'",
+ "5, '0,3,1,4,2'",
+ "6, '0,3,1,4,2,5'",
+ "10, '0,5,1,6,2,7,3,8,4,9'",
+ "50, '0,25,1,26,2,27,3,28,4,29,5,30,6,31,7,32,8,33,9,34,10,35,"
+ + "11,36,12,37,13,38,14,39,15,40,16,41,17,42,18,43,19,44,20,45,21,46,"
+ + "22,47,23,48,24,49'"
})
void oddEvenMerge_multi_test(int totalNumberOfPages, String expectedPageOrder) {
List newPageOrder = sut.oddEvenMerge(totalNumberOfPages);
assertNotNull(newPageOrder, "Returning null instead of page order list");
- assertEquals(Arrays.stream(expectedPageOrder.split(",")).map(Integer::parseInt).toList(), newPageOrder, "Page order doesn't match");
+ assertEquals(
+ Arrays.stream(expectedPageOrder.split(",")).map(Integer::parseInt).toList(),
+ newPageOrder,
+ "Page order doesn't match");
}
}
diff --git a/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java b/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java
index 986ca55c2..372751e8e 100644
--- a/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java
+++ b/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java
@@ -7,20 +7,16 @@ import org.mockito.MockitoAnnotations;
import stirling.software.SPDF.config.RuntimePathConfig;
import stirling.software.SPDF.model.api.converters.UrlToPdfRequest;
-import stirling.software.SPDF.service.CustomPDDocumentFactory;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ConvertWebsiteToPdfTest {
+ @Mock private CustomPDFDocumentFactory mockPdfDocumentFactory;
- @Mock
- private CustomPDDocumentFactory mockPdfDocumentFactory;
-
- @Mock
- private RuntimePathConfig runtimePathConfig;
-
+ @Mock private RuntimePathConfig runtimePathConfig;
private ConvertWebsiteToPDF convertWebsiteToPDF;
@@ -38,9 +34,12 @@ public class ConvertWebsiteToPdfTest {
UrlToPdfRequest request = new UrlToPdfRequest();
request.setUrlInput(invalid_format_Url);
// Act
- IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> {
- convertWebsiteToPDF.urlToPdf(request);
- });
+ IllegalArgumentException thrown =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> {
+ convertWebsiteToPDF.urlToPdf(request);
+ });
// Assert
assertEquals("Invalid URL format provided.", thrown.getMessage());
}
@@ -53,9 +52,12 @@ public class ConvertWebsiteToPdfTest {
UrlToPdfRequest request = new UrlToPdfRequest();
request.setUrlInput(unreachable_Url);
// Act
- IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> {
- convertWebsiteToPDF.urlToPdf(request);
- });
+ IllegalArgumentException thrown =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> {
+ convertWebsiteToPDF.urlToPdf(request);
+ });
// Assert
assertEquals("URL is not reachable, please provide a valid URL.", thrown.getMessage());
}
From 4408ecfa5bfc4902a730995844fcf97192cf6878 Mon Sep 17 00:00:00 2001
From: Ludy
Date: Thu, 13 Mar 2025 10:22:06 +0100
Subject: [PATCH 04/12] Fix: string comparison and formatting inconsistencies
in `CompressController` (#3168)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Description of Changes
Please provide a summary of the changes, including:
- Replaced `format.equals("jpeg")` with `"jpeg".equals(format)` to
prevent potential `NullPointerException`
- Standardized percentage reduction logging by formatting values before
passing them into the log statement
- Fixed inconsistent formatting in log messages by replacing `{:.1f}%`
with pre-formatted string values
`63.32 MB → 61.77 MB (reduced by {:.1f}%)` -> `63.32 MB → 61.77 MB
(reduced by 2.5%)`
These changes improve code robustness and ensure consistent logging
output.
---
## Checklist
### General
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---
build.gradle | 5 ++++-
.../controller/api/misc/CompressController.java | 16 ++++++++--------
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/build.gradle b/build.gradle
index 0e1ccb47b..f1a8427fb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -289,12 +289,15 @@ tasks.wrapper {
// options.compilerArgs << "-Xlint:deprecation"
//}
configurations.all {
+ // Remove all commons-logging dependencies so that only spring-jcl is used
+ exclude group: 'commons-logging', module: 'commons-logging'
+ // Exclude Tomcat
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
dependencies {
//tmp for security bumps
- implementation 'ch.qos.logback:logback-core:1.5.17'
+ implementation 'ch.qos.logback:logback-core:1.5.17'
implementation 'ch.qos.logback:logback-classic:1.5.17'
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
index 54897f7c1..167e1cb1d 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
@@ -209,7 +209,7 @@ public class CompressController {
// First get the actual size of the original image by encoding it to the chosen
// format
ByteArrayOutputStream originalImageStream = new ByteArrayOutputStream();
- if (format.equals("jpeg")) {
+ if ("jpeg".equals(format)) {
// Get the best available JPEG writer (prioritizes TwelveMonkeys if
// available)
Iterator writers = ImageIO.getImageWritersByFormatName("jpeg");
@@ -252,7 +252,7 @@ public class CompressController {
// Now compress the scaled image
ByteArrayOutputStream compressedImageStream = new ByteArrayOutputStream();
- if (format.equals("jpeg")) {
+ if ("jpeg".equals(format)) {
Iterator writers = ImageIO.getImageWritersByFormatName(format);
if (writers.hasNext()) {
ImageWriter writer = writers.next();
@@ -338,10 +338,10 @@ public class CompressController {
compressedImages,
skippedImages);
log.info(
- "Total original image size: {}, compressed: {} (reduced by {:.1f}%)",
+ "Total original image size: {}, compressed: {} (reduced by {}%)",
GeneralUtils.formatBytes(totalOriginalBytes),
GeneralUtils.formatBytes(totalCompressedBytes),
- overallImageReduction);
+ String.format("%.1f", overallImageReduction));
// Save the document
log.info("Saving compressed PDF to {}", pdfFile.toString());
@@ -351,10 +351,10 @@ public class CompressController {
long compressedFileSize = Files.size(pdfFile);
double overallReduction = 100.0 - ((compressedFileSize * 100.0) / originalFileSize);
log.info(
- "Overall PDF compression: {} → {} (reduced by {:.1f}%)",
+ "Overall PDF compression: {} → {} (reduced by {}%)",
GeneralUtils.formatBytes(originalFileSize),
GeneralUtils.formatBytes(compressedFileSize),
- overallReduction);
+ String.format("%.1f", overallReduction));
}
}
@@ -477,8 +477,8 @@ public class CompressController {
long postQpdfSize = Files.size(tempOutputFile);
double qpdfReduction = 100.0 - ((postQpdfSize * 100.0) / preQpdfSize);
log.info(
- "Post-QPDF file size: {} (reduced by {:.1f}%)",
- GeneralUtils.formatBytes(postQpdfSize), qpdfReduction);
+ "Post-QPDF file size: {} (reduced by {}%)",
+ GeneralUtils.formatBytes(postQpdfSize), String.format("%.1f", qpdfReduction));
} else {
tempOutputFile = tempInputFile;
From 0cb745b9aebdad9d8af76ad252bd3d67e3b38a85 Mon Sep 17 00:00:00 2001
From: Ludy
Date: Thu, 13 Mar 2025 10:22:44 +0100
Subject: [PATCH 05/12] Refactor test imports (#3170)
# Description of Changes
Please provide a summary of the changes, including:
Refactor test imports and update Gradle file to include all Java files
from the src directory
---
## Checklist
### General
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---
build.gradle | 2 +-
.../software/SPDF/SPDFApplicationTest.java | 21 ++-----
.../CustomLogoutSuccessHandlerTest.java | 44 ++++++++-----
.../security/database/DatabaseConfigTest.java | 14 +++--
.../api/RearrangePagesPDFControllerTest.java | 35 +++++------
.../converters/ConvertWebsiteToPdfTest.java | 6 +-
.../software/SPDF/utils/FileInfoTest.java | 33 +++++-----
.../software/SPDF/utils/FileToPdfTest.java | 29 +++++----
.../software/SPDF/utils/GeneralUtilsTest.java | 62 +++++++++----------
.../SPDF/utils/ImageProcessingUtilsTest.java | 18 ++++--
.../software/SPDF/utils/PdfUtilsTest.java | 19 +++---
.../SPDF/utils/ProcessExecutorTest.java | 26 +++++---
.../SPDF/utils/PropertyConfigsTest.java | 4 +-
.../SPDF/utils/RequestUriUtilsTest.java | 4 +-
.../software/SPDF/utils/UrlUtilsTest.java | 5 +-
.../SPDF/utils/WebResponseUtilsTest.java | 32 ++++++----
.../SPDF/utils/validation/ValidatorTest.java | 27 ++++----
17 files changed, 195 insertions(+), 186 deletions(-)
diff --git a/build.gradle b/build.gradle
index f1a8427fb..7914b8d1f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -256,7 +256,7 @@ launch4j {
spotless {
java {
- target project.fileTree('src/main/java')
+ target project.fileTree('src').include('**/*.java')
googleJavaFormat("1.25.2").aosp().reorderImports(false)
diff --git a/src/test/java/stirling/software/SPDF/SPDFApplicationTest.java b/src/test/java/stirling/software/SPDF/SPDFApplicationTest.java
index 3b05e8761..c4dae34bf 100644
--- a/src/test/java/stirling/software/SPDF/SPDFApplicationTest.java
+++ b/src/test/java/stirling/software/SPDF/SPDFApplicationTest.java
@@ -1,11 +1,6 @@
package stirling.software.SPDF;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -16,22 +11,15 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.env.Environment;
import stirling.software.SPDF.model.ApplicationProperties;
-import static java.nio.file.Files.createDirectories;
-import static java.nio.file.Files.createFile;
-import static java.nio.file.Files.delete;
-import static java.nio.file.Files.exists;
@ExtendWith(MockitoExtension.class)
public class SPDFApplicationTest {
- @Mock
- private Environment env;
+ @Mock private Environment env;
- @Mock
- private ApplicationProperties applicationProperties;
+ @Mock private ApplicationProperties applicationProperties;
- @InjectMocks
- private SPDFApplication sPDFApplication;
+ @InjectMocks private SPDFApplication sPDFApplication;
@BeforeEach
public void setUp() {
@@ -48,5 +36,4 @@ public class SPDFApplicationTest {
public void testGetStaticPort() {
assertEquals("8080", SPDFApplication.getStaticPort());
}
-
}
diff --git a/src/test/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandlerTest.java b/src/test/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandlerTest.java
index 37a9f86e6..72dd95418 100644
--- a/src/test/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandlerTest.java
+++ b/src/test/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandlerTest.java
@@ -1,27 +1,29 @@
package stirling.software.SPDF.config.security;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import java.io.IOException;
+
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
import stirling.software.SPDF.model.ApplicationProperties;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class CustomLogoutSuccessHandlerTest {
- @Mock
- private ApplicationProperties applicationProperties;
+ @Mock private ApplicationProperties applicationProperties;
- @InjectMocks
- private CustomLogoutSuccessHandler customLogoutSuccessHandler;
+ @InjectMocks private CustomLogoutSuccessHandler customLogoutSuccessHandler;
@Test
void testSuccessfulLogout() throws IOException {
@@ -44,7 +46,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken oAuth2AuthenticationToken = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
@@ -70,7 +73,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
@@ -100,7 +104,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter(error)).thenReturn("true");
@@ -125,7 +130,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
@@ -151,7 +157,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
@@ -179,7 +186,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
@@ -209,7 +217,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
@@ -240,7 +249,8 @@ class CustomLogoutSuccessHandlerTest {
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
- ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
+ ApplicationProperties.Security.OAUTH2 oauth =
+ mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
diff --git a/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java b/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java
index 6d933d721..0118e8e32 100644
--- a/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java
+++ b/src/test/java/stirling/software/SPDF/config/security/database/DatabaseConfigTest.java
@@ -1,6 +1,12 @@
package stirling.software.SPDF.config.security.database;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import javax.sql.DataSource;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -8,18 +14,14 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.exception.UnsupportedProviderException;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class DatabaseConfigTest {
- @Mock
- private ApplicationProperties applicationProperties;
+ @Mock private ApplicationProperties applicationProperties;
private DatabaseConfig databaseConfig;
diff --git a/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java b/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java
index 2270d68f0..d6085b6f2 100644
--- a/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java
+++ b/src/test/java/stirling/software/SPDF/controller/api/RearrangePagesPDFControllerTest.java
@@ -1,25 +1,19 @@
package stirling.software.SPDF.controller.api;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import stirling.software.SPDF.service.CustomPDFDocumentFactory;
-
-import java.util.Arrays;
-import java.util.List;
-
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import java.util.Arrays;
+import java.util.List;
+
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
class RearrangePagesPDFControllerTest {
@@ -33,9 +27,7 @@ class RearrangePagesPDFControllerTest {
sut = new RearrangePagesPDFController(mockPdfDocumentFactory);
}
- /**
- * Tests the behavior of the oddEvenMerge method when there are no pages in the document.
- */
+ /** Tests the behavior of the oddEvenMerge method when there are no pages in the document. */
@Test
void oddEvenMerge_noPages() {
int totalNumberOfPages = 0;
@@ -60,7 +52,8 @@ class RearrangePagesPDFControllerTest {
}
/**
- * Tests the behavior of the oddEvenMerge method when there are even total pages in the document.
+ * Tests the behavior of the oddEvenMerge method when there are even total pages in the
+ * document.
*/
@Test
void oddEvenMerge_evenTotalPageNumber() {
@@ -76,7 +69,7 @@ class RearrangePagesPDFControllerTest {
* Tests the behavior of the oddEvenMerge method with multiple test cases of multiple pages.
*
* @param totalNumberOfPages The total number of pages in the document.
- * @param expectedPageOrder The expected order of the pages after rearranging.
+ * @param expectedPageOrder The expected order of the pages after rearranging.
*/
@ParameterizedTest
@CsvSource({
diff --git a/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java b/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java
index 372751e8e..952d765fc 100644
--- a/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java
+++ b/src/test/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPdfTest.java
@@ -1,5 +1,8 @@
package stirling.software.SPDF.controller.api.converters;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
@@ -9,9 +12,6 @@ import stirling.software.SPDF.config.RuntimePathConfig;
import stirling.software.SPDF.model.api.converters.UrlToPdfRequest;
import stirling.software.SPDF.service.CustomPDFDocumentFactory;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
public class ConvertWebsiteToPdfTest {
@Mock private CustomPDFDocumentFactory mockPdfDocumentFactory;
diff --git a/src/test/java/stirling/software/SPDF/utils/FileInfoTest.java b/src/test/java/stirling/software/SPDF/utils/FileInfoTest.java
index e83a062f8..6192d1dea 100644
--- a/src/test/java/stirling/software/SPDF/utils/FileInfoTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/FileInfoTest.java
@@ -1,31 +1,32 @@
package stirling.software.SPDF.utils;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.LocalDateTime;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
public class FileInfoTest {
@ParameterizedTest(name = "{index}: fileSize={0}")
@CsvSource({
- "0, '0 Bytes'",
- "1023, '1023 Bytes'",
- "1024, '1.00 KB'",
- "1048575, '1024.00 KB'", // Do we really want this as result?
- "1048576, '1.00 MB'",
- "1073741823, '1024.00 MB'", // Do we really want this as result?
- "1073741824, '1.00 GB'"
+ "0, '0 Bytes'",
+ "1023, '1023 Bytes'",
+ "1024, '1.00 KB'",
+ "1048575, '1024.00 KB'", // Do we really want this as result?
+ "1048576, '1.00 MB'",
+ "1073741823, '1024.00 MB'", // Do we really want this as result?
+ "1073741824, '1.00 GB'"
})
void testGetFormattedFileSize(long fileSize, String expectedFormattedSize) {
- FileInfo fileInfo = new FileInfo(
- "example.txt",
- "/path/to/example.txt",
- LocalDateTime.now(),
- fileSize,
- LocalDateTime.now().minusDays(1));
+ FileInfo fileInfo =
+ new FileInfo(
+ "example.txt",
+ "/path/to/example.txt",
+ LocalDateTime.now(),
+ fileSize,
+ LocalDateTime.now().minusDays(1));
assertEquals(expectedFormattedSize, fileInfo.getFormattedFileSize());
}
diff --git a/src/test/java/stirling/software/SPDF/utils/FileToPdfTest.java b/src/test/java/stirling/software/SPDF/utils/FileToPdfTest.java
index 8edb1b871..38e2ec3b8 100644
--- a/src/test/java/stirling/software/SPDF/utils/FileToPdfTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/FileToPdfTest.java
@@ -1,17 +1,20 @@
package stirling.software.SPDF.utils;
-import org.junit.jupiter.api.Test;
-import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
-import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
+
+import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
public class FileToPdfTest {
/**
- * Test the HTML to PDF conversion.
- * This test expects an IOException when an empty HTML input is provided.
+ * Test the HTML to PDF conversion. This test expects an IOException when an empty HTML input is
+ * provided.
*/
@Test
public void testConvertHtmlToPdf() {
@@ -31,8 +34,8 @@ public class FileToPdfTest {
}
/**
- * Test sanitizeZipFilename with null or empty input.
- * It should return an empty string in these cases.
+ * Test sanitizeZipFilename with null or empty input. It should return an empty string in these
+ * cases.
*/
@Test
public void testSanitizeZipFilename_NullOrEmpty() {
@@ -41,8 +44,8 @@ public class FileToPdfTest {
}
/**
- * Test sanitizeZipFilename to ensure it removes path traversal sequences.
- * This includes removing both forward and backward slash sequences.
+ * Test sanitizeZipFilename to ensure it removes path traversal sequences. This includes
+ * removing both forward and backward slash sequences.
*/
@Test
public void testSanitizeZipFilename_RemovesTraversalSequences() {
@@ -58,9 +61,7 @@ public class FileToPdfTest {
assertEquals(expected, FileToPdf.sanitizeZipFilename(input));
}
- /**
- * Test sanitizeZipFilename to ensure that it removes leading drive letters and slashes.
- */
+ /** Test sanitizeZipFilename to ensure that it removes leading drive letters and slashes. */
@Test
public void testSanitizeZipFilename_RemovesLeadingDriveAndSlashes() {
String input = "C:\\folder\\file.txt";
@@ -72,9 +73,7 @@ public class FileToPdfTest {
assertEquals(expected, FileToPdf.sanitizeZipFilename(input));
}
- /**
- * Test sanitizeZipFilename to verify that safe filenames remain unchanged.
- */
+ /** Test sanitizeZipFilename to verify that safe filenames remain unchanged. */
@Test
public void testSanitizeZipFilename_NoChangeForSafeNames() {
String input = "folder/subfolder/file.txt";
diff --git a/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java b/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java
index 18afcad62..72389130d 100644
--- a/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java
@@ -1,161 +1,157 @@
package stirling.software.SPDF.utils;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
public class GeneralUtilsTest {
-
@Test
void testParsePageListWithAll() {
- List result = GeneralUtils.parsePageList(new String[]{"all"}, 5, false);
+ List result = GeneralUtils.parsePageList(new String[] {"all"}, 5, false);
assertEquals(List.of(0, 1, 2, 3, 4), result, "'All' keyword should return all pages.");
}
@Test
void testParsePageListWithAllOneBased() {
- List result = GeneralUtils.parsePageList(new String[]{"all"}, 5, true);
+ List result = GeneralUtils.parsePageList(new String[] {"all"}, 5, true);
assertEquals(List.of(1, 2, 3, 4, 5), result, "'All' keyword should return all pages.");
}
@Test
void nFunc() {
- List result = GeneralUtils.parsePageList(new String[]{"n"}, 5, true);
+ List result = GeneralUtils.parsePageList(new String[] {"n"}, 5, true);
assertEquals(List.of(1, 2, 3, 4, 5), result, "'n' keyword should return all pages.");
}
@Test
void nFuncAdvanced() {
- List result = GeneralUtils.parsePageList(new String[]{"4n"}, 9, true);
- //skip 0 as not valid
+ List result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, true);
+ // skip 0 as not valid
assertEquals(List.of(4, 8), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvancedZero() {
- List result = GeneralUtils.parsePageList(new String[]{"4n"}, 9, false);
- //skip 0 as not valid
+ List result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, false);
+ // skip 0 as not valid
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvanced2() {
- List result = GeneralUtils.parsePageList(new String[]{"4n-1"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"4n-1"}, 9, true);
// skip -1 as not valid
assertEquals(List.of(3, 7), result, "4n-1 should do (0-1), (4-1), (8-1)");
}
@Test
void nFuncAdvanced3() {
- List result = GeneralUtils.parsePageList(new String[]{"4n+1"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"4n+1"}, 9, true);
assertEquals(List.of(5, 9), result, "'All' keyword should return all pages.");
}
@Test
void nFunc_spaces() {
- List result = GeneralUtils.parsePageList(new String[]{"n + 1"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"n + 1"}, 9, true);
assertEquals(List.of(2, 3, 4, 5, 6, 7, 8, 9), result);
}
@Test
void nFunc_consecutive_Ns_nnn() {
- List result = GeneralUtils.parsePageList(new String[]{"nnn"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"nnn"}, 9, true);
assertEquals(List.of(1, 8), result);
}
@Test
void nFunc_consecutive_Ns_nn() {
- List result = GeneralUtils.parsePageList(new String[]{"nn"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"nn"}, 9, true);
assertEquals(List.of(1, 4, 9), result);
}
@Test
void nFunc_opening_closing_round_brackets() {
- List result = GeneralUtils.parsePageList(new String[]{"(n-1)(n-2)"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"(n-1)(n-2)"}, 9, true);
assertEquals(List.of(2, 6), result);
}
@Test
void nFunc_opening_round_brackets() {
- List result = GeneralUtils.parsePageList(new String[]{"2(n-1)"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"2(n-1)"}, 9, true);
assertEquals(List.of(2, 4, 6, 8), result);
}
@Test
void nFunc_opening_round_brackets_n() {
- List result = GeneralUtils.parsePageList(new String[]{"n(n-1)"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"n(n-1)"}, 9, true);
assertEquals(List.of(2, 6), result);
}
@Test
void nFunc_closing_round_brackets() {
- List result = GeneralUtils.parsePageList(new String[]{"(n-1)2"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"(n-1)2"}, 9, true);
assertEquals(List.of(2, 4, 6, 8), result);
}
@Test
void nFunc_closing_round_brackets_n() {
- List result = GeneralUtils.parsePageList(new String[]{"(n-1)n"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"(n-1)n"}, 9, true);
assertEquals(List.of(2, 6), result);
}
@Test
void nFunc_function_surrounded_with_brackets() {
- List result = GeneralUtils.parsePageList(new String[]{"(n-1)"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"(n-1)"}, 9, true);
assertEquals(List.of(1, 2, 3, 4, 5, 6, 7, 8), result);
}
-
@Test
void nFuncAdvanced4() {
- List result = GeneralUtils.parsePageList(new String[]{"3+2n"}, 9, true);
+ List result = GeneralUtils.parsePageList(new String[] {"3+2n"}, 9, true);
assertEquals(List.of(5, 7, 9), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvancedZerobased() {
- List result = GeneralUtils.parsePageList(new String[]{"4n"}, 9, false);
+ List result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, false);
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvanced2Zerobased() {
- List result = GeneralUtils.parsePageList(new String[]{"4n-1"}, 9, false);
+ List result = GeneralUtils.parsePageList(new String[] {"4n-1"}, 9, false);
assertEquals(List.of(2, 6), result, "'All' keyword should return all pages.");
}
@Test
void testParsePageListWithRangeOneBasedOutput() {
- List result = GeneralUtils.parsePageList(new String[]{"1-3"}, 5, true);
+ List result = GeneralUtils.parsePageList(new String[] {"1-3"}, 5, true);
assertEquals(List.of(1, 2, 3), result, "Range should be parsed correctly.");
}
@Test
void testParsePageListWithRangeZeroBaseOutput() {
- List result = GeneralUtils.parsePageList(new String[]{"1-3"}, 5, false);
+ List result = GeneralUtils.parsePageList(new String[] {"1-3"}, 5, false);
assertEquals(List.of(0, 1, 2), result, "Range should be parsed correctly.");
}
-
@Test
void testParsePageListWithRangeOneBasedOutputFull() {
- List result = GeneralUtils.parsePageList(new String[]{"1,3,7-8"}, 8, true);
+ List result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 8, true);
assertEquals(List.of(1, 3, 7, 8), result, "Range should be parsed correctly.");
}
@Test
void testParsePageListWithRangeOneBasedOutputFullOutOfRange() {
- List result = GeneralUtils.parsePageList(new String[]{"1,3,7-8"}, 5, true);
+ List result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 5, true);
assertEquals(List.of(1, 3), result, "Range should be parsed correctly.");
}
@Test
void testParsePageListWithRangeZeroBaseOutputFull() {
- List result = GeneralUtils.parsePageList(new String[]{"1,3,7-8"}, 8, false);
+ List result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 8, false);
assertEquals(List.of(0, 2, 6, 7), result, "Range should be parsed correctly.");
}
}
diff --git a/src/test/java/stirling/software/SPDF/utils/ImageProcessingUtilsTest.java b/src/test/java/stirling/software/SPDF/utils/ImageProcessingUtilsTest.java
index af4bc22fb..dc4a94d7b 100644
--- a/src/test/java/stirling/software/SPDF/utils/ImageProcessingUtilsTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/ImageProcessingUtilsTest.java
@@ -1,11 +1,13 @@
package stirling.software.SPDF.utils;
-import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.awt.*;
import java.awt.image.BufferedImage;
-import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
public class ImageProcessingUtilsTest {
@@ -14,7 +16,8 @@ public class ImageProcessingUtilsTest {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
- BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "greyscale");
+ BufferedImage convertedImage =
+ ImageProcessingUtils.convertColorType(sourceImage, "greyscale");
assertNotNull(convertedImage);
assertEquals(BufferedImage.TYPE_BYTE_GRAY, convertedImage.getType());
@@ -32,7 +35,8 @@ public class ImageProcessingUtilsTest {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
- BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "blackwhite");
+ BufferedImage convertedImage =
+ ImageProcessingUtils.convertColorType(sourceImage, "blackwhite");
assertNotNull(convertedImage);
assertEquals(BufferedImage.TYPE_BYTE_BINARY, convertedImage.getType());
@@ -49,7 +53,8 @@ public class ImageProcessingUtilsTest {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
- BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "fullcolor");
+ BufferedImage convertedImage =
+ ImageProcessingUtils.convertColorType(sourceImage, "fullcolor");
assertNotNull(convertedImage);
assertEquals(sourceImage, convertedImage);
@@ -60,7 +65,8 @@ public class ImageProcessingUtilsTest {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
- BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "invalidtype");
+ BufferedImage convertedImage =
+ ImageProcessingUtils.convertColorType(sourceImage, "invalidtype");
assertNotNull(convertedImage);
assertEquals(sourceImage, convertedImage);
diff --git a/src/test/java/stirling/software/SPDF/utils/PdfUtilsTest.java b/src/test/java/stirling/software/SPDF/utils/PdfUtilsTest.java
index e57e92035..a03564ee9 100644
--- a/src/test/java/stirling/software/SPDF/utils/PdfUtilsTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/PdfUtilsTest.java
@@ -1,5 +1,15 @@
package stirling.software.SPDF.utils;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
@@ -8,13 +18,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import static org.junit.jupiter.api.Assertions.*;
-
public class PdfUtilsTest {
@Test
@@ -46,6 +49,4 @@ public class PdfUtilsTest {
assertTrue(PdfUtils.hasImagesOnPage(page));
}
-
-
}
diff --git a/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java b/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java
index 10910b125..871a1678c 100644
--- a/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java
@@ -1,13 +1,16 @@
package stirling.software.SPDF.utils;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
public class ProcessExecutorTest {
@@ -27,7 +30,8 @@ public class ProcessExecutorTest {
command.add("-version");
// Execute the command
- ProcessExecutor.ProcessExecutorResult result = processExecutor.runCommandWithOutputHandling(command);
+ ProcessExecutor.ProcessExecutorResult result =
+ processExecutor.runCommandWithOutputHandling(command);
// Check the exit code and output messages
assertEquals(0, result.getRc());
@@ -41,15 +45,21 @@ public class ProcessExecutorTest {
command.add("nonexistent-command");
// Execute the command and expect an IOException
- IOException thrown = assertThrows(IOException.class, () -> {
- processExecutor.runCommandWithOutputHandling(command);
- });
+ IOException thrown =
+ assertThrows(
+ IOException.class,
+ () -> {
+ processExecutor.runCommandWithOutputHandling(command);
+ });
// Log the actual error message
System.out.println("Caught IOException: " + thrown.getMessage());
// Check the exception message to ensure it indicates the command was not found
String errorMessage = thrown.getMessage();
- assertTrue(errorMessage.contains("error=2") || errorMessage.contains("No such file or directory"), "Unexpected error message: " + errorMessage);
+ assertTrue(
+ errorMessage.contains("error=2")
+ || errorMessage.contains("No such file or directory"),
+ "Unexpected error message: " + errorMessage);
}
}
diff --git a/src/test/java/stirling/software/SPDF/utils/PropertyConfigsTest.java b/src/test/java/stirling/software/SPDF/utils/PropertyConfigsTest.java
index 7909f1d9f..be0605735 100644
--- a/src/test/java/stirling/software/SPDF/utils/PropertyConfigsTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/PropertyConfigsTest.java
@@ -1,11 +1,11 @@
package stirling.software.SPDF.utils;
-import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
public class PropertyConfigsTest {
diff --git a/src/test/java/stirling/software/SPDF/utils/RequestUriUtilsTest.java b/src/test/java/stirling/software/SPDF/utils/RequestUriUtilsTest.java
index 7b586f472..f18196030 100644
--- a/src/test/java/stirling/software/SPDF/utils/RequestUriUtilsTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/RequestUriUtilsTest.java
@@ -1,10 +1,10 @@
package stirling.software.SPDF.utils;
-import org.junit.jupiter.api.Test;
-
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
+
public class RequestUriUtilsTest {
@Test
diff --git a/src/test/java/stirling/software/SPDF/utils/UrlUtilsTest.java b/src/test/java/stirling/software/SPDF/utils/UrlUtilsTest.java
index c17c0e747..c6383accb 100644
--- a/src/test/java/stirling/software/SPDF/utils/UrlUtilsTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/UrlUtilsTest.java
@@ -1,10 +1,11 @@
package stirling.software.SPDF.utils;
-import jakarta.servlet.http.HttpServletRequest;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import jakarta.servlet.http.HttpServletRequest;
public class UrlUtilsTest {
diff --git a/src/test/java/stirling/software/SPDF/utils/WebResponseUtilsTest.java b/src/test/java/stirling/software/SPDF/utils/WebResponseUtilsTest.java
index 49ecab328..9175e7a1b 100644
--- a/src/test/java/stirling/software/SPDF/utils/WebResponseUtilsTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/WebResponseUtilsTest.java
@@ -1,5 +1,12 @@
package stirling.software.SPDF.utils;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
@@ -8,11 +15,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import static org.junit.jupiter.api.Assertions.*;
-
public class WebResponseUtilsTest {
@Test
@@ -22,7 +24,8 @@ public class WebResponseUtilsTest {
baos.write("Sample PDF content".getBytes());
String docName = "sample.pdf";
- ResponseEntity responseEntity = WebResponseUtils.boasToWebResponse(baos, docName);
+ ResponseEntity responseEntity =
+ WebResponseUtils.boasToWebResponse(baos, docName);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
@@ -32,7 +35,8 @@ public class WebResponseUtilsTest {
assertNotNull(headers);
assertEquals(MediaType.APPLICATION_PDF, headers.getContentType());
assertNotNull(headers.getContentDisposition());
- //assertEquals("attachment; filename=\"sample.pdf\"", headers.getContentDisposition().toString());
+ // assertEquals("attachment; filename=\"sample.pdf\"",
+ // headers.getContentDisposition().toString());
} catch (IOException e) {
fail("Exception thrown: " + e.getMessage());
@@ -43,9 +47,11 @@ public class WebResponseUtilsTest {
public void testMultiPartFileToWebResponse() {
try {
byte[] fileContent = "Sample file content".getBytes();
- MockMultipartFile file = new MockMultipartFile("file", "sample.txt", "text/plain", fileContent);
+ MockMultipartFile file =
+ new MockMultipartFile("file", "sample.txt", "text/plain", fileContent);
- ResponseEntity responseEntity = WebResponseUtils.multiPartFileToWebResponse(file);
+ ResponseEntity responseEntity =
+ WebResponseUtils.multiPartFileToWebResponse(file);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
@@ -68,7 +74,8 @@ public class WebResponseUtilsTest {
String docName = "sample.txt";
MediaType mediaType = MediaType.TEXT_PLAIN;
- ResponseEntity responseEntity = WebResponseUtils.bytesToWebResponse(bytes, docName, mediaType);
+ ResponseEntity responseEntity =
+ WebResponseUtils.bytesToWebResponse(bytes, docName, mediaType);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
@@ -79,7 +86,6 @@ public class WebResponseUtilsTest {
assertEquals(MediaType.TEXT_PLAIN, headers.getContentType());
assertNotNull(headers.getContentDisposition());
-
} catch (IOException e) {
fail("Exception thrown: " + e.getMessage());
}
@@ -92,7 +98,8 @@ public class WebResponseUtilsTest {
document.addPage(new org.apache.pdfbox.pdmodel.PDPage());
String docName = "sample.pdf";
- ResponseEntity responseEntity = WebResponseUtils.pdfDocToWebResponse(document, docName);
+ ResponseEntity responseEntity =
+ WebResponseUtils.pdfDocToWebResponse(document, docName);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
@@ -103,7 +110,6 @@ public class WebResponseUtilsTest {
assertEquals(MediaType.APPLICATION_PDF, headers.getContentType());
assertNotNull(headers.getContentDisposition());
-
} catch (IOException e) {
fail("Exception thrown: " + e.getMessage());
}
diff --git a/src/test/java/stirling/software/SPDF/utils/validation/ValidatorTest.java b/src/test/java/stirling/software/SPDF/utils/validation/ValidatorTest.java
index 1e2b075ac..1ec8acd91 100644
--- a/src/test/java/stirling/software/SPDF/utils/validation/ValidatorTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/validation/ValidatorTest.java
@@ -1,24 +1,25 @@
package stirling.software.SPDF.utils.validation;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import java.util.stream.Stream;
+
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.junit.jupiter.MockitoExtension;
+
import stirling.software.SPDF.model.UsernameAttribute;
import stirling.software.SPDF.model.provider.GitHubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
-import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.model.provider.Provider;
-import java.util.List;
-import java.util.stream.Stream;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
@ExtendWith(MockitoExtension.class)
class ValidatorTest {
@@ -41,14 +42,10 @@ class ValidatorTest {
public static Stream providerParams() {
Provider generic = null;
- var google = new GoogleProvider(null, "clientSecret", List.of("scope"), UsernameAttribute.EMAIL);
+ var google =
+ new GoogleProvider(null, "clientSecret", List.of("scope"), UsernameAttribute.EMAIL);
var github = new GitHubProvider("clientId", "", List.of("scope"), UsernameAttribute.LOGIN);
- return Stream.of(
- Arguments.of(generic),
- Arguments.of(google),
- Arguments.of(github)
- );
+ return Stream.of(Arguments.of(generic), Arguments.of(google), Arguments.of(github));
}
-
}
From 885b3f049e7f32d0237c3b592de1c4f6524b37b5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 13 Mar 2025 10:19:27 +0000
Subject: [PATCH 06/12] Bump gradle from 8.12-jdk21 to 8.13-jdk21 (#3158)
Bumps gradle from 8.12-jdk21 to 8.13-jdk21.
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Dockerfile.fat | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile.fat b/Dockerfile.fat
index 2cc2d2133..8855be6c0 100644
--- a/Dockerfile.fat
+++ b/Dockerfile.fat
@@ -1,5 +1,5 @@
# Build the application
-FROM gradle:8.12-jdk21 AS build
+FROM gradle:8.13-jdk21 AS build
COPY build.gradle .
COPY settings.gradle .
From 0747ea68f5b43226b8386ab561858c6f2c6c0299 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 13 Mar 2025 10:19:49 +0000
Subject: [PATCH 07/12] Bump io.micrometer:micrometer-core from 1.14.4 to
1.14.5 (#3159)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bumps
[io.micrometer:micrometer-core](https://github.com/micrometer-metrics/micrometer)
from 1.14.4 to 1.14.5.
Release notes
Sourced from io.micrometer:micrometer-core's
releases.
1.14.5
:lady_beetle: Bug Fixes
Distribution value with |count| of 0 has a non-zero |mean|
value of XXX
errors in logs - similar to #4868
#5927
:hammer: Dependency Upgrades
- Bump com.fasterxml.jackson.core:jackson-databind from 2.18.2 to
2.18.3 #5989
- Bump com.netflix.spectator:spectator-reg-atlas from 1.8.4 to 1.8.6
#5941
- Bump io.prometheus:prometheus-metrics-bom from 1.3.5 to 1.3.6 #5938
- Bump me.champeau.gradle:japicmp-gradle-plugin from 0.4.5 to 0.4.6 #5940
- Bump spring6 from 6.1.16 to 6.1.17 #5926
- Bump testcontainers from 1.20.4 to 1.20.5 #5949
:heart: Contributors
Thank you to all the contributors who worked on this release:
@AlexElin
,
and @izeye
Commits
4ff1bbf
Merge branch '1.13.x' into 1.14.x
c92ff3d
Added release train gh action workflow
7cdce34
Merge branch '1.13.x' into 1.14.x
3a55d71
Clarify JavaDoc for JMS DESTINATION_NAME
(#5988)
0d6bcec
Merge branch '1.13.x' into 1.14.x
6e70957
Fix flakiness in
JmsInstrumentationTests.shouldInstrumentMessageListener() (#...
a5fe903
Try to reduce flakiness in
JvmGcMetricsTest.gcTimingIsCorrectForPauseCycleCol...
4106963
Bump testcontainers from 1.20.5 to 1.20.6 (#5998)
c3d8dcf
Bump com.fasterxml.jackson.core:jackson-databind from 2.18.2 to 2.18.3
(#5989)
d73e341
Bump io.netty:netty-bom from 4.1.118.Final to 4.1.119.Final (#5980)
- Additional commits viewable in compare
view
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build.gradle b/build.gradle
index 7914b8d1f..bbd66361c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -410,7 +410,7 @@ dependencies {
implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion"
implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion"
implementation "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
- implementation "io.micrometer:micrometer-core:1.14.4"
+ implementation "io.micrometer:micrometer-core:1.14.5"
implementation group: "com.google.zxing", name: "core", version: "3.5.3"
// https://mvnrepository.com/artifact/org.commonmark/commonmark
implementation "org.commonmark:commonmark:0.24.0"
From 05686021637bb7d1f25c4cd32109f528bb14b03b Mon Sep 17 00:00:00 2001
From: Ludy
Date: Thu, 13 Mar 2025 11:20:55 +0100
Subject: [PATCH 08/12] Add: Validation for rotation angle and create unit
tests for RotationController (#3162)
# Description of Changes
Please provide a summary of the changes, including:
- What was changed
- Why the change was made
- Any challenges encountered
Closes #(issue_number)
---
## Checklist
### General
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---
.github/labeler-config.yml | 3 +-
.../controller/api/RotationController.java | 6 ++
.../api/RotationControllerTest.java | 74 +++++++++++++++++++
3 files changed, 82 insertions(+), 1 deletion(-)
create mode 100644 src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java
diff --git a/.github/labeler-config.yml b/.github/labeler-config.yml
index 73f92aaa3..a0a634840 100644
--- a/.github/labeler-config.yml
+++ b/.github/labeler-config.yml
@@ -72,7 +72,8 @@ Devtools:
Test:
- changed-files:
- any-glob-to-any-file: 'cucumber/**/*'
- - any-glob-to-any-file: 'src/test**/*'
+ - any-glob-to-any-file: 'src/test/**/*'
+ - any-glob-to-any-file: 'src/testing/**/*'
- any-glob-to-any-file: '.pre-commit-config'
- any-glob-to-any-file: '.github/workflows/pre_commit.yml'
- any-glob-to-any-file: '.github/workflows/scorecards.yml'
diff --git a/src/main/java/stirling/software/SPDF/controller/api/RotationController.java b/src/main/java/stirling/software/SPDF/controller/api/RotationController.java
index 41891c7f5..b029450ef 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/RotationController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/RotationController.java
@@ -43,6 +43,12 @@ public class RotationController {
throws IOException {
MultipartFile pdfFile = request.getFileInput();
Integer angle = request.getAngle();
+
+ // Validate the angle is a multiple of 90
+ if (angle % 90 != 0) {
+ throw new IllegalArgumentException("Angle must be a multiple of 90");
+ }
+
// Load the PDF document
PDDocument document = pdfDocumentFactory.load(request);
diff --git a/src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java b/src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java
new file mode 100644
index 000000000..edd9cada1
--- /dev/null
+++ b/src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java
@@ -0,0 +1,74 @@
+package stirling.software.SPDF.controller.api;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import java.io.IOException;
+import org.apache.pdfbox.pdmodel.PDPageTree;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.ResponseEntity;
+import org.springframework.mock.web.MockMultipartFile;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
+import stirling.software.SPDF.model.api.general.RotatePDFRequest;
+
+@ExtendWith(MockitoExtension.class)
+public class RotationControllerTest {
+
+ @Mock private CustomPDFDocumentFactory pdfDocumentFactory;
+
+ @InjectMocks private RotationController rotationController;
+
+ @Test
+ public void testRotatePDF() throws IOException {
+ // Create a mock file
+ MockMultipartFile mockFile =
+ new MockMultipartFile("file", "test.pdf", "application/pdf", new byte[] {1, 2, 3});
+ RotatePDFRequest request = new RotatePDFRequest();
+ request.setFileInput(mockFile);
+ request.setAngle(90);
+
+ PDDocument mockDocument = mock(PDDocument.class);
+ PDPageTree mockPages = mock(PDPageTree.class);
+ PDPage mockPage = mock(PDPage.class);
+
+ when(pdfDocumentFactory.load(request)).thenReturn(mockDocument);
+ when(mockDocument.getPages()).thenReturn(mockPages);
+ when(mockPages.iterator())
+ .thenReturn(java.util.Collections.singletonList(mockPage).iterator());
+ when(mockPage.getRotation()).thenReturn(0);
+
+ // Act
+ ResponseEntity response = rotationController.rotatePDF(request);
+
+ // Assert
+ verify(mockPage).setRotation(90);
+ assertNotNull(response);
+ assertEquals(200, response.getStatusCode().value());
+ }
+
+ @Test
+ public void testRotatePDFInvalidAngle() throws IOException {
+ // Create a mock file
+ MockMultipartFile mockFile =
+ new MockMultipartFile("file", "test.pdf", "application/pdf", new byte[] {1, 2, 3});
+ RotatePDFRequest request = new RotatePDFRequest();
+ request.setFileInput(mockFile);
+ request.setAngle(45); // Invalid angle
+
+ // Act & Assert: Controller direkt aufrufen und Exception erwarten
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> rotationController.rotatePDF(request));
+ assertEquals("Angle must be a multiple of 90", exception.getMessage());
+ }
+}
From 4a1cec96c01088bea739eebcdeeb9c84bfe2cba5 Mon Sep 17 00:00:00 2001
From: "stirlingbot[bot]" <195170888+stirlingbot[bot]@users.noreply.github.com>
Date: Thu, 13 Mar 2025 10:38:05 +0000
Subject: [PATCH 09/12] :globe_with_meridians: Sync Translations + Update
README Progress Table (#3165)
### Description of Changes
This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:
#### **1. Synchronization of Translation Files**
- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.
#### **2. Update README.md**
- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.
#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.
---
Auto-generated by [create-pull-request][1].
[1]: https://github.com/peter-evans/create-pull-request
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
---
README.md | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index 4f07c2428..a152fddb5 100644
--- a/README.md
+++ b/README.md
@@ -120,17 +120,17 @@ Stirling-PDF currently supports 39 languages!
| Azerbaijani (Azərbaycan Dili) (az_AZ) |  |
| Basque (Euskara) (eu_ES) |  |
| Bulgarian (Български) (bg_BG) |  |
-| Catalan (Català) (ca_CA) |  |
+| Catalan (Català) (ca_CA) |  |
| Croatian (Hrvatski) (hr_HR) |  |
| Czech (Česky) (cs_CZ) |  |
| Danish (Dansk) (da_DK) |  |
-| Dutch (Nederlands) (nl_NL) |  |
+| Dutch (Nederlands) (nl_NL) |  |
| English (English) (en_GB) |  |
| English (US) (en_US) |  |
| French (Français) (fr_FR) |  |
| German (Deutsch) (de_DE) |  |
| Greek (Ελληνικά) (el_GR) |  |
-| Hindi (हिंदी) (hi_IN) |  |
+| Hindi (हिंदी) (hi_IN) |  |
| Hungarian (Magyar) (hu_HU) |  |
| Indonesian (Bahasa Indonesia) (id_ID) |  |
| Irish (Gaeilge) (ga_IE) |  |
@@ -138,7 +138,7 @@ Stirling-PDF currently supports 39 languages!
| Japanese (日本語) (ja_JP) |  |
| Korean (한국어) (ko_KR) |  |
| Norwegian (Norsk) (no_NB) |  |
-| Persian (فارسی) (fa_IR) |  |
+| Persian (فارسی) (fa_IR) |  |
| Polish (Polski) (pl_PL) |  |
| Portuguese (Português) (pt_PT) |  |
| Portuguese Brazilian (Português) (pt_BR) |  |
@@ -146,7 +146,7 @@ Stirling-PDF currently supports 39 languages!
| Russian (Русский) (ru_RU) |  |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
| Simplified Chinese (简体中文) (zh_CN) |  |
-| Slovakian (Slovensky) (sk_SK) |  |
+| Slovakian (Slovensky) (sk_SK) |  |
| Slovenian (Slovenščina) (sl_SI) |  |
| Spanish (Español) (es_ES) |  |
| Swedish (Svenska) (sv_SE) |  |
@@ -154,7 +154,7 @@ Stirling-PDF currently supports 39 languages!
| Tibetan (བོད་ཡིག་) (zh_BO) |  |
| Traditional Chinese (繁體中文) (zh_TW) |  |
| Turkish (Türkçe) (tr_TR) |  |
-| Ukrainian (Українська) (uk_UA) |  |
+| Ukrainian (Українська) (uk_UA) |  |
| Vietnamese (Tiếng Việt) (vi_VN) |  |
From bc35687e8e929b11c256993a06564fd4e1398035 Mon Sep 17 00:00:00 2001
From: "stirlingbot[bot]" <195170888+stirlingbot[bot]@users.noreply.github.com>
Date: Thu, 13 Mar 2025 10:38:37 +0000
Subject: [PATCH 10/12] Update 3rd Party Licenses (#3173)
Auto-generated by StirlingBot
Signed-off-by: stirlingbot[bot] <1113334+stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
---
src/main/resources/static/3rdPartyLicenses.json | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/src/main/resources/static/3rdPartyLicenses.json b/src/main/resources/static/3rdPartyLicenses.json
index 620eaeee6..2101765d9 100644
--- a/src/main/resources/static/3rdPartyLicenses.json
+++ b/src/main/resources/static/3rdPartyLicenses.json
@@ -530,13 +530,6 @@
"moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
- {
- "moduleName": "commons-logging:commons-logging",
- "moduleUrl": "https://commons.apache.org/proper/commons-logging/",
- "moduleVersion": "1.3.4",
- "moduleLicense": "Apache-2.0",
- "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
- },
{
"moduleName": "io.dropwizard.metrics:metrics-core",
"moduleVersion": "4.2.25",
@@ -560,7 +553,7 @@
{
"moduleName": "io.micrometer:micrometer-core",
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
- "moduleVersion": "1.14.4",
+ "moduleVersion": "1.14.5",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
From 2848ccd12e470a7eaed1fea37d4a076a33105529 Mon Sep 17 00:00:00 2001
From: Ludy
Date: Fri, 14 Mar 2025 19:18:40 +0100
Subject: [PATCH 11/12] Update springdoc plugin to 1.9.0 & Improve SwaggerHub
Configuration and Gradle Setup (#3175)
eneration
# Description of Changes
Please provide a summary of the changes, including:
- Refactored `SWAGGERHUB_USER` to use an environment variable instead of
a hardcoded value, increasing flexibility.
- Updated `.gitignore` to exclude `SwaggerDoc.json`, `node_modules/`,
and `.mjs` files.
- Upgraded `org.springdoc.openapi-gradle-plugin` from `1.8.0` to `1.9.0`
for better compatibility.
- Adjusted `openApi` configuration to increase `waitTimeInSeconds` to
`60` for improved Swagger doc generation stability.
- Ensured `swaggerhubUpload` task dynamically references
`SWAGGERHUB_USER` from environment variables.
- Improved `generateOpenApiDocs` task to disable state tracking,
avoiding unnecessary rebuilds.
---
## Checklist
### General
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---
.github/workflows/swagger.yml | 4 +++-
.gitignore | 6 ++++++
build.gradle | 24 ++++++++++++------------
3 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/swagger.yml b/.github/workflows/swagger.yml
index 95e2529e9..97ad11efc 100644
--- a/.github/workflows/swagger.yml
+++ b/.github/workflows/swagger.yml
@@ -35,6 +35,7 @@ jobs:
run: ./gradlew swaggerhubUpload
env:
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
+ SWAGGERHUB_USER: "Frooodle"
- name: Get version number
id: versionNumber
@@ -42,6 +43,7 @@ jobs:
- name: Set API version as published and default on SwaggerHub
run: |
- curl -X PUT -H "Authorization: ${SWAGGERHUB_API_KEY}" "https://api.swaggerhub.com/apis/Frooodle/Stirling-PDF/${{ steps.versionNumber.outputs.versionNumber }}/settings/lifecycle" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"published\":true,\"default\":true}"
+ curl -X PUT -H "Authorization: ${SWAGGERHUB_API_KEY}" "https://api.swaggerhub.com/apis/${SWAGGERHUB_USER}/Stirling-PDF/${{ steps.versionNumber.outputs.versionNumber }}/settings/lifecycle" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"published\":true,\"default\":true}"
env:
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
+ SWAGGERHUB_USER: "Frooodle"
diff --git a/.gitignore b/.gitignore
index e5d8ad209..90d48ccea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,8 @@ clientWebUI/
!cucumber/exampleFiles/example_html.zip
exampleYmlFiles/stirling/
/testing/file_snapshots
+SwaggerDoc.json
+
# Gradle
.gradle
.lock
@@ -188,3 +190,7 @@ id_ed25519.pub
.ipynb_checkpoints
**/jcef-bundle/
+
+# node_modules
+node_modules/
+*.mjs
diff --git a/build.gradle b/build.gradle
index bbd66361c..e225613db 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,7 +2,7 @@ plugins {
id "java"
id "org.springframework.boot" version "3.4.3"
id "io.spring.dependency-management" version "1.1.7"
- id "org.springdoc.openapi-gradle-plugin" version "1.8.0"
+ id "org.springdoc.openapi-gradle-plugin" version "1.9.0"
id "io.swagger.swaggerhub" version "1.3.2"
id "edu.sc.seis.launch4j" version "3.0.6"
id "com.diffplug.spotless" version "7.0.2"
@@ -98,6 +98,7 @@ openApi {
apiDocsUrl = "http://localhost:8080/v1/api-docs"
outputDir = file("$projectDir")
outputFileName = "SwaggerDoc.json"
+ waitTimeInSeconds = 60 // Increase the wait time to 60 seconds
}
//0.11.5 to 2024.11.5
@@ -284,6 +285,7 @@ sonar {
// }
tasks.wrapper {
gradleVersion = "8.12"
+ distributionType = Wrapper.DistributionType.ALL
}
//tasks.withType(JavaCompile) {
// options.compilerArgs << "-Xlint:deprecation"
@@ -384,19 +386,13 @@ dependencies {
//general PDF
// https://mvnrepository.com/artifact/com.opencsv/opencsv
- implementation ("com.opencsv:opencsv:5.10") {
- exclude group: "commons-logging", module: "commons-logging"
- }
+ implementation ("com.opencsv:opencsv:5.10")
- implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion") {
- exclude group: "commons-logging", module: "commons-logging"
- }
+ implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion")
implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
- implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion") {
- exclude group: "commons-logging", module: "commons-logging"
- }
+ implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion")
// https://mvnrepository.com/artifact/technology.tabula/tabula
implementation ('technology.tabula:tabula:1.0.5') {
@@ -446,9 +442,9 @@ task writeVersion {
swaggerhubUpload {
// dependsOn = generateOpenApiDocs // Depends on your task generating Swagger docs
api = "Stirling-PDF" // The name of your API on SwaggerHub
- owner = "Frooodle" // Your SwaggerHub username (or organization name)
+ owner = "${System.getenv().getOrDefault('SWAGGERHUB_USER', 'Frooodle')}" // Your SwaggerHub username (or organization name)
version = project.version // The version of your API
- inputFile = "./SwaggerDoc.json" // The path to your Swagger docs
+ inputFile = file("SwaggerDoc.json") // The path to your Swagger docs
token = "${System.getenv("SWAGGERHUB_API_KEY")}" // Your SwaggerHub API key, passed as an environment variable
oas = "3.0.0" // The version of the OpenAPI Specification you"re using
}
@@ -476,3 +472,7 @@ task printMacVersion {
println getMacVersion(project.version.toString())
}
}
+
+tasks.named('generateOpenApiDocs') {
+ doNotTrackState("Tracking state is not supported for this task")
+}
From c7a8b9f0114de07dad678e08d7e79530d232c8a9 Mon Sep 17 00:00:00 2001
From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
Date: Fri, 14 Mar 2025 21:00:06 +0000
Subject: [PATCH 12/12] Further compression fixes (#3177)
# Description of Changes
Please provide a summary of the changes, including:
- What was changed
- Why the change was made
- Any challenges encountered
Closes #(issue_number)
---
## Checklist
### General
- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---------
Co-authored-by: a
---
build.gradle | 2 +-
.../api/misc/CompressController.java | 700 ++++++++++--------
.../service/CustomPDFDocumentFactory.java | 16 +
.../resources/templates/fragments/common.html | 4 +
.../api/RotationControllerTest.java | 19 +-
5 files changed, 427 insertions(+), 314 deletions(-)
diff --git a/build.gradle b/build.gradle
index e225613db..f883c55ea 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,7 +25,7 @@ ext {
}
group = "stirling.software"
-version = "0.44.1"
+version = "0.44.2"
java {
// 17 is lowest but we support and recommend 21
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
index 167e1cb1d..7d1985cec 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
@@ -3,13 +3,19 @@ package stirling.software.SPDF.controller.api.misc;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
+import java.util.Map.Entry;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
@@ -36,11 +42,15 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.OptimizePdfRequest;
import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.SPDF.utils.GeneralUtils;
+import stirling.software.SPDF.utils.ImageProcessingUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -58,303 +68,366 @@ public class CompressController {
this.pdfDocumentFactory = pdfDocumentFactory;
}
- private void compressImagesInPDF(Path pdfFile, double scaleFactor, float jpegQuality)
+ @Data
+ @AllArgsConstructor
+ @NoArgsConstructor
+ private static class ImageReference {
+ int pageNum; // Page number where the image appears
+ COSName name; // The name used to reference this image
+ }
+
+ public Path compressImagesInPDF(
+ Path pdfFile, double scaleFactor, float jpegQuality, boolean convertToGrayscale)
throws Exception {
- byte[] fileBytes = Files.readAllBytes(pdfFile);
- long originalFileSize = fileBytes.length;
+ Path newCompressedPDF = Files.createTempFile("compressedPDF", ".pdf");
+ long originalFileSize = Files.size(pdfFile);
log.info(
- "Starting image compression with scale factor: {} and JPEG quality: {} on file"
- + " size: {}",
+ "Starting image compression with scale factor: {}, JPEG quality: {}, grayscale: {} on file size: {}",
scaleFactor,
jpegQuality,
+ convertToGrayscale,
GeneralUtils.formatBytes(originalFileSize));
- // Track processed images to avoid recompression
- Set processedImages = new HashSet<>();
+ try (PDDocument doc = pdfDocumentFactory.load(pdfFile)) {
+
+ // Collect all unique images by content hash
+ Map> uniqueImages = new HashMap<>();
+ Map compressedVersions = new HashMap<>();
- try (PDDocument doc = pdfDocumentFactory.load(fileBytes)) {
int totalImages = 0;
+
+ for (int pageNum = 0; pageNum < doc.getNumberOfPages(); pageNum++) {
+ PDPage page = doc.getPage(pageNum);
+ PDResources res = page.getResources();
+ if (res == null || res.getXObjectNames() == null) continue;
+
+ for (COSName name : res.getXObjectNames()) {
+ PDXObject xobj = res.getXObject(name);
+ if (!(xobj instanceof PDImageXObject)) continue;
+
+ totalImages++;
+ PDImageXObject image = (PDImageXObject) xobj;
+ String imageHash = generateImageHash(image);
+
+ // Store only page number and name reference
+ ImageReference ref = new ImageReference();
+ ref.pageNum = pageNum;
+ ref.name = name;
+
+ uniqueImages.computeIfAbsent(imageHash, k -> new ArrayList<>()).add(ref);
+ }
+ }
+
+ int uniqueImagesCount = uniqueImages.size();
+ int duplicatedImages = totalImages - uniqueImagesCount;
+ log.info(
+ "Found {} unique images and {} duplicated instances across {} pages",
+ uniqueImagesCount,
+ duplicatedImages,
+ doc.getNumberOfPages());
+
+ // SECOND PASS: Process each unique image exactly once
int compressedImages = 0;
int skippedImages = 0;
long totalOriginalBytes = 0;
long totalCompressedBytes = 0;
- // Minimum dimensions to preserve reasonable quality
- int MIN_WIDTH = 400; // Higher minimum
- int MIN_HEIGHT = 400; // Higher minimum
+ for (Entry> entry : uniqueImages.entrySet()) {
+ String imageHash = entry.getKey();
+ List references = entry.getValue();
- log.info("PDF has {} pages", doc.getNumberOfPages());
+ if (references.isEmpty()) continue;
- for (int pageNum = 0; pageNum < doc.getNumberOfPages(); pageNum++) {
- PDPage page = doc.getPage(pageNum);
- PDResources res = page.getResources();
+ // Get the first instance of this image
+ ImageReference firstRef = references.get(0);
+ PDPage firstPage = doc.getPage(firstRef.pageNum);
+ PDResources firstPageResources = firstPage.getResources();
+ PDImageXObject originalImage =
+ (PDImageXObject) firstPageResources.getXObject(firstRef.name);
- if (res == null || res.getXObjectNames() == null) {
- continue;
- }
+ // Track original size
+ int originalSize = (int) originalImage.getCOSObject().getLength();
+ totalOriginalBytes += originalSize;
- int pageImages = 0;
+ // Process this unique image once
+ BufferedImage processedImage =
+ processAndCompressImage(
+ originalImage, scaleFactor, jpegQuality, convertToGrayscale);
- for (COSName name : res.getXObjectNames()) {
- String imageName = name.getName();
+ if (processedImage != null) {
+ // Convert to bytes for storage
+ byte[] compressedData = convertToBytes(processedImage, jpegQuality);
- // Skip already processed images
- if (processedImages.contains(imageName)) {
- skippedImages++;
- continue;
- }
+ // Check if compression is beneficial
+ if (compressedData.length < originalSize || convertToGrayscale) {
+ // Create a single compressed version
+ PDImageXObject compressedImage =
+ PDImageXObject.createFromByteArray(
+ doc,
+ compressedData,
+ originalImage.getCOSObject().toString());
- PDXObject xobj = res.getXObject(name);
- if (!(xobj instanceof PDImageXObject)) {
- continue;
- }
+ // Store the compressed version only once in our map
+ compressedVersions.put(imageHash, compressedImage);
- totalImages++;
- pageImages++;
- PDImageXObject image = (PDImageXObject) xobj;
- BufferedImage bufferedImage = image.getImage();
-
- int originalWidth = bufferedImage.getWidth();
- int originalHeight = bufferedImage.getHeight();
-
- log.info(
- "Page {}, Image {}: Original dimensions: {}x{}",
- pageNum + 1,
- imageName,
- originalWidth,
- originalHeight);
-
- // Skip if already small enough
- if (originalWidth <= MIN_WIDTH || originalHeight <= MIN_HEIGHT) {
+ // Report compression stats
+ double reductionPercentage =
+ 100.0 - ((compressedData.length * 100.0) / originalSize);
log.info(
- "Page {}, Image {}: Skipping - below minimum dimensions threshold",
- pageNum + 1,
- imageName);
- skippedImages++;
- processedImages.add(imageName);
- continue;
- }
+ "Image hash {}: Compressed from {} to {} (reduced by {}%)",
+ imageHash,
+ GeneralUtils.formatBytes(originalSize),
+ GeneralUtils.formatBytes(compressedData.length),
+ String.format("%.1f", reductionPercentage));
- // Adjust scale factor for very large or very small images
- double adjustedScaleFactor = scaleFactor;
- if (originalWidth > 3000 || originalHeight > 3000) {
- // More aggressive for very large images
- adjustedScaleFactor = Math.min(scaleFactor, 0.75);
- log.info(
- "Page {}, Image {}: Very large image, using more aggressive scale:"
- + " {}",
- pageNum + 1,
- imageName,
- adjustedScaleFactor);
- } else if (originalWidth < 1000 || originalHeight < 1000) {
- // More conservative for smaller images
- adjustedScaleFactor = Math.max(scaleFactor, 0.9);
- log.info(
- "Page {}, Image {}: Smaller image, using conservative scale: {}",
- pageNum + 1,
- imageName,
- adjustedScaleFactor);
- }
+ // Replace ALL instances with the compressed version
+ for (ImageReference ref : references) {
+ // Get the page and resources when needed
+ PDPage page = doc.getPage(ref.pageNum);
+ PDResources resources = page.getResources();
+ resources.put(ref.name, compressedImage);
- int newWidth = (int) (originalWidth * adjustedScaleFactor);
- int newHeight = (int) (originalHeight * adjustedScaleFactor);
-
- // Ensure minimum dimensions
- newWidth = Math.max(newWidth, MIN_WIDTH);
- newHeight = Math.max(newHeight, MIN_HEIGHT);
-
- // Skip if change is negligible
- if ((double) newWidth / originalWidth > 0.95
- && (double) newHeight / originalHeight > 0.95) {
- log.info(
- "Page {}, Image {}: Change too small, skipping compression",
- pageNum + 1,
- imageName);
- skippedImages++;
- processedImages.add(imageName);
- continue;
- }
-
- log.info(
- "Page {}, Image {}: Resizing to {}x{} ({}% of original)",
- pageNum + 1,
- imageName,
- newWidth,
- newHeight,
- Math.round((newWidth * 100.0) / originalWidth));
-
- // Use high quality scaling
- BufferedImage scaledImage =
- new BufferedImage(
- newWidth,
- newHeight,
- bufferedImage.getColorModel().hasAlpha()
- ? BufferedImage.TYPE_INT_ARGB
- : BufferedImage.TYPE_INT_RGB);
-
- Graphics2D g2d = scaledImage.createGraphics();
- g2d.setRenderingHint(
- RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_BICUBIC);
- g2d.setRenderingHint(
- RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
- g2d.setRenderingHint(
- RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g2d.drawImage(bufferedImage, 0, 0, newWidth, newHeight, null);
- g2d.dispose();
-
- // Choose appropriate format and compression
- String format = bufferedImage.getColorModel().hasAlpha() ? "png" : "jpeg";
-
- // First get the actual size of the original image by encoding it to the chosen
- // format
- ByteArrayOutputStream originalImageStream = new ByteArrayOutputStream();
- if ("jpeg".equals(format)) {
- // Get the best available JPEG writer (prioritizes TwelveMonkeys if
- // available)
- Iterator writers = ImageIO.getImageWritersByFormatName("jpeg");
- ImageWriter writer = null;
-
- // Prefer TwelveMonkeys writer if available
- while (writers.hasNext()) {
- ImageWriter candidate = writers.next();
- if (candidate.getClass().getName().contains("twelvemonkeys")) {
- writer = candidate;
- break;
- }
- }
- if (writer == null) {
- writer = ImageIO.getImageWritersByFormatName("jpeg").next();
+ log.info(
+ "Replaced image on page {} with compressed version",
+ ref.pageNum + 1);
}
- JPEGImageWriteParam param =
- (JPEGImageWriteParam) writer.getDefaultWriteParam();
-
- // Set advanced compression parameters
- param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- param.setCompressionQuality(jpegQuality);
- param.setOptimizeHuffmanTables(true); // Better compression
- param.setProgressiveMode(
- ImageWriteParam.MODE_DEFAULT); // Progressive scanning
-
- // Write compressed image
- try (ImageOutputStream ios =
- ImageIO.createImageOutputStream(originalImageStream)) {
- writer.setOutput(ios);
- writer.write(null, new IIOImage(scaledImage, null, null), param);
- }
- writer.dispose();
+ totalCompressedBytes += compressedData.length * references.size();
+ compressedImages++;
} else {
- ImageIO.write(bufferedImage, format, originalImageStream);
- }
- int originalEncodedSize = (int) image.getCOSObject().getLength();
- originalImageStream.close();
-
- // Now compress the scaled image
- ByteArrayOutputStream compressedImageStream = new ByteArrayOutputStream();
- if ("jpeg".equals(format)) {
- Iterator writers = ImageIO.getImageWritersByFormatName(format);
- if (writers.hasNext()) {
- ImageWriter writer = writers.next();
- ImageWriteParam param = writer.getDefaultWriteParam();
-
- if (param.canWriteCompressed()) {
- param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- param.setCompressionQuality(jpegQuality);
-
- ImageOutputStream imageOut =
- ImageIO.createImageOutputStream(compressedImageStream);
- writer.setOutput(imageOut);
- writer.write(null, new IIOImage(scaledImage, null, null), param);
- writer.dispose();
- imageOut.close();
- } else {
- ImageIO.write(scaledImage, format, compressedImageStream);
- }
- } else {
- ImageIO.write(scaledImage, format, compressedImageStream);
- }
- } else {
- ImageIO.write(scaledImage, format, compressedImageStream);
- }
- byte[] imageBytes = compressedImageStream.toByteArray();
- compressedImageStream.close();
-
- // Format sizes using our utility method
- String originalSizeStr = GeneralUtils.formatBytes(originalEncodedSize);
- String compressedSizeStr = GeneralUtils.formatBytes(imageBytes.length);
-
- // Calculate reduction percentage (how much smaller the new file is)
- double reductionPercentage =
- 100.0 - ((imageBytes.length * 100.0) / originalEncodedSize);
-
- if (imageBytes.length >= originalEncodedSize) {
- log.info(
- "Page {}, Image {}: Compressed size {} not smaller than original"
- + " {}, skipping replacement",
- pageNum + 1,
- imageName,
- GeneralUtils.formatBytes(imageBytes.length),
- GeneralUtils.formatBytes(originalEncodedSize));
-
- // Accumulate original size for both counters (no change)
- totalOriginalBytes += originalEncodedSize;
- totalCompressedBytes += originalEncodedSize;
+ log.info("Image hash {}: Compression not beneficial, skipping", imageHash);
+ totalCompressedBytes += originalSize * references.size();
skippedImages++;
- processedImages.add(imageName);
- continue;
}
- log.info(
- "Page {}, Image {}: Compressed from {} to {} (reduced by {}%)",
- pageNum + 1,
- imageName,
- originalSizeStr,
- compressedSizeStr,
- String.format("%.1f", reductionPercentage));
-
- // Only replace if compressed size is smaller
- PDImageXObject compressedImage =
- PDImageXObject.createFromByteArray(
- doc, imageBytes, image.getCOSObject().toString());
- res.put(name, compressedImage);
-
- // Update counters with compressed size
- totalOriginalBytes += originalEncodedSize;
- totalCompressedBytes += imageBytes.length;
- compressedImages++;
- processedImages.add(imageName);
+ } else {
+ log.info("Image hash {}: Not suitable for compression, skipping", imageHash);
+ totalCompressedBytes += originalSize * references.size();
+ skippedImages++;
}
}
- // Log overall image compression statistics
+ // Log compression statistics
double overallImageReduction =
totalOriginalBytes > 0
? 100.0 - ((totalCompressedBytes * 100.0) / totalOriginalBytes)
: 0;
log.info(
- "Image compression summary - Total: {}, Compressed: {}, Skipped: {}",
- totalImages,
+ "Image compression summary - Total unique: {}, Compressed: {}, Skipped: {}, Duplicates: {}",
+ uniqueImagesCount,
compressedImages,
- skippedImages);
+ skippedImages,
+ duplicatedImages);
log.info(
"Total original image size: {}, compressed: {} (reduced by {}%)",
GeneralUtils.formatBytes(totalOriginalBytes),
GeneralUtils.formatBytes(totalCompressedBytes),
String.format("%.1f", overallImageReduction));
+ // Free memory before saving
+ compressedVersions.clear();
+ uniqueImages.clear();
+
// Save the document
- log.info("Saving compressed PDF to {}", pdfFile.toString());
- doc.save(pdfFile.toString());
+ log.info("Saving compressed PDF to {}", newCompressedPDF.toString());
+ doc.save(newCompressedPDF.toString());
// Log overall file size reduction
- long compressedFileSize = Files.size(pdfFile);
+ long compressedFileSize = Files.size(newCompressedPDF);
double overallReduction = 100.0 - ((compressedFileSize * 100.0) / originalFileSize);
log.info(
"Overall PDF compression: {} → {} (reduced by {}%)",
GeneralUtils.formatBytes(originalFileSize),
GeneralUtils.formatBytes(compressedFileSize),
String.format("%.1f", overallReduction));
+ return newCompressedPDF;
+ }
+
+ }
+
+ private BufferedImage convertToGrayscale(BufferedImage image) {
+ BufferedImage grayImage =
+ new BufferedImage(
+ image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
+
+ Graphics2D g = grayImage.createGraphics();
+ g.drawImage(image, 0, 0, null);
+ g.dispose();
+
+ return grayImage;
+ }
+
+ /**
+ * Processes and compresses an image if beneficial. Returns the processed image if compression
+ * is worthwhile, null otherwise.
+ */
+ private BufferedImage processAndCompressImage(
+ PDImageXObject image, double scaleFactor, float jpegQuality, boolean convertToGrayscale)
+ throws IOException {
+ BufferedImage bufferedImage = image.getImage();
+ int originalWidth = bufferedImage.getWidth();
+ int originalHeight = bufferedImage.getHeight();
+
+ // Minimum dimensions to preserve reasonable quality
+ int MIN_WIDTH = 400;
+ int MIN_HEIGHT = 400;
+
+ log.info("Original dimensions: {}x{}", originalWidth, originalHeight);
+
+ // Skip if already small enough
+ if ((originalWidth <= MIN_WIDTH || originalHeight <= MIN_HEIGHT) && !convertToGrayscale) {
+ log.info("Skipping - below minimum dimensions threshold");
+ return null;
+ }
+
+ // Convert to grayscale first if requested (before resizing for better quality)
+ if (convertToGrayscale) {
+ bufferedImage = convertToGrayscale(bufferedImage);
+ log.info("Converted image to grayscale");
+ }
+
+ // Adjust scale factor for very large or very small images
+ double adjustedScaleFactor = scaleFactor;
+ if (originalWidth > 3000 || originalHeight > 3000) {
+ // More aggressive for very large images
+ adjustedScaleFactor = Math.min(scaleFactor, 0.75);
+ log.info("Very large image, using more aggressive scale: {}", adjustedScaleFactor);
+ } else if (originalWidth < 1000 || originalHeight < 1000) {
+ // More conservative for smaller images
+ adjustedScaleFactor = Math.max(scaleFactor, 0.9);
+ log.info("Smaller image, using conservative scale: {}", adjustedScaleFactor);
+ }
+
+ int newWidth = (int) (originalWidth * adjustedScaleFactor);
+ int newHeight = (int) (originalHeight * adjustedScaleFactor);
+
+ // Ensure minimum dimensions
+ newWidth = Math.max(newWidth, MIN_WIDTH);
+ newHeight = Math.max(newHeight, MIN_HEIGHT);
+
+ // Skip if change is negligible
+ if ((double) newWidth / originalWidth > 0.95
+ && (double) newHeight / originalHeight > 0.95
+ && !convertToGrayscale) {
+ log.info("Change too small, skipping compression");
+ return null;
+ }
+
+ log.info(
+ "Resizing to {}x{} ({}% of original)",
+ newWidth, newHeight, Math.round((newWidth * 100.0) / originalWidth));
+
+ BufferedImage scaledImage;
+ if (convertToGrayscale) {
+ // If already grayscale, maintain the grayscale format
+ scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_BYTE_GRAY);
+ } else {
+ // Otherwise use original color model
+ scaledImage =
+ new BufferedImage(
+ newWidth,
+ newHeight,
+ bufferedImage.getColorModel().hasAlpha()
+ ? BufferedImage.TYPE_INT_ARGB
+ : BufferedImage.TYPE_INT_RGB);
+ }
+ Graphics2D g2d = scaledImage.createGraphics();
+ g2d.setRenderingHint(
+ RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.drawImage(bufferedImage, 0, 0, newWidth, newHeight, null);
+ g2d.dispose();
+
+ return scaledImage;
+ }
+
+ /**
+ * Converts a BufferedImage to a byte array with specified JPEG quality. Checks if compression
+ * is beneficial compared to original.
+ */
+ private byte[] convertToBytes(BufferedImage scaledImage, float jpegQuality) throws IOException {
+ String format = scaledImage.getColorModel().hasAlpha() ? "png" : "jpeg";
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ if ("jpeg".equals(format)) {
+ // Get the best available JPEG writer
+ Iterator writers = ImageIO.getImageWritersByFormatName("jpeg");
+ ImageWriter writer = writers.next();
+
+ JPEGImageWriteParam param = (JPEGImageWriteParam) writer.getDefaultWriteParam();
+
+ // Set compression parameters
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param.setCompressionQuality(jpegQuality);
+ param.setOptimizeHuffmanTables(true); // Better compression
+ param.setProgressiveMode(ImageWriteParam.MODE_DEFAULT); // Progressive scanning
+
+ // Write compressed image
+ try (ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream)) {
+ writer.setOutput(ios);
+ writer.write(null, new IIOImage(scaledImage, null, null), param);
+ }
+ writer.dispose();
+ } else {
+ ImageIO.write(scaledImage, format, outputStream);
+ }
+
+ return outputStream.toByteArray();
+ }
+
+ /** Modified hash function to consistently identify identical image content */
+ private String generateImageHash(PDImageXObject image) {
+ try {
+ // Create a stream for the raw stream data
+ try (InputStream stream = image.getCOSObject().createRawInputStream()) {
+ // Read up to first 8KB of data for the hash
+ byte[] buffer = new byte[8192];
+ int bytesRead = stream.read(buffer);
+ if (bytesRead > 0) {
+ byte[] dataToHash =
+ bytesRead == buffer.length ? buffer : Arrays.copyOf(buffer, bytesRead);
+ return bytesToHexString(generatMD5(dataToHash));
+ }
+ return "empty-stream";
+ }
+ } catch (Exception e) {
+ log.error("Error generating image hash", e);
+ return "fallback-" + System.identityHashCode(image);
+ }
+ }
+
+ private String bytesToHexString(byte[] bytes) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(String.format("%02x", b));
+ }
+ return sb.toString();
+ }
+
+ private byte[] generatMD5(byte[] data) throws IOException {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ return md.digest(data); // Get the MD5 hash of the image bytes
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("MD5 algorithm not available", e);
+ }
+ }
+
+ private byte[] generateImageMD5(PDImageXObject image) throws IOException {
+ return generatMD5(ImageProcessingUtils.getImageData(image.getImage()));
+ }
+
+ /** Generates a hash string from a byte array */
+ private String generateHashFromBytes(byte[] data) {
+ try {
+ // Use the existing method to generate MD5 hash
+ byte[] hash = generatMD5(data);
+ return bytesToHexString(hash);
+ } catch (Exception e) {
+ log.error("Error generating hash from bytes", e);
+ // Return a unique string as fallback
+ return "fallback-" + System.identityHashCode(data);
}
}
@@ -392,7 +465,7 @@ public class CompressController {
MultipartFile inputFile = request.getFileInput();
Integer optimizeLevel = request.getOptimizeLevel();
String expectedOutputSizeString = request.getExpectedOutputSize();
-
+ Boolean convertToGrayscale = request.getGrayscale();
if (expectedOutputSizeString == null && optimizeLevel == null) {
throw new Exception("Both expected output size and optimize level are not specified");
}
@@ -404,48 +477,61 @@ public class CompressController {
autoMode = true;
}
- Path tempInputFile = Files.createTempFile("input_", ".pdf");
- inputFile.transferTo(tempInputFile.toFile());
-
- long inputFileSize = Files.size(tempInputFile);
-
- Path tempOutputFile = null;
- byte[] pdfBytes;
+ // Create initial input file
+ Path originalFile = Files.createTempFile("input_", ".pdf");
+ inputFile.transferTo(originalFile.toFile());
+ long inputFileSize = Files.size(originalFile);
+
+ // Start with original as current working file
+ Path currentFile = originalFile;
+
+ // Keep track of all temporary files for cleanup
+ List tempFiles = new ArrayList<>();
+ tempFiles.add(originalFile);
+
try {
- tempOutputFile = Files.createTempFile("output_", ".pdf");
-
if (autoMode) {
double sizeReductionRatio = expectedOutputSize / (double) inputFileSize;
optimizeLevel = determineOptimizeLevel(sizeReductionRatio);
}
boolean sizeMet = false;
- boolean imageCompressionApplied = false; // Track if we've already compressed images
+ boolean imageCompressionApplied = false;
boolean qpdfCompressionApplied = false;
while (!sizeMet && optimizeLevel <= 9) {
- // Apply appropriate compression based on level
-
- // Levels 4-9: Apply image compression
- if (optimizeLevel >= 4 && !imageCompressionApplied) {
+ // Apply image compression for levels 4-9
+ if ((optimizeLevel >= 4 || Boolean.TRUE.equals(convertToGrayscale))
+ && !imageCompressionApplied) {
double scaleFactor = getScaleFactorForLevel(optimizeLevel);
float jpegQuality = getJpegQualityForLevel(optimizeLevel);
- compressImagesInPDF(tempInputFile, scaleFactor, jpegQuality);
- imageCompressionApplied = true; // Mark that we've compressed images
+
+ // Use the returned path from compressImagesInPDF
+ Path compressedImageFile = compressImagesInPDF(
+ currentFile,
+ scaleFactor,
+ jpegQuality,
+ Boolean.TRUE.equals(convertToGrayscale));
+
+ // Add to temp files list and update current file
+ tempFiles.add(compressedImageFile);
+ currentFile = compressedImageFile;
+ imageCompressionApplied = true;
}
- // All levels (1-9): Apply QPDF compression
+ // Apply QPDF compression for all levels
if (!qpdfCompressionApplied) {
- long preQpdfSize = Files.size(tempInputFile);
+ long preQpdfSize = Files.size(currentFile);
log.info("Pre-QPDF file size: {}", GeneralUtils.formatBytes(preQpdfSize));
- // For levels 1-3, map to qpdf compression levels 1-9
- int qpdfCompressionLevel = optimizeLevel;
- if (optimizeLevel <= 3) {
- qpdfCompressionLevel = optimizeLevel * 3; // Level 1->3, 2->6, 3->9
- } else {
- qpdfCompressionLevel = 9; // Max QPDF compression for levels 4-9
- }
+ // Map optimization levels to QPDF compression levels
+ int qpdfCompressionLevel = optimizeLevel <= 3
+ ? optimizeLevel * 3 // Level 1->3, 2->6, 3->9
+ : 9; // Max compression for levels 4-9
+
+ // Create output file for QPDF
+ Path qpdfOutputFile = Files.createTempFile("qpdf_output_", ".pdf");
+ tempFiles.add(qpdfOutputFile);
// Run QPDF optimization
List command = new ArrayList<>();
@@ -460,49 +546,50 @@ public class CompressController {
command.add("--compression-level=" + qpdfCompressionLevel);
command.add("--compress-streams=y");
command.add("--object-streams=generate");
- command.add(tempInputFile.toString());
- command.add(tempOutputFile.toString());
+ command.add(currentFile.toString());
+ command.add(qpdfOutputFile.toString());
ProcessExecutorResult returnCode = null;
try {
- returnCode =
- ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
- .runCommandWithOutputHandling(command);
+ returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.QPDF)
+ .runCommandWithOutputHandling(command);
qpdfCompressionApplied = true;
+
+ // Update current file to the QPDF output
+ currentFile = qpdfOutputFile;
+
+ long postQpdfSize = Files.size(currentFile);
+ double qpdfReduction = 100.0 - ((postQpdfSize * 100.0) / preQpdfSize);
+ log.info(
+ "Post-QPDF file size: {} (reduced by {}%)",
+ GeneralUtils.formatBytes(postQpdfSize),
+ String.format("%.1f", qpdfReduction));
+
} catch (Exception e) {
if (returnCode != null && returnCode.getRc() != 3) {
throw e;
}
+ // If QPDF fails, keep using the current file
+ log.warn("QPDF compression failed, continuing with current file");
}
- long postQpdfSize = Files.size(tempOutputFile);
- double qpdfReduction = 100.0 - ((postQpdfSize * 100.0) / preQpdfSize);
- log.info(
- "Post-QPDF file size: {} (reduced by {}%)",
- GeneralUtils.formatBytes(postQpdfSize), String.format("%.1f", qpdfReduction));
-
- } else {
- tempOutputFile = tempInputFile;
}
// Check if file size is within expected size or not auto mode
- long outputFileSize = Files.size(tempOutputFile);
+ long outputFileSize = Files.size(currentFile);
if (outputFileSize <= expectedOutputSize || !autoMode) {
sizeMet = true;
} else {
- int newOptimizeLevel =
- incrementOptimizeLevel(
- optimizeLevel, outputFileSize, expectedOutputSize);
+ int newOptimizeLevel = incrementOptimizeLevel(
+ optimizeLevel, outputFileSize, expectedOutputSize);
// Check if we can't increase the level further
if (newOptimizeLevel == optimizeLevel) {
if (autoMode) {
- log.info(
- "Maximum optimization level reached without meeting target"
- + " size.");
+ log.info("Maximum optimization level reached without meeting target size.");
sizeMet = true;
}
} else {
- // Reset image compression if moving to a new level
+ // Reset flags for next iteration with higher optimization level
imageCompressionApplied = false;
qpdfCompressionApplied = false;
optimizeLevel = newOptimizeLevel;
@@ -510,27 +597,30 @@ public class CompressController {
}
}
- // Read the optimized PDF file
- pdfBytes = Files.readAllBytes(tempOutputFile);
- Path finalFile = tempOutputFile;
-
// Check if optimized file is larger than the original
- if (pdfBytes.length > inputFileSize) {
- log.warn(
- "Optimized file is larger than the original. Returning the original file"
- + " instead.");
- finalFile = tempInputFile;
+ long finalFileSize = Files.size(currentFile);
+ if (finalFileSize > inputFileSize) {
+ log.warn("Optimized file is larger than the original. Using the original file instead.");
+ // Use the stored reference to the original file
+ currentFile = originalFile;
}
- String outputFilename =
- Filenames.toSimpleFileName(inputFile.getOriginalFilename())
+ String outputFilename = Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_Optimized.pdf";
+
return WebResponseUtils.pdfDocToWebResponse(
- pdfDocumentFactory.load(finalFile.toFile()), outputFilename);
+ pdfDocumentFactory.load(currentFile.toFile()), outputFilename);
} finally {
- Files.deleteIfExists(tempOutputFile);
+ // Clean up all temporary files
+ for (Path tempFile : tempFiles) {
+ try {
+ Files.deleteIfExists(tempFile);
+ } catch (IOException e) {
+ log.warn("Failed to delete temporary file: " + tempFile, e);
+ }
+ }
}
}
diff --git a/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java
index 5aa6ee335..354324744 100644
--- a/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java
+++ b/src/main/java/stirling/software/SPDF/service/CustomPDFDocumentFactory.java
@@ -82,6 +82,21 @@ public class CustomPDFDocumentFactory {
return loadAdaptively(file, fileSize);
}
+ /**
+ * Main entry point for loading a PDF document from a Path. Automatically selects the most
+ * appropriate loading strategy.
+ */
+ public PDDocument load(Path path) throws IOException {
+ if (path == null) {
+ throw new IllegalArgumentException("File cannot be null");
+ }
+
+ long fileSize = Files.size(path);
+ log.info("Loading PDF from file, size: {}MB", fileSize / (1024 * 1024));
+
+ return loadAdaptively(path.toFile(), fileSize);
+ }
+
/** Load a PDF from byte array with automatic optimization. */
public PDDocument load(byte[] input) throws IOException {
if (input == null) {
@@ -246,6 +261,7 @@ public class CustomPDFDocumentFactory {
removePassword(doc);
}
+
private PDDocument loadFromFile(File file, long size, StreamCacheCreateFunction cache)
throws IOException {
return Loader.loadPDF(new DeletingRandomAccessFile(file), "", null, null, cache);
diff --git a/src/main/resources/templates/fragments/common.html b/src/main/resources/templates/fragments/common.html
index 28c7b0225..1e801d06f 100644
--- a/src/main/resources/templates/fragments/common.html
+++ b/src/main/resources/templates/fragments/common.html
@@ -34,11 +34,15 @@
+
+
+
+
diff --git a/src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java b/src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java
index edd9cada1..ec84b0e4c 100644
--- a/src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java
+++ b/src/test/java/stirling/software/SPDF/controller/api/RotationControllerTest.java
@@ -1,24 +1,27 @@
package stirling.software.SPDF.controller.api;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import java.io.IOException;
-import org.apache.pdfbox.pdmodel.PDPageTree;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageTree;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
-import stirling.software.SPDF.service.CustomPDFDocumentFactory;
+
import stirling.software.SPDF.model.api.general.RotatePDFRequest;
+import stirling.software.SPDF.service.CustomPDFDocumentFactory;
@ExtendWith(MockitoExtension.class)
public class RotationControllerTest {