Skip to content

Commit

Permalink
Jar-in-Jar: Prefix Jar files embedded from subprojects to avoid JPMS …
Browse files Browse the repository at this point in the history
…module-name conflicts (#31)

I.e. for a subproject named `coremod` in a project with group `testmod`,
the resulting jar filename would be `testproject.coremod`.
This would result in module name `testproject.coremod` when no
`Automatic-Module-Name` is specified.
  • Loading branch information
shartte authored Jun 16, 2024
1 parent ae4f8ae commit 5acdebf
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.gradle.api.artifacts.component.ComponentSelector;
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
import org.gradle.api.artifacts.component.ModuleComponentSelector;
import org.gradle.api.artifacts.component.ProjectComponentIdentifier;
import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
import org.gradle.api.artifacts.result.ResolvedComponentResult;
Expand Down Expand Up @@ -106,14 +107,28 @@ private static List<ResolvedJarJarArtifact> getIncludedJars(Set<ResolvedComponen
String versionRange = makeOpenRange(variant);

if (version != null && versionRange != null) {
data.add(new ResolvedJarJarArtifact(result.getFile(), version, versionRange, jarIdentifier.group(), jarIdentifier.artifact()));
var embeddedFilename = getEmbeddedFilename(result, jarIdentifier);

data.add(new ResolvedJarJarArtifact(result.getFile(), embeddedFilename, version, versionRange, jarIdentifier.group(), jarIdentifier.artifact()));
}
}
return data.stream()
.sorted(Comparator.comparing(d -> d.getGroup() + ":" + d.getArtifact()))
.collect(Collectors.toList());
}

private static String getEmbeddedFilename(ResolvedArtifactResult result, ContainedJarIdentifier jarIdentifier) {
// When we include subprojects, we add the group to the front of the filename in an attempt to avoid
// ambiguous module-names between jar-files embedded by different mods.
// Example: two mods call their submodule "coremod" and end up with a "coremod.jar", and neither set
// an Automatic-Module-Name.
String embeddedFilename = result.getFile().getName();
if (result.getId().getComponentIdentifier() instanceof ProjectComponentIdentifier) {
embeddedFilename = jarIdentifier.group() + "." + result.getFile().getName();
}
return embeddedFilename;
}

private static void collectFromComponent(ResolvedComponentResult rootComponent, Set<ContainedJarIdentifier> knownIdentifiers, Map<ContainedJarIdentifier, String> versions, Map<ContainedJarIdentifier, String> versionRanges) {
for (DependencyResult result : rootComponent.getDependencies()) {
if (!(result instanceof ResolvedDependencyResult)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
public class ResolvedJarJarArtifact {

private final File file;
private final String embeddedFilename;
private final String version;
private final String versionRange;
private final String group;
private final String artifact;

public ResolvedJarJarArtifact(File file, String version, String versionRange, String group, String artifact) {
public ResolvedJarJarArtifact(File file, String embeddedFilename, String version, String versionRange, String group, String artifact) {
this.file = file;
this.embeddedFilename = embeddedFilename;
this.version = version;
this.versionRange = versionRange;
this.group = group;
Expand All @@ -48,7 +50,7 @@ public ContainedVersion createContainedVersion() {
}

public ContainedJarMetadata createContainerMetadata() {
return new ContainedJarMetadata(createContainedJarIdentifier(), createContainedVersion(), "META-INF/jarjar/"+file.getName(), isObfuscated(file));
return new ContainedJarMetadata(createContainedJarIdentifier(), createContainedVersion(), "META-INF/jarjar/"+embeddedFilename, isObfuscated(file));
}

@InputFile
Expand All @@ -57,6 +59,11 @@ public File getFile() {
return file;
}

@Input
public String getEmbeddedFilename() {
return embeddedFilename;
}

@Input
public String getVersion() {
return version;
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/net/neoforged/moddevgradle/tasks/JarJar.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public abstract class JarJar extends DefaultTask {
Expand Down Expand Up @@ -63,6 +65,13 @@ protected void run() {
fileSystemOperations.copy(spec -> {
spec.into(getOutputDirectory().dir("META-INF/jarjar"));
spec.from(includedJars.stream().map(ResolvedJarJarArtifact::getFile).toArray());
for (var includedJar : includedJars) {
var originalName = includedJar.getFile().getName();
var embeddedName = includedJar.getEmbeddedFilename();
if (!originalName.equals(embeddedName)) {
spec.rename(Pattern.quote(originalName), Matcher.quoteReplacement(embeddedName));
}
}
spec.from(writeMetadata(includedJars).toFile());
});
}
Expand Down

0 comments on commit 5acdebf

Please sign in to comment.