From 961e60642c77702108bf0dab64ade891ddcc5a72 Mon Sep 17 00:00:00 2001 From: Adam Farley Date: Wed, 13 Mar 2024 15:34:13 +0000 Subject: [PATCH] Centralising sbom dependency data, plus adding versions to sboms This is to centralise the jar versions and shas to simplify future updates, and to enable a user to easily set their own values. This also adds cyclonedx dependency version strings to sboms. Signed-off-by: Adam Farley --- cyclonedx-lib/README.md | 11 ++- cyclonedx-lib/build.xml | 68 ++++++++----------- .../shas/commons-codec.jar.sha256 | 1 + .../shas/commons-io.jar.sha256 | 1 + .../shas/cyclonedx-core-java.jar.sha256 | 1 + .../shas/github-package-url.jar.sha256 | 1 + .../shas/jackson-annotations.jar.sha256 | 1 + .../shas/jackson-core.jar.sha256 | 1 + .../shas/jackson-databind.jar.sha256 | 1 + .../shas/jackson-dataformat-xml.jar.sha256 | 1 + .../shas/json-schema.jar.sha256 | 1 + .../versions/commons-codec.jar.version | 1 + .../versions/commons-io.jar.version | 1 + .../versions/cyclonedx-core-java.jar.version | 1 + .../versions/github-package-url.jar.version | 1 + .../versions/jackson-annotations.jar.version | 1 + .../versions/jackson-core.jar.version | 1 + .../versions/jackson-databind.jar.version | 1 + .../jackson-dataformat-xml.jar.version | 1 + .../versions/json-schema.jar.version | 1 + cyclonedx-lib/getDependencies | 68 ++++++++++++------- sbin/build.sh | 14 +++- 22 files changed, 106 insertions(+), 73 deletions(-) create mode 100644 cyclonedx-lib/dependency_data/shas/commons-codec.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/commons-io.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/cyclonedx-core-java.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/github-package-url.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/jackson-annotations.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/jackson-core.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/jackson-databind.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/jackson-dataformat-xml.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/shas/json-schema.jar.sha256 create mode 100644 cyclonedx-lib/dependency_data/versions/commons-codec.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/commons-io.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/cyclonedx-core-java.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/github-package-url.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/jackson-annotations.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/jackson-core.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/jackson-databind.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/jackson-dataformat-xml.jar.version create mode 100644 cyclonedx-lib/dependency_data/versions/json-schema.jar.version diff --git a/cyclonedx-lib/README.md b/cyclonedx-lib/README.md index 5dc5740a2..711077035 100644 --- a/cyclonedx-lib/README.md +++ b/cyclonedx-lib/README.md @@ -34,13 +34,12 @@ formulation section (mostly because the author of this added such a section recently) 1. Check that the version of CycloneDX you are using supports the - functionality you want. If not, it will need to be updated. To do this - you need to do three steps [Sample PR](https://github.com/adoptium/temurin-build/pull/3558/files): - - Update [getDependencies](https://github.com/adoptium/temurin-build/blob/master/cyclonedx-lib/getDependencies) with the new version and SHA + functionality you want. If not, it will need to be updated. To do this + you need to do two steps: + - Update the [sha and version files](https://github.com/adoptium/temurin-build/blob/master/cyclonedx-lib/dependency_data) for each jar you plan to change. - Ensure [build.getDependency](https://ci.adoptium.net/job/build.getDependency/) is run to pick up the new version - - Update [build.xml](https://github.com/adoptium/temurin-build/blob/master/cyclonedx-lib/build.xml) with the new SHA to allow it to be downloaded successfully during the build (This change can be made along with the getDependencies one if you co--ordinate the update appopriately -2. If the build and java code does not already have support for the CycloneDX functionality that you need the follow ([Sample PR](https://github.com/adoptium/temurin-build/blob/master/cyclonedx-lib/build.xml)) - - Updates to [cyclonedx-lib/TemurinGenSBOM.java])https://github.com/adoptium/temurin-build/blob/master/sbin/common/sbom.sh) to add a new parameter, a new function to implement it, the call to that function from the `switch` functionality in the `main` function +2. If the build and java code does not already have support for the CycloneDX functionality that you need, then follow these steps ([Sample PR](https://github.com/adoptium/temurin-build/pull/3538)) + - Updates to [cyclonedx-lib/TemurinGenSBOM.java](https://github.com/adoptium/temurin-build/blob/master/sbin/common/sbom.sh) to add a new parameter, a new function to implement it, the call to that function from the `switch` functionality in the `main` function - Update [cyclonedx-lib/build.xml](https://github.com/adoptium/temurin-build/blob/master/cyclonedx-lib/build.xml) to add tests for the new functionality - Add a new function to [sbin/common/sbom.sh](https://github.com/adoptium/temurin-build/blob/master/sbin/common/sbom.sh) to add the fields you need - Updates to [sbin/build.sh](https://github.com/adoptium/temurin-build/blob/master/sbin/build.sh) to invoke the new function(s) in sbom.sh diff --git a/cyclonedx-lib/build.xml b/cyclonedx-lib/build.xml index 96ff9ec5c..afa45beeb 100644 --- a/cyclonedx-lib/build.xml +++ b/cyclonedx-lib/build.xml @@ -20,9 +20,12 @@ // jscpd:ignore-start --> - + + + + @@ -41,20 +44,12 @@ - - + + - + @@ -91,58 +86,37 @@ - + - + - + - + - + - + - + @@ -505,6 +479,20 @@ + + + + + + + + + + + diff --git a/cyclonedx-lib/dependency_data/shas/commons-codec.jar.sha256 b/cyclonedx-lib/dependency_data/shas/commons-codec.jar.sha256 new file mode 100644 index 000000000..a5f27b9cb --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/commons-codec.jar.sha256 @@ -0,0 +1 @@ +b3e9f6d63a790109bf0d056611fbed1cf69055826defeb9894a71369d246ed63 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/commons-io.jar.sha256 b/cyclonedx-lib/dependency_data/shas/commons-io.jar.sha256 new file mode 100644 index 000000000..854ca3d3e --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/commons-io.jar.sha256 @@ -0,0 +1 @@ +961b2f6d87dbacc5d54abf45ab7a6e2495f89b75598962d8c723cea9bc210908 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/cyclonedx-core-java.jar.sha256 b/cyclonedx-lib/dependency_data/shas/cyclonedx-core-java.jar.sha256 new file mode 100644 index 000000000..44090c667 --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/cyclonedx-core-java.jar.sha256 @@ -0,0 +1 @@ +ecc371d12808dfe76047f87f8235665d74dd6cf8ec12c41d052715a3fd79e0b5 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/github-package-url.jar.sha256 b/cyclonedx-lib/dependency_data/shas/github-package-url.jar.sha256 new file mode 100644 index 000000000..b9d1f60ef --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/github-package-url.jar.sha256 @@ -0,0 +1 @@ +8e23280221afd1e6561d433dfb133252cd287167acb0eca5a991667118ff10a2 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/jackson-annotations.jar.sha256 b/cyclonedx-lib/dependency_data/shas/jackson-annotations.jar.sha256 new file mode 100644 index 000000000..95f7e9a2e --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/jackson-annotations.jar.sha256 @@ -0,0 +1 @@ +2c6869d505cf60dc066734b7d50339f975bd3adc635e26a78abb71acb4473c0d \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/jackson-core.jar.sha256 b/cyclonedx-lib/dependency_data/shas/jackson-core.jar.sha256 new file mode 100644 index 000000000..c75a5db5e --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/jackson-core.jar.sha256 @@ -0,0 +1 @@ +b5d37a77c88277b97e3593c8740925216c06df8e4172bbde058528df04ad3e7a \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/jackson-databind.jar.sha256 b/cyclonedx-lib/dependency_data/shas/jackson-databind.jar.sha256 new file mode 100644 index 000000000..49bdf8a3a --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/jackson-databind.jar.sha256 @@ -0,0 +1 @@ +501d3abce4d18dcc381058ec593c5b94477906bba6efbac14dae40a642f77424 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/jackson-dataformat-xml.jar.sha256 b/cyclonedx-lib/dependency_data/shas/jackson-dataformat-xml.jar.sha256 new file mode 100644 index 000000000..bdf90ce8c --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/jackson-dataformat-xml.jar.sha256 @@ -0,0 +1 @@ +edbda6c775a36049cf0088b111ab958cca0dc70cb9326918d6cf153cb3fa426b \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/shas/json-schema.jar.sha256 b/cyclonedx-lib/dependency_data/shas/json-schema.jar.sha256 new file mode 100644 index 000000000..492cd69b8 --- /dev/null +++ b/cyclonedx-lib/dependency_data/shas/json-schema.jar.sha256 @@ -0,0 +1 @@ +968991e5718520cdd7b224770f790cf2c241cddf64d10a36c21f9f8b4a15e79c \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/commons-codec.jar.version b/cyclonedx-lib/dependency_data/versions/commons-codec.jar.version new file mode 100644 index 000000000..07fe6f6c9 --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/commons-codec.jar.version @@ -0,0 +1 @@ +1.15 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/commons-io.jar.version b/cyclonedx-lib/dependency_data/versions/commons-io.jar.version new file mode 100644 index 000000000..ed0edc885 --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/commons-io.jar.version @@ -0,0 +1 @@ +2.11.0 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/cyclonedx-core-java.jar.version b/cyclonedx-lib/dependency_data/versions/cyclonedx-core-java.jar.version new file mode 100644 index 000000000..24afbc91d --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/cyclonedx-core-java.jar.version @@ -0,0 +1 @@ +8.0.3 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/github-package-url.jar.version b/cyclonedx-lib/dependency_data/versions/github-package-url.jar.version new file mode 100644 index 000000000..13175fdc4 --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/github-package-url.jar.version @@ -0,0 +1 @@ +1.4.1 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/jackson-annotations.jar.version b/cyclonedx-lib/dependency_data/versions/jackson-annotations.jar.version new file mode 100644 index 000000000..fb71e071a --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/jackson-annotations.jar.version @@ -0,0 +1 @@ +2.14.2 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/jackson-core.jar.version b/cyclonedx-lib/dependency_data/versions/jackson-core.jar.version new file mode 100644 index 000000000..fb71e071a --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/jackson-core.jar.version @@ -0,0 +1 @@ +2.14.2 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/jackson-databind.jar.version b/cyclonedx-lib/dependency_data/versions/jackson-databind.jar.version new file mode 100644 index 000000000..fb71e071a --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/jackson-databind.jar.version @@ -0,0 +1 @@ +2.14.2 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/jackson-dataformat-xml.jar.version b/cyclonedx-lib/dependency_data/versions/jackson-dataformat-xml.jar.version new file mode 100644 index 000000000..fb71e071a --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/jackson-dataformat-xml.jar.version @@ -0,0 +1 @@ +2.14.2 \ No newline at end of file diff --git a/cyclonedx-lib/dependency_data/versions/json-schema.jar.version b/cyclonedx-lib/dependency_data/versions/json-schema.jar.version new file mode 100644 index 000000000..0c59751cf --- /dev/null +++ b/cyclonedx-lib/dependency_data/versions/json-schema.jar.version @@ -0,0 +1 @@ +1.0.77 \ No newline at end of file diff --git a/cyclonedx-lib/getDependencies b/cyclonedx-lib/getDependencies index fbbdca11b..03164a7b3 100644 --- a/cyclonedx-lib/getDependencies +++ b/cyclonedx-lib/getDependencies @@ -2,6 +2,9 @@ LABEL=params.LABEL ? params.LABEL : 'ci.role.test&&hw.arch.x86&&sw.os.linux' +TEMURIN_BUILD_REPO="https://github.com/adamfarley/temurin-build" +TEMURIN_BUILD_BRANCH="add_versions_and_shas_to_build_getdependencies" + stage('Queue') { node("$LABEL") { cleanWs() @@ -9,9 +12,17 @@ stage('Queue') { } } -def fetchSingleFile(String jarFile, String sha, String mavenURL) { - sh 'echo "' + sha + ' sbom_dependencies/' + jarFile + '" >> sbom_dep_shas.txt' +// Fetch a single file from a location under Maven. +// Args: +// - jarFile: The name of the file after we've downloaded it. +// - mavenURL: The file and location of the jarfile to be downloaded (under Maven). +def fetchSingleFile(String jarFile, String mavenURL) { + // Downloads the requested jarfile sh 'curl -L -o "sbom_dependencies/' + jarFile + '" "https://search.maven.org/classic/remotecontent?filepath=' + mavenURL + '"' + + // Puts the matching sha for the jarfile into the list of shas to check. + def jarSHA = readFile(file : './temurin-build/cyclonedx-lib/dependency_data/shas/' + jarFile + '.sha256').replaceAll("\\s","") + sh 'echo "' + jarSHA + ' sbom_dependencies/' + jarFile + '" >> sbom_dependency_shas.txt' } def fetchDeps() { @@ -21,38 +32,45 @@ def fetchDeps() { } timeout(time: time_limit, unit: 'HOURS') { try { + // This allows us to easily specify which of our workspace files are to be archived later. sh 'mkdir sbom_dependencies' - - + // These versions come from https://github.com/CycloneDX/cyclonedx-core-java/tags // Version->spec mappings are in https://github.com/CycloneDX/cyclonedx-core-java#cyclonedx-schema-support - def cyclonedx_core_java_version = "8.0.3" - def jackson_core_version = "2.14.2" - def jackson_annotations_version = "2.14.2" - def jackson_databind_version = "2.14.2" - def json_schema_version = "1.0.77" - def commons_codec_version = "1.15" - def commons_io_version = "2.11.0" - def github_package_url_version = "1.4.1" - - fetchSingleFile("cyclonedx-core-java.jar", "ecc371d12808dfe76047f87f8235665d74dd6cf8ec12c41d052715a3fd79e0b5", "org/cyclonedx/cyclonedx-core-java/${cyclonedx_core_java_version}/cyclonedx-core-java-${cyclonedx_core_java_version}.jar") - fetchSingleFile("jackson-core.jar", "b5d37a77c88277b97e3593c8740925216c06df8e4172bbde058528df04ad3e7a", "com/fasterxml/jackson/core/jackson-core/${jackson_core_version}/jackson-core-${jackson_core_version}.jar") - fetchSingleFile("jackson-dataformat-xml.jar", "edbda6c775a36049cf0088b111ab958cca0dc70cb9326918d6cf153cb3fa426b", "com/fasterxml/jackson/dataformat/jackson-dataformat-xml/${jackson_databind_version}/jackson-dataformat-xml-${jackson_databind_version}.jar") - fetchSingleFile("jackson-databind.jar", "501d3abce4d18dcc381058ec593c5b94477906bba6efbac14dae40a642f77424", "com/fasterxml/jackson/core/jackson-databind/${jackson_databind_version}/jackson-databind-${jackson_databind_version}.jar") - fetchSingleFile("jackson-annotations.jar", "2c6869d505cf60dc066734b7d50339f975bd3adc635e26a78abb71acb4473c0d", "com/fasterxml/jackson/core/jackson-annotations/${jackson_annotations_version}/jackson-annotations-${jackson_annotations_version}.jar") - fetchSingleFile("json-schema.jar", "968991e5718520cdd7b224770f790cf2c241cddf64d10a36c21f9f8b4a15e79c", "com/networknt/json-schema-validator/${json_schema_version}/json-schema-validator-${json_schema_version}.jar") - fetchSingleFile("commons-codec.jar", "b3e9f6d63a790109bf0d056611fbed1cf69055826defeb9894a71369d246ed63", "commons-codec/commons-codec/${commons_codec_version}/commons-codec-${commons_codec_version}.jar") - fetchSingleFile("github-package-url.jar", "8e23280221afd1e6561d433dfb133252cd287167acb0eca5a991667118ff10a2", "com/github/package-url/packageurl-java/${github_package_url_version}/packageurl-java-${github_package_url_version}.jar") - fetchSingleFile("commons-io.jar", "961b2f6d87dbacc5d54abf45ab7a6e2495f89b75598962d8c723cea9bc210908", "commons-io/commons-io/${commons_io_version}/commons-io-${commons_io_version}.jar") - - sh 'sha256sum -c sbom_dep_shas.txt' + sh 'git clone -b ' + TEMURIN_BUILD_BRANCH + ' ' + TEMURIN_BUILD_REPO + ' temurin-build' + def dep_data = WORKSPACE + "/temurin-build/cyclonedx-lib/dependency_data/" + + def cyclonedx_core_java_version = readFile(file : dep_data + 'versions/cyclonedx-core-java.jar.version').replaceAll("\\s","") + def jackson_core_version = readFile(file : dep_data + 'versions/jackson-core.jar.version').replaceAll("\\s","") + def jackson_annotations_version = readFile(file : dep_data + 'versions/jackson-annotations.jar.version').replaceAll("\\s","") + def jackson_databind_version = readFile(file : dep_data + 'versions/jackson-databind.jar.version').replaceAll("\\s","") + def json_schema_version = readFile(file : dep_data + 'versions/json-schema.jar.version').replaceAll("\\s","") + def commons_codec_version = readFile(file : dep_data + 'versions/commons-codec.jar.version').replaceAll("\\s","") + def commons_io_version = readFile(file : dep_data + 'versions/commons-io.jar.version').replaceAll("\\s","") + def github_package_url_version = readFile(file : dep_data + 'versions/github-package-url.jar.version').replaceAll("\\s","") + // Each of these fetches a jar in the format: fetchSingleFile(jar name post-download, current jar location under Maven) + fetchSingleFile("cyclonedx-core-java.jar", "org/cyclonedx/cyclonedx-core-java/${cyclonedx_core_java_version}/cyclonedx-core-java-${cyclonedx_core_java_version}.jar") + fetchSingleFile("jackson-core.jar", "com/fasterxml/jackson/core/jackson-core/${jackson_core_version}/jackson-core-${jackson_core_version}.jar") + fetchSingleFile("jackson-dataformat-xml.jar", "com/fasterxml/jackson/dataformat/jackson-dataformat-xml/${jackson_databind_version}/jackson-dataformat-xml-${jackson_databind_version}.jar") + fetchSingleFile("jackson-databind.jar", "com/fasterxml/jackson/core/jackson-databind/${jackson_databind_version}/jackson-databind-${jackson_databind_version}.jar") + fetchSingleFile("jackson-annotations.jar", "com/fasterxml/jackson/core/jackson-annotations/${jackson_annotations_version}/jackson-annotations-${jackson_annotations_version}.jar") + fetchSingleFile("json-schema.jar", "com/networknt/json-schema-validator/${json_schema_version}/json-schema-validator-${json_schema_version}.jar") + fetchSingleFile("commons-codec.jar", "commons-codec/commons-codec/${commons_codec_version}/commons-codec-${commons_codec_version}.jar") + fetchSingleFile("github-package-url.jar", "com/github/package-url/packageurl-java/${github_package_url_version}/packageurl-java-${github_package_url_version}.jar") + fetchSingleFile("commons-io.jar", "commons-io/commons-io/${commons_io_version}/commons-io-${commons_io_version}.jar") + + + // Check that every file matches the sha of the file we expected. + sh 'sha256sum -c sbom_dependency_shas.txt' + + // Store all retrieved files on Jenkins, for use during sbom creation. archiveArtifacts '**/sbom_dependencies/*' } finally { + // Clean up workspace. cleanWs() } } } - return this diff --git a/sbin/build.sh b/sbin/build.sh index bfe03555a..8f42a1a1a 100755 --- a/sbin/build.sh +++ b/sbin/build.sh @@ -900,6 +900,7 @@ generateSBoM() { # Set default SBOM formulation addSBOMFormulation "${javaHome}" "${classpath}" "${sbomJson}" "CycloneDX" addSBOMFormulationComp "${javaHome}" "${classpath}" "${sbomJson}" "CycloneDX" "CycloneDX jar SHAs" + addSBOMFormulationComp "${javaHome}" "${classpath}" "${sbomJson}" "CycloneDX" "CycloneDX jar versions" # Below add build tools into metadata tools if [ "${BUILD_CONFIG[OS_KERNEL_NAME]}" == "linux" ]; then @@ -1096,11 +1097,20 @@ addCycloneDXVersions() { for JAR in "${CYCLONEDB_DIR}/build/jar"/*.jar; do JarName=$(basename "$JAR") if [ "$(uname)" = "Darwin" ]; then - JarSha=$(shasum -a 256 "${CYCLONEDB_DIR}/build/jar/cyclonedx-core-java.jar" | cut -d' ' -f1) + JarSha=$(shasum -a 256 "$JAR" | cut -d' ' -f1) else - JarSha=$(sha256sum "${CYCLONEDB_DIR}/build/jar/cyclonedx-core-java.jar" | cut -d' ' -f1) + JarSha=$(sha256sum "$JAR" | cut -d' ' -f1) fi addSBOMFormulationComponentProperty "${javaHome}" "${classpath}" "${sbomJson}" "CycloneDX" "CycloneDX jar SHAs" "${JarName}" "${JarSha}" + # Now the jar's SHA has been added, we add the version string. + JarVersionFile="$(joinPath ${CYCLONEDB_DIR} dependency_data versions ${JarName}.version)" + if [ -f "${JarVersionFile}" ]; then + JarVersionString=$(cat "${JarVersionFile}") + addSBOMFormulationComponentProperty "${javaHome}" "${classpath}" "${sbomJson}" "CycloneDX" "CycloneDX jar versions" "${JarName}" "${JarVersionString}" + elif [ "${JarName}" != "temurin-gen-sbom.jar" ]; then + echo "ERROR: Cannot find jar version file for SBOM creation dependency ${JarName}." + echo "ERROR: Expected location: ${JarVersionFile}" + fi done fi }