1818
1919import java .io .File ;
2020import java .io .IOException ;
21+ import java .io .UncheckedIOException ;
2122import java .nio .file .FileSystem ;
2223import java .nio .file .Files ;
24+ import java .nio .file .LinkOption ;
2325import java .nio .file .Path ;
2426import java .nio .file .Paths ;
2527import java .nio .file .attribute .FileAttribute ;
28+ import java .nio .file .attribute .PosixFileAttributes ;
2629import java .nio .file .attribute .PosixFilePermission ;
2730import java .nio .file .attribute .PosixFilePermissions ;
31+ import java .nio .file .attribute .UserPrincipal ;
2832import java .security .MessageDigest ;
2933import java .util .EnumSet ;
3034import java .util .HexFormat ;
@@ -54,6 +58,8 @@ public class ApplicationTemp {
5458
5559 private final Lock pathLock = new ReentrantLock ();
5660
61+ private final UserPrincipal directoryOwner ;
62+
5763 private volatile Path path ;
5864
5965 /**
@@ -69,6 +75,22 @@ public ApplicationTemp() {
6975 */
7076 public ApplicationTemp (Class <?> sourceClass ) {
7177 this .sourceClass = sourceClass ;
78+ this .directoryOwner = directoryOwner ();
79+ }
80+
81+ private static UserPrincipal directoryOwner () {
82+ try {
83+ Path tempFile = Files .createTempFile ("application-temp" , "-owner" );
84+ UserPrincipal owner = Files .getOwner (tempFile );
85+ Files .delete (tempFile );
86+ return owner ;
87+ }
88+ catch (UnsupportedOperationException ex ) {
89+ return null ;
90+ }
91+ catch (IOException ex ) {
92+ throw new UncheckedIOException (ex );
93+ }
7294 }
7395
7496 @ Override
@@ -111,8 +133,28 @@ private Path getPath() {
111133
112134 private Path createDirectory (Path path ) {
113135 try {
114- if (!Files .exists (path )) {
115- Files .createDirectory (path , getFileAttributes (path .getFileSystem (), DIRECTORY_PERMISSIONS ));
136+ FileSystem fileSystem = path .getFileSystem ();
137+ if (!Files .exists (path , LinkOption .NOFOLLOW_LINKS )) {
138+ Files .createDirectory (path , asFileAttributes (fileSystem , DIRECTORY_PERMISSIONS ));
139+ }
140+ else {
141+ if (supportsPosixView (fileSystem )) {
142+ PosixFileAttributes attributes = Files .readAttributes (path , PosixFileAttributes .class ,
143+ LinkOption .NOFOLLOW_LINKS );
144+ Assert .state (attributes .isDirectory (),
145+ () -> "'" + path + "' already exists but it is not a directory" );
146+ Assert .state (DIRECTORY_PERMISSIONS .equals (attributes .permissions ()), () -> "Existing directory '"
147+ + path + "' does not have the permissions " + DIRECTORY_PERMISSIONS );
148+ assertDirectoryOwnership (attributes .owner (), path );
149+ }
150+ else {
151+ try {
152+ assertDirectoryOwnership (Files .getOwner (path , LinkOption .NOFOLLOW_LINKS ), path );
153+ }
154+ catch (UnsupportedOperationException ex ) {
155+ // Ownership check not supported. Continue.
156+ }
157+ }
116158 }
117159 return path ;
118160 }
@@ -121,13 +163,22 @@ private Path createDirectory(Path path) {
121163 }
122164 }
123165
124- private FileAttribute <?>[] getFileAttributes (FileSystem fileSystem , EnumSet <PosixFilePermission > ownerReadWrite ) {
125- if (!fileSystem .supportedFileAttributeViews ().contains ("posix" )) {
166+ private void assertDirectoryOwnership (UserPrincipal owner , Path path ) {
167+ Assert .state ((this .directoryOwner == null ) || this .directoryOwner .equals (owner ),
168+ () -> "Existing directory '" + path + "' is not owned by " + this .directoryOwner .getName ());
169+ }
170+
171+ private FileAttribute <?>[] asFileAttributes (FileSystem fileSystem , EnumSet <PosixFilePermission > ownerReadWrite ) {
172+ if (!supportsPosixView (fileSystem )) {
126173 return NO_FILE_ATTRIBUTES ;
127174 }
128175 return new FileAttribute <?>[] { PosixFilePermissions .asFileAttribute (ownerReadWrite ) };
129176 }
130177
178+ private boolean supportsPosixView (FileSystem fileSystem ) {
179+ return fileSystem .supportedFileAttributeViews ().contains ("posix" );
180+ }
181+
131182 private Path getTempDirectory () {
132183 String property = System .getProperty ("java.io.tmpdir" );
133184 Assert .state (StringUtils .hasLength (property ), "No 'java.io.tmpdir' property set" );
0 commit comments