Skip to content

Commit 42ee6b9

Browse files
committed
Use new permissions API with Gradle 8.3+
Closes gh-37878
1 parent c0eb2cb commit 42ee6b9

File tree

3 files changed

+101
-5
lines changed

3 files changed

+101
-5
lines changed

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ApplicationPluginAction.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import java.io.IOException;
2020
import java.io.InputStreamReader;
2121
import java.io.StringWriter;
22+
import java.lang.reflect.Method;
2223
import java.util.concurrent.Callable;
2324

25+
import org.gradle.api.Action;
2426
import org.gradle.api.GradleException;
2527
import org.gradle.api.Plugin;
2628
import org.gradle.api.Project;
@@ -34,6 +36,7 @@
3436
import org.gradle.api.tasks.TaskProvider;
3537
import org.gradle.jvm.application.scripts.TemplateBasedScriptGenerator;
3638
import org.gradle.jvm.application.tasks.CreateStartScripts;
39+
import org.gradle.util.GradleVersion;
3740

3841
import org.springframework.boot.gradle.tasks.run.BootRun;
3942

@@ -55,7 +58,7 @@ public void execute(Project project) {
5558
.register("bootStartScripts", CreateStartScripts.class,
5659
(task) -> configureCreateStartScripts(project, javaApplication, distribution, task));
5760
CopySpec binCopySpec = project.copySpec().into("bin").from(bootStartScripts);
58-
binCopySpec.setFileMode(0755);
61+
configureFilePermissions(binCopySpec, 0755);
5962
distribution.getContents().with(binCopySpec);
6063
project.getTasks()
6164
.named(SpringBootPlugin.BOOT_RUN_TASK_NAME, BootRun.class)
@@ -85,7 +88,7 @@ private void configureCreateStartScripts(Project project, JavaApplication javaAp
8588

8689
private CopySpec artifactFilesToLibCopySpec(Project project, Configuration configuration) {
8790
CopySpec copySpec = project.copySpec().into("lib").from(artifactFiles(configuration));
88-
copySpec.setFileMode(0644);
91+
configureFilePermissions(copySpec, 0644);
8992
return copySpec;
9093
}
9194

@@ -113,4 +116,34 @@ private String loadResource(String name) {
113116
}
114117
}
115118

119+
private void configureFilePermissions(CopySpec copySpec, int mode) {
120+
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
121+
try {
122+
Method filePermissions = copySpec.getClass().getMethod("filePermissions", Action.class);
123+
filePermissions.invoke(copySpec, new Action<Object>() {
124+
125+
@Override
126+
public void execute(Object filePermissions) {
127+
String unixPermissions = Integer.toString(mode, 8);
128+
try {
129+
Method unix = filePermissions.getClass().getMethod("unix", String.class);
130+
unix.invoke(filePermissions, unixPermissions);
131+
}
132+
catch (Exception ex) {
133+
throw new GradleException("Failed to set file permissions to '" + unixPermissions + "'",
134+
ex);
135+
}
136+
}
137+
138+
});
139+
}
140+
catch (Exception ex) {
141+
throw new GradleException("Failed to set file permissions", ex);
142+
}
143+
}
144+
else {
145+
copySpec.setFileMode(mode);
146+
}
147+
}
148+
116149
}

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
import java.util.Set;
2727
import java.util.TreeMap;
2828
import java.util.function.Function;
29+
import java.util.function.Supplier;
2930

31+
import org.gradle.api.GradleException;
3032
import org.gradle.api.file.CopySpec;
3133
import org.gradle.api.file.FileCopyDetails;
3234
import org.gradle.api.file.FileTreeElement;
@@ -36,11 +38,13 @@
3638
import org.gradle.api.internal.file.copy.FileCopyDetailsInternal;
3739
import org.gradle.api.java.archives.Attributes;
3840
import org.gradle.api.java.archives.Manifest;
41+
import org.gradle.api.provider.Property;
3942
import org.gradle.api.specs.Spec;
4043
import org.gradle.api.specs.Specs;
4144
import org.gradle.api.tasks.WorkResult;
4245
import org.gradle.api.tasks.bundling.Jar;
4346
import org.gradle.api.tasks.util.PatternSet;
47+
import org.gradle.util.GradleVersion;
4448

4549
/**
4650
* Support class for implementations of {@link BootArchive}.
@@ -114,8 +118,8 @@ CopyAction createCopyAction(Jar jar, LayerResolver layerResolver, String layerTo
114118
File output = jar.getArchiveFile().get().getAsFile();
115119
Manifest manifest = jar.getManifest();
116120
boolean preserveFileTimestamps = jar.isPreserveFileTimestamps();
117-
Integer dirMode = jar.getDirMode();
118-
Integer fileMode = jar.getFileMode();
121+
Integer dirMode = getDirMode(jar);
122+
Integer fileMode = getFileMode(jar);
119123
boolean includeDefaultLoader = isUsingDefaultLoader(jar);
120124
Spec<FileTreeElement> requiresUnpack = this.requiresUnpack.getAsSpec();
121125
Spec<FileTreeElement> exclusions = this.exclusions.getAsExcludeSpec();
@@ -129,6 +133,46 @@ CopyAction createCopyAction(Jar jar, LayerResolver layerResolver, String layerTo
129133
return jar.isReproducibleFileOrder() ? new ReproducibleOrderingCopyAction(action) : action;
130134
}
131135

136+
private Integer getDirMode(CopySpec copySpec) {
137+
return getMode(copySpec, "getDirPermissions", copySpec::getDirMode);
138+
}
139+
140+
private Integer getFileMode(CopySpec copySpec) {
141+
return getMode(copySpec, "getFilePermissions", copySpec::getFileMode);
142+
}
143+
144+
@SuppressWarnings("unchecked")
145+
private Integer getMode(CopySpec copySpec, String methodName, Supplier<Integer> fallback) {
146+
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
147+
try {
148+
Object filePermissions = ((Property<Object>) copySpec.getClass().getMethod(methodName).invoke(copySpec))
149+
.getOrNull();
150+
return getMode(filePermissions);
151+
}
152+
catch (Exception ex) {
153+
throw new GradleException("Failed to get permissions", ex);
154+
}
155+
}
156+
return fallback.get();
157+
}
158+
159+
private Integer getMode(Object permissions) throws Exception {
160+
if (permissions == null) {
161+
return null;
162+
}
163+
String user = asIntegerString(permissions.getClass().getMethod("getUser").invoke(permissions));
164+
String group = asIntegerString(permissions.getClass().getMethod("getGroup").invoke(permissions));
165+
String other = asIntegerString(permissions.getClass().getMethod("getOther").invoke(permissions));
166+
return Integer.parseInt("0" + user + group + other, 8);
167+
}
168+
169+
private String asIntegerString(Object permissions) throws Exception {
170+
boolean read = (boolean) permissions.getClass().getMethod("getRead").invoke(permissions);
171+
boolean write = (boolean) permissions.getClass().getMethod("getWrite").invoke(permissions);
172+
boolean execute = (boolean) permissions.getClass().getMethod("getExecute").invoke(permissions);
173+
return Integer.toString(((read) ? 4 : 0) + ((write) ? 2 : 0) + ((execute) ? 1 : 0));
174+
}
175+
132176
private boolean isUsingDefaultLoader(Jar jar) {
133177
return DEFAULT_LAUNCHER_CLASSES.contains(jar.getManifest().getAttributes().get("Main-Class"));
134178
}

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@
4444
import org.gradle.api.internal.file.copy.CopyActionProcessingStream;
4545
import org.gradle.api.java.archives.Attributes;
4646
import org.gradle.api.java.archives.Manifest;
47+
import org.gradle.api.provider.Provider;
4748
import org.gradle.api.specs.Spec;
4849
import org.gradle.api.tasks.WorkResult;
4950
import org.gradle.api.tasks.WorkResults;
51+
import org.gradle.util.GradleVersion;
5052

5153
import org.springframework.boot.loader.tools.DefaultLaunchScript;
5254
import org.springframework.boot.loader.tools.FileUtils;
@@ -412,7 +414,24 @@ private int getFileMode() {
412414

413415
private int getFileMode(FileCopyDetails details) {
414416
return (BootZipCopyAction.this.fileMode != null) ? BootZipCopyAction.this.fileMode
415-
: UnixStat.FILE_FLAG | details.getMode();
417+
: UnixStat.FILE_FLAG | getPermissions(details);
418+
}
419+
420+
@SuppressWarnings("unchecked")
421+
private int getPermissions(FileCopyDetails details) {
422+
if (GradleVersion.current().compareTo(GradleVersion.version("8.3")) >= 0) {
423+
try {
424+
Object permissions = ((Provider<Object>) details.getClass()
425+
.getMethod("getImmutablePermissions")
426+
.invoke(details)).get();
427+
return ((Provider<Integer>) permissions.getClass().getMethod("toUnixNumeric").invoke(permissions))
428+
.get();
429+
}
430+
catch (Exception ex) {
431+
throw new GradleException("Failed to get permissions", ex);
432+
}
433+
}
434+
return details.getMode();
416435
}
417436

418437
}

0 commit comments

Comments
 (0)