Align ApplicationTemp with Files.createTempDirectory
Update `ApplicationTemp` to align the way that it creates temp folders with the way that `Files.createTempDirectory` works. Closes gh-27857
This commit is contained in:
parent
7cec0b3cb6
commit
44eb8c39d2
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +17,16 @@
|
||||||
package org.springframework.boot.system;
|
package org.springframework.boot.system;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.attribute.FileAttribute;
|
||||||
|
import java.nio.file.attribute.PosixFilePermission;
|
||||||
|
import java.nio.file.attribute.PosixFilePermissions;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -34,9 +43,14 @@ public class ApplicationTemp {
|
||||||
|
|
||||||
private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
|
private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
|
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 final Class<?> sourceClass;
|
private final Class<?> sourceClass;
|
||||||
|
|
||||||
private volatile File dir;
|
private volatile Path path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link ApplicationTemp} instance.
|
* Create a new {@link ApplicationTemp} instance.
|
||||||
|
@ -58,40 +72,60 @@ public class ApplicationTemp {
|
||||||
return getDir().getAbsolutePath();
|
return getDir().getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the directory to be used for application specific temp files.
|
||||||
|
* @return the application temp directory
|
||||||
|
*/
|
||||||
|
public File getDir() {
|
||||||
|
return getPath().toFile();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a sub-directory of the application temp.
|
* Return a sub-directory of the application temp.
|
||||||
* @param subDir the sub-directory name
|
* @param subDir the sub-directory name
|
||||||
* @return a sub-directory
|
* @return a sub-directory
|
||||||
*/
|
*/
|
||||||
public File getDir(String subDir) {
|
public File getDir(String subDir) {
|
||||||
File dir = new File(getDir(), subDir);
|
return createDirectory(getPath().resolve(subDir)).toFile();
|
||||||
dir.mkdirs();
|
|
||||||
return dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Path getPath() {
|
||||||
* Return the directory to be used for application specific temp files.
|
if (this.path == null) {
|
||||||
* @return the application temp directory
|
|
||||||
*/
|
|
||||||
public File getDir() {
|
|
||||||
if (this.dir == null) {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
byte[] hash = generateHash(this.sourceClass);
|
String hash = toHexString(generateHash(this.sourceClass));
|
||||||
this.dir = new File(getTempDirectory(), toHexString(hash));
|
this.path = createDirectory(getTempDirectory().resolve(hash));
|
||||||
this.dir.mkdirs();
|
|
||||||
Assert.state(this.dir.exists(), () -> "Unable to create temp directory " + this.dir);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.dir;
|
return this.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File getTempDirectory() {
|
private Path createDirectory(Path path) {
|
||||||
|
try {
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
Files.createDirectory(path, getFileAttributes(path.getFileSystem(), DIRECTORY_PERMISSIONS));
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new IllegalStateException("Unable to create application temp directory " + path, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileAttribute<?>[] getFileAttributes(FileSystem fileSystem, EnumSet<PosixFilePermission> ownerReadWrite) {
|
||||||
|
if (!fileSystem.supportedFileAttributeViews().contains("posix")) {
|
||||||
|
return NO_FILE_ATTRIBUTES;
|
||||||
|
}
|
||||||
|
return new FileAttribute<?>[] { PosixFilePermissions.asFileAttribute(ownerReadWrite) };
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path getTempDirectory() {
|
||||||
String property = System.getProperty("java.io.tmpdir");
|
String property = System.getProperty("java.io.tmpdir");
|
||||||
Assert.state(StringUtils.hasLength(property), "No 'java.io.tmpdir' property set");
|
Assert.state(StringUtils.hasLength(property), "No 'java.io.tmpdir' property set");
|
||||||
File file = new File(property);
|
Path tempDirectory = Paths.get(property);
|
||||||
Assert.state(file.exists(), () -> "Temp directory " + file + " does not exist");
|
Assert.state(Files.exists(tempDirectory), () -> "Temp directory '" + tempDirectory + "' does not exist");
|
||||||
Assert.state(file.isDirectory(), () -> "Temp location " + file + " is not a directory");
|
Assert.state(Files.isDirectory(tempDirectory),
|
||||||
return file;
|
() -> "Temp location '" + tempDirectory + "' is not a directory");
|
||||||
|
return tempDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] generateHash(Class<?> sourceClass) {
|
private byte[] generateHash(Class<?> sourceClass) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,9 +17,20 @@
|
||||||
package org.springframework.boot.system;
|
package org.springframework.boot.system;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.attribute.PosixFileAttributeView;
|
||||||
|
import java.nio.file.attribute.PosixFilePermission;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.util.FileSystemUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +40,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*/
|
*/
|
||||||
class ApplicationTempTests {
|
class ApplicationTempTests {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
@AfterEach
|
||||||
|
void cleanup() {
|
||||||
|
FileSystemUtils.deleteRecursively(new ApplicationTemp().getDir());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void generatesConsistentTemp() {
|
void generatesConsistentTemp() {
|
||||||
ApplicationTemp t1 = new ApplicationTemp();
|
ApplicationTemp t1 = new ApplicationTemp();
|
||||||
|
@ -57,4 +74,22 @@ class ApplicationTempTests {
|
||||||
assertThat(temp.getDir("abc")).isEqualTo(new File(temp.getDir(), "abc"));
|
assertThat(temp.getDir("abc")).isEqualTo(new File(temp.getDir(), "abc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void posixPermissions() throws IOException {
|
||||||
|
ApplicationTemp temp = new ApplicationTemp();
|
||||||
|
Path path = temp.getDir().toPath();
|
||||||
|
FileSystem fileSystem = path.getFileSystem();
|
||||||
|
if (fileSystem.supportedFileAttributeViews().contains("posix")) {
|
||||||
|
assertDirectoryPermissions(path);
|
||||||
|
assertDirectoryPermissions(temp.getDir("sub").toPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertDirectoryPermissions(Path path) throws IOException {
|
||||||
|
Set<PosixFilePermission> permissions = Files.getFileAttributeView(path, PosixFileAttributeView.class)
|
||||||
|
.readAttributes().permissions();
|
||||||
|
assertThat(permissions).containsExactlyInAnyOrder(PosixFilePermission.OWNER_READ,
|
||||||
|
PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue