Skip to content

Commit ab67b63

Browse files
feat: add BND Maven Plugins (#201)
* Adds BND Maven Plugins Adds [BND Maven Plugins](https://github.com/bndtools/bnd/blob/master/maven-plugins/README.md) to: - Generate an OSGi bundle descriptor (`MANIFEST.MF`). - Generate a JPMS bundle descriptor. - Check for binary compatibility between releases. The binary compatibility check is implemented by: - Annotating each package with `@Version`. See [Versioning in OSGi](https://bnd.bndtools.org/chapters/170-versioning.html#versions-in-osgi) for details. - Adding the `bnd-baseline-maven-plugin` that checks if the version increment is compatible with the change type (`MICRO`—only annotations added, `MINOR`—only binary compatible changes, `MAJOR`—binary incompatible changes). * Enable reproducible builds * Change module name * Make JSpecify optional --------- Co-authored-by: Jeremy Long <[email protected]>
1 parent e11a8ff commit ab67b63

File tree

4 files changed

+157
-3
lines changed

4 files changed

+157
-3
lines changed

bnd.bnd

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#
2+
# MIT License
3+
#
4+
# Permission is hereby granted, free of charge, to any person obtaining a copy
5+
# of this software and associated documentation files (the "Software"), to deal
6+
# in the Software without restriction, including without limitation the rights
7+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
# copies of the Software, and to permit persons to whom the Software is
9+
# furnished to do so, subject to the following conditions:
10+
#
11+
# The above copyright notice and this permission notice shall be included in all
12+
# copies or substantial portions of the Software.
13+
#
14+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
# SOFTWARE.
21+
#
22+
##
23+
24+
# Create OSGi and JPMS module names based on the `groupId` and `artifactId`.
25+
# This almost agrees with `maven-bundle-plugin`, but replaces non-alphanumeric characters
26+
# with full stops `.`.
27+
Bundle-SymbolicName: com.github.packageurl
28+
-jpms-module-info: $[Bundle-SymbolicName];access=0
29+
30+
# Convert API leakage warnings to errors
31+
-fixupmessages.priv_refs: "private references";restrict:=warning;is:=error
32+
33+
# Options specific to dependency packages:
34+
#
35+
# Jakarta Validation and JSpecify are optional dependencies.
36+
Import-Package: \
37+
jakarta.validation;resolution:=optional,\
38+
org.jspecify.annotations;resolution:=optional,\
39+
*
40+
41+
# Options specific to dependency modules:
42+
#
43+
# Optional dependencies can not be `transitive`, otherwise consumers will need them at compile time.
44+
-jpms-module-info-options: \
45+
jakarta.validation;transitive=false,\
46+
org.jspecify;transitive=false
47+
48+
# Adds certain `Implementation-*` and `Specification-*` entries to the generated `MANIFEST.MF`.
49+
# We set these values to their Maven Archiver defaults: https://maven.apache.org/shared/maven-archiver/#class_manifest
50+
Implementation-Title: ${project.name}
51+
# Implementation-Vendor: ${project.organization.name}
52+
Implementation-Version: ${project.version}
53+
Specification-Title: ${project.name}
54+
# Specification-Vendor: ${project.organization.name}
55+
Specification-Version: ${parsedVersion.majorVersion}.${parsedVersion.minorVersion}

pom.xml

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.github.package-url</groupId>
55
<artifactId>packageurl-java</artifactId>
6-
<version>1.5.1-SNAPSHOT</version>
6+
<version>1.6.0-SNAPSHOT</version>
77
<packaging>jar</packaging>
88

99
<name>Package URL</name>
@@ -41,6 +41,13 @@
4141
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
4242
<maven.javadoc.failOnError>false</maven.javadoc.failOnError>
4343

44+
<!--
45+
~ `project.build.outputTimestamp` is required to be present for reproducible builds
46+
~
47+
~ Its value fixes various timestamps present in the JAR and should be incremented at each release.
48+
-->
49+
<project.build.outputTimestamp>2025-03-15T10:12:28Z</project.build.outputTimestamp>
50+
4451
<!-- Build requirements -->
4552
<!--
4653
~ Minimum JDK version required to build the library:
@@ -55,6 +62,8 @@
5562
<max.jdk.version>18</max.jdk.version>
5663

5764
<!-- Maven Plugin Versions -->
65+
<bnd.maven.plugin.version>7.1.0</bnd.maven.plugin.version>
66+
<builder.helper.maven.plugin.version>3.6.0</builder.helper.maven.plugin.version>
5867
<cyclonedx-maven-plugin.version>2.9.1</cyclonedx-maven-plugin.version>
5968
<maven.clean.plugin.version>3.4.1</maven.clean.plugin.version>
6069
<maven.compiler.plugin.version>3.14.0</maven.compiler.plugin.version>
@@ -131,6 +140,12 @@
131140
<optional>true</optional>
132141
<scope>provided</scope>
133142
</dependency>
143+
<dependency>
144+
<groupId>org.osgi</groupId>
145+
<artifactId>org.osgi.annotation.bundle</artifactId>
146+
<version>2.0.0</version>
147+
<scope>provided</scope>
148+
</dependency>
134149
<dependency>
135150
<groupId>org.jspecify</groupId>
136151
<artifactId>jspecify</artifactId>
@@ -159,6 +174,16 @@
159174
<build>
160175
<pluginManagement>
161176
<plugins>
177+
<plugin>
178+
<groupId>biz.aQute.bnd</groupId>
179+
<artifactId>bnd-baseline-maven-plugin</artifactId>
180+
<version>${bnd.maven.plugin.version}</version>
181+
</plugin>
182+
<plugin>
183+
<groupId>biz.aQute.bnd</groupId>
184+
<artifactId>bnd-maven-plugin</artifactId>
185+
<version>${bnd.maven.plugin.version}</version>
186+
</plugin>
162187
<plugin>
163188
<groupId>org.apache.maven.plugins</groupId>
164189
<artifactId>maven-clean-plugin</artifactId>
@@ -217,6 +242,25 @@
217242
</plugins>
218243
</pluginManagement>
219244
<plugins>
245+
<!--
246+
~ Parses the version into components.
247+
~
248+
~ The parsed version is used to generate the `Specification-Version` manifest header.
249+
-->
250+
<plugin>
251+
<groupId>org.codehaus.mojo</groupId>
252+
<artifactId>build-helper-maven-plugin</artifactId>
253+
<version>${builder.helper.maven.plugin.version}</version>
254+
<executions>
255+
<execution>
256+
<id>parse-version</id>
257+
<goals>
258+
<goal>parse-version</goal>
259+
</goals>
260+
<phase>validate</phase>
261+
</execution>
262+
</executions>
263+
</plugin>
220264
<plugin>
221265
<groupId>org.apache.maven.plugins</groupId>
222266
<artifactId>maven-enforcer-plugin</artifactId>
@@ -347,6 +391,54 @@
347391
</execution>
348392
</executions>
349393
</plugin>
394+
<!--
395+
~ Generates:
396+
~
397+
~ - An OSGi manifest.
398+
~ - A JPMS module descriptor.
399+
~ - The JAR artifact, by replacing `maven-jar-plugin`.
400+
~
401+
~ The advantage of the `jar` goal over `bnd-process`
402+
~ is that it does not leave `module-info.class` files in the output directory,
403+
~ which tend to confuse IDEs and need to be removed before a recompilation.
404+
~
405+
~ If `ServiceLoader` services were to be added `bnd-process` must be used to generate the appropriate
406+
~ `META-INF/services` files and equivalent OSGi and JPMS entries.
407+
-->
408+
<plugin>
409+
<groupId>biz.aQute.bnd</groupId>
410+
<artifactId>bnd-maven-plugin</artifactId>
411+
<!-- Replaces the `default-jar` execution of the Maven Jar Plugin -->
412+
<extensions>true</extensions>
413+
<executions>
414+
<execution>
415+
<id>generate-jar-and-module-descriptors</id>
416+
<goals>
417+
<goal>jar</goal>
418+
</goals>
419+
</execution>
420+
</executions>
421+
</plugin>
422+
<!--
423+
~ Checks for binary compatibility with the previous revision.
424+
~ If this goal fails, the version of packages in `package-info.java` files must be incremented.
425+
~
426+
~ - If the difference type is `MICRO`, follow BND suggestions.
427+
~ - If the difference type is `MINOR`, bump the artifact version to the next minor version.
428+
~ - If the difference type is `MAJOR`, revert the breaking changes or make a major release.
429+
-->
430+
<plugin>
431+
<groupId>biz.aQute.bnd</groupId>
432+
<artifactId>bnd-baseline-maven-plugin</artifactId>
433+
<executions>
434+
<execution>
435+
<id>check-api-compatibility</id>
436+
<goals>
437+
<goal>baseline</goal>
438+
</goals>
439+
</execution>
440+
</executions>
441+
</plugin>
350442
<plugin>
351443
<groupId>org.cyclonedx</groupId>
352444
<artifactId>cyclonedx-maven-plugin</artifactId>

src/main/java/com/github/packageurl/package-info.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* <p><a href="https://github.com/package-url/purl-spec">https://github.com/package-url/purl-spec</a></p>
2525
*/
2626
@NullMarked
27+
@Export
2728
package com.github.packageurl;
2829

29-
import org.jspecify.annotations.NullMarked;
30+
import org.jspecify.annotations.NullMarked;
31+
import org.osgi.annotation.bundle.Export;

src/main/java/com/github/packageurl/validator/package-info.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
* SOFTWARE.
2121
*/
22+
/**
23+
* This package contains a validator for Jakarta Validation.
24+
*/
2225
@NullMarked
26+
@Export
2327
package com.github.packageurl.validator;
2428

25-
import org.jspecify.annotations.NullMarked;
29+
import org.jspecify.annotations.NullMarked;
30+
import org.osgi.annotation.bundle.Export;

0 commit comments

Comments
 (0)