mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Apply Gradle fileMode and dirMode consistently in jar and war archives
Fixes gh-37496
This commit is contained in:
parent
fce64878b4
commit
aeeb5cf1f8
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -47,6 +47,7 @@ import org.gradle.api.tasks.util.PatternSet;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @author Scott Frederick
|
||||
* @see BootJar
|
||||
* @see BootWar
|
||||
*/
|
||||
@ -113,6 +114,8 @@ class BootArchiveSupport {
|
||||
File output = jar.getArchiveFile().get().getAsFile();
|
||||
Manifest manifest = jar.getManifest();
|
||||
boolean preserveFileTimestamps = jar.isPreserveFileTimestamps();
|
||||
Integer dirMode = jar.getDirMode();
|
||||
Integer fileMode = jar.getFileMode();
|
||||
boolean includeDefaultLoader = isUsingDefaultLoader(jar);
|
||||
Spec<FileTreeElement> requiresUnpack = this.requiresUnpack.getAsSpec();
|
||||
Spec<FileTreeElement> exclusions = this.exclusions.getAsExcludeSpec();
|
||||
@ -120,9 +123,9 @@ class BootArchiveSupport {
|
||||
Spec<FileCopyDetails> librarySpec = this.librarySpec;
|
||||
Function<FileCopyDetails, ZipCompression> compressionResolver = this.compressionResolver;
|
||||
String encoding = jar.getMetadataCharset();
|
||||
CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, includeDefaultLoader,
|
||||
layerToolsLocation, requiresUnpack, exclusions, launchScript, librarySpec, compressionResolver,
|
||||
encoding, layerResolver);
|
||||
CopyAction action = new BootZipCopyAction(output, manifest, preserveFileTimestamps, dirMode, fileMode,
|
||||
includeDefaultLoader, layerToolsLocation, requiresUnpack, exclusions, launchScript, librarySpec,
|
||||
compressionResolver, encoding, layerResolver);
|
||||
return jar.isReproducibleFileOrder() ? new ReproducibleOrderingCopyAction(action) : action;
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,10 @@ class BootZipCopyAction implements CopyAction {
|
||||
|
||||
private final boolean preserveFileTimestamps;
|
||||
|
||||
private final Integer dirMode;
|
||||
|
||||
private final Integer fileMode;
|
||||
|
||||
private final boolean includeDefaultLoader;
|
||||
|
||||
private final String layerToolsLocation;
|
||||
@ -95,14 +99,16 @@ class BootZipCopyAction implements CopyAction {
|
||||
|
||||
private final LayerResolver layerResolver;
|
||||
|
||||
BootZipCopyAction(File output, Manifest manifest, boolean preserveFileTimestamps, boolean includeDefaultLoader,
|
||||
String layerToolsLocation, Spec<FileTreeElement> requiresUnpack, Spec<FileTreeElement> exclusions,
|
||||
LaunchScriptConfiguration launchScript, Spec<FileCopyDetails> librarySpec,
|
||||
BootZipCopyAction(File output, Manifest manifest, boolean preserveFileTimestamps, Integer dirMode, Integer fileMode,
|
||||
boolean includeDefaultLoader, String layerToolsLocation, Spec<FileTreeElement> requiresUnpack,
|
||||
Spec<FileTreeElement> exclusions, LaunchScriptConfiguration launchScript, Spec<FileCopyDetails> librarySpec,
|
||||
Function<FileCopyDetails, ZipCompression> compressionResolver, String encoding,
|
||||
LayerResolver layerResolver) {
|
||||
this.output = output;
|
||||
this.manifest = manifest;
|
||||
this.preserveFileTimestamps = preserveFileTimestamps;
|
||||
this.dirMode = dirMode;
|
||||
this.fileMode = fileMode;
|
||||
this.includeDefaultLoader = includeDefaultLoader;
|
||||
this.layerToolsLocation = layerToolsLocation;
|
||||
this.requiresUnpack = requiresUnpack;
|
||||
@ -225,7 +231,7 @@ class BootZipCopyAction implements CopyAction {
|
||||
private void processDirectory(FileCopyDetails details) throws IOException {
|
||||
String name = details.getRelativePath().getPathString();
|
||||
ZipArchiveEntry entry = new ZipArchiveEntry(name + '/');
|
||||
prepareEntry(entry, name, getTime(details), UnixStat.FILE_FLAG | details.getMode());
|
||||
prepareEntry(entry, name, getTime(details), getFileMode(details));
|
||||
this.out.putArchiveEntry(entry);
|
||||
this.out.closeArchiveEntry();
|
||||
this.writtenDirectories.add(name);
|
||||
@ -234,7 +240,7 @@ class BootZipCopyAction implements CopyAction {
|
||||
private void processFile(FileCopyDetails details) throws IOException {
|
||||
String name = details.getRelativePath().getPathString();
|
||||
ZipArchiveEntry entry = new ZipArchiveEntry(name);
|
||||
prepareEntry(entry, name, getTime(details), UnixStat.FILE_FLAG | details.getMode());
|
||||
prepareEntry(entry, name, getTime(details), getFileMode(details));
|
||||
ZipCompression compression = BootZipCopyAction.this.compressionResolver.apply(details);
|
||||
if (compression == ZipCompression.STORED) {
|
||||
prepareStoredEntry(details, entry);
|
||||
@ -255,7 +261,7 @@ class BootZipCopyAction implements CopyAction {
|
||||
String parentDirectory = getParentDirectory(name);
|
||||
if (parentDirectory != null && this.writtenDirectories.add(parentDirectory)) {
|
||||
ZipArchiveEntry entry = new ZipArchiveEntry(parentDirectory + '/');
|
||||
prepareEntry(entry, parentDirectory, time, UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM);
|
||||
prepareEntry(entry, parentDirectory, time, getDirMode());
|
||||
this.out.putArchiveEntry(entry);
|
||||
this.out.closeArchiveEntry();
|
||||
}
|
||||
@ -285,7 +291,7 @@ class BootZipCopyAction implements CopyAction {
|
||||
// Always write loader entries after META-INF directory (see gh-16698)
|
||||
return;
|
||||
}
|
||||
LoaderZipEntries loaderEntries = new LoaderZipEntries(getTime());
|
||||
LoaderZipEntries loaderEntries = new LoaderZipEntries(getTime(), getDirMode(), getFileMode());
|
||||
this.writtenLoaderEntries = loaderEntries.writeTo(this.out);
|
||||
if (BootZipCopyAction.this.layerResolver != null) {
|
||||
for (String name : this.writtenLoaderEntries.getFiles()) {
|
||||
@ -350,7 +356,7 @@ class BootZipCopyAction implements CopyAction {
|
||||
private void writeEntry(String name, ZipEntryContentWriter entryWriter, boolean addToLayerIndex,
|
||||
ZipEntryCustomizer entryCustomizer) throws IOException {
|
||||
ZipArchiveEntry entry = new ZipArchiveEntry(name);
|
||||
prepareEntry(entry, name, getTime(), UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM);
|
||||
prepareEntry(entry, name, getTime(), getFileMode());
|
||||
entryCustomizer.customize(entry);
|
||||
this.out.putArchiveEntry(entry);
|
||||
entryWriter.writeTo(this.out);
|
||||
@ -394,6 +400,21 @@ class BootZipCopyAction implements CopyAction {
|
||||
return null;
|
||||
}
|
||||
|
||||
private int getDirMode() {
|
||||
return (BootZipCopyAction.this.dirMode != null) ? BootZipCopyAction.this.dirMode
|
||||
: UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM;
|
||||
}
|
||||
|
||||
private int getFileMode() {
|
||||
return (BootZipCopyAction.this.fileMode != null) ? BootZipCopyAction.this.fileMode
|
||||
: UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM;
|
||||
}
|
||||
|
||||
private int getFileMode(FileCopyDetails details) {
|
||||
return (BootZipCopyAction.this.fileMode != null) ? BootZipCopyAction.this.fileMode
|
||||
: UnixStat.FILE_FLAG | details.getMode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,6 @@ import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.UnixStat;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
|
||||
import org.gradle.api.file.FileTreeElement;
|
||||
@ -42,8 +41,14 @@ class LoaderZipEntries {
|
||||
|
||||
private final Long entryTime;
|
||||
|
||||
LoaderZipEntries(Long entryTime) {
|
||||
private final int dirMode;
|
||||
|
||||
private final int fileMode;
|
||||
|
||||
LoaderZipEntries(Long entryTime, int dirMode, int fileMode) {
|
||||
this.entryTime = entryTime;
|
||||
this.dirMode = dirMode;
|
||||
this.fileMode = fileMode;
|
||||
}
|
||||
|
||||
WrittenEntries writeTo(ZipArchiveOutputStream out) throws IOException {
|
||||
@ -67,13 +72,13 @@ class LoaderZipEntries {
|
||||
}
|
||||
|
||||
private void writeDirectory(ZipArchiveEntry entry, ZipArchiveOutputStream out) throws IOException {
|
||||
prepareEntry(entry, UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM);
|
||||
prepareEntry(entry, this.dirMode);
|
||||
out.putArchiveEntry(entry);
|
||||
out.closeArchiveEntry();
|
||||
}
|
||||
|
||||
private void writeClass(ZipArchiveEntry entry, ZipInputStream in, ZipArchiveOutputStream out) throws IOException {
|
||||
prepareEntry(entry, UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM);
|
||||
prepareEntry(entry, this.fileMode);
|
||||
out.putArchiveEntry(entry);
|
||||
copy(in, out);
|
||||
out.closeArchiveEntry();
|
||||
|
@ -29,6 +29,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -45,6 +46,9 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.UnixStat;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.jupiter.api.TestTemplate;
|
||||
@ -62,6 +66,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
abstract class AbstractBootArchiveIntegrationTests {
|
||||
|
||||
@ -515,6 +520,48 @@ abstract class AbstractBootArchiveIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void defaultDirAndFileModesAreUsed() throws IOException {
|
||||
BuildResult result = this.gradleBuild.build(this.taskName);
|
||||
assertThat(result.task(":" + this.taskName).getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
try (ZipFile jarFile = new ZipFile(new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0])) {
|
||||
Enumeration<ZipArchiveEntry> entries = jarFile.getEntries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipArchiveEntry entry = entries.nextElement();
|
||||
if (entry.getName().startsWith("META-INF/")) {
|
||||
continue;
|
||||
}
|
||||
if (entry.isDirectory()) {
|
||||
assertEntryMode(entry, UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM);
|
||||
}
|
||||
else {
|
||||
assertEntryMode(entry, UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void dirModeAndFileModeAreApplied() throws IOException {
|
||||
BuildResult result = this.gradleBuild.build(this.taskName);
|
||||
assertThat(result.task(":" + this.taskName).getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
try (ZipFile jarFile = new ZipFile(new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0])) {
|
||||
Enumeration<ZipArchiveEntry> entries = jarFile.getEntries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipArchiveEntry entry = entries.nextElement();
|
||||
if (entry.getName().startsWith("META-INF/")) {
|
||||
continue;
|
||||
}
|
||||
if (entry.isDirectory()) {
|
||||
assertEntryMode(entry, 0500);
|
||||
}
|
||||
else {
|
||||
assertEntryMode(entry, 0400);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyMainClassApplication() throws IOException {
|
||||
copyApplication("main");
|
||||
}
|
||||
@ -650,4 +697,11 @@ abstract class AbstractBootArchiveIntegrationTests {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void assertEntryMode(ZipArchiveEntry entry, int expectedMode) {
|
||||
assertThat(entry.getUnixMode())
|
||||
.withFailMessage(() -> "Expected mode " + Integer.toOctalString(expectedMode) + " for entry "
|
||||
+ entry.getName() + " but actual is " + Integer.toOctalString(entry.getUnixMode()))
|
||||
.isEqualTo(expectedMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '{version}'
|
||||
}
|
||||
|
||||
tasks.named("bootJar") {
|
||||
fileMode = 0400
|
||||
dirMode = 0500
|
||||
mainClass = 'com.example.Application'
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id 'war'
|
||||
id 'org.springframework.boot' version '{version}'
|
||||
}
|
||||
|
||||
tasks.named("bootWar") {
|
||||
fileMode = 0400
|
||||
dirMode = 0500
|
||||
mainClass = 'com.example.Application'
|
||||
}
|
Loading…
Reference in New Issue
Block a user