4
4
package com .azure .storage .blob .nio ;
5
5
6
6
import com .azure .core .util .logging .ClientLogger ;
7
- import com .azure .storage .blob .models .BlobProperties ;
8
- import com .azure .storage .blob .models .BlobStorageException ;
9
7
10
8
import java .io .IOException ;
11
9
import java .nio .file .Path ;
24
22
* {@link AzureBlobFileAttributes} is generally preferred.
25
23
* <p>
26
24
* Some attributes are not supported. Refer to the javadocs on each method for more information.
25
+ * <p>
26
+ * If the target file is a virtual directory, most attributes will be set to null.
27
27
*/
28
28
public final class AzureBasicFileAttributes implements BasicFileAttributes {
29
29
private final ClientLogger logger = new ClientLogger (AzureBasicFileAttributes .class );
@@ -35,64 +35,60 @@ public final class AzureBasicFileAttributes implements BasicFileAttributes {
35
35
set .add ("lastModifiedTime" );
36
36
set .add ("isRegularFile" );
37
37
set .add ("isDirectory" );
38
+ set .add ("isVirtualDirectory" );
38
39
set .add ("isSymbolicLink" );
39
40
set .add ("isOther" );
40
41
set .add ("size" );
41
42
set .add ("creationTime" );
42
43
ATTRIBUTE_STRINGS = Collections .unmodifiableSet (set );
43
44
}
44
45
45
- private final BlobProperties properties ;
46
- private final AzureResource resource ;
46
+ private final AzureBlobFileAttributes internalAttributes ;
47
47
48
48
/*
49
- There are some work-arounds we could do to try to accommodate virtual directories such as making a checkDirStatus
50
- call before or after getProperties to throw an appropriate error or adding an isVirtualDirectory method. However,
51
- the former wastes network time only to throw a slightly more specific error when we will throw on 404 anyway. The
52
- latter introduces virtual directories into the actual code path/api surface. While we are clear in our docs about
53
- the possible pitfalls of virtual directories, and customers should be aware of it, they shouldn 't have to code
54
- against it. Therefore, we fall back to documenting that reading attributes on a virtual directory will throw .
49
+ In order to support Files.exist() and other methods like Files.walkFileTree() which depend on it, we have had to add
50
+ support for virtual directories. This is not ideal as customers will have to now perform null checks when inspecting
51
+ attributes (or at least check if it is a virtual directory before inspecting properties). It also incurs extra
52
+ network requests as we have to call a checkDirectoryExists() after receiving the initial 404. This is two
53
+ additional network requests, though they only happen in the case when a file doesn 't exist or is virtual, so it
54
+ shouldn't happen in the majority of api calls .
55
55
*/
56
56
AzureBasicFileAttributes (Path path ) throws IOException {
57
- try {
58
- this .resource = new AzureResource (path );
59
- this .properties = resource .getBlobClient ().getProperties ();
60
- } catch (BlobStorageException e ) {
61
- throw LoggingUtility .logError (logger , new IOException (e ));
62
- }
57
+ this .internalAttributes = new AzureBlobFileAttributes (path );
63
58
}
64
59
65
60
/**
66
- * Returns the time of last modification.
61
+ * Returns the time of last modification or null if this is a virtual directory .
67
62
*
68
- * @return the time of last modification.
63
+ * @return the time of last modification or null if this is a virtual directory
69
64
*/
70
65
@ Override
71
66
public FileTime lastModifiedTime () {
72
- return FileTime . from ( properties . getLastModified (). toInstant () );
67
+ return this . internalAttributes . lastModifiedTime ( );
73
68
}
74
69
75
70
/**
76
- * Returns the time of last modification.
71
+ * Returns the time of last modification or null if this is a virtual directory
77
72
* <p>
78
73
* Last access time is not supported by the blob service. In this case, it is typical for implementations to return
79
74
* the {@link #lastModifiedTime()}.
80
75
*
81
- * @return the time of last modification.
76
+ * @return the time of last modification or null if this is a virtual directory
82
77
*/
83
78
@ Override
84
79
public FileTime lastAccessTime () {
85
- return this .lastModifiedTime ();
80
+ return this .internalAttributes . lastAccessTime ();
86
81
}
87
82
88
83
/**
89
- * Returns the creation time. The creation time is the time that the file was created.
84
+ * Returns the creation time. The creation time is the time that the file was created. Returns null if this is a
85
+ * virtual directory.
90
86
*
91
- * @return The creation time.
87
+ * @return The creation time or null if this is a virtual directory
92
88
*/
93
89
@ Override
94
90
public FileTime creationTime () {
95
- return FileTime . from ( properties . getCreationTime (). toInstant () );
91
+ return this . internalAttributes . creationTime ( );
96
92
}
97
93
98
94
/**
@@ -102,7 +98,7 @@ public FileTime creationTime() {
102
98
*/
103
99
@ Override
104
100
public boolean isRegularFile () {
105
- return ! this .properties . getMetadata (). getOrDefault ( AzureResource . DIR_METADATA_MARKER , "false" ). equals ( "true" );
101
+ return this .internalAttributes . isRegularFile ( );
106
102
}
107
103
108
104
/**
@@ -116,7 +112,19 @@ public boolean isRegularFile() {
116
112
*/
117
113
@ Override
118
114
public boolean isDirectory () {
119
- return !this .isRegularFile ();
115
+ return this .internalAttributes .isDirectory ();
116
+ }
117
+
118
+ /**
119
+ * Tells whether the file is a virtual directory.
120
+ * <p>
121
+ * See {@link AzureFileSystemProvider#createDirectory(Path, FileAttribute[])} for more information on virtual and
122
+ * concrete directories.
123
+ *
124
+ * @return whether the file is a virtual directory
125
+ */
126
+ public boolean isVirtualDirectory () {
127
+ return this .internalAttributes .isVirtualDirectory ();
120
128
}
121
129
122
130
/**
@@ -126,7 +134,7 @@ public boolean isDirectory() {
126
134
*/
127
135
@ Override
128
136
public boolean isSymbolicLink () {
129
- return false ;
137
+ return this . internalAttributes . isSymbolicLink () ;
130
138
}
131
139
132
140
/**
@@ -136,7 +144,7 @@ public boolean isSymbolicLink() {
136
144
*/
137
145
@ Override
138
146
public boolean isOther () {
139
- return false ;
147
+ return this . internalAttributes . isOther () ;
140
148
}
141
149
142
150
/**
@@ -146,7 +154,7 @@ public boolean isOther() {
146
154
*/
147
155
@ Override
148
156
public long size () {
149
- return properties . getBlobSize ();
157
+ return this . internalAttributes . size ();
150
158
}
151
159
152
160
/**
@@ -156,6 +164,6 @@ public long size() {
156
164
*/
157
165
@ Override
158
166
public Object fileKey () {
159
- return this .resource . getBlobClient (). getBlobUrl ();
167
+ return this .internalAttributes . fileKey ();
160
168
}
161
169
}
0 commit comments