Skip to content

Commit e6a3cdc

Browse files
committed
Introduce setting plugin to configure module locations and identity
1 parent b182130 commit e6a3cdc

File tree

9 files changed

+381
-20
lines changed

9 files changed

+381
-20
lines changed

src/main/java/org/gradlex/javamodule/dependencies/JavaModuleDependenciesExtension.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public Provider<Dependency> create(String moduleName, SourceSet sourceSetWithMod
218218

219219
Provider<String> coordinates = getModuleNameToGA().getting(moduleName).orElse(mapByPrefix(getProviders().provider(() -> moduleName)));
220220

221-
ModuleInfo moduleInfo = getModuleInfoCache().get(sourceSetWithModuleInfo);
221+
ModuleInfo moduleInfo = getModuleInfoCache().get(sourceSetWithModuleInfo, getProviders());
222222
String ownModuleNamesPrefix = moduleInfo.moduleNamePrefix(getProject().getName(), sourceSetWithModuleInfo.getName(), getModuleNameCheck().get());
223223

224224
String moduleNameSuffix = ownModuleNamesPrefix == null ? null :
@@ -478,7 +478,7 @@ public void addRequiresRuntimeSupport(SourceSet sourceSetForModuleInfo, SourceSe
478478
}
479479

480480
void doAddRequiresRuntimeSupport(SourceSet sourceSetForModuleInfo, SourceSet sourceSetForClasspath) {
481-
List<String> requiresRuntime = getModuleInfoCache().get(sourceSetForModuleInfo).get(REQUIRES_RUNTIME);
481+
List<String> requiresRuntime = getModuleInfoCache().get(sourceSetForModuleInfo, getProviders()).get(REQUIRES_RUNTIME);
482482
String generatorTaskName = sourceSetForClasspath.getTaskName("generate", "syntheticModuleInfoFolders");
483483
if (requiresRuntime.isEmpty() || getProject().getTasks().getNames().contains(generatorTaskName)) {
484484
// Already active or not needed for this source set

src/main/java/org/gradlex/javamodule/dependencies/JavaModuleDependenciesPlugin.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import org.gradle.api.artifacts.Configuration;
2525
import org.gradle.api.artifacts.ConfigurationContainer;
2626
import org.gradle.api.artifacts.VersionCatalogsExtension;
27+
import org.gradle.api.initialization.Settings;
28+
import org.gradle.api.plugins.ExtensionAware;
2729
import org.gradle.api.plugins.ExtensionContainer;
2830
import org.gradle.api.plugins.JavaPlugin;
2931
import org.gradle.api.tasks.SourceSet;
@@ -32,6 +34,7 @@
3234
import org.gradle.util.GradleVersion;
3335
import org.gradlex.javamodule.dependencies.dsl.AllDirectives;
3436
import org.gradlex.javamodule.dependencies.dsl.GradleOnlyDirectives;
37+
import org.gradlex.javamodule.dependencies.initialization.JavaModuleDependenciesSettingsPlugin;
3538
import org.gradlex.javamodule.dependencies.internal.bridges.DependencyAnalysisBridge;
3639
import org.gradlex.javamodule.dependencies.internal.bridges.ExtraJavaModuleInfoBridge;
3740
import org.gradlex.javamodule.dependencies.internal.dsl.AllDirectivesInternal;
@@ -62,16 +65,23 @@
6265

6366
@SuppressWarnings("unused")
6467
@NonNullApi
65-
public abstract class JavaModuleDependenciesPlugin implements Plugin<Project> {
68+
public abstract class JavaModuleDependenciesPlugin implements Plugin<ExtensionAware> {
6669

6770
private static final String EXTRA_JAVA_MODULE_INFO_PLUGIN_ID = "org.gradlex.extra-java-module-info";
6871

6972
@Override
70-
public void apply(Project project) {
73+
public void apply(ExtensionAware projectOrSettings) {
7174
if (GradleVersion.current().compareTo(GradleVersion.version("7.4")) < 0) {
7275
throw new GradleException("This plugin requires Gradle 7.4+");
7376
}
77+
if (projectOrSettings instanceof Project) {
78+
applyProject((Project) projectOrSettings);
79+
} else if (projectOrSettings instanceof Settings) {
80+
((Settings) projectOrSettings).getPlugins().apply(JavaModuleDependenciesSettingsPlugin.class);
81+
}
82+
}
7483

84+
private void applyProject(Project project) {
7585
VersionCatalogsExtension versionCatalogs = project.getExtensions().findByType(VersionCatalogsExtension.class);
7686
JavaModuleDependenciesExtension javaModuleDependencies = project.getExtensions().create(
7787
JAVA_MODULE_DEPENDENCIES, JavaModuleDependenciesExtension.class, versionCatalogs);
@@ -224,7 +234,7 @@ private void setupOrderingCheckTasks(Project project, TaskProvider<Task> checkAl
224234
t.setGroup("java modules");
225235
t.setDescription("Check order of directives in 'module-info.java' in '" + sourceSet.getName() + "' source set");
226236

227-
ModuleInfo moduleInfo = javaModuleDependencies.getModuleInfoCache().get(sourceSet);
237+
ModuleInfo moduleInfo = javaModuleDependencies.getModuleInfoCache().get(sourceSet, project.getProviders());
228238

229239
t.getModuleInfoPath().convention(moduleInfo.getFilePath().getAbsolutePath());
230240
t.getModuleNamePrefix().convention(moduleInfo.moduleNamePrefix(project.getName(), sourceSet.getName(), false));
@@ -254,7 +264,7 @@ private void readModuleInfo(ModuleInfo.Directive moduleDirective, SourceSet sour
254264
if (javaModuleDependenciesExtension.getAnalyseOnly().get()) {
255265
return;
256266
}
257-
ModuleInfo moduleInfo = javaModuleDependenciesExtension.getModuleInfoCache().get(sourceSet);
267+
ModuleInfo moduleInfo = javaModuleDependenciesExtension.getModuleInfoCache().get(sourceSet, project.getProviders());
258268
for (String moduleName : moduleInfo.get(moduleDirective)) {
259269
declareDependency(moduleName, moduleInfo.getFilePath(), project, sourceSet, configuration, javaModuleDependenciesExtension);
260270
}
@@ -270,7 +280,7 @@ private void declareDependency(String moduleName, File moduleInfoFile, Project p
270280
}
271281

272282
private List<BuildFileDependenciesGenerate.DependencyDeclaration> collectDependencies(Project project, JavaModuleDependenciesExtension javaModuleDependencies, SourceSet sourceSet, ModuleInfo.Directive directive, String scope) {
273-
ModuleInfo moduleInfo = javaModuleDependencies.getModuleInfoCache().get(sourceSet);
283+
ModuleInfo moduleInfo = javaModuleDependencies.getModuleInfoCache().get(sourceSet, project.getProviders());
274284
if (moduleInfo == ModuleInfo.EMPTY) {
275285
// check if there is a whiltebox module-info we can use isntead
276286
File sourceSetDir = sourceSet.getJava().getSrcDirs().iterator().next().getParentFile();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.gradlex.javamodule.dependencies.initialization;
2+
3+
import org.gradle.api.NonNullApi;
4+
import org.gradle.api.Plugin;
5+
import org.gradle.api.initialization.Settings;
6+
7+
@NonNullApi
8+
public abstract class JavaModuleDependenciesSettingsPlugin implements Plugin<Settings> {
9+
10+
@Override
11+
public void apply(Settings settings) {
12+
registerExtension(settings);
13+
}
14+
15+
private void registerExtension(Settings settings) {
16+
settings.getExtensions().create("rootPlugins", RootPluginsExtension.class, settings);
17+
settings.getExtensions().create("javaModules", JavaModulesExtension.class, settings);
18+
}
19+
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Copyright the GradleX team.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.gradlex.javamodule.dependencies.initialization;
18+
19+
import org.gradle.api.Action;
20+
import org.gradle.api.IsolatedAction;
21+
import org.gradle.api.NonNullApi;
22+
import org.gradle.api.Project;
23+
import org.gradle.api.initialization.ProjectDescriptor;
24+
import org.gradle.api.initialization.Settings;
25+
import org.gradle.api.model.ObjectFactory;
26+
import org.gradle.api.plugins.ApplicationPlugin;
27+
import org.gradle.api.plugins.JavaApplication;
28+
import org.gradle.api.plugins.JavaPlatformPlugin;
29+
import org.gradle.util.GradleVersion;
30+
import org.gradlex.javamodule.dependencies.JavaModuleDependenciesPlugin;
31+
import org.gradlex.javamodule.dependencies.JavaModuleVersionsPlugin;
32+
import org.gradlex.javamodule.dependencies.internal.utils.ModuleInfo;
33+
import org.gradlex.javamodule.dependencies.internal.utils.ModuleInfoCache;
34+
35+
import javax.annotation.Nullable;
36+
import javax.inject.Inject;
37+
import java.io.File;
38+
import java.nio.file.Paths;
39+
import java.util.List;
40+
41+
public abstract class JavaModulesExtension {
42+
43+
static final boolean SUPPORT_PROJECT_ISOLATION =
44+
GradleVersion.current().compareTo(GradleVersion.version("8.8")) >= 0;
45+
46+
private final Settings settings;
47+
private final ModuleInfoCache moduleInfoCache;
48+
49+
@Inject
50+
public abstract ObjectFactory getObjects();
51+
52+
@Inject
53+
public JavaModulesExtension(Settings settings) {
54+
this.settings = settings;
55+
this.moduleInfoCache = getObjects().newInstance(ModuleInfoCache.class);
56+
}
57+
58+
public void module(String folder) {
59+
module(folder, m -> {});
60+
}
61+
62+
public void module(String folder, Action<Module> action) {
63+
Module module = getObjects().newInstance(Module.class);
64+
module.getFolder().set(folder);
65+
action.execute(module);
66+
includeModule(module, new File(settings.getRootDir(), module.getFolder().get()));
67+
}
68+
69+
public void modules(String folder) {
70+
modules(folder, m -> {});
71+
}
72+
73+
public void modules(String folder, Action<Modules> action) {
74+
Modules moduleGroup = getObjects().newInstance(Modules.class);
75+
action.execute(moduleGroup);
76+
77+
File[] projectFolders = new File(settings.getRootDir(), folder).listFiles();
78+
if (projectFolders == null) {
79+
throw new RuntimeException("Failed to inspect: " + new File(settings.getRootDir(), folder));
80+
}
81+
82+
for (File projectFolder : projectFolders) {
83+
if (moduleGroup.customizedModules.containsKey(projectFolder.getName())) {
84+
includeModule(moduleGroup.customizedModules.get(projectFolder.getName()), projectFolder);
85+
} else {
86+
includeModule(moduleGroup.addModule(projectFolder.getName()), projectFolder);
87+
}
88+
}
89+
}
90+
91+
public void versions(String folder) {
92+
String projectName = Paths.get(folder).getFileName().toString();
93+
settings.include(projectName);
94+
settings.project(":" + projectName).setProjectDir(new File(settings.getRootDir(), folder));
95+
if (SUPPORT_PROJECT_ISOLATION) {
96+
settings.getGradle().getLifecycle().beforeProject(new ApplyJavaModuleVersionsPluginAction(projectName));
97+
} else {
98+
settings.getGradle().beforeProject(new ApplyJavaModuleVersionsPluginAction(projectName));
99+
}
100+
}
101+
102+
private void includeModule(Module module, File projectDir) {
103+
ModuleInfo moduleInfo = moduleInfoCache.get(projectDir, module.getModuleInfoPath().get(),
104+
module.getArtifact().get(), module.getGroup(), settings.getProviders());
105+
if (moduleInfo == ModuleInfo.EMPTY) {
106+
return;
107+
}
108+
109+
String artifact = module.getArtifact().get();
110+
settings.include(artifact);
111+
ProjectDescriptor project = settings.project(":" + artifact);
112+
project.setProjectDir(projectDir);
113+
114+
String group = module.getGroup().getOrNull();
115+
116+
List<String> plugins = module.getPlugins().get();
117+
if (SUPPORT_PROJECT_ISOLATION) {
118+
settings.getGradle().getLifecycle().beforeProject(new ApplyPluginsAction(artifact, group, plugins, moduleInfo.getModuleName()));
119+
} else {
120+
settings.getGradle().beforeProject(new ApplyPluginsAction(artifact, group, plugins, moduleInfo.getModuleName()));
121+
}
122+
}
123+
124+
@NonNullApi
125+
private static class ApplyPluginsAction implements IsolatedAction<Project>, Action<Project> {
126+
127+
private final String artifact;
128+
private final String group;
129+
private final List<String> plugins;
130+
private final String modueName;
131+
132+
public ApplyPluginsAction(String artifact, @Nullable String group, List<String> plugins, String modueName) {
133+
this.artifact = artifact;
134+
this.group = group;
135+
this.plugins = plugins;
136+
this.modueName = modueName;
137+
}
138+
139+
@Override
140+
public void execute(Project project) {
141+
if (project.getName().equals(artifact)) {
142+
if (group != null) project.setGroup(group);
143+
project.getPlugins().apply(JavaModuleDependenciesPlugin.class);
144+
plugins.forEach(id -> project.getPlugins().apply(id));
145+
project.getPlugins().withType(ApplicationPlugin.class, p ->
146+
project.getExtensions().getByType(JavaApplication.class).getMainModule().set(modueName));
147+
}
148+
}
149+
}
150+
151+
@NonNullApi
152+
private static class ApplyJavaModuleVersionsPluginAction implements IsolatedAction<Project>, Action<Project> {
153+
154+
private final String projectName;
155+
156+
public ApplyJavaModuleVersionsPluginAction(String projectName) {
157+
this.projectName = projectName;
158+
}
159+
160+
@Override
161+
public void execute(Project project) {
162+
if (projectName.equals(project.getName())) {
163+
project.getPlugins().apply(JavaPlatformPlugin.class);
164+
project.getPlugins().apply(JavaModuleVersionsPlugin.class);
165+
}
166+
}
167+
}
168+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.gradlex.javamodule.dependencies.initialization;
2+
3+
import org.gradle.api.provider.ListProperty;
4+
import org.gradle.api.provider.Property;
5+
6+
import java.nio.file.Paths;
7+
8+
public abstract class Module {
9+
public abstract Property<String> getFolder();
10+
public abstract Property<String> getArtifact();
11+
public abstract Property<String> getGroup();
12+
public abstract Property<String> getModuleInfoPath();
13+
public abstract ListProperty<String> getPlugins();
14+
15+
public Module() {
16+
getArtifact().convention(getFolder().map(f -> Paths.get(f).getFileName().toString()));
17+
getModuleInfoPath().convention("src/main/java");
18+
}
19+
20+
public void plugin(String id) {
21+
getPlugins().add(id);
22+
}
23+
24+
25+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.gradlex.javamodule.dependencies.initialization;
2+
3+
import org.gradle.api.Action;
4+
import org.gradle.api.model.ObjectFactory;
5+
import org.gradle.api.provider.ListProperty;
6+
import org.gradle.api.provider.Property;
7+
8+
import javax.inject.Inject;
9+
import java.util.LinkedHashMap;
10+
import java.util.Map;
11+
12+
public abstract class Modules {
13+
14+
final Map<String, Module> customizedModules = new LinkedHashMap<>();
15+
16+
public abstract Property<String> getGroup();
17+
public abstract Property<String> getModuleInfoPath();
18+
public abstract ListProperty<String> getPlugins();
19+
20+
@Inject
21+
public abstract ObjectFactory getObjects();
22+
23+
public Modules() {
24+
getModuleInfoPath().convention("src/main/java");
25+
}
26+
27+
public void plugin(String id) {
28+
getPlugins().add(id);
29+
}
30+
31+
public void module(String moduleFolder, Action<Module> action) {
32+
Module module = addModule(moduleFolder);
33+
action.execute(module);
34+
customizedModules.put(moduleFolder, module);
35+
}
36+
37+
Module addModule(String moduleFolder) {
38+
Module module = getObjects().newInstance(Module.class);
39+
module.getFolder().convention(moduleFolder);
40+
module.getGroup().convention(getGroup());
41+
module.getPlugins().addAll(getPlugins());
42+
module.getModuleInfoPath().convention(getModuleInfoPath());
43+
return module;
44+
}
45+
}

0 commit comments

Comments
 (0)