From d3d9966a210e01e687468354b37c4f507c749847 Mon Sep 17 00:00:00 2001 From: Karl Kauc Date: Fri, 15 May 2026 23:10:15 +0200 Subject: [PATCH] Phase 1: Java examples standalone & cross-platform via Maven MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the bash-only Java toolchain (tools/fetch-tools.sh + raw javac + .lib/ ":"-classpaths + run-*.sh wrappers) with a standard Maven build so every Java example runs on Windows too, with no prior tool step. - Root pom.xml aggregator + committed Maven Wrapper (mvnw/mvnw.cmd, only-script, Maven 3.9.9) so no preinstalled Maven is needed. - One module per example; left at the existing flat example dirs so the teaching sources do not move. Dependency versions pinned to exactly what fetch-tools.sh used (behaviour unchanged). The SchXslt (bundled-Saxon) module is kept separate from the Saxon-HE XSLT/XQuery modules to preserve the org.xmlresolver-conflict fix. - XsdValidate resolves the official XSD itself: $FUNDSXML_SCHEMA_DIR (offline/corporate escape hatch) -> .schema-cache/ -> download from the GitHub release (follows the 302, fetches the xmldsig sibling when imported). Source of truth stays the official release; no committed catalog. - New XML_Signature/java/GenerateTestKey.java generates the throwaway signing key with the JDK's own keytool (no openssl) -> works on Windows. - Deleted: tools/fetch-tools.sh, run-schematron.sh, run-transform.sh, run-xquery.sh, generate-test-key.sh. - ci.yml: all Java steps now drive ./mvnw; exit codes propagate (blockSystemExit=false) so negative-fixture asserts still hold. - Docs swept (READMEs / CONTRIBUTING / issue template / .gitignore) to the Maven Wrapper commands; not-yet-migrated Python/.NET reference comments no longer point at deleted scripts. Verified locally via ./mvnw: XSD (env/cache/download + negative fixture), Schematron (±), XSLT, XQuery, sign/verify/tamper, DB round-trip + xml_equiv + XSD-valid, large-file streaming, data binding. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/ISSUE_TEMPLATE/bug_report.md | 4 +- .github/workflows/ci.yml | 97 ++++--- .gitignore | 15 +- .mvn/wrapper/maven-wrapper.properties | 19 ++ CONTRIBUTING.md | 16 +- Data_Binding_JSON/java/NativeBinding.java | 5 +- Data_Binding_JSON/java/pom.xml | 29 ++ Database_Integration/README.md | 13 +- Database_Integration/java/ExportFundsXml.java | 11 +- Database_Integration/java/ImportFundsXml.java | 13 +- Database_Integration/java/pom.xml | 51 ++++ Large_File_Processing/README.md | 6 +- .../java/StreamAggregate.java | 6 +- Large_File_Processing/java/pom.xml | 30 ++ README.md | 11 +- .../Basic_Checks/invocation/README.md | 30 +- .../invocation/SchematronValidate.cs | 8 +- .../invocation/SchematronValidate.java | 21 +- .../Basic_Checks/invocation/pom.xml | 63 +++++ .../Basic_Checks/invocation/run-schematron.sh | 34 --- .../invocation/validate_schematron.py | 9 +- XML_Signature/README.md | 29 +- XML_Signature/dotnet/SignVerify.cs | 4 +- XML_Signature/generate-test-key.sh | 30 -- XML_Signature/java/GenerateTestKey.java | 87 ++++++ XML_Signature/java/SignFundsXml.java | 14 +- XML_Signature/java/VerifyFundsXml.java | 4 +- XML_Signature/java/pom.xml | 68 +++++ XML_Signature/python/sign_verify_signxml.py | 7 +- XQuery_Examples/README.md | 22 +- XQuery_Examples/invocation/RunXQuery.java | 11 +- XQuery_Examples/invocation/pom.xml | 51 ++++ XQuery_Examples/invocation/run-xquery.sh | 32 --- XSD_Validation/java/XsdValidate.java | 95 ++++++- XSD_Validation/java/pom.xml | 31 +++ .../Custom_Internal_Checks/README.md | 17 +- XSLT_Transformations/README.md | 28 +- .../invocation/RunTransform.java | 11 +- XSLT_Transformations/invocation/pom.xml | 50 ++++ .../invocation/run-transform.sh | 29 -- mvnw | 259 ++++++++++++++++++ mvnw.cmd | 149 ++++++++++ pom.xml | 106 +++++++ tools/fetch-tools.sh | 63 ----- 44 files changed, 1312 insertions(+), 376 deletions(-) create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 Data_Binding_JSON/java/pom.xml create mode 100644 Database_Integration/java/pom.xml create mode 100644 Large_File_Processing/java/pom.xml create mode 100644 Schematron_DataQuality_Checks/Basic_Checks/invocation/pom.xml delete mode 100755 Schematron_DataQuality_Checks/Basic_Checks/invocation/run-schematron.sh delete mode 100755 XML_Signature/generate-test-key.sh create mode 100644 XML_Signature/java/GenerateTestKey.java create mode 100644 XML_Signature/java/pom.xml create mode 100644 XQuery_Examples/invocation/pom.xml delete mode 100755 XQuery_Examples/invocation/run-xquery.sh create mode 100644 XSD_Validation/java/pom.xml create mode 100644 XSLT_Transformations/invocation/pom.xml delete mode 100755 XSLT_Transformations/invocation/run-transform.sh create mode 100755 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml delete mode 100755 tools/fetch-tools.sh diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index af37e70..be44285 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -14,8 +14,8 @@ e.g. 4.2.9, `FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml` (or attach/inline a minimal FundsXML snippet — no real/PII data). **What I ran** -The exact command(s), including any `tools/fetch-schema.sh` / -`tools/fetch-tools.sh` step. +The exact command(s), including the `./mvnw` (or `mvnw.cmd`) invocation for +Java examples, or any `tools/fetch-schema.sh` step. **Expected vs. actual** What you expected and what happened (paste the full error / output). diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56675cd..9c31b5c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,14 +67,37 @@ jobs: fi echo "xsd-invalid correctly rejected" - - name: Fetch Java toolchain (Saxon + SchXslt) - run: tools/fetch-tools.sh + # --------------------------------------------------------------------- + # Java examples — built & run via the committed Maven Wrapper. The first + # ./mvnw bootstraps Maven itself, then resolves all deps from Central. + # A repo-wide `compile` builds every module once so later `exec:java` + # steps need no `compile` goal (keeps stdout clean for the XQuery step, + # which serializes its result to stdout). + # --------------------------------------------------------------------- + - name: Java - build all modules (Maven Wrapper) + run: ./mvnw -q -B compile + + - name: Java - XSD validation (in-language schema resolve) + run: | + set -e + M="./mvnw -q -B -pl XSD_Validation/java exec:java" + # Cache is warm from the xmllint step: exercises the resolver's + # cache-hit path and the $FUNDSXML_SCHEMA_DIR env override. + $M -Dexec.args="4.2.9 FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml" + FUNDSXML_SCHEMA_DIR="$PWD/.schema-cache/4.1.0" \ + $M -Dexec.args="4.1.0 FundsXML_Files/4.1.0/positions/Equity-Fund_Positions.xml" + if $M -Dexec.args="4.2.9 tests/fixtures/invalid/xsd-invalid_Positions.xml"; then + echo "::error::xsd-invalid unexpectedly validated (Java)"; exit 1 + fi + echo "Java XsdValidate: positive ok, negative correctly rejected" - name: Schematron - canonical sample passes, fixture fails run: | - RS=Schematron_DataQuality_Checks/Basic_Checks/invocation/run-schematron.sh - "$RS" FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml - if "$RS" tests/fixtures/invalid/schematron-invalid_Positions.xml; then + set -e + SCH=Schematron_DataQuality_Checks/Basic_Checks/basic_checks.sch + M="./mvnw -q -B -pl Schematron_DataQuality_Checks/Basic_Checks/invocation exec:java" + $M -Dexec.args="$SCH FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml" + if $M -Dexec.args="$SCH tests/fixtures/invalid/schematron-invalid_Positions.xml"; then echo "::error::schematron-invalid fixture unexpectedly passed"; exit 1 fi echo "schematron-invalid correctly failed" @@ -82,12 +105,12 @@ jobs: - name: Smoke - XSLT transforms produce non-empty output run: | set -e - RT=XSLT_Transformations/invocation/run-transform.sh + M="./mvnw -q -B -pl XSLT_Transformations/invocation exec:java" SRC=FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml - "$RT" XSLT_DataQuality_Checks/Custom_Internal_Checks/custom_internal_checks.xslt "$SRC" out_dq.html - "$RT" XSLT_Transformations/Factsheet/factsheet_html.xslt "$SRC" out_fs.html - "$RT" XSLT_Transformations/Factsheet/factsheet_fo.xslt "$SRC" out_fs.fo - "$RT" XSLT_Transformations/CSV_Export/positions_csv.xslt "$SRC" out_pos.csv + $M -Dexec.args="XSLT_DataQuality_Checks/Custom_Internal_Checks/custom_internal_checks.xslt $SRC out_dq.html" + $M -Dexec.args="XSLT_Transformations/Factsheet/factsheet_html.xslt $SRC out_fs.html" + $M -Dexec.args="XSLT_Transformations/Factsheet/factsheet_fo.xslt $SRC out_fs.fo" + $M -Dexec.args="XSLT_Transformations/CSV_Export/positions_csv.xslt $SRC out_pos.csv" xmllint --noout out_fs.fo for f in out_dq.html out_fs.html out_pos.csv; do test -s "$f" || { echo "::error::$f is empty"; exit 1; } @@ -97,12 +120,14 @@ jobs: - name: Smoke - XQuery examples run and produce XML run: | set -e - RQ=XQuery_Examples/invocation/run-xquery.sh + M="./mvnw -q -B -pl XQuery_Examples/invocation exec:java" SRC=FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml - "$RQ" XQuery_Examples/aggregate-by-assettype.xq "$SRC" out_agg.xml - "$RQ" XQuery_Examples/top-holdings.xq "$SRC" out_top.xml n=5 - "$RQ" XQuery_Examples/fund-summary.xq "$SRC" out_sum.xml - "$RQ" XQuery_Examples/look-through.xq "$SRC" out_lt.xml + # RunXQuery serializes to stdout; -q keeps Maven silent so the + # redirect captures pure XML. + $M -Dexec.args="XQuery_Examples/aggregate-by-assettype.xq $SRC" > out_agg.xml + $M -Dexec.args="XQuery_Examples/top-holdings.xq $SRC n=5" > out_top.xml + $M -Dexec.args="XQuery_Examples/fund-summary.xq $SRC" > out_sum.xml + $M -Dexec.args="XQuery_Examples/look-through.xq $SRC" > out_lt.xml for f in out_agg.xml out_top.xml out_sum.xml out_lt.xml; do xmllint --noout "$f" done @@ -111,19 +136,18 @@ jobs: - name: XML signature - Apache Santuario sign/verify/tamper roundtrip run: | set -e - XML_Signature/generate-test-key.sh - CP=.lib/xmlsec-4.0.4.jar:.lib/commons-codec-1.18.0.jar:.lib/slf4j-api-2.0.17.jar:.lib/slf4j-nop-2.0.17.jar - javac -cp "$CP" -d /tmp/sig \ - XML_Signature/java/SignFundsXml.java XML_Signature/java/VerifyFundsXml.java + M="./mvnw -q -B -pl XML_Signature/java exec:java" SRC=FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml - java -cp "$CP:/tmp/sig" SignFundsXml "$SRC" signed.xml \ - XML_Signature/keys/test-signing.p12 changeit fundsxml - java -cp "$CP:/tmp/sig" VerifyFundsXml signed.xml \ - XML_Signature/keys/test-signing-cert.pem + # In-language key generation (JDK keytool, no openssl). + $M -Dexec.mainClass=GenerateTestKey + $M -Dexec.mainClass=SignFundsXml \ + -Dexec.args="$SRC signed.xml XML_Signature/keys/test-signing.p12 changeit fundsxml" + $M -Dexec.mainClass=VerifyFundsXml \ + -Dexec.args="signed.xml XML_Signature/keys/test-signing-cert.pem" xmllint --noout --nonet --schema .schema-cache/4.2.9/FundsXML.xsd signed.xml sed 's/8.339.33 tampered.xml - if java -cp "$CP:/tmp/sig" VerifyFundsXml tampered.xml \ - XML_Signature/keys/test-signing-cert.pem; then + if $M -Dexec.mainClass=VerifyFundsXml \ + -Dexec.args="tampered.xml XML_Signature/keys/test-signing-cert.pem"; then echo "::error::tampered file unexpectedly verified"; exit 1 fi echo "tamper correctly detected" @@ -132,7 +156,6 @@ jobs: run: | set -e python3 -m pip install --quiet lxml - tools/fetch-tools.sh # sqlite-jdbc -> .lib/ FX=FundsXML_Files/4.2.9/positions/Multi-Fund_Positions.xml MX=FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml DOC=FUNDSXML_MULTI_1 @@ -151,15 +174,10 @@ jobs: xmllint --noout --nonet --schema "$XSD" py.xml $EQ "$FX" py.xml - # Java (sqlite-jdbc) - CP=.lib/sqlite-jdbc-3.46.1.3.jar - javac -cp "$CP" -d /tmp/jdb \ - Database_Integration/java/ImportFundsXml.java \ - Database_Integration/java/ExportFundsXml.java - java --enable-native-access=ALL-UNNAMED -cp "$CP:/tmp/jdb" \ - ImportFundsXml java.db "$FX" - java --enable-native-access=ALL-UNNAMED -cp "$CP:/tmp/jdb" \ - ExportFundsXml java.db "$DOC" java.xml + # Java (sqlite-jdbc via Maven; classes already built above) + MJ="./mvnw -q -B -pl Database_Integration/java exec:java" + $MJ -Dexec.mainClass=ImportFundsXml -Dexec.args="java.db $FX" + $MJ -Dexec.mainClass=ExportFundsXml -Dexec.args="java.db $DOC java.xml" xmllint --noout --nonet --schema "$XSD" java.xml $EQ "$FX" java.xml @@ -195,8 +213,10 @@ jobs: python3 $P/stream_aggregate.py big.xml | tee agg.txt grep -q '^positions : 30000$' agg.txt grep -q '^sum value (EUR): 30000000.00$' agg.txt - javac -d /tmp/lf Large_File_Processing/java/StreamAggregate.java - java -Xmx64m -cp /tmp/lf StreamAggregate big.xml | tee aggj.txt + # Java StreamAggregate (pure JDK) under a small heap proves the + # constant-memory claim; MAVEN_OPTS bounds the in-process JVM. + MAVEN_OPTS=-Xmx64m ./mvnw -q -B -pl Large_File_Processing/java exec:java \ + -Dexec.args="big.xml" | tee aggj.txt grep -q '^positions : 30000$' aggj.txt python3 $P/split.py big.xml chunks/ 10000 test "$(ls chunks/chunk-*.xml | wc -l)" = "3" @@ -224,8 +244,7 @@ jobs: assert npos(o) == npos(r), (npos(o), npos(r)) print("JSON round-trip preserved:", nav(r), npos(r)) PY - javac -d /tmp/nb Data_Binding_JSON/java/NativeBinding.java - java -cp /tmp/nb NativeBinding "$SRC" | tee nb.txt + ./mvnw -q -B -pl Data_Binding_JSON/java exec:java -Dexec.args="$SRC" | tee nb.txt grep -q '^Positions : 21$' nb.txt - name: Regression - legacy XSLT 1.0 report still runs diff --git a/.gitignore b/.gitignore index 63d49dd..b2a01d4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,12 +4,15 @@ CLAUDE.md .DS_Store ._* -# Locally fetched XSD releases (via tools/fetch-schema.sh) — not committed, -# the source of truth is the official GitHub release. +# Locally cached XSD releases — not committed, the source of truth is the +# official GitHub release. Each example downloads + caches it here itself +# (honouring $FUNDSXML_SCHEMA_DIR); see XSD_Validation/java/XsdValidate.java. .schema-cache/ -# Locally fetched Java toolchain jars (via tools/fetch-tools.sh) — external -# dependencies from Maven Central, not repo source. +# Maven build output. Dependencies come from Maven Central via ./mvnw; the +# committed Maven Wrapper bootstraps Maven itself — nothing is vendored. +target/ +# Legacy: jars the since-removed tools/fetch-tools.sh used to download here. .lib/ # Throwaway signing keys (XML_Signature/generate-test-key.sh) — never commit @@ -38,6 +41,10 @@ fund.json *.db *.svrl +# Python bytecode cache +__pycache__/ +*.pyc + # Node example deps (Database_Integration/javascript) — restored via npm install node_modules/ package-lock.json diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b0977a..4c8dbe4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,22 @@ Please read this before opening a pull request. Run what you changed and confirm it actually works — no "should pass" claims. +The Java examples build standalone via the committed Maven Wrapper (`./mvnw`, +or `mvnw.cmd` on Windows) — dependencies come from Maven Central, there is no +`fetch-tools.sh` and no `.lib/`. + ```bash -tools/fetch-schema.sh 4.2.9 # XSD cache (gitignored) -tools/fetch-tools.sh # Saxon / SchXslt / sqlite-jdbc / Santuario +tools/fetch-schema.sh 4.2.9 # XSD cache for the xmllint/Python steps + # (the Java examples also resolve the + # XSD themselves; see XsdValidate) xmllint --noout --schema .schema-cache/4.2.9/FundsXML.xsd .xml -Schematron_DataQuality_Checks/Basic_Checks/invocation/run-schematron.sh .xml + +# Schematron via the Maven Wrapper (positive sample -> exit 0) +./mvnw -q -pl Schematron_DataQuality_Checks/Basic_Checks/invocation \ + compile exec:java \ + -Dexec.args="Schematron_DataQuality_Checks/Basic_Checks/basic_checks.sch .xml" + # DB round-trip example: python3 Database_Integration/python/import_fundsxml.py fx.db .xml python3 Database_Integration/python/export_fundsxml.py fx.db out.xml diff --git a/Data_Binding_JSON/java/NativeBinding.java b/Data_Binding_JSON/java/NativeBinding.java index 36b30ca..dfe0325 100644 --- a/Data_Binding_JSON/java/NativeBinding.java +++ b/Data_Binding_JSON/java/NativeBinding.java @@ -1,7 +1,8 @@ // Native Java data binding for FundsXML — DOM + XPath into records, NO JAXB. // -// javac -d /tmp/nb Data_Binding_JSON/java/NativeBinding.java -// java -cp /tmp/nb NativeBinding +// Standalone & cross-platform — run from the repo root with the Maven Wrapper: +// ./mvnw -q -pl Data_Binding_JSON/java compile exec:java \ +// -Dexec.args="" // // Why no JAXB: the FundsXML schema is huge; generating/maintaining a full JAXB // model is heavy and brittle across versions. For most integration work a thin diff --git a/Data_Binding_JSON/java/pom.xml b/Data_Binding_JSON/java/pom.xml new file mode 100644 index 0000000..9dcba6b --- /dev/null +++ b/Data_Binding_JSON/java/pom.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../pom.xml + + + data-binding-java + + NativeBinding + + + + ${project.basedir} + + diff --git a/Database_Integration/README.md b/Database_Integration/README.md index b0ca4d7..ac41bfc 100644 --- a/Database_Integration/README.md +++ b/Database_Integration/README.md @@ -67,14 +67,11 @@ DOC=FUNDSXML_MULTI_1 python3 Database_Integration/python/import_fundsxml.py fx.db "$FX" python3 Database_Integration/python/export_fundsxml.py fx.db "$DOC" out.xml -# Java (sqlite-jdbc fetched into .lib/ by tools/fetch-tools.sh) -tools/fetch-tools.sh -CP=.lib/sqlite-jdbc-3.46.1.3.jar -javac -cp "$CP" -d /tmp/db \ - Database_Integration/java/ImportFundsXml.java \ - Database_Integration/java/ExportFundsXml.java -java --enable-native-access=ALL-UNNAMED -cp "$CP:/tmp/db" ImportFundsXml fx.db "$FX" -java --enable-native-access=ALL-UNNAMED -cp "$CP:/tmp/db" ExportFundsXml fx.db "$DOC" out.xml +# Java (sqlite-jdbc from Maven Central via the committed Maven Wrapper; +# on Windows use mvnw.cmd) +MJ="./mvnw -q -pl Database_Integration/java compile exec:java" +$MJ -Dexec.mainClass=ImportFundsXml -Dexec.args="fx.db $FX" +$MJ -Dexec.mainClass=ExportFundsXml -Dexec.args="fx.db $DOC out.xml" # JavaScript ( cd Database_Integration/javascript && npm install ) diff --git a/Database_Integration/java/ExportFundsXml.java b/Database_Integration/java/ExportFundsXml.java index 3dc977e..6b0d0ab 100644 --- a/Database_Integration/java/ExportFundsXml.java +++ b/Database_Integration/java/ExportFundsXml.java @@ -6,13 +6,12 @@ // // DB SCHEMA ../ddl/schema.sql (already populated by ImportFundsXml). // -// RUN -// CP=.lib/sqlite-jdbc-3.46.1.3.jar -// javac -cp "$CP" -d /tmp/db Database_Integration/java/ExportFundsXml.java -// java --enable-native-access=ALL-UNNAMED -cp "$CP:/tmp/db" \ -// ExportFundsXml fx.db FUNDSXML_MULTI_1 out.xml +// RUN Standalone & cross-platform, from the repo root via the Maven Wrapper: +// ./mvnw -q -pl Database_Integration/java compile exec:java \ +// -Dexec.mainClass=ExportFundsXml -Dexec.args="fx.db FUNDSXML_MULTI_1 out.xml" // -// DEPENDENCIES org.xerial:sqlite-jdbc + the JDK (native javax.xml, no JAXB). +// DEPENDENCIES org.xerial:sqlite-jdbc (Maven Central, see pom.xml) + the JDK +// (native javax.xml, no JAXB). // // FUNDSXML NOTES // * No XML namespace -> plain element names. diff --git a/Database_Integration/java/ImportFundsXml.java b/Database_Integration/java/ImportFundsXml.java index a31fbf0..5c65da3 100644 --- a/Database_Integration/java/ImportFundsXml.java +++ b/Database_Integration/java/ImportFundsXml.java @@ -8,14 +8,13 @@ // share_class per fund; asset document-scoped). Creates the schema in a // fresh SQLite DB, then loads the file. // -// RUN (sqlite-jdbc fetched by tools/fetch-tools.sh into .lib/) -// tools/fetch-tools.sh -// CP=.lib/sqlite-jdbc-3.46.1.3.jar -// javac -cp "$CP" -d /tmp/db Database_Integration/java/ImportFundsXml.java -// java --enable-native-access=ALL-UNNAMED -cp "$CP:/tmp/db" \ -// ImportFundsXml fx.db FundsXML_Files/4.2.9/positions/Multi-Fund_Positions.xml +// RUN Standalone & cross-platform, from the repo root via the Maven Wrapper: +// ./mvnw -q -pl Database_Integration/java compile exec:java \ +// -Dexec.mainClass=ImportFundsXml \ +// -Dexec.args="fx.db FundsXML_Files/4.2.9/positions/Multi-Fund_Positions.xml" // -// DEPENDENCIES org.xerial:sqlite-jdbc + the JDK. XML via native javax.xml +// DEPENDENCIES org.xerial:sqlite-jdbc (Maven Central, see pom.xml) + the JDK. +// XML via native javax.xml // DOM/XPath — NO JAXB (a thin DOM binding is smaller and version-tolerant). // // FUNDSXML ASSUMPTIONS diff --git a/Database_Integration/java/pom.xml b/Database_Integration/java/pom.xml new file mode 100644 index 0000000..5052654 --- /dev/null +++ b/Database_Integration/java/pom.xml @@ -0,0 +1,51 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../pom.xml + + + database-integration-java + + ImportFundsXml + + + + + org.xerial + sqlite-jdbc + ${sqlite-jdbc.version} + + + + + ${project.basedir} + + diff --git a/Large_File_Processing/README.md b/Large_File_Processing/README.md index 8bc533d..38af7a4 100644 --- a/Large_File_Processing/README.md +++ b/Large_File_Processing/README.md @@ -26,8 +26,10 @@ python3 Large_File_Processing/python/make_large_sample.py big.xml 50000 # 2. aggregate — Python and Java give identical totals at flat memory python3 Large_File_Processing/python/stream_aggregate.py big.xml -javac -d /tmp/lf Large_File_Processing/java/StreamAggregate.java -java -Xmx64m -cp /tmp/lf StreamAggregate big.xml +# Java via the committed Maven Wrapper (mvnw.cmd on Windows); a small heap +# proves the constant-memory claim. +MAVEN_OPTS=-Xmx64m ./mvnw -q -pl Large_File_Processing/java compile exec:java \ + -Dexec.args="big.xml" # 3. split into XSD-valid chunks of 10k positions python3 Large_File_Processing/python/split.py big.xml chunks/ 10000 diff --git a/Large_File_Processing/java/StreamAggregate.java b/Large_File_Processing/java/StreamAggregate.java index b8447bb..e203242 100644 --- a/Large_File_Processing/java/StreamAggregate.java +++ b/Large_File_Processing/java/StreamAggregate.java @@ -1,8 +1,10 @@ // Constant-memory aggregation over a huge FundsXML file via StAX (native Java, // no JAXB, no DOM). Pull parser — never holds more than the current element. // -// javac -d /tmp/lf Large_File_Processing/java/StreamAggregate.java -// java -cp /tmp/lf StreamAggregate +// Standalone & cross-platform — run from the repo root with the Maven Wrapper: +// ./mvnw -q -pl Large_File_Processing/java compile exec:java \ +// -Dexec.args="" +// (Memory-bounded: set a small heap via MAVEN_OPTS=-Xmx64m to prove it.) // // FundsXML 4.x has no XML namespace — match the bare "Position" local name. // Security: external entities / DTDs disabled (XXE-safe). diff --git a/Large_File_Processing/java/pom.xml b/Large_File_Processing/java/pom.xml new file mode 100644 index 0000000..07b6b63 --- /dev/null +++ b/Large_File_Processing/java/pom.xml @@ -0,0 +1,30 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../pom.xml + + + large-file-java + + StreamAggregate + + + + ${project.basedir} + + diff --git a/README.md b/README.md index 00752d1..cec5324 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,13 @@ own README, and is exercised by the CI workflow on each push. fundsxml_examples/ ├── README.md # This file (index above) ├── LICENSE # Apache 2.0 -├── tools/ # fetch-schema.sh, fetch-tools.sh -│ # (proxy-aware XSD / jar fetchers) +├── pom.xml mvnw mvnw.cmd .mvn/ # Maven aggregator + committed +│ # wrapper: builds all Java +│ # examples standalone (deps from +│ # Maven Central), no preinstall +├── tools/ # fetch-schema.sh (proxy-aware XSD +│ # fetcher; Java examples also +│ # resolve the XSD themselves) │ ├── FundsXML_Files/ # Sample documents, per version & use-case │ ├── 4.2.9/{positions,transactions,documents,regulatory,signed}/ @@ -72,7 +77,7 @@ fundsxml_examples/ │ ├── XML_Signature/ # enveloped XML-DSig sign/verify │ ├── java/ csharp/ python/ cli/ # Apache Santuario, SignedXml, … -│ └── generate-test-key.sh +│ │ └── java/GenerateTestKey.java # throwaway keys via JDK keytool │ ├── Database_Integration/ # FundsXML ⇄ relational DB (multi-fund) │ ├── ddl/schema.sql diff --git a/Schematron_DataQuality_Checks/Basic_Checks/invocation/README.md b/Schematron_DataQuality_Checks/Basic_Checks/invocation/README.md index 338e9b0..91650f4 100644 --- a/Schematron_DataQuality_Checks/Basic_Checks/invocation/README.md +++ b/Schematron_DataQuality_Checks/Basic_Checks/invocation/README.md @@ -10,8 +10,9 @@ SVRL semantics and pass/fail definition everywhere. **SVRL** report. That needs an XSLT 2.0 engine — Saxon. `xmllint`/`xsltproc`/ `lxml` (XSLT 1.0 only) **cannot** run this ruleset. -`tools/fetch-tools.sh` fetches the SchXslt CLI jar (a self-contained runner that -bundles its own Saxon) into `.lib/`. +The SchXslt CLI jar (a self-contained runner that bundles its own Saxon) is a +Maven dependency of this module's `pom.xml`, resolved from Maven Central by the +committed Maven Wrapper — no prior fetch step, no `.lib/`. ## SVRL semantics & pass/fail @@ -36,27 +37,22 @@ exits 1 on any failed-assert (including warnings). | Stack | File | Runnable on this box | |-------|------|----------------------| -| CLI | [`run-schematron.sh`](run-schematron.sh) | ✅ verified | -| Java (native) | [`SchematronValidate.java`](SchematronValidate.java) | ✅ verified (SchXslt Java API) | +| Java (native) | [`SchematronValidate.java`](SchematronValidate.java) | ✅ verified (SchXslt Java API, via Maven Wrapper) | | Python | [`validate_schematron.py`](validate_schematron.py) | needs `pip install saxonche` | | .NET/C# | [`SchematronValidate.cs`](SchematronValidate.cs) | needs .NET SDK + `SaxonHE` package | | shared | [`svrl-summary.py`](svrl-summary.py) | ✅ classifier used by all + CI | -Java classpath (the CLI jar already bundles Saxon — do **not** add the -standalone `Saxon-HE` jar, the two need different `org.xmlresolver` APIs): - -```bash -tools/fetch-tools.sh -CP=.lib/schxslt-cli-1.10.1.jar:.lib/commons-cli-1.5.0.jar:.lib/slf4j-api-1.7.32.jar:.lib/slf4j-nop-1.7.32.jar -javac -cp "$CP" -d /tmp/scv Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.java -java -cp "$CP:/tmp/scv" SchematronValidate Schematron_DataQuality_Checks/Basic_Checks/basic_checks.sch \ - FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml -``` +The Java example runs standalone and cross-platform via the committed Maven +Wrapper (`./mvnw`, or `mvnw.cmd` on Windows) from the repo root. The SchXslt +CLI dependency already bundles Saxon — this module deliberately does **not** +depend on the standalone `Saxon-HE` jar (the two need different +`org.xmlresolver` APIs), which is why it is its own Maven module. ## Quick check (positive + negative) ```bash -RS=Schematron_DataQuality_Checks/Basic_Checks/invocation/run-schematron.sh -$RS FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml # exit 0 (0 errors) -$RS tests/fixtures/invalid/schematron-invalid_Positions.xml # exit 1 (percentage 120%) +SCH=Schematron_DataQuality_Checks/Basic_Checks/basic_checks.sch +M="./mvnw -q -pl Schematron_DataQuality_Checks/Basic_Checks/invocation compile exec:java" +$M -Dexec.args="$SCH FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml" # exit 0 (0 errors) +$M -Dexec.args="$SCH tests/fixtures/invalid/schematron-invalid_Positions.xml" # exit 1 (percentage 120%) ``` diff --git a/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.cs b/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.cs index 95cc10f..a330a3f 100644 --- a/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.cs +++ b/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.cs @@ -7,7 +7,8 @@ // // basic_checks.sch uses queryBinding="xslt2"; Saxon supplies the XSLT 3.0 // engine. The SchXslt pipeline stylesheets are reused from the SchXslt CLI jar -// (tools/fetch-tools.sh puts it in .lib/): the whole xslt/ tree is extracted so +// (this .NET stack resolves it via NuGet once migrated; the Java example +// already runs standalone via the Maven Wrapper): the whole xslt/ tree is extracted so // the pipeline's relative imports resolve, then compile .sch -> SVRL stylesheet // -> apply to instance -> SVRL, then classify (same logic as svrl-summary.py). // @@ -42,7 +43,10 @@ private static int Main(string[] args) string cliJar = Path.Combine(repoRoot, ".lib", "schxslt-cli-1.10.1.jar"); if (!File.Exists(cliJar)) { - Console.Error.WriteLine("SchXslt jar missing; run: tools/fetch-tools.sh"); + Console.Error.WriteLine( + "SchXslt jar missing (this .NET stack is migrated to NuGet in " + + "a later phase; the Java example already runs standalone via " + + "the Maven Wrapper)"); return 2; } diff --git a/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.java b/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.java index 00483f8..d04fde4 100644 --- a/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.java +++ b/Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.java @@ -1,18 +1,19 @@ // Native-Java Schematron validation using the SchXslt Java API. // -// Compile + run against the SchXslt CLI classpath (it bundles Saxon): -// tools/fetch-tools.sh # populates .lib/ -// CP=.lib/schxslt-cli-1.10.1.jar:.lib/commons-cli-1.5.0.jar:\ -// .lib/slf4j-api-1.7.32.jar:.lib/slf4j-nop-1.7.32.jar -// javac -cp "$CP" -d /tmp Schematron_DataQuality_Checks/Basic_Checks/invocation/SchematronValidate.java -// java -cp "$CP:/tmp" SchematronValidate basic_checks.sch document.xml +// Standalone & cross-platform — run from the repo root with the Maven Wrapper +// (no bash, no .lib/, works on Windows): +// ./mvnw -q -pl Schematron_DataQuality_Checks/Basic_Checks/invocation \ +// compile exec:java \ +// -Dexec.args="Schematron_DataQuality_Checks/Basic_Checks/basic_checks.sch \ +// FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml" // // Exit: 0 = no error-role failed-assert, 1 = at least one, 2 = setup error. // -// Why this classpath: basic_checks.sch uses queryBinding="xslt2". SchXslt -// compiles the Schematron to XSLT 2.0 and Saxon (bundled in the SchXslt CLI -// jar) executes it. Do NOT add the standalone Saxon-HE jar — its org.xmlresolver -// API differs from the one SchXslt bundles and the two conflict. +// Why the SchXslt CLI dependency: basic_checks.sch uses queryBinding="xslt2". +// SchXslt compiles the Schematron to XSLT 2.0 and the Saxon that the SchXslt +// CLI jar BUNDLES executes it. Do NOT add the standalone Saxon-HE jar — its +// org.xmlresolver API differs from the one SchXslt bundles and the two +// conflict; that is why this is its own Maven module (see pom.xml). import java.io.File; import javax.xml.transform.stream.StreamSource; diff --git a/Schematron_DataQuality_Checks/Basic_Checks/invocation/pom.xml b/Schematron_DataQuality_Checks/Basic_Checks/invocation/pom.xml new file mode 100644 index 0000000..6ed1b72 --- /dev/null +++ b/Schematron_DataQuality_Checks/Basic_Checks/invocation/pom.xml @@ -0,0 +1,63 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../../pom.xml + + + schematron-validate-java + + SchematronValidate + + + + + + name.dmaus.schxslt + cli + ${schxslt.version} + + + commons-cli + commons-cli + ${commons-cli.version} + + + org.slf4j + slf4j-api + ${slf4j1.version} + + + + org.slf4j + slf4j-nop + ${slf4j1.version} + runtime + + + + + ${project.basedir} + + diff --git a/Schematron_DataQuality_Checks/Basic_Checks/invocation/run-schematron.sh b/Schematron_DataQuality_Checks/Basic_Checks/invocation/run-schematron.sh deleted file mode 100755 index 79e7765..0000000 --- a/Schematron_DataQuality_Checks/Basic_Checks/invocation/run-schematron.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# Schematron validation via the command line (SchXslt + Saxon). -# -# Usage: run-schematron.sh [--fail-on error|any] -# Exit: 0 = pass, 1 = fail (per --fail-on), 2 = setup error -# -# basic_checks.sch uses queryBinding="xslt2", so an XSLT 2.0 processor (Saxon) -# is required. SchXslt compiles the Schematron to XSLT and applies it, emitting -# an SVRL report which svrl-summary.py then classifies. -set -euo pipefail - -XML="${1:?usage: run-schematron.sh [--fail-on error|any]}" -shift || true - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" -SCH="${REPO_ROOT}/Schematron_DataQuality_Checks/Basic_Checks/basic_checks.sch" -LIB="${REPO_ROOT}/.lib" - -if [[ ! -f "${LIB}/schxslt-cli-1.10.1.jar" ]]; then - echo "Java toolchain not present; fetching (Saxon + SchXslt)..." >&2 - "${REPO_ROOT}/tools/fetch-tools.sh" >/dev/null -fi - -# SchXslt-only classpath. The CLI jar bundles its own Saxon; do NOT add the -# standalone Saxon-HE jar here (different org.xmlresolver API → breakage). -CP="${LIB}/schxslt-cli-1.10.1.jar:${LIB}/commons-cli-1.5.0.jar:${LIB}/slf4j-api-1.7.32.jar:${LIB}/slf4j-nop-1.7.32.jar" -SVRL="$(mktemp)" -trap 'rm -f "$SVRL"' EXIT - -java -cp "$CP" name.dmaus.schxslt.cli.Application \ - -s "$SCH" -d "$XML" -o "$SVRL" >/dev/null 2>&1 || true - -python3 "${REPO_ROOT}/Schematron_DataQuality_Checks/Basic_Checks/invocation/svrl-summary.py" \ - "$SVRL" "$@" diff --git a/Schematron_DataQuality_Checks/Basic_Checks/invocation/validate_schematron.py b/Schematron_DataQuality_Checks/Basic_Checks/invocation/validate_schematron.py index 0a33217..18e0488 100644 --- a/Schematron_DataQuality_Checks/Basic_Checks/invocation/validate_schematron.py +++ b/Schematron_DataQuality_Checks/Basic_Checks/invocation/validate_schematron.py @@ -9,7 +9,9 @@ (`pip install saxonche`) embeds Saxon's XSLT 3.0 engine. The SchXslt pipeline stylesheets are reused straight out of the SchXslt CLI jar -(`tools/fetch-tools.sh` puts it in .lib/). The whole `xslt/` tree is extracted +(this Python stack will resolve it via pyproject.toml once migrated; the Java +Schematron example already runs standalone via the Maven Wrapper). The whole +`xslt/` tree is extracted to a temp dir so the pipeline's relative xsl:import/include resolve, then: 1) compile the .sch into an SVRL stylesheet, 2) apply it to the instance to get SVRL, @@ -42,7 +44,10 @@ def main() -> int: return 2 if not CLI_JAR.is_file(): - print("SchXslt jar missing; run: tools/fetch-tools.sh", file=sys.stderr) + print("SchXslt jar missing (this Python stack is migrated to a build " + "system in a later phase; the Java example already runs " + "standalone: ./mvnw -pl Schematron_DataQuality_Checks/" + "Basic_Checks/invocation compile exec:java)", file=sys.stderr) return 2 with tempfile.TemporaryDirectory() as tmp: diff --git a/XML_Signature/README.md b/XML_Signature/README.md index ba00ae3..e8a6fd5 100644 --- a/XML_Signature/README.md +++ b/XML_Signature/README.md @@ -22,10 +22,13 @@ placeholder. ## Keys ```bash -XML_Signature/generate-test-key.sh # -> XML_Signature/keys/ (gitignored) +./mvnw -q -pl XML_Signature/java compile exec:java -Dexec.mainClass=GenerateTestKey +# -> XML_Signature/keys/ (gitignored). Windows: use mvnw.cmd ``` -Throwaway self-signed RSA-2048 (`test-signing.p12` alias `fundsxml`, pass -`changeit`; plus PEM key/cert). **Demo only — never commit private keys.** +`GenerateTestKey` uses the JDK's own `keytool` (no openssl, so it works on +Windows too) to write a throwaway self-signed RSA-2048 keystore +`test-signing.p12` (alias `fundsxml`, pass `changeit`) and the PEM certificate +`test-signing-cert.pem`. **Demo only — never commit private keys.** ## Stacks @@ -38,19 +41,23 @@ Throwaway self-signed RSA-2048 (`test-signing.p12` alias `fundsxml`, pass ## Run (Java / Apache Santuario — verified) +Standalone & cross-platform via the committed Maven Wrapper (`./mvnw`, or +`mvnw.cmd` on Windows), from the repo root — xmlsec comes from Maven Central: + ```bash -tools/fetch-tools.sh -XML_Signature/generate-test-key.sh -CP=.lib/xmlsec-4.0.4.jar:.lib/commons-codec-1.18.0.jar:.lib/slf4j-api-2.0.17.jar:.lib/slf4j-nop-2.0.17.jar -javac -cp "$CP" -d /tmp/sig XML_Signature/java/SignFundsXml.java XML_Signature/java/VerifyFundsXml.java +M="./mvnw -q -pl XML_Signature/java compile exec:java" + +# one-off: throwaway key (JDK keytool, no openssl) +$M -Dexec.mainClass=GenerateTestKey # sign -java -cp "$CP:/tmp/sig" SignFundsXml \ - FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml signed.xml \ - XML_Signature/keys/test-signing.p12 changeit fundsxml +$M -Dexec.mainClass=SignFundsXml \ + -Dexec.args="FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml signed.xml \ + XML_Signature/keys/test-signing.p12 changeit fundsxml" # verify — pin the signer cert (don't trust only the embedded key) -java -cp "$CP:/tmp/sig" VerifyFundsXml signed.xml XML_Signature/keys/test-signing-cert.pem +$M -Dexec.mainClass=VerifyFundsXml \ + -Dexec.args="signed.xml XML_Signature/keys/test-signing-cert.pem" ``` `VerifyFundsXml` exits 0 on a valid signature, 1 on tamper/failure (verified: diff --git a/XML_Signature/dotnet/SignVerify.cs b/XML_Signature/dotnet/SignVerify.cs index fe42201..44f168b 100644 --- a/XML_Signature/dotnet/SignVerify.cs +++ b/XML_Signature/dotnet/SignVerify.cs @@ -7,7 +7,9 @@ // Reference implementation — not executed in the dev environment (no .NET SDK). // Same profile as the Apache Santuario (Java) example: RSA-SHA256, exclusive // C14N, enveloped, signer cert embedded in KeyInfo, so files cross-verify. -// Keys: XML_Signature/generate-test-key.sh (PKCS#12 test-signing.p12). +// Keys: the Java GenerateTestKey (./mvnw -pl XML_Signature/java compile +// exec:java -Dexec.mainClass=GenerateTestKey) writes the PKCS#12 +// test-signing.p12 used here. using System; using System.IO; diff --git a/XML_Signature/generate-test-key.sh b/XML_Signature/generate-test-key.sh deleted file mode 100755 index 77dd220..0000000 --- a/XML_Signature/generate-test-key.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -# generate-test-key.sh — create a THROWAWAY self-signed RSA key + cert for the -# XML-signature examples. -# -# Output (into XML_Signature/keys/, gitignored — never commit private keys): -# test-signing.p12 PKCS#12 keystore (alias: fundsxml, pass: changeit) -# test-signing-cert.pem public certificate (for verification / xmlsec1) -# test-signing-key.pem private key in PEM (for xmlsec1 / signxml) -# -# FOR DEMO USE ONLY — 2048-bit, 10-year self-signed, hard-coded password. -set -euo pipefail - -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/keys" -mkdir -p "$DIR" -PASS="changeit" - -openssl req -x509 -newkey rsa:2048 -sha256 -days 3650 -nodes \ - -keyout "$DIR/test-signing-key.pem" \ - -out "$DIR/test-signing-cert.pem" \ - -subj "/C=AT/O=FundsXML Examples/OU=Demo/CN=fundsxml-test-signer" 2>/dev/null - -openssl pkcs12 -export \ - -inkey "$DIR/test-signing-key.pem" \ - -in "$DIR/test-signing-cert.pem" \ - -name fundsxml \ - -out "$DIR/test-signing.p12" \ - -passout "pass:${PASS}" - -echo "wrote: $DIR/test-signing.p12 (alias=fundsxml pass=${PASS})" -echo " $DIR/test-signing-cert.pem $DIR/test-signing-key.pem" diff --git a/XML_Signature/java/GenerateTestKey.java b/XML_Signature/java/GenerateTestKey.java new file mode 100644 index 0000000..ad0203a --- /dev/null +++ b/XML_Signature/java/GenerateTestKey.java @@ -0,0 +1,87 @@ +// GenerateTestKey — create a THROWAWAY self-signed RSA key + certificate for +// the XML-signature examples, using only the JDK's own `keytool`. +// +// This replaces the old openssl-based generate-test-key.sh: keytool ships with +// every JDK (keytool / keytool.exe), so this runs identically on Windows, +// Linux and macOS with no extra tool to install. +// +// ./mvnw -q -pl XML_Signature/java compile exec:java \ +// -Dexec.mainClass=GenerateTestKey +// (optional first arg: output directory; default XML_Signature/keys) +// +// Output (gitignored — never commit private keys, even demo ones): +// test-signing.p12 PKCS#12 keystore (alias: fundsxml, pass: changeit) +// test-signing-cert.pem public certificate (for verification) +// +// FOR DEMO USE ONLY — 2048-bit RSA, 10-year self-signed, hard-coded password. + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class GenerateTestKey { + + static final String ALIAS = "fundsxml"; + static final String PASS = "changeit"; + + public static void main(String[] args) throws Exception { + // Default to XML_Signature/keys relative to the working directory + // (the repo root when launched via mvnw from the root). + Path dir = Paths.get(args.length > 0 ? args[0] + : "XML_Signature/keys"); + Files.createDirectories(dir); + Path p12 = dir.resolve("test-signing.p12"); + Path cert = dir.resolve("test-signing-cert.pem"); + + // keytool's genkeypair fails if the alias already exists, so start + // from a clean keystore for idempotent re-runs. + Files.deleteIfExists(p12); + Files.deleteIfExists(cert); + + String keytool = keytool(); + + run(keytool, "-genkeypair", + "-alias", ALIAS, + "-keyalg", "RSA", "-keysize", "2048", + "-sigalg", "SHA256withRSA", + "-validity", "3650", + "-dname", "CN=fundsxml-test-signer, OU=Demo, " + + "O=FundsXML Examples, C=AT", + "-keystore", p12.toString(), "-storetype", "PKCS12", + "-storepass", PASS, "-keypass", PASS); + + // -rfc => Base64 PEM certificate (same content the old script's + // test-signing-cert.pem held; used to pin verification). + run(keytool, "-exportcert", "-rfc", + "-alias", ALIAS, + "-keystore", p12.toString(), "-storepass", PASS, + "-file", cert.toString()); + + System.out.println("wrote: " + p12 + + " (alias=" + ALIAS + " pass=" + PASS + ")"); + System.out.println(" " + cert); + } + + /** Locate the keytool that belongs to the running JDK (cross-platform). */ + static String keytool() { + String home = System.getProperty("java.home"); + boolean win = System.getProperty("os.name", "") + .toLowerCase().contains("win"); + Path k = Paths.get(home, "bin", win ? "keytool.exe" : "keytool"); + return Files.isExecutable(k) ? k.toString() : "keytool"; + } + + /** Run a process, stream its output, and fail loudly on a non-zero exit. */ + static void run(String... cmd) throws Exception { + Process p = new ProcessBuilder(cmd) + .redirectErrorStream(true) + .inheritIO() + .start(); + int code = p.waitFor(); + if (code != 0) { + System.err.println("keytool failed (exit " + code + "): " + + String.join(" ", cmd)); + System.exit(2); + } + } +} diff --git a/XML_Signature/java/SignFundsXml.java b/XML_Signature/java/SignFundsXml.java index 4196cf3..86b7c0f 100644 --- a/XML_Signature/java/SignFundsXml.java +++ b/XML_Signature/java/SignFundsXml.java @@ -1,12 +1,12 @@ // SignFundsXml — enveloped XML-DSig signing with Apache Santuario (xmlsec 4.x). // -// tools/fetch-tools.sh -// XML_Signature/generate-test-key.sh -// CP=.lib/xmlsec-4.0.4.jar:.lib/commons-codec-1.18.0.jar:\ -// .lib/slf4j-api-2.0.17.jar:.lib/slf4j-nop-2.0.17.jar -// javac -cp "$CP" -d /tmp/sig XML_Signature/java/SignFundsXml.java -// java -cp "$CP:/tmp/sig" SignFundsXml \ -// XML_Signature/keys/test-signing.p12 changeit fundsxml +// Standalone & cross-platform — run from the repo root with the Maven Wrapper +// (xmlsec comes from Maven Central; keys via the in-language GenerateTestKey): +// ./mvnw -q -pl XML_Signature/java compile exec:java \ +// -Dexec.mainClass=GenerateTestKey +// ./mvnw -q -pl XML_Signature/java exec:java -Dexec.mainClass=SignFundsXml \ +// -Dexec.args=" \ +// XML_Signature/keys/test-signing.p12 changeit fundsxml" // // Produces an enveloped signature whose ds:Signature is appended as the last // child of — exactly where the FundsXML 4.2.9 schema allows it diff --git a/XML_Signature/java/VerifyFundsXml.java b/XML_Signature/java/VerifyFundsXml.java index 0141a83..fbf4950 100644 --- a/XML_Signature/java/VerifyFundsXml.java +++ b/XML_Signature/java/VerifyFundsXml.java @@ -1,6 +1,8 @@ // VerifyFundsXml — verify an enveloped XML-DSig signature with Apache Santuario. // -// java -cp "$CP:/tmp/sig" VerifyFundsXml [cert.pem] +// Run from the repo root with the Maven Wrapper: +// ./mvnw -q -pl XML_Signature/java exec:java -Dexec.mainClass=VerifyFundsXml \ +// -Dexec.args=" [cert.pem]" // // With no cert argument the certificate embedded in KeyInfo/X509Data is used // (self-verifiable file). Pass a PEM cert to pin verification to a known key diff --git a/XML_Signature/java/pom.xml b/XML_Signature/java/pom.xml new file mode 100644 index 0000000..c9b53f6 --- /dev/null +++ b/XML_Signature/java/pom.xml @@ -0,0 +1,68 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../pom.xml + + + xml-signature-java + + + GenerateTestKey + + + + + org.apache.santuario + xmlsec + ${xmlsec.version} + + + commons-codec + commons-codec + ${commons-codec.version} + + + org.slf4j + slf4j-api + ${slf4j2.version} + + + org.slf4j + slf4j-nop + ${slf4j2.version} + runtime + + + + + ${project.basedir} + + diff --git a/XML_Signature/python/sign_verify_signxml.py b/XML_Signature/python/sign_verify_signxml.py index 7c064f4..09da046 100644 --- a/XML_Signature/python/sign_verify_signxml.py +++ b/XML_Signature/python/sign_verify_signxml.py @@ -9,8 +9,11 @@ Reference implementation (signxml not installed in the dev environment): pip install signxml -Keys come from XML_Signature/generate-test-key.sh (key/cert PEM in -XML_Signature/keys/). RSA-SHA256, exclusive C14N, enveloped — same profile as +Keys: the Java GenerateTestKey (./mvnw -pl XML_Signature/java compile +exec:java -Dexec.mainClass=GenerateTestKey) writes test-signing.p12 + +test-signing-cert.pem to XML_Signature/keys/; the PEM *private* key this +signxml path also needs is produced when the Python signature stack is +migrated to its build system. RSA-SHA256, exclusive C14N, enveloped — same profile as the Apache Santuario (Java) example, so files cross-verify between stacks. """ import sys diff --git a/XQuery_Examples/README.md b/XQuery_Examples/README.md index 350803f..0986b33 100644 --- a/XQuery_Examples/README.md +++ b/XQuery_Examples/README.md @@ -18,25 +18,25 @@ no XML namespace — queries use bare element names, so they work unchanged on t | Stack | Entry point | Status | |-------|-------------|--------| -| CLI (Saxon) | [`invocation/run-xquery.sh`](invocation/run-xquery.sh) | ✅ verified | -| Java (s9api, no JAXB) | [`invocation/RunXQuery.java`](invocation/RunXQuery.java) | ✅ verified | +| Java (s9api, no JAXB) | [`invocation/RunXQuery.java`](invocation/RunXQuery.java) | ✅ verified (via Maven Wrapper) | | Python | [`invocation/run_xquery.py`](invocation/run_xquery.py) | needs `pip install saxonche` | | BaseX | see below | needs BaseX install | +The Java runner is standalone & cross-platform via the committed Maven Wrapper +(`./mvnw`, or `mvnw.cmd` on Windows), from the repo root. It serializes the +result to stdout (redirect to capture): + ```bash -tools/fetch-tools.sh +M="./mvnw -q -pl XQuery_Examples/invocation compile exec:java" SRC=FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml -# CLI — to stdout -XQuery_Examples/invocation/run-xquery.sh XQuery_Examples/fund-summary.xq "$SRC" +# to stdout +$M -Dexec.args="XQuery_Examples/fund-summary.xq $SRC" -# CLI — external variable + output file (Saxon Query: bare name=value) -XQuery_Examples/invocation/run-xquery.sh XQuery_Examples/top-holdings.xq "$SRC" top.xml n=5 +# external variable; redirect stdout to a file +$M -Dexec.args="XQuery_Examples/top-holdings.xq $SRC n=5" > top.xml -# Java s9api -SCP=.lib/Saxon-HE-12.5.jar:.lib/xmlresolver-5.2.2.jar:.lib/xmlresolver-5.2.2-data.jar -javac -cp "$SCP" -d /tmp/xq XQuery_Examples/invocation/RunXQuery.java -java -cp "$SCP:/tmp/xq" RunXQuery XQuery_Examples/aggregate-by-assettype.xq "$SRC" +$M -Dexec.args="XQuery_Examples/aggregate-by-assettype.xq $SRC" # BaseX (in-memory, binds the document and the external variable) basex -i "$SRC" -bn=5 XQuery_Examples/top-holdings.xq diff --git a/XQuery_Examples/invocation/RunXQuery.java b/XQuery_Examples/invocation/RunXQuery.java index 3cf41e2..39fa1ba 100644 --- a/XQuery_Examples/invocation/RunXQuery.java +++ b/XQuery_Examples/invocation/RunXQuery.java @@ -1,13 +1,12 @@ // Run an XQuery against FundsXML via the Saxon s9api (native Java, no JAXB). // -// tools/fetch-tools.sh -// SCP=.lib/Saxon-HE-12.5.jar:.lib/xmlresolver-5.2.2.jar:.lib/xmlresolver-5.2.2-data.jar -// javac -cp "$SCP" -d /tmp/xq XQuery_Examples/invocation/RunXQuery.java -// java -cp "$SCP:/tmp/xq" RunXQuery [k=v ...] +// Standalone & cross-platform — run from the repo root with the Maven Wrapper: +// ./mvnw -q -pl XQuery_Examples/invocation compile exec:java \ +// -Dexec.args=" [k=v ...]" // Exit: 0 success, 2 setup error. // -// Dependencies: Saxon-HE + xmlresolver jars only (fetched by -// tools/fetch-tools.sh into .lib/); no other libraries. +// Dependencies (from Maven Central, see pom.xml): Saxon-HE + xmlresolver +// (+ its -data artifact); no other libraries. // // This is a generic, FundsXML-agnostic XQuery runner: it binds the input as // the context item and passes string external variables — the FundsXML diff --git a/XQuery_Examples/invocation/pom.xml b/XQuery_Examples/invocation/pom.xml new file mode 100644 index 0000000..a6156b4 --- /dev/null +++ b/XQuery_Examples/invocation/pom.xml @@ -0,0 +1,51 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../pom.xml + + + xquery-run-java + + RunXQuery + + + + + net.sf.saxon + Saxon-HE + ${saxon.version} + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + data + runtime + + + + + ${project.basedir} + + diff --git a/XQuery_Examples/invocation/run-xquery.sh b/XQuery_Examples/invocation/run-xquery.sh deleted file mode 100755 index f6be744..0000000 --- a/XQuery_Examples/invocation/run-xquery.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash -# Run an XQuery against a FundsXML document via Saxon-HE (CLI). -# -# Usage: run-xquery.sh [output] [name=value ...] -# Exit: 0 on success, 2 setup error, Saxon's code otherwise. -# -# Saxon's net.sf.saxon.Query takes external variables as bare `name=value` -# arguments (NOT `-param:` — that is the XSLT entry point; and a leading `!` -# would set serialization params instead). tools/fetch-tools.sh provides -# Saxon-HE in .lib/. -set -euo pipefail - -Q="${1:?usage: run-xquery.sh [output] [name=value ...]}" -IN="${2:?input xml required}" -OUT="${3:-}" -shift 2 || true -[[ $# -ge 1 && "${1:-}" != *=* ]] && { OUT="$1"; shift; } - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -LIB="${REPO_ROOT}/.lib" -if [[ ! -f "${LIB}/Saxon-HE-12.5.jar" ]]; then - echo "Saxon not present; fetching..." >&2 - "${REPO_ROOT}/tools/fetch-tools.sh" >/dev/null -fi -SCP="${LIB}/Saxon-HE-12.5.jar:${LIB}/xmlresolver-5.2.2.jar:${LIB}/xmlresolver-5.2.2-data.jar" - -if [[ -n "$OUT" ]]; then - java -cp "$SCP" net.sf.saxon.Query -q:"$Q" -s:"$IN" -o:"$OUT" "$@" - echo "wrote $OUT" -else - java -cp "$SCP" net.sf.saxon.Query -q:"$Q" -s:"$IN" "$@" -fi diff --git a/XSD_Validation/java/XsdValidate.java b/XSD_Validation/java/XsdValidate.java index 44c47a3..7efe7af 100644 --- a/XSD_Validation/java/XsdValidate.java +++ b/XSD_Validation/java/XsdValidate.java @@ -1,19 +1,34 @@ // XSD validation in native Java (no JAXB) via javax.xml.validation. // -// Single-file program — run directly with a modern JDK (11+): -// java XSD_Validation/java/XsdValidate.java +// Standalone & cross-platform — no prior tool, no bash, works on Windows. +// Run from the repo root with the committed Maven Wrapper: +// ./mvnw -q -pl XSD_Validation/java compile exec:java \ +// -Dexec.args="4.2.9 FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml" // Exit: 0 = valid, 1 = invalid, 2 = usage/setup error // -// Validates against the official released schema, materialized locally by -// tools/fetch-schema.sh (handles the GitHub 302 redirect and the relative -// xmldsig-core-schema.xsd import that FundsXML 4.2.9+ requires). +// The official released schema is obtained by this program itself, in this +// order (identical convention across all stacks): +// 1. $FUNDSXML_SCHEMA_DIR — a directory holding FundsXML.xsd (+ the +// xmldsig-core-schema.xsd sibling for 4.2.9+). Used as-is, NO network. +// The escape hatch for locked-down corporate networks / offline use. +// 2. .schema-cache//FundsXML.xsd — reused if already present. +// 3. download from the official GitHub release (following the 302), caching +// into .schema-cache//; the relative xmldsig-core-schema.xsd +// sibling is fetched only when FundsXML.xsd actually imports it (4.2.9+). +// The source of truth stays the official release URL — no committed catalog. // // Security: FEATURE_SECURE_PROCESSING on, external DTD/schema access denied, // XXE vectors closed. FundsXML needs no external entities. import java.io.File; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; @@ -32,13 +47,7 @@ public static void main(String[] args) throws Exception { String version = args[0]; String xmlFile = args[1]; - Path repoRoot = Paths.get(System.getProperty("user.dir")); - File schema = repoRoot.resolve(".schema-cache").resolve(version) - .resolve("FundsXML.xsd").toFile(); - if (!schema.isFile()) { - System.err.println("schema not cached; run: tools/fetch-schema.sh " + version); - System.exit(2); - } + File schema = resolveSchema(version).toFile(); SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); @@ -79,4 +88,66 @@ private void report(SAXParseException e) { } System.out.println("VALID: " + xmlFile + " (FundsXML " + version + ")"); } + + static final String RELEASE_BASE = + "https://github.com/fundsxml/schema/releases/download/"; + + /** + * Resolve FundsXML.xsd for {@code version}: env-var dir, else local cache, + * else download from the official GitHub release (caching the result). + * The xmldsig-core-schema.xsd sibling is fetched only when imported. + */ + static Path resolveSchema(String version) throws Exception { + // 1. Offline / corporate-network escape hatch: a hand-placed copy. + String envDir = System.getenv("FUNDSXML_SCHEMA_DIR"); + if (envDir != null && !envDir.isBlank()) { + Path xsd = Paths.get(envDir, "FundsXML.xsd"); + if (!Files.isRegularFile(xsd)) { + System.err.println("FUNDSXML_SCHEMA_DIR set but " + + xsd + " not found"); + System.exit(2); + } + System.err.println("schema: using $FUNDSXML_SCHEMA_DIR -> " + xsd); + return xsd; + } + + // 2. Local cache (shared by every stack, gitignored). + Path cacheDir = Paths.get(System.getProperty("user.dir"), + ".schema-cache", version); + Path xsd = cacheDir.resolve("FundsXML.xsd"); + if (Files.isRegularFile(xsd)) { + System.err.println("schema: cached -> " + xsd); + return xsd; + } + + // 3. Download from the official release (source of truth). + Files.createDirectories(cacheDir); + download(RELEASE_BASE + version + "/FundsXML.xsd", xsd); + // From 4.2.9 on, FundsXML.xsd imports xmldsig-core-schema.xsd via a + // relative path — it must sit next to FundsXML.xsd or the schema does + // not compile. Fetch the sibling only when it is actually referenced. + if (Files.readString(xsd).contains("xmldsig-core-schema.xsd")) { + download(RELEASE_BASE + version + "/xmldsig-core-schema.xsd", + cacheDir.resolve("xmldsig-core-schema.xsd")); + } + return xsd; + } + + /** GET {@code url} (following the GitHub 302) atomically into {@code out}. */ + static void download(String url, Path out) throws Exception { + System.err.println("schema: fetch " + url); + HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.NORMAL).build(); + HttpResponse resp = client.send( + HttpRequest.newBuilder(URI.create(url)).GET().build(), + HttpResponse.BodyHandlers.ofByteArray()); + if (resp.statusCode() != 200) { + System.err.println("download failed (HTTP " + resp.statusCode() + + "): " + url); + System.exit(2); + } + Path tmp = Files.createTempFile(out.getParent(), "xsd", ".part"); + Files.write(tmp, resp.body()); + Files.move(tmp, out, StandardCopyOption.REPLACE_EXISTING); + } } diff --git a/XSD_Validation/java/pom.xml b/XSD_Validation/java/pom.xml new file mode 100644 index 0000000..688c608 --- /dev/null +++ b/XSD_Validation/java/pom.xml @@ -0,0 +1,31 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../pom.xml + + + xsd-validation-java + + XsdValidate + + + + + ${project.basedir} + + diff --git a/XSLT_DataQuality_Checks/Custom_Internal_Checks/README.md b/XSLT_DataQuality_Checks/Custom_Internal_Checks/README.md index 29c94cd..2ef1194 100644 --- a/XSLT_DataQuality_Checks/Custom_Internal_Checks/README.md +++ b/XSLT_DataQuality_Checks/Custom_Internal_Checks/README.md @@ -17,17 +17,18 @@ On the canonical 4.2.9 sample all four rules **PASS** (verified). ## Run +Run the generic XSLT runner via the committed Maven Wrapper (`mvnw.cmd` on +Windows), from the repo root: + ```bash -tools/fetch-tools.sh -XSLT_Transformations/invocation/run-transform.sh \ - XSLT_DataQuality_Checks/Custom_Internal_Checks/custom_internal_checks.xslt \ - FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml custom_dq.html +M="./mvnw -q -pl XSLT_Transformations/invocation compile exec:java" +XSL=XSLT_DataQuality_Checks/Custom_Internal_Checks/custom_internal_checks.xslt +SRC=FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml + +$M -Dexec.args="$XSL $SRC custom_dq.html" # Tighten the concentration limit to 5% to see R3 fail: -XSLT_Transformations/invocation/run-transform.sh \ - XSLT_DataQuality_Checks/Custom_Internal_Checks/custom_internal_checks.xslt \ - FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml custom_dq.html \ - "concentrationLimitPct=5" +$M -Dexec.args="$XSL $SRC custom_dq.html concentrationLimitPct=5" ``` XSLT 2.0 → use Saxon (see [`../../XSLT_Transformations/`](../../XSLT_Transformations/) diff --git a/XSLT_Transformations/README.md b/XSLT_Transformations/README.md index 9e92d95..b914fa9 100644 --- a/XSLT_Transformations/README.md +++ b/XSLT_Transformations/README.md @@ -2,7 +2,8 @@ Company-facing transformations of FundsXML positions data. All stylesheets are **XSLT 2.0** — run with Saxon (`xsltproc`/`lxml` are XSLT 1.0 and will not work). -`tools/fetch-tools.sh` provides Saxon-HE in `.lib/`. +Saxon-HE is a Maven dependency of `invocation/pom.xml`, resolved from Maven +Central by the committed Maven Wrapper — no prior fetch step, no `.lib/`. | Output | Stylesheet | Notes | |--------|-----------|-------| @@ -17,26 +18,25 @@ Company-internal DQ rules live next door in | Stack | Entry point | Status | |-------|-------------|--------| -| CLI (Saxon) | [`invocation/run-transform.sh`](invocation/run-transform.sh) | ✅ verified | -| Java (s9api, no JAXB) | [`invocation/RunTransform.java`](invocation/RunTransform.java) | ✅ verified | +| Java (s9api, no JAXB) | [`invocation/RunTransform.java`](invocation/RunTransform.java) | ✅ verified (via Maven Wrapper) | | Python | [`invocation/run_transform.py`](invocation/run_transform.py) | needs `pip install saxonche` | | Node.js | see below | needs `npm i xslt3` (saxon-js) | +The Java runner is standalone & cross-platform via the committed Maven Wrapper +(`./mvnw`, or `mvnw.cmd` on Windows), launched from the repo root: + ```bash -# CLI — HTML factsheet -XSLT_Transformations/invocation/run-transform.sh \ - XSLT_Transformations/Factsheet/factsheet_html.xslt \ - FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml factsheet.html +M="./mvnw -q -pl XSLT_Transformations/invocation compile exec:java" +SRC=FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml + +# HTML factsheet +$M -Dexec.args="XSLT_Transformations/Factsheet/factsheet_html.xslt $SRC factsheet.html" -# CLI — CSV with semicolon delimiter (parameter pass-through) -XSLT_Transformations/invocation/run-transform.sh \ - XSLT_Transformations/CSV_Export/positions_csv.xslt \ - FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml positions.csv "delimiter=;" +# CSV with semicolon delimiter (parameter pass-through) +$M -Dexec.args="XSLT_Transformations/CSV_Export/positions_csv.xslt $SRC positions.csv delimiter=;" # PDF — two steps (Saxon then Apache FOP) -XSLT_Transformations/invocation/run-transform.sh \ - XSLT_Transformations/Factsheet/factsheet_fo.xslt \ - FundsXML_Files/4.2.9/positions/Mixed-Fund_Positions.xml factsheet.fo +$M -Dexec.args="XSLT_Transformations/Factsheet/factsheet_fo.xslt $SRC factsheet.fo" fop -fo factsheet.fo -pdf factsheet.pdf # Node.js (SaxonJS / xslt3) — XSLT 3.0 engine runs these XSLT 2.0 sheets: diff --git a/XSLT_Transformations/invocation/RunTransform.java b/XSLT_Transformations/invocation/RunTransform.java index 212c71b..3b1c605 100644 --- a/XSLT_Transformations/invocation/RunTransform.java +++ b/XSLT_Transformations/invocation/RunTransform.java @@ -1,13 +1,12 @@ // Run an XSLT 2.0 stylesheet via the Saxon s9api (native Java, no JAXB). // -// tools/fetch-tools.sh -// SCP=.lib/Saxon-HE-12.5.jar:.lib/xmlresolver-5.2.2.jar:.lib/xmlresolver-5.2.2-data.jar -// javac -cp "$SCP" -d /tmp/rt XSLT_Transformations/invocation/RunTransform.java -// java -cp "$SCP:/tmp/rt" RunTransform [k=v ...] +// Standalone & cross-platform — run from the repo root with the Maven Wrapper: +// ./mvnw -q -pl XSLT_Transformations/invocation compile exec:java \ +// -Dexec.args=" [k=v ...]" // Exit: 0 success, 2 setup error. // -// Dependencies: Saxon-HE + xmlresolver jars only (fetched by -// tools/fetch-tools.sh into .lib/); no other libraries. +// Dependencies (from Maven Central, see pom.xml): Saxon-HE + xmlresolver +// (+ its -data artifact); no other libraries. // // This is a generic, FundsXML-agnostic invocation wrapper: it applies any // stylesheet to any XML and passes through string parameters (k=v) — the diff --git a/XSLT_Transformations/invocation/pom.xml b/XSLT_Transformations/invocation/pom.xml new file mode 100644 index 0000000..91bfc79 --- /dev/null +++ b/XSLT_Transformations/invocation/pom.xml @@ -0,0 +1,50 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + ../../pom.xml + + + xslt-transform-java + + RunTransform + + + + + net.sf.saxon + Saxon-HE + ${saxon.version} + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + + + org.xmlresolver + xmlresolver + ${xmlresolver.version} + data + runtime + + + + + ${project.basedir} + + diff --git a/XSLT_Transformations/invocation/run-transform.sh b/XSLT_Transformations/invocation/run-transform.sh deleted file mode 100755 index 9ca0642..0000000 --- a/XSLT_Transformations/invocation/run-transform.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -# Run any XSLT 2.0 stylesheet in this repo via Saxon-HE (CLI). -# -# Usage: run-transform.sh [name=value ...] -# Exit: 0 on success, 2 on setup error, Saxon's code otherwise. -# -# The Custom_Internal_Checks / Factsheet / CSV stylesheets are XSLT 2.0, so an -# XSLT 2.0/3.0 engine (Saxon) is required — xsltproc/lxml (XSLT 1.0) will not -# work. tools/fetch-tools.sh provides Saxon-HE in .lib/. -set -euo pipefail - -XSL="${1:?usage: run-transform.sh [params...]}" -IN="${2:?input xml required}" -OUT="${3:?output path required}" -shift 3 || true - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -LIB="${REPO_ROOT}/.lib" -if [[ ! -f "${LIB}/Saxon-HE-12.5.jar" ]]; then - echo "Saxon not present; fetching..." >&2 - "${REPO_ROOT}/tools/fetch-tools.sh" >/dev/null -fi - -# Saxon 12.x needs xmlresolver on the classpath (CatalogResourceResolver). -SCP="${LIB}/Saxon-HE-12.5.jar:${LIB}/xmlresolver-5.2.2.jar:${LIB}/xmlresolver-5.2.2-data.jar" - -java -cp "$SCP" net.sf.saxon.Transform \ - -s:"$IN" -xsl:"$XSL" -o:"$OUT" "$@" -echo "wrote $OUT" diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..b150b91 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2f4ea62 --- /dev/null +++ b/pom.xml @@ -0,0 +1,106 @@ + + + + 4.0.0 + + org.fundsxml.examples + fundsxml-examples + 1.0.0 + pom + FundsXML Reference Examples (Java) + + + XSD_Validation/java + Schematron_DataQuality_Checks/Basic_Checks/invocation + XSLT_Transformations/invocation + XQuery_Examples/invocation + XML_Signature/java + Large_File_Processing/java + Data_Binding_JSON/java + Database_Integration/java + + + + UTF-8 + + 17 + + + 12.5 + 5.2.2 + 1.10.1 + 1.5.0 + 1.7.32 + 4.0.4 + 1.18.0 + 2.0.17 + 3.46.1.3 + + 3.5.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + + ${exec.mainClass} + + false + + + + + + diff --git a/tools/fetch-tools.sh b/tools/fetch-tools.sh deleted file mode 100755 index aae1c91..0000000 --- a/tools/fetch-tools.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env bash -# fetch-tools.sh — Fetch the Java XML toolchain jars used by the examples. -# -# Why: this repo's Schematron uses queryBinding="xslt2" and the Basic/Custom -# XSLT reports are XSLT 2.0 — both need a Saxon (XSLT 2.0/3.0) processor, which -# is not part of a base OS install. SchXslt compiles ISO Schematron to XSLT. -# -# Two independent classpaths are produced, on purpose: -# * SAXON_CP — Saxon-HE + xmlresolver, for XSLT 2.0 transforms. -# * SCHXSLT_CP — the SchXslt CLI (a self-contained jar that already bundles -# its own Saxon) + commons-cli + slf4j. Mixing the standalone -# Saxon-HE-12.5 into this classpath breaks SchXslt: the two -# Saxons need different org.xmlresolver APIs. -# -# All jars come from Maven Central (curl honours https_proxy / HTTPS_PROXY for -# locked-down enterprise networks). Jars land in .lib/ (gitignored) — they are -# external dependencies, not repo source. -# -# Usage: tools/fetch-tools.sh -# Output: SAXON_CP=... and SCHXSLT_CP=... (consumed by the invocation scripts). -set -euo pipefail - -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -LIB="${REPO_ROOT}/.lib" -mkdir -p "$LIB" -M2="https://repo1.maven.org/maven2" - -fetch() { - local url="$1" out="$2" - if [[ -s "$out" ]]; then echo "cached: $out" >&2; return 0; fi - echo "fetch: $url" >&2 - curl -sSL --fail -m 120 "$url" -o "$out" -} - -# --- Saxon-HE (XSLT 2.0/3.0) ------------------------------------------------- -fetch "${M2}/net/sf/saxon/Saxon-HE/12.5/Saxon-HE-12.5.jar" "${LIB}/Saxon-HE-12.5.jar" -# Saxon 12.x requires org.xmlresolver at runtime (CatalogResourceResolver). -fetch "${M2}/org/xmlresolver/xmlresolver/5.2.2/xmlresolver-5.2.2.jar" "${LIB}/xmlresolver-5.2.2.jar" -fetch "${M2}/org/xmlresolver/xmlresolver/5.2.2/xmlresolver-5.2.2-data.jar" "${LIB}/xmlresolver-5.2.2-data.jar" - -# --- SchXslt CLI (self-contained: bundles its own Saxon + XSLT) -------------- -fetch "${M2}/name/dmaus/schxslt/cli/1.10.1/cli-1.10.1.jar" "${LIB}/schxslt-cli-1.10.1.jar" -fetch "${M2}/commons-cli/commons-cli/1.5.0/commons-cli-1.5.0.jar" "${LIB}/commons-cli-1.5.0.jar" -fetch "${M2}/org/slf4j/slf4j-api/1.7.32/slf4j-api-1.7.32.jar" "${LIB}/slf4j-api-1.7.32.jar" -fetch "${M2}/org/slf4j/slf4j-nop/1.7.32/slf4j-nop-1.7.32.jar" "${LIB}/slf4j-nop-1.7.32.jar" - -# --- Apache Santuario (XML Signature, Phase 3) ------------------------------ -# xmlsec 4.0.4 runtime needs commons-codec; slf4j-api for logging (+ a no-op -# binding to silence "no SLF4J providers" on the console). -fetch "${M2}/org/apache/santuario/xmlsec/4.0.4/xmlsec-4.0.4.jar" "${LIB}/xmlsec-4.0.4.jar" -fetch "${M2}/commons-codec/commons-codec/1.18.0/commons-codec-1.18.0.jar" "${LIB}/commons-codec-1.18.0.jar" -fetch "${M2}/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar" "${LIB}/slf4j-api-2.0.17.jar" -fetch "${M2}/org/slf4j/slf4j-nop/2.0.17/slf4j-nop-2.0.17.jar" "${LIB}/slf4j-nop-2.0.17.jar" - -# --- SQLite JDBC (Database_Integration Java example) ------------------------- -# Self-contained driver: bundles the native SQLite libraries for common -# platforms, so the Java example needs no system SQLite install. -fetch "${M2}/org/xerial/sqlite-jdbc/3.46.1.3/sqlite-jdbc-3.46.1.3.jar" "${LIB}/sqlite-jdbc-3.46.1.3.jar" - -echo "SAXON_CP=${LIB}/Saxon-HE-12.5.jar:${LIB}/xmlresolver-5.2.2.jar:${LIB}/xmlresolver-5.2.2-data.jar" -echo "SQLITE_JDBC=${LIB}/sqlite-jdbc-3.46.1.3.jar" -echo "SCHXSLT_CP=${LIB}/schxslt-cli-1.10.1.jar:${LIB}/commons-cli-1.5.0.jar:${LIB}/slf4j-api-1.7.32.jar:${LIB}/slf4j-nop-1.7.32.jar" -echo "SANTUARIO_CP=${LIB}/xmlsec-4.0.4.jar:${LIB}/commons-codec-1.18.0.jar:${LIB}/slf4j-api-2.0.17.jar:${LIB}/slf4j-nop-2.0.17.jar"