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
pull/26093/head
Phillip Webb 4 years ago
parent b8873578ca
commit 05f61bccea

@ -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<PosixFilePermission> DIRECTORY_PERMISSIONS = EnumSet.of(PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE);
private static final EnumSet<PosixFilePermission> 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<PosixFilePermission> ownerReadWrite) {
if (!fileSystem.supportedFileAttributeViews().contains("posix")) {
return NO_FILE_ATTRIBUTES;
}
return new FileAttribute<?>[] { PosixFilePermissions.asFileAttribute(ownerReadWrite) };
}
@Override
public String toString() {
try {

Loading…
Cancel
Save