Browse Source

Include shadowed jar source in published source artifacts

Add a new `ShadowSource` Gradle task and update `spring-core.gradle`
to include source for cglib, javapoet and objenesis.

Closes gh-28892

Co-authored-by: Andy Wilkinson <wilkinsona@vmware.com>
pull/28896/head
Phillip Webb 3 years ago
parent
commit
9d1e9703ae
  1. 175
      buildSrc/src/main/java/org/springframework/build/shadow/ShadowSource.java
  2. 26
      spring-core/spring-core.gradle

175
buildSrc/src/main/java/org/springframework/build/shadow/ShadowSource.java

@ -0,0 +1,175 @@ @@ -0,0 +1,175 @@
package org.springframework.build.shadow;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.gradle.api.DefaultTask;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.component.ModuleComponentSelector;
import org.gradle.api.artifacts.query.ArtifactResolutionQuery;
import org.gradle.api.artifacts.result.ArtifactResolutionResult;
import org.gradle.api.artifacts.result.ComponentArtifactsResult;
import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolutionResult;
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.jvm.JvmLibrary;
import org.gradle.language.base.artifact.SourcesArtifact;
/**
* Gradle task to add source from shadowed jars into our own source jars.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
public class ShadowSource extends DefaultTask {
private final DirectoryProperty outputDirectory = getProject().getObjects().directoryProperty();
private List<Configuration> configurations = new ArrayList<>();
private final List<Relocation> relocations = new ArrayList<>();
@Classpath
@Optional
public List<Configuration> getConfigurations() {
return this.configurations;
}
public void setConfigurations(List<Configuration> configurations) {
this.configurations = configurations;
}
@Nested
public List<Relocation> getRelocations() {
return this.relocations;
}
public void relocate(String pattern, String destination) {
this.relocations.add(new Relocation(pattern, destination));
}
@OutputDirectory
DirectoryProperty getOutputDirectory() {
return this.outputDirectory;
}
@TaskAction
void syncSourceJarFiles() {
sync(getSourceJarFiles());
}
private List<File> getSourceJarFiles() {
List<File> sourceJarFiles = new ArrayList<>();
for (Configuration configuration : this.configurations) {
ResolutionResult resolutionResult = configuration.getIncoming().getResolutionResult();
resolutionResult.getRootComponent().get().getDependencies().forEach(dependency -> {
Set<ComponentArtifactsResult> artifactsResults = resolveSourceArtifacts(dependency);
for (ComponentArtifactsResult artifactResult : artifactsResults) {
artifactResult.getArtifacts(SourcesArtifact.class).forEach(sourceArtifact -> {
sourceJarFiles.add(((ResolvedArtifactResult) sourceArtifact).getFile());
});
}
});
}
return Collections.unmodifiableList(sourceJarFiles);
}
private Set<ComponentArtifactsResult> resolveSourceArtifacts(DependencyResult dependency) {
ModuleComponentSelector componentSelector = (ModuleComponentSelector) dependency.getRequested();
ArtifactResolutionQuery query = getProject().getDependencies().createArtifactResolutionQuery()
.forModule(componentSelector.getGroup(), componentSelector.getModule(), componentSelector.getVersion());
return executeQuery(query).getResolvedComponents();
}
@SuppressWarnings("unchecked")
private ArtifactResolutionResult executeQuery(ArtifactResolutionQuery query) {
return query.withArtifacts(JvmLibrary.class, SourcesArtifact.class).execute();
}
private void sync(List<File> sourceJarFiles) {
getProject().sync(spec -> {
spec.into(this.outputDirectory);
spec.eachFile(this::relocateFile);
spec.filter(this::transformContent);
spec.exclude("META-INF/**");
spec.setIncludeEmptyDirs(false);
sourceJarFiles.forEach(sourceJar -> spec.from(zipTree(sourceJar)));
});
}
private void relocateFile(FileCopyDetails details) {
String path = details.getPath();
for (Relocation relocation : this.relocations) {
path = relocation.relocatePath(path);
}
details.setPath(path);
}
private String transformContent(String content) {
for (Relocation relocation : this.relocations) {
content = relocation.transformContent(content);
}
return content;
}
private FileTree zipTree(File sourceJar) {
return getProject().zipTree(sourceJar);
}
/**
* A single relocation.
*/
static class Relocation {
private final String pattern;
private final String pathPattern;
private final String destination;
private final String pathDestination;
Relocation(String pattern, String destination) {
this.pattern = pattern;
this.pathPattern = pattern.replace('.', '/');
this.destination = destination;
this.pathDestination = destination.replace('.', '/');
}
@Input
public String getPattern() {
return this.pattern;
}
@Input
public String getDestination() {
return this.destination;
}
String relocatePath(String path) {
return path.replace(this.pathPattern, this.pathDestination);
}
public String transformContent(String content) {
return content.replaceAll("\\b" + this.pattern, this.destination);
}
}
}

26
spring-core/spring-core.gradle

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.springframework.build.shadow.ShadowSource
description = "Spring Core"
@ -27,6 +28,13 @@ task cglibRepackJar(type: ShadowJar) { @@ -27,6 +28,13 @@ task cglibRepackJar(type: ShadowJar) {
relocate 'org.objectweb.asm', 'org.springframework.asm'
}
task cglibSource(type: ShadowSource) {
configurations = [project.configurations.cglib]
relocate 'net.sf.cglib', 'org.springframework.cglib'
relocate 'org.objectweb.asm', 'org.springframework.asm'
outputDirectory = file("build/shadow-source/cglib")
}
task javapoetRepackJar(type: ShadowJar) {
archiveBaseName.set('spring-javapoet-repack')
archiveVersion.set(javapoetVersion)
@ -34,6 +42,12 @@ task javapoetRepackJar(type: ShadowJar) { @@ -34,6 +42,12 @@ task javapoetRepackJar(type: ShadowJar) {
relocate 'com.squareup.javapoet', 'org.springframework.javapoet'
}
task javapoetSource(type: ShadowSource) {
configurations = [project.configurations.javapoet]
relocate 'com.squareup.javapoet', 'org.springframework.javapoet'
outputDirectory = file("build/shadow-source/javapoet")
}
task objenesisRepackJar(type: ShadowJar) {
archiveBaseName.set('spring-objenesis-repack')
archiveVersion.set(objenesisVersion)
@ -41,6 +55,12 @@ task objenesisRepackJar(type: ShadowJar) { @@ -41,6 +55,12 @@ task objenesisRepackJar(type: ShadowJar) {
relocate 'org.objenesis', 'org.springframework.objenesis'
}
task objenesisSource(type: ShadowSource) {
configurations = [project.configurations.objenesis]
relocate 'org.objenesis', 'org.springframework.objenesis'
outputDirectory = file("build/shadow-source/objenesis")
}
dependencies {
cglib("cglib:cglib:${cglibVersion}@jar")
javapoet("com.squareup:javapoet:${javapoetVersion}@jar")
@ -122,3 +142,9 @@ test { @@ -122,3 +142,9 @@ test {
"-XX:+AllowRedefinitionToAddDeleteMethods"
]
}
sourcesJar {
from cglibSource
from javapoetSource
from objenesisSource
}

Loading…
Cancel
Save