mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 11:23:10 +02:00
## Summary Migrates `SplitPDFController`, `SplitPdfByChaptersController`, `SplitPdfBySizeController` from PDFBox to JPDFium. `SplitPdfBySectionsController` and `AutoSplitPdfController` are intentionally left on PDFBox (require JPDFium 1.0.2 features that don't exist yet). ## Benchmark (audited on `audit/jpdfium-split`, file `app/core/src/test/java/stirling/software/SPDF/bench/SplitBenchmark.java`) | Workload | PDFBox heap | JPDFium heap | PDFBox wall | JPDFium wall | |---|---|---|---|---| | 100 pp, chunk 10 | +21-26 MB | **+0.02 MB** | 80-106 ms | **25 ms** | | 300 pp, chunk 10 | +59 MB | **+1.0 MB** | 232 ms | **76 ms** | **98-99.9% heap reduction. 3-4.2x faster wall.** ## Hybrid - AcroForm-bearing splits keep PDFBox `FormUtils.pruneOrphanedFormFields` post-pass (FPDF_ImportPagesByIndex drops AcroForm dict). Sub-bench shows +1.0 MB / +27 ms - tightly bounded. - Metadata extraction stays on PDFBox. - `SplitPdfBySectionsController` - JPDFium `PdfPageSplitter` only does 2-up halving, not arbitrary MxN. - `AutoSplitPdfController` - needs PDFRenderer + zxing for QR markers. ## Test plan - [ ] 30/30 unit tests pass with PDFBox `Loader.loadPDF` as the oracle (assert page counts + document totals) - [ ] Existing cucumber feature `split.feature` continues to pass - [ ] AcroForm-bearing PDF round-trips without orphaned widgets (covered by existing FormUtils tests)
112 lines
3.4 KiB
Bash
112 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|
# Sign every .dylib inside the bootJar's JPDFium native jars.
|
|
# Requires APPLE_SIGNING_IDENTITY set to a Developer ID identity in the keychain.
|
|
#
|
|
# Usage: sign-jpdfium-dylibs-in-bootjar.sh [path/to/stirling-pdf-*.jar]
|
|
|
|
set -u
|
|
|
|
echo "sign-jpdfium-dylibs-in-bootjar.sh: start ($(uname -s) $(uname -m))"
|
|
|
|
case "$(uname -s)" in
|
|
Darwin*) ;;
|
|
*) echo "Not macOS, skipping"; exit 0;;
|
|
esac
|
|
|
|
if [ -z "${APPLE_SIGNING_IDENTITY:-}" ]; then
|
|
echo "APPLE_SIGNING_IDENTITY not set; skipping"
|
|
exit 0
|
|
fi
|
|
if ! command -v codesign >/dev/null 2>&1; then
|
|
echo "codesign not on PATH; skipping"
|
|
exit 0
|
|
fi
|
|
if ! command -v jar >/dev/null 2>&1; then
|
|
echo "jar not on PATH (need a JDK setup-action earlier); skipping"
|
|
exit 0
|
|
fi
|
|
|
|
BOOTJARS=()
|
|
if [ -n "${1:-}" ]; then
|
|
BOOTJARS+=("$1")
|
|
else
|
|
for cand in app/core/build/libs/stirling-pdf-*.jar \
|
|
frontend/editor/src-tauri/libs/stirling-pdf-*.jar; do
|
|
[ -f "$cand" ] || continue
|
|
BOOTJARS+=("$cand")
|
|
done
|
|
fi
|
|
if [ "${#BOOTJARS[@]:-0}" = 0 ]; then
|
|
echo "bootJar not found (expected app/core/build/libs/stirling-pdf-*.jar" \
|
|
"or frontend/editor/src-tauri/libs/stirling-pdf-*.jar)"
|
|
exit 0
|
|
fi
|
|
|
|
for BOOTJAR in "${BOOTJARS[@]}"; do
|
|
BOOTJAR=$(cd "$(dirname "$BOOTJAR")" && pwd)/$(basename "$BOOTJAR")
|
|
echo ""
|
|
echo "=== Target bootJar: $BOOTJAR ($(du -h "$BOOTJAR" | cut -f1)) ==="
|
|
|
|
WORK=$(mktemp -d)
|
|
# shellcheck disable=SC2064
|
|
trap "rm -rf '$WORK'" EXIT
|
|
|
|
NATIVE_JAR_PATHS=()
|
|
while IFS= read -r line; do
|
|
[ -n "$line" ] || continue
|
|
NATIVE_JAR_PATHS+=("$line")
|
|
done < <(jar tf "$BOOTJAR" \
|
|
| grep -E '^BOOT-INF/lib/jpdfium-natives-darwin-(x64|arm64)-.*\.jar$' || true)
|
|
|
|
if [ "${#NATIVE_JAR_PATHS[@]:-0}" = 0 ]; then
|
|
echo " No JPDFium darwin natives in this bootJar; skipping"
|
|
rm -rf "$WORK"
|
|
continue
|
|
fi
|
|
|
|
( cd "$WORK" && jar xf "$BOOTJAR" ${NATIVE_JAR_PATHS[@]+"${NATIVE_JAR_PATHS[@]}"} ) \
|
|
|| { echo "jar xf failed to extract natives jars" >&2; exit 1; }
|
|
|
|
ANY_SIGNED=0
|
|
for nat_jar in "$WORK/BOOT-INF/lib"/jpdfium-natives-darwin-*.jar; do
|
|
[ -f "$nat_jar" ] || continue
|
|
base=$(basename "$nat_jar")
|
|
echo " Processing $base"
|
|
|
|
exp_dir="$WORK/${base%.jar}.expanded"
|
|
mkdir -p "$exp_dir"
|
|
( cd "$exp_dir" && jar xf "$nat_jar" )
|
|
|
|
signed=0
|
|
while IFS= read -r dylib; do
|
|
codesign --force --sign "$APPLE_SIGNING_IDENTITY" \
|
|
--options runtime --timestamp "$dylib" 2>&1 | sed 's/^/ /'
|
|
signed=$((signed + 1))
|
|
done < <(find "$exp_dir" -name '*.dylib' -type f)
|
|
|
|
if [ "$signed" = 0 ]; then
|
|
echo " (no .dylibs found)"
|
|
continue
|
|
fi
|
|
echo " signed $signed dylib(s)"
|
|
|
|
rm -f "$nat_jar"
|
|
( cd "$exp_dir" && jar cfM0 "$nat_jar" . )
|
|
ANY_SIGNED=1
|
|
done
|
|
|
|
if [ "$ANY_SIGNED" = 0 ]; then
|
|
echo " No .dylibs signed; skipping update"
|
|
rm -rf "$WORK"
|
|
continue
|
|
fi
|
|
|
|
# `jar uf` always DEFLATEs; Spring Boot's nested-jar loader only reads
|
|
# STORED entries. Use `zip -0` to update in place with no compression.
|
|
( cd "$WORK" && zip -q0 "$BOOTJAR" ${NATIVE_JAR_PATHS[@]+"${NATIVE_JAR_PATHS[@]}"} ) \
|
|
|| { echo "zip update failed" >&2; exit 1; }
|
|
|
|
echo " Updated: $BOOTJAR ($(du -h "$BOOTJAR" | cut -f1))"
|
|
rm -rf "$WORK"
|
|
done
|