Skip to content

Commit dfb6b7a

Browse files
Added support for "provides ... with..." directive. (#212)
Co-authored-by: Jendrik Johannes <jendrik@onepiece.software>
1 parent e831193 commit dfb6b7a

File tree

4 files changed

+103
-6
lines changed

4 files changed

+103
-6
lines changed

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,15 @@ The plugin also allows you to ignore some unwanted services from being automatic
163163
```kotlin
164164
extraJavaModuleInfo {
165165
module("groovy-all-2.4.15.jar", "groovy.all", "2.4.15") {
166-
requiresTransitive("java.scripting")
167-
requires("java.logging")
168-
requires("java.desktop")
169-
ignoreServiceProvider("org.codehaus.groovy.runtime.ExtensionModule")
170-
ignoreServiceProvider("org.codehaus.groovy.plugins.Runners")
171-
ignoreServiceProvider("org.codehaus.groovy.source.Extensions")
166+
requiresTransitive("java.scripting")
167+
requires("java.logging")
168+
requires("java.desktop")
169+
ignoreServiceProvider("org.codehaus.groovy.runtime.ExtensionModule")
170+
ignoreServiceProvider("org.codehaus.groovy.plugins.Runners")
171+
ignoreServiceProvider("org.codehaus.groovy.source.Extensions")
172+
173+
// or add a service provider registration if it is missing
174+
// provides("org.hibernate.dialect.Dialect", "org.sqlite.hibernate.dialect.SQLiteDialect")
172175
}
173176
}
174177
```

src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ private byte[] addModuleInfo(
463463
explicitlyHandledPackage.addAll(moduleInfo.exports.keySet());
464464
explicitlyHandledPackage.addAll(autoExportedPackages);
465465
explicitlyHandledPackage.addAll(removedPackages);
466+
Map<String, Set<String>> additionalProviders = moduleInfo.getProviders();
466467

467468
ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9, classWriter) {
468469
@Override
@@ -619,6 +620,15 @@ private void addModuleInfoEntries(
619620
.toArray(String[]::new));
620621
}
621622
}
623+
for (Map.Entry<String, Set<String>> provider : moduleInfo.getProviders().entrySet()) {
624+
if (!provider.getValue().isEmpty()) {
625+
moduleVisitor.visitProvide(
626+
packageToPath(provider.getKey()),
627+
provider.getValue().stream()
628+
.map(ExtraJavaModuleInfoTransform::packageToPath)
629+
.toArray(String[]::new));
630+
}
631+
}
622632
}
623633

624634
private void mergeJars(

src/main/java/org/gradlex/javamodule/moduleinfo/ModuleInfo.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class ModuleInfo extends ModuleSpec {
2929
final Set<String> requiresStaticTransitive = new LinkedHashSet<>();
3030
final Map<String, Set<String>> ignoreServiceProviders = new LinkedHashMap<>();
3131
final Set<String> uses = new LinkedHashSet<>();
32+
final Map<String, Set<String>> providers = new LinkedHashMap<>();
3233
final Set<String> exportAllPackagesExceptions = new LinkedHashSet<>();
3334

3435
boolean exportAllPackages;
@@ -95,6 +96,22 @@ public void requiresStaticTransitive(String requiresStaticTransitive) {
9596
addOrThrow(this.requiresStaticTransitive, requiresStaticTransitive);
9697
}
9798

99+
/**
100+
* @param provides corresponds to the directive in a 'module-info.java' file
101+
* @param with specifys the package(s) containing provided service classes
102+
*/
103+
public void provides(String provides, String... with) {
104+
addOrThrow(this.providers, provides, with);
105+
}
106+
107+
/**
108+
* Getter for the providers map (needed for the transformation logic)
109+
* @return
110+
*/
111+
public Map<String, Set<String>> getProviders() {
112+
return providers;
113+
}
114+
98115
/**
99116
* @param uses corresponds to the directive in a 'module-info.java' file
100117
*/
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package org.gradlex.javamodule.moduleinfo.test
2+
3+
import org.gradlex.javamodule.moduleinfo.test.fixture.GradleBuild
4+
import spock.lang.Specification
5+
6+
class ProvidesWithFunctionalTest extends Specification {
7+
8+
@Delegate
9+
GradleBuild build = new GradleBuild()
10+
11+
def setup() {
12+
settingsFile << 'rootProject.name = "test-project"'
13+
buildFile << """
14+
plugins {
15+
id("application")
16+
id("org.gradlex.extra-java-module-info")
17+
}
18+
application {
19+
mainModule.set("org.gradle.sample.app")
20+
mainClass.set("org.gradle.sample.app.Main")
21+
}
22+
"""
23+
}
24+
25+
def "can define missing service providers"() {
26+
setup:
27+
file("src/main/java/module-info.java") << """
28+
module org.gradle.sample.app {
29+
requires org.hibernate.sqlite;
30+
requires org.hibernate.orm.core;
31+
uses org.hibernate.dialect.Dialect;
32+
}
33+
"""
34+
file("src/main/java/org/gradle/sample/app/Main.java") << """
35+
package org.gradle.sample.app;
36+
37+
public class Main {
38+
public static void main(String[] args) {
39+
java.util.ServiceLoader.load(org.hibernate.dialect.Dialect.class).forEach(
40+
d -> System.out.println(d.getClass()));
41+
}
42+
}
43+
"""
44+
buildFile << """
45+
dependencies {
46+
implementation("com.github.gwenn:sqlite-dialect:0.2.0")
47+
}
48+
extraJavaModuleInfo {
49+
module("com.github.gwenn:sqlite-dialect", "org.hibernate.sqlite") {
50+
requires("java.sql")
51+
requires("org.hibernate.orm.core")
52+
provides("org.hibernate.dialect.Dialect", "org.sqlite.hibernate.dialect.SQLiteDialect")
53+
}
54+
module("org.hibernate:hibernate-core", "org.hibernate.orm.core") {
55+
requires("java.persistence")
56+
requires("java.sql")
57+
exportAllPackages()
58+
}
59+
module("antlr:antlr", "org.antlr") { }
60+
}
61+
"""
62+
63+
expect:
64+
def result = run()
65+
result.output.contains("INFO: HHH000400: Using dialect: org.sqlite.hibernate.dialect.SQLiteDialect")
66+
}
67+
}

0 commit comments

Comments
 (0)