diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootArchiveSupport.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootArchiveSupport.java index 64eb4266c7..3d8acf6bd6 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootArchiveSupport.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootArchiveSupport.java @@ -16,13 +16,14 @@ package org.springframework.boot.gradle.bundling; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.function.Function; +import org.gradle.api.file.FileCopyDetails; import org.gradle.api.file.FileTreeElement; import org.gradle.api.file.RelativePath; import org.gradle.api.internal.file.copy.CopyAction; @@ -54,7 +55,7 @@ class BootArchiveSupport { private final PatternSet requiresUnpack = new PatternSet(); - private final Set storedPathPrefixes; + private final Function compressionResolver; private final PatternSet exclusions = new PatternSet(); @@ -64,9 +65,10 @@ class BootArchiveSupport { private boolean excludeDevtools = true; - BootArchiveSupport(String loaderMainClass, String... storedPathPrefixes) { + BootArchiveSupport(String loaderMainClass, + Function compressionResolver) { this.loaderMainClass = loaderMainClass; - this.storedPathPrefixes = new HashSet<>(Arrays.asList(storedPathPrefixes)); + this.compressionResolver = compressionResolver; this.requiresUnpack.include(Specs.satisfyNone()); configureExclusions(); } @@ -81,7 +83,7 @@ class BootArchiveSupport { CopyAction copyAction = new BootZipCopyAction(jar.getArchivePath(), jar.isPreserveFileTimestamps(), isUsingDefaultLoader(jar), this.requiresUnpack.getAsSpec(), this.exclusions.getAsExcludeSpec(), - this.launchScript, this.storedPathPrefixes); + this.launchScript, this.compressionResolver); if (!jar.isReproducibleFileOrder()) { return copyAction; } diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootJar.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootJar.java index 9665c0f8aa..fc331f6edd 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootJar.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootJar.java @@ -23,6 +23,7 @@ import java.util.concurrent.Callable; import org.gradle.api.Action; import org.gradle.api.file.CopySpec; import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileCopyDetails; import org.gradle.api.file.FileTreeElement; import org.gradle.api.internal.file.copy.CopyAction; import org.gradle.api.specs.Spec; @@ -36,7 +37,7 @@ import org.gradle.api.tasks.bundling.Jar; public class BootJar extends Jar implements BootArchive { private BootArchiveSupport support = new BootArchiveSupport( - "org.springframework.boot.loader.JarLauncher", "BOOT-INF/lib"); + "org.springframework.boot.loader.JarLauncher", this::resolveZipCompression); private FileCollection classpath; @@ -122,4 +123,21 @@ public class BootJar extends Jar implements BootArchive { this.support.setExcludeDevtools(excludeDevtools); } + /** + * Returns the {@link ZipCompression} that should be used when adding the file + * represented by the given {@code details} to the jar. + *

+ * By default, any file in {@code BOOT-INF/lib/} is stored and all other files are + * deflated. + * + * @param details the details + * @return the compression to use + */ + protected ZipCompression resolveZipCompression(FileCopyDetails details) { + if (details.getRelativePath().getPathString().startsWith("BOOT-INF/lib/")) { + return ZipCompression.STORED; + } + return ZipCompression.DEFLATED; + } + } diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootWar.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootWar.java index 8203ffa6fc..8c243ed864 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootWar.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootWar.java @@ -23,6 +23,7 @@ import java.util.concurrent.Callable; import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileCopyDetails; import org.gradle.api.file.FileTreeElement; import org.gradle.api.internal.file.copy.CopyAction; import org.gradle.api.specs.Spec; @@ -37,8 +38,7 @@ import org.gradle.api.tasks.bundling.War; public class BootWar extends War implements BootArchive { private final BootArchiveSupport support = new BootArchiveSupport( - "org.springframework.boot.loader.WarLauncher", "WEB-INF/lib/", - "WEB-INF/lib-provided"); + "org.springframework.boot.loader.WarLauncher", this::resolveZipCompression); private String mainClass; @@ -122,4 +122,23 @@ public class BootWar extends War implements BootArchive { this.support.setExcludeDevtools(excludeDevtools); } + /** + * Returns the {@link ZipCompression} that should be used when adding the file + * represented by the given {@code details} to the jar. + *

+ * By default, any file in {@code WEB-INF/lib/} or {@code WEB-INF/lib-provided/} is + * stored and all other files are deflated. + * + * @param details the details + * @return the compression to use + */ + protected ZipCompression resolveZipCompression(FileCopyDetails details) { + String relativePath = details.getRelativePath().getPathString(); + if (relativePath.startsWith("WEB-INF/lib/") + || relativePath.startsWith("WEB-INF/lib-provided/")) { + return ZipCompression.STORED; + } + return ZipCompression.DEFLATED; + } + } diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootZipCopyAction.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootZipCopyAction.java index 348f352d4e..0eaa6c3890 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootZipCopyAction.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BootZipCopyAction.java @@ -21,7 +21,7 @@ import java.io.FileOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.Set; +import java.util.function.Function; import java.util.zip.CRC32; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -61,19 +61,19 @@ class BootZipCopyAction implements CopyAction { private final LaunchScriptConfiguration launchScript; - private final Set storedPathPrefixes; + private final Function compressionResolver; BootZipCopyAction(File output, boolean preserveFileTimestamps, boolean includeDefaultLoader, Spec requiresUnpack, Spec exclusions, LaunchScriptConfiguration launchScript, - Set storedPathPrefixes) { + Function compressionResolver) { this.output = output; this.preserveFileTimestamps = preserveFileTimestamps; this.includeDefaultLoader = includeDefaultLoader; this.requiresUnpack = requiresUnpack; this.exclusions = exclusions; this.launchScript = launchScript; - this.storedPathPrefixes = storedPathPrefixes; + this.compressionResolver = compressionResolver; } @Override @@ -91,7 +91,7 @@ class BootZipCopyAction implements CopyAction { try { stream.process(new ZipStreamAction(zipStream, this.output, this.preserveFileTimestamps, this.requiresUnpack, this.exclusions, - this.storedPathPrefixes)); + this.compressionResolver)); } finally { try { @@ -162,17 +162,18 @@ class BootZipCopyAction implements CopyAction { private final Spec exclusions; - private final Set storedPathPrefixes; + private final Function compressionType; private ZipStreamAction(ZipOutputStream zipStream, File output, boolean preserveFileTimestamps, Spec requiresUnpack, - Spec exclusions, Set storedPathPrefixes) { + Spec exclusions, + Function compressionType) { this.zipStream = zipStream; this.output = output; this.preserveFileTimestamps = preserveFileTimestamps; this.requiresUnpack = requiresUnpack; this.exclusions = exclusions; - this.storedPathPrefixes = storedPathPrefixes; + this.compressionType = compressionType; } @Override @@ -207,7 +208,8 @@ class BootZipCopyAction implements CopyAction { ZipEntry archiveEntry = new ZipEntry(relativePath); archiveEntry.setTime(getTime(details)); this.zipStream.putNextEntry(archiveEntry); - if (isStoredEntry(relativePath)) { + ZipCompression compression = this.compressionType.apply(details); + if (compression == ZipCompression.STORED) { archiveEntry.setMethod(ZipEntry.STORED); archiveEntry.setSize(details.getSize()); archiveEntry.setCompressedSize(details.getSize()); @@ -225,15 +227,6 @@ class BootZipCopyAction implements CopyAction { this.zipStream.closeEntry(); } - private boolean isStoredEntry(String relativePath) { - for (String prefix : this.storedPathPrefixes) { - if (relativePath.startsWith(prefix)) { - return true; - } - } - return false; - } - private long getTime(FileCopyDetails details) { return this.preserveFileTimestamps ? details.getLastModified() : GUtil.CONSTANT_TIME_FOR_ZIP_ENTRIES; diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/ZipCompression.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/ZipCompression.java new file mode 100644 index 0000000000..b34e0793d8 --- /dev/null +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/ZipCompression.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.gradle.bundling; + +import java.util.zip.ZipEntry; + +/** + * An enumeration of supported compression options for an entry in a ZIP archive. + * + * @author Andy Wilkinson + */ +public enum ZipCompression { + + /** + * The entry should be {@link ZipEntry#STORED} in the archive. + */ + STORED, + + /** + * The entry should be {@link ZipEntry#DEFLATED} in the archive. + */ + DEFLATED; + +}