diff --git a/.reuse/dep5 b/.reuse/dep5 deleted file mode 100644 index f43556c..0000000 --- a/.reuse/dep5 +++ /dev/null @@ -1,29 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: SOP-Java -Upstream-Contact: Paul Schaub -Source: https://pgpainless.org - -# Sample paragraph, commented out: -# -# Files: src/* -# Copyright: $YEAR $NAME <$CONTACT> -# License: ... - -# Gradle build tool -Files: gradle* -Copyright: 2015 the original author or authors. -License: Apache-2.0 - -# Woodpecker build files -Files: .woodpecker/* -Copyright: 2022 the original author or authors. -License: Apache-2.0 - -Files: external-sop/src/main/resources/sop/testsuite/external/* -Copyright: 2023 the original author or authors -License: Apache-2.0 - -# Github Issue Templates -Files: .github/ISSUE_TEMPLATE/* -Copyright: 2024 the original author or authors -License: Apache-2.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 49113f6..c0500cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ SPDX-License-Identifier: Apache-2.0 # Changelog +## 10.1.1 +- Prepare jar files for use in native images, e.g. using GraalVM by generating and including + configuration files for reflection, resources and dynamic proxies. +- gradle: Make use of jvmToolchain functionality +- gradle: Improve reproducibility +- gradle: Bump animalsniffer to `2.0.0` + ## 10.1.0 - `sop-java`: - Remove `label()` option from `armor()` subcommand diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 0000000..f82d8f8 --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2025 Paul Schaub +# +# SPDX-License-Identifier: Apache-2.0 + +version = 1 +SPDX-PackageName = "SOP-Java" +SPDX-PackageSupplier = "Paul Schaub " +SPDX-PackageDownloadLocation = "https://pgpainless.org" + +[[annotations]] +path = "gradle**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2015 the original author or authors." +SPDX-License-Identifier = "Apache-2.0" + +[[annotations]] +path = ".woodpecker/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2022 the original author or authors." +SPDX-License-Identifier = "Apache-2.0" + +[[annotations]] +path = "external-sop/src/main/resources/sop/testsuite/external/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2023 the original author or authors" +SPDX-License-Identifier = "Apache-2.0" + +[[annotations]] +path = ".github/ISSUE_TEMPLATE/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2024 the original author or authors" +SPDX-License-Identifier = "Apache-2.0" diff --git a/build.gradle b/build.gradle index 577c2aa..1bff704 100644 --- a/build.gradle +++ b/build.gradle @@ -18,8 +18,8 @@ buildscript { } plugins { - id 'ru.vyarus.animalsniffer' version '1.5.3' - id 'org.jetbrains.kotlin.jvm' version "1.8.10" + id 'ru.vyarus.animalsniffer' version '2.0.0' + id 'org.jetbrains.kotlin.jvm' version "1.9.21" id 'com.diffplug.spotless' version '6.22.0' apply false } @@ -32,6 +32,7 @@ allprojects { apply plugin: 'jacoco' apply plugin: 'checkstyle' apply plugin: 'kotlin' + apply plugin: 'kotlin-kapt' apply plugin: 'com.diffplug.spotless' // For non-cli modules enable android api compatibility check @@ -67,8 +68,6 @@ allprojects { description = "Stateless OpenPGP Protocol API for Java" version = shortVersion - sourceCompatibility = javaSourceCompatibility - repositories { mavenCentral() } @@ -77,6 +76,13 @@ allprojects { tasks.withType(AbstractArchiveTask) { preserveFileTimestamps = false reproducibleFileOrder = true + + dirMode = 0755 + fileMode = 0644 + } + + kotlin { + jvmToolchain(javaSourceCompatibility) } // Compatibility of default implementations in kotlin interfaces with Java implementations. @@ -111,7 +117,7 @@ allprojects { } jacoco { - toolVersion = "0.8.7" + toolVersion = "0.8.8" } jacocoTestReport { @@ -119,7 +125,7 @@ allprojects { sourceDirectories.setFrom(project.files(sourceSets.main.allSource.srcDirs)) classDirectories.setFrom(project.files(sourceSets.main.output)) reports { - xml.enabled true + xml.required = true } } @@ -137,15 +143,15 @@ subprojects { apply plugin: 'signing' task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' + archiveClassifier = 'sources' from sourceSets.main.allSource } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc.destinationDir } task testsJar(type: Jar, dependsOn: testClasses) { - classifier = 'tests' + archiveClassifier = 'tests' from sourceSets.test.output } @@ -242,7 +248,7 @@ task jacocoRootReport(type: JacocoReport) { classDirectories.setFrom(files(subprojects.sourceSets.main.output)) executionData.setFrom(files(subprojects.jacocoTestReport.executionData)) reports { - xml.enabled true + xml.required = true xml.destination file("${buildDir}/reports/jacoco/test/jacocoTestReport.xml") } // We could remove the following setOnlyIf line, but then @@ -253,10 +259,6 @@ task jacocoRootReport(type: JacocoReport) { } task javadocAll(type: Javadoc) { - def currentJavaVersion = JavaVersion.current() - if (currentJavaVersion.compareTo(JavaVersion.VERSION_1_9) >= 0) { - options.addStringOption("-release", "8"); - } source subprojects.collect {project -> project.sourceSets.main.allJava } destinationDir = new File(buildDir, 'javadoc') diff --git a/external-sop/src/main/kotlin/sop/external/operation/EncryptExternal.kt b/external-sop/src/main/kotlin/sop/external/operation/EncryptExternal.kt index 12d9cff..679e09b 100644 --- a/external-sop/src/main/kotlin/sop/external/operation/EncryptExternal.kt +++ b/external-sop/src/main/kotlin/sop/external/operation/EncryptExternal.kt @@ -37,7 +37,7 @@ class EncryptExternal( override fun signWith(key: InputStream): Encrypt = apply { commandList.add("--sign-with=@ENV:SIGN_WITH_$argCounter") - envList.add("SIGN_WITH_$argCounter=${ExternalSOP.readString(key)}") + envList.add("SIGN_WITH_$argCounter=${readString(key)}") argCounter += 1 } diff --git a/sop-java-picocli/build.gradle b/sop-java-picocli/build.gradle index dbf0cc1..2203abe 100644 --- a/sop-java-picocli/build.gradle +++ b/sop-java-picocli/build.gradle @@ -21,7 +21,7 @@ dependencies { // CLI implementation "info.picocli:picocli:$picocliVersion" - annotationProcessor "info.picocli:picocli-codegen:$picocliVersion" + kapt "info.picocli:picocli-codegen:$picocliVersion" // @Nonnull, @Nullable... implementation "com.google.code.findbugs:jsr305:$jsrVersion" @@ -33,6 +33,10 @@ application { mainClass = mainClassName } +compileJava { + options.compilerArgs += ["-Aproject=${project.group}/${project.name}"] +} + jar { dependsOn(":sop-java:jar") duplicatesStrategy(DuplicatesStrategy.EXCLUDE) diff --git a/sop-java-picocli/src/main/kotlin/sop/cli/picocli/SopCLI.kt b/sop-java-picocli/src/main/kotlin/sop/cli/picocli/SopCLI.kt index b919370..62065f4 100644 --- a/sop-java-picocli/src/main/kotlin/sop/cli/picocli/SopCLI.kt +++ b/sop-java-picocli/src/main/kotlin/sop/cli/picocli/SopCLI.kt @@ -60,7 +60,7 @@ class SopCLI { @JvmField var EXECUTABLE_NAME = "sop" @JvmField - @Option(names = ["--stacktrace"], scope = CommandLine.ScopeType.INHERIT) + @Option(names = ["--stacktrace"], scope = ScopeType.INHERIT) var stacktrace = false @JvmStatic diff --git a/sop-java-testfixtures/src/main/java/sop/testsuite/AbortOnUnsupportedOption.java b/sop-java-testfixtures/src/main/java/sop/testsuite/AbortOnUnsupportedOption.java new file mode 100644 index 0000000..cbd0746 --- /dev/null +++ b/sop-java-testfixtures/src/main/java/sop/testsuite/AbortOnUnsupportedOption.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2025 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.testsuite; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface AbortOnUnsupportedOption { + +} diff --git a/sop-java-testfixtures/src/main/java/sop/testsuite/AbortOnUnsupportedOptionExtension.java b/sop-java-testfixtures/src/main/java/sop/testsuite/AbortOnUnsupportedOptionExtension.java new file mode 100644 index 0000000..0bf366d --- /dev/null +++ b/sop-java-testfixtures/src/main/java/sop/testsuite/AbortOnUnsupportedOptionExtension.java @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2025 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.testsuite; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; +import sop.exception.SOPGPException; + +import java.lang.annotation.Annotation; + +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class AbortOnUnsupportedOptionExtension implements TestExecutionExceptionHandler { + + @Override + public void handleTestExecutionException(ExtensionContext extensionContext, Throwable throwable) throws Throwable { + Class testClass = extensionContext.getRequiredTestClass(); + Annotation annotation = testClass.getAnnotation(AbortOnUnsupportedOption.class); + if (annotation != null && throwable instanceof SOPGPException.UnsupportedOption) { + assumeTrue(false, "Test aborted due to: " + throwable.getMessage()); + } + throw throwable; + } +} diff --git a/sop-java-testfixtures/src/main/kotlin/sop/testsuite/AbortOnUnsupportedOption.kt b/sop-java-testfixtures/src/main/kotlin/sop/testsuite/AbortOnUnsupportedOption.kt deleted file mode 100644 index cf99671..0000000 --- a/sop-java-testfixtures/src/main/kotlin/sop/testsuite/AbortOnUnsupportedOption.kt +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package sop.testsuite - -import java.lang.annotation.Inherited - -@Target(AnnotationTarget.TYPE) -@Retention(AnnotationRetention.RUNTIME) -@Inherited -annotation class AbortOnUnsupportedOption diff --git a/sop-java-testfixtures/src/main/kotlin/sop/testsuite/AbortOnUnsupportedOptionExtension.kt b/sop-java-testfixtures/src/main/kotlin/sop/testsuite/AbortOnUnsupportedOptionExtension.kt deleted file mode 100644 index 809c78f..0000000 --- a/sop-java-testfixtures/src/main/kotlin/sop/testsuite/AbortOnUnsupportedOptionExtension.kt +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package sop.testsuite - -import org.junit.jupiter.api.Assumptions -import org.junit.jupiter.api.extension.ExtensionContext -import org.junit.jupiter.api.extension.TestExecutionExceptionHandler -import sop.exception.SOPGPException - -class AbortOnUnsupportedOptionExtension : TestExecutionExceptionHandler { - override fun handleTestExecutionException(context: ExtensionContext, throwable: Throwable) { - val testClass = context.requiredTestClass - val annotation = testClass.getAnnotation(AbortOnUnsupportedOption::class.java) - if (annotation != null && SOPGPException.UnsupportedOption::class.isInstance(throwable)) { - Assumptions.assumeTrue(false, "Test aborted due to: " + throwable.message) - } - throw throwable - } -} diff --git a/sop-java/src/main/kotlin/sop/SigningResult.kt b/sop-java/src/main/kotlin/sop/SigningResult.kt index 29304ea..651f8c1 100644 --- a/sop-java/src/main/kotlin/sop/SigningResult.kt +++ b/sop-java/src/main/kotlin/sop/SigningResult.kt @@ -9,8 +9,10 @@ package sop * * @param micAlg string identifying the digest mechanism used to create the signed message. This is * useful for setting the `micalg=` parameter for the multipart/signed content-type of a PGP/MIME - * object as described in section 5 of [RFC3156]. If more than one signature was generated and - * different digest mechanisms were used, the value of the micalg object is an empty string. + * object as described in section 5 of + * [RFC3156](https://www.rfc-editor.org/rfc/rfc3156#section-5). If more than one signature was + * generated and different digest mechanisms were used, the value of the micalg object is an empty + * string. */ data class SigningResult(val micAlg: MicAlg) { diff --git a/sop-java/src/main/kotlin/sop/operation/GenerateKey.kt b/sop-java/src/main/kotlin/sop/operation/GenerateKey.kt index 3b83b99..13de39a 100644 --- a/sop-java/src/main/kotlin/sop/operation/GenerateKey.kt +++ b/sop-java/src/main/kotlin/sop/operation/GenerateKey.kt @@ -78,7 +78,7 @@ interface GenerateKey { fun signingOnly(): GenerateKey /** - * Generate the OpenPGP key and return it encoded as an [InputStream]. + * Generate the OpenPGP key and return it encoded as an [java.io.InputStream]. * * @return key * @throws MissingArg if no user-id was provided diff --git a/sop-java/src/main/kotlin/sop/util/ProxyOutputStream.kt b/sop-java/src/main/kotlin/sop/util/ProxyOutputStream.kt index a608c89..4ba24b8 100644 --- a/sop-java/src/main/kotlin/sop/util/ProxyOutputStream.kt +++ b/sop-java/src/main/kotlin/sop/util/ProxyOutputStream.kt @@ -16,6 +16,7 @@ import java.io.OutputStream * target output stream is not yet known. */ @Deprecated("Marked for removal.") +// TODO: Remove in 11.X class ProxyOutputStream : OutputStream() { private val buffer = ByteArrayOutputStream() private var swapped: OutputStream? = null diff --git a/version.gradle b/version.gradle index 33a2251..b4908ee 100644 --- a/version.gradle +++ b/version.gradle @@ -4,10 +4,10 @@ allprojects { ext { - shortVersion = '10.1.1' + shortVersion = '10.1.2' isSnapshot = true minAndroidSdk = 10 - javaSourceCompatibility = 1.8 + javaSourceCompatibility = 11 gsonVersion = '2.10.1' jsrVersion = '3.0.2' junitVersion = '5.8.2'