Skip to content

Add artifact sink generating module-uri properties#397

Merged
cstamas merged 7 commits into
mainfrom
module-properties-sink
May 22, 2026
Merged

Add artifact sink generating module-uri properties#397
cstamas merged 7 commits into
mainfrom
module-properties-sink

Conversation

@sormuras
Copy link
Copy Markdown
Contributor

@sormuras sormuras commented May 21, 2026

This change adds an artifact sink that prints and generates a .properties file with modul-uri entries.

Usage example:

java -jar toolbox-0.15.13-SNAPSHOT-cli.jar
  copy-transitive
  --boms org.junit:junit-bom:6.1.0
  modules(junit-6.1.0-modules.properties)
  org.junit.jupiter:junit-jupiter,org.junit:junit-start

Yields:

Copied 23 artifacts
Found 14 distinct modules
org.apiguardian.api=https://repo.maven.apache.org/maven2/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar#SIZE=6806&SHA-1=a231e0d844d2721b0fa1b238006d15c6ded6842a
org.jspecify=https://repo.maven.apache.org/maven2/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar#SIZE=3819&SHA-1=7425a601c1c7ec76645a78d22b8c6a627edee507
org.junit.jupiter=https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter/6.1.0/junit-jupiter-6.1.0.jar#SIZE=6375&SHA-1=52aef21f8c9fa491ff7eb20008e39102a8479f79
org.junit.jupiter.api=https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter-api/6.1.0/junit-jupiter-api-6.1.0.jar#SIZE=312240&SHA-1=5376d10370f32af4f3b1b7a378906ee58dcdacb3
org.junit.jupiter.engine=https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter-engine/6.1.0/junit-jupiter-engine-6.1.0.jar#SIZE=352590&SHA-1=82414ee1a0308d2f096c37d317b93b66c13dbb9a
org.junit.jupiter.params=https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter-params/6.1.0/junit-jupiter-params-6.1.0.jar#SIZE=303146&SHA-1=6e6dcbd963a6c16217350535a640e1c0fde0d619
org.junit.platform.commons=https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-commons/6.1.0/junit-platform-commons-6.1.0.jar#SIZE=175866&SHA-1=03bb0447338b81f4396648c406d3e1c22f65f689
org.junit.platform.console=https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-console/6.1.0/junit-platform-console-6.1.0.jar#SIZE=562445&SHA-1=b4785a1945051b8f5fa2daa82b72ea0f7188c47e
org.junit.platform.engine=https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-engine/6.1.0/junit-platform-engine-6.1.0.jar#SIZE=323857&SHA-1=754271e8493a0be2838f3500b30971969b8603d0
org.junit.platform.launcher=https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-launcher/6.1.0/junit-platform-launcher-6.1.0.jar#SIZE=251171&SHA-1=78124de837a3e0b9e4e32a2c80ba47117f7f8c60
org.junit.platform.reporting=https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-reporting/6.1.0/junit-platform-reporting-6.1.0.jar#SIZE=153927&SHA-1=914dbb41a35cf269e575037eca4b201bd5a803bb
org.junit.start=https://repo.maven.apache.org/maven2/org/junit/junit-start/6.1.0/junit-start-6.1.0.jar#SIZE=9579&SHA-1=80f80607ff0ddfc33353f1bcd4ecba11f9c250f7
org.opentest4j=https://repo.maven.apache.org/maven2/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar#SIZE=14304&SHA-1=152ea56b3a72f655d4fd677fc0ef2596c3dd5e6e
org.opentest4j.reporting.tooling.spi=https://repo.maven.apache.org/maven2/org/opentest4j/reporting/open-test-reporting-tooling-spi/0.2.5/open-test-reporting-tooling-spi-0.2.5.jar#SIZE=45871&SHA-1=92a64a32e3fbdfc094d05a714d88c619c0d12f38
------------------------------
Module properties written to: file:///.../junit-6.1.0-modules.properties
------------------------------

Summary by CodeRabbit

  • New Features
    • Added a modules operation that writes per-module property files for modular JARs (requires an output path, optional classifier). Each line maps module name to origin URI, file size and SHA-1; non-modular artifacts are skipped. Output is sorted and a completion summary is emitted.

Review Change Stack

@sormuras sormuras requested a review from cstamas May 21, 2026 20:48
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a39a817-22df-4ad6-a3d2-7f6fe5bfe0b9

📥 Commits

Reviewing files that changed from the base of the PR and between c4e5533 and 3e4fbda.

📒 Files selected for processing (1)
  • shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java

📝 Walkthrough

Walkthrough

Adds a modules sink operation to the artifact-sink parser and implements ModulePropertiesArtifactSink to collect each Java module’s origin URI, size, and SHA-1 from resolved .jar artifacts and write sorted module properties to a specified file.

Changes

Module Properties Sink Operation

Layer / File(s) Summary
Imports and builder entry filtering
shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java
Adds import for ModuleDescriptor and excludes modules from the generic operator-name filter in visitEnter.
Spec handler wiring for modules
shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java
processOp handles modules: requires 1–2 arguments (output path, optional classifier), resolves the path under tc.basedir(), and registers modulePropertiesArtifactSink(path, classifier, output, tc).
ModulePropertiesArtifactSink implementation
shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java
Adds modulePropertiesArtifactSink(...) factory and ModulePropertiesArtifactSink that filters resolved .jar artifacts, optionally filters by classifier, extracts module names, looks up origin URIs, requires SHA-1 checksum, aggregates entries by module name, and on close() writes sorted module=origin#SIZE=...&SHA-1=... lines while emitting Output messages.
StatArtifactSink descriptor type update
shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java
Replaces fully-qualified nested type with imported ModuleDescriptor in StatArtifactSink.

Sequence Diagram

sequenceDiagram
  participant Builder as ArtifactSinkBuilder
  participant Sink as ModulePropertiesArtifactSink
  participant ModuleExtractor as ModuleDescriptorExtractingSink
  participant UriResolver as ArtifactUriSink
  participant Checksum as ChecksumArtifactSink
  participant Output as Output
  Builder->>Builder: recognize modules operation
  Builder->>Sink: accept(artifact)
  Sink->>ModuleExtractor: extract module name from .jar
  Sink->>UriResolver: lookup artifact origin URI
  Sink->>Checksum: require SHA-1 and size
  Sink->>Sink: store in concurrent map by module name
  Sink->>Output: close() writes sorted module=origin#SIZE=...&SHA-1=... lines
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A tiny sink hops out to play,
It peeks inside each jar to find a name,
Notes origin, size, and SHA to tame,
Sorts the list and writes it neat today,
Hooray — metadata all in frame!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding an artifact sink that generates a properties file mapping modules to URIs, which is the core functionality introduced in this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch module-properties-sink

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java`:
- Line 631: The code calls Files.write(file, lines) without ensuring the file's
parent directory exists (in ArtifactSinks where Files.write is invoked), which
will fail for non-existent directories; before writing, check if
file.getParent() is non-null and call Files.createDirectories(file.getParent())
to create any missing parent directories so Files.write succeeds.
- Around line 617-621: Guard building Property entries by first verifying
moduleArtifactSink.getModuleDescriptor(artifact) is present (non-null/optional)
and that artifactUriSink.getUri(artifact) and
checksumArtifactSink.checksums(artifact).get("SHA-1") are non-null; if any of
those are missing, skip adding the entry (or return early/log debug) instead of
calling .name() or constructing a Property with nulls. Update the code around
moduleArtifactSink.getModuleDescriptor, artifactUriSink.getUri,
checksumArtifactSink.checksums and the propertyByModuleName.put calls to perform
these null/optional checks before creating new Property.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c09901f8-82b2-4bdc-9f4a-66dfae032b37

📥 Commits

Reviewing files that changed from the base of the PR and between 29a7fd0 and 15cc229.

📒 Files selected for processing (1)
  • shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java`:
- Around line 742-743: The two-line assignment of ModuleDescriptor from
moduleDescriptorExtractingSink.getModuleDescriptor(artifact) violates Spotless
formatting; reformat that statement into a single line or the project's
canonical multi-line style to satisfy Spotless (e.g., align the type, variable
and assignment per project conventions) by editing the ModuleDescriptor
descriptor = moduleDescriptorExtractingSink.getModuleDescriptor(artifact)
statement so it matches surrounding formatting or run mvn spotless:apply to
auto-fix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd61417d-8e68-42c3-8b72-79d4c6d7971f

📥 Commits

Reviewing files that changed from the base of the PR and between 15cc229 and 406d1cb.

📒 Files selected for processing (1)
  • shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java`:
- Around line 121-131: The "modules" branch in ArtifactSinks silently ignores
extra arguments; change it to validate maximum arity and fail fast: after
checking minimum arity in the case "modules" block, add a guard that throws an
IllegalArgumentException if node.getChildren().size() > 2 (since
modules(<output>[, <classifier>]) allows at most two arguments); keep
constructing Path file, classifier, and calling
modulePropertiesArtifactSink(file, classifier, tc.output(), tc) only when size
is 1 or 2, and then clear node.getChildren() as before. Ensure the exception
message clearly states the allowed signature (e.g., "modules requires 1 or 2
arguments: output[, classifier]").
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40398c02-8cee-48a2-ad33-b36e70e72bda

📥 Commits

Reviewing files that changed from the base of the PR and between 406d1cb and c4e5533.

📒 Files selected for processing (1)
  • shared/src/main/java/eu/maveniverse/maven/toolbox/shared/internal/ArtifactSinks.java

@maxandersen
Copy link
Copy Markdown
Member

just curious - what are module-uri properties? I haven't seen that format/style before.

@sormuras
Copy link
Copy Markdown
Contributor Author

The format/style is described here: https://github.com/sormuras/modules

Caveat: that "database" is dormant since summer 2025, due to Sonatype's shift in repository hosting.

@maxandersen
Copy link
Copy Markdown
Member

gotcha. it was the sha-1 / size approach I hadn't seen before - i dont see that described on that page?

and side question - i was wondering where you got the module info from central on; as I was wondering if we could build up a index of jars with main methods - but seems your page is hinting sonatype doesn't expose such metadata anymore?

@sormuras
Copy link
Copy Markdown
Contributor Author

gotcha. it was the sha-1 / size approach I hadn't seen before - i dont see that described on that page?

Yes, that's a recent addition ... using URI's fragment syntax.

and side question - i was wondering where you got the module info from central on; as I was wondering if we could build up a index of jars with main methods - but seems your page is hinting sonatype doesn't expose such metadata anymore?

It's partially described the README; https://github.com/sandermak/modulescanner is run by Sonatype internally on "upload events" and fills an AWS S3 bucket with the scanner result. With the new/shifted publish root (storage?) for open source projects, the scanner only sees some old (unshifted) projects. Is that correct, @jorlina?

See also: sonatype-nexus-community/search-maven-org#6

@sormuras
Copy link
Copy Markdown
Contributor Author

[...] index of jars with main methods [...]

Are project-local catalogs, like https://github.com/junit-team/jbang-catalog, not sufficient (for jbang)?

@sormuras
Copy link
Copy Markdown
Contributor Author

sormuras commented May 22, 2026

While we are here and already derailed the review thread ... takes some seconds to load and might not be useful; yet, still pretty:

@maxandersen
Copy link
Copy Markdown
Member

definitely pretty 3d graph :)

jbang-catalog is great but thats like 0.1% of jars with main methods that are added there :)

jbang io.whatever:wonka:1.2 also works - but it would be nice to actually have index of those jars with a main method :)

@cstamas cstamas merged commit dceed7a into main May 22, 2026
30 checks passed
@cstamas cstamas deleted the module-properties-sink branch May 22, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants