From b8873578ca545e2b6309c64a8ccbedc1803e48e1 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 23 Mar 2021 16:16:49 -0700 Subject: [PATCH 1/3] Add missing @Deprecated annotations --- .../springframework/boot/loader/archive/ExplodedArchive.java | 4 +++- .../springframework/boot/loader/archive/JarFileArchive.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java index f804268827..170948b5d1 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -103,6 +103,7 @@ public class ExplodedArchive implements Archive { } @Override + @Deprecated public Iterator iterator() { return new EntryIterator(this.root, this.recursive, null, null); } @@ -321,6 +322,7 @@ public class ExplodedArchive implements Archive { } @Override + @Deprecated public Iterator iterator() { return Collections.emptyIterator(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java index c43c179a20..73f62549a2 100755 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -81,6 +81,7 @@ public class JarFileArchive implements Archive { } @Override + @Deprecated public Iterator iterator() { return new EntryIterator(this.jarFile.iterator(), null, null); } From 05f61bccea2833c04f471c36552ce879143c9ce9 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 23 Mar 2021 17:01:37 -0700 Subject: [PATCH 2/3] Align unpack logic with Files.createTempDirectory Update `JarFileArchive` to align the way that it creates temp files and folders with the way that `Files.createTempDirectory` works. Closes gh-25772 --- .../boot/loader/archive/JarFileArchive.java | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java index 73f62549a2..579ea4399f 100755 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java @@ -17,12 +17,20 @@ package org.springframework.boot.loader.archive; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.EnumSet; import java.util.Iterator; import java.util.UUID; import java.util.jar.JarEntry; @@ -43,11 +51,19 @@ public class JarFileArchive implements Archive { private static final int BUFFER_SIZE = 32 * 1024; + private static final FileAttribute[] NO_FILE_ATTRIBUTES = {}; + + private static final EnumSet DIRECTORY_PERMISSIONS = EnumSet.of(PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE); + + private static final EnumSet FILE_PERMISSIONS = EnumSet.of(PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE); + private final JarFile jarFile; private URL url; - private File tempUnpackDirectory; + private Path tempUnpackDirectory; public JarFileArchive(File file) throws IOException { this(file, file.toURI().toURL()); @@ -110,36 +126,41 @@ public class JarFileArchive implements Archive { if (name.lastIndexOf('/') != -1) { name = name.substring(name.lastIndexOf('/') + 1); } - File file = new File(getTempUnpackDirectory(), name); - if (!file.exists() || file.length() != jarEntry.getSize()) { - unpack(jarEntry, file); + Path path = getTempUnpackDirectory().resolve(name); + if (!Files.exists(path) || Files.size(path) != jarEntry.getSize()) { + unpack(jarEntry, path); } - return new JarFileArchive(file, file.toURI().toURL()); + return new JarFileArchive(path.toFile(), path.toUri().toURL()); } - private File getTempUnpackDirectory() { + private Path getTempUnpackDirectory() { if (this.tempUnpackDirectory == null) { - File tempDirectory = new File(System.getProperty("java.io.tmpdir")); + Path tempDirectory = Paths.get(System.getProperty("java.io.tmpdir")); this.tempUnpackDirectory = createUnpackDirectory(tempDirectory); } return this.tempUnpackDirectory; } - private File createUnpackDirectory(File parent) { + private Path createUnpackDirectory(Path parent) { int attempts = 0; while (attempts++ < 1000) { - String fileName = new File(this.jarFile.getName()).getName(); - File unpackDirectory = new File(parent, fileName + "-spring-boot-libs-" + UUID.randomUUID()); - if (unpackDirectory.mkdirs()) { + String fileName = Paths.get(this.jarFile.getName()).getFileName().toString(); + Path unpackDirectory = parent.resolve(fileName + "-spring-boot-libs-" + UUID.randomUUID()); + try { + createDirectory(unpackDirectory); return unpackDirectory; } + catch (IOException ex) { + } } throw new IllegalStateException("Failed to create unpack directory in directory '" + parent + "'"); } - private void unpack(JarEntry entry, File file) throws IOException { + private void unpack(JarEntry entry, Path path) throws IOException { + createFile(path); try (InputStream inputStream = this.jarFile.getInputStream(entry); - OutputStream outputStream = new FileOutputStream(file)) { + OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.WRITE, + StandardOpenOption.TRUNCATE_EXISTING)) { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { @@ -149,6 +170,21 @@ public class JarFileArchive implements Archive { } } + private void createDirectory(Path path) throws IOException { + Files.createDirectory(path, getFileAttributes(path.getFileSystem(), DIRECTORY_PERMISSIONS)); + } + + private void createFile(Path path) throws IOException { + Files.createFile(path, getFileAttributes(path.getFileSystem(), FILE_PERMISSIONS)); + } + + private FileAttribute[] getFileAttributes(FileSystem fileSystem, EnumSet ownerReadWrite) { + if (!fileSystem.supportedFileAttributeViews().contains("posix")) { + return NO_FILE_ATTRIBUTES; + } + return new FileAttribute[] { PosixFilePermissions.asFileAttribute(ownerReadWrite) }; + } + @Override public String toString() { try { From ec21202d54454e252c05fcd88ddadf00972c6abe Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 23 Mar 2021 17:04:42 -0700 Subject: [PATCH 3/3] Delete unpacked jars when the JVM exits Update `JarFileArchive` so that any unpacked files are now deleted when the JVM exits. Closes gh-25773 --- .../org/springframework/boot/loader/archive/JarFileArchive.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java index 579ea4399f..bab4125f5c 100755 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java @@ -158,6 +158,7 @@ public class JarFileArchive implements Archive { private void unpack(JarEntry entry, Path path) throws IOException { createFile(path); + path.toFile().deleteOnExit(); try (InputStream inputStream = this.jarFile.getInputStream(entry); OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {