@@ -8,6 +8,9 @@ import com.intellij.openapi.fileTypes.FileTypeRegistry
8
8
import com.intellij.openapi.util.io.FileUtilRt
9
9
import com.intellij.ui.treeStructure.SimpleNode
10
10
import kotlinx.coroutines.runBlocking
11
+ import software.aws.toolkits.core.utils.error
12
+ import software.aws.toolkits.core.utils.getLogger
13
+ import software.aws.toolkits.jetbrains.core.utils.buildList
11
14
import software.aws.toolkits.jetbrains.services.s3.NOT_VERSIONED_VERSION_ID
12
15
import software.aws.toolkits.resources.message
13
16
import java.time.Instant
@@ -61,8 +64,12 @@ abstract class S3LazyLoadParentNode<T>(bucket: S3VirtualBucket, parent: S3LazyLo
61
64
return
62
65
}
63
66
64
- loadedPages.add(continuationMarker)
65
- cachedList = children.dropLastWhile { it is S3TreeContinuationNode <* > } + loadObjects(continuationMarker)
67
+ val more = loadObjects(continuationMarker)
68
+ // Only say it has loaded before if it loaded successfully
69
+ if (more.none { it is S3TreeErrorNode || it is S3TreeErrorContinuationNode <* > }) {
70
+ loadedPages.add(continuationMarker)
71
+ }
72
+ cachedList = children.dropLastWhile { it is S3TreeContinuationNode <* > || it is S3TreeErrorNode } + more
66
73
}
67
74
}
68
75
@@ -77,26 +84,41 @@ class S3TreeDirectoryNode(bucket: S3VirtualBucket, parent: S3TreeDirectoryNode?,
77
84
override fun directoryPath (): String = key
78
85
79
86
override fun loadObjects (continuationMarker : String? ): List <S3TreeNode > {
80
- val response = runBlocking {
81
- bucket.listObjects(key, continuationMarker)
82
- }
83
-
84
- val continuation = listOfNotNull(
85
- response.nextContinuationToken()?.let {
86
- S3TreeContinuationNode (bucket, this , this .key, it)
87
+ try {
88
+ val response = runBlocking {
89
+ bucket.listObjects(key, continuationMarker)
87
90
}
88
- )
89
-
90
- val folders = response.commonPrefixes()?.map { S3TreeDirectoryNode (bucket, this , it.prefix()) } ? : emptyList()
91
91
92
- val s3Objects = response
93
- .contents()
94
- ?.filterNotNull()
95
- ?.filterNot { it.key() == key }
96
- ?.map { S3TreeObjectNode (this , it.key(), it.size(), it.lastModified()) as S3TreeNode }
97
- ? : emptyList()
92
+ val continuation = listOfNotNull(
93
+ response.nextContinuationToken()?.let {
94
+ S3TreeContinuationNode (bucket, this , this .key, it)
95
+ }
96
+ )
97
+
98
+ val folders = response.commonPrefixes()?.map { S3TreeDirectoryNode (bucket, this , it.prefix()) } ? : emptyList()
99
+
100
+ val s3Objects = response
101
+ .contents()
102
+ ?.filterNotNull()
103
+ ?.filterNot { it.key() == key }
104
+ ?.map { S3TreeObjectNode (this , it.key(), it.size(), it.lastModified()) as S3TreeNode }
105
+ ? : emptyList()
106
+
107
+ return (folders + s3Objects).sortedBy { it.key } + continuation
108
+ } catch (e: Exception ) {
109
+ LOG .error(e) { " Loading objects failed!" }
110
+ return buildList {
111
+ if (continuationMarker != null ) {
112
+ add(S3TreeErrorContinuationNode (bucket, this @S3TreeDirectoryNode, this @S3TreeDirectoryNode.key, continuationMarker))
113
+ } else {
114
+ add(S3TreeErrorNode (bucket, this @S3TreeDirectoryNode))
115
+ }
116
+ }
117
+ }
118
+ }
98
119
99
- return (folders + s3Objects).sortedBy { it.key } + continuation
120
+ companion object {
121
+ private val LOG = getLogger<S3TreeDirectoryNode >()
100
122
}
101
123
}
102
124
@@ -129,12 +151,16 @@ class S3TreeObjectNode(parent: S3TreeDirectoryNode, key: String, override val si
129
151
override fun fileName () = key.substringAfterLast(" /" )
130
152
131
153
override fun loadObjects (continuationMarker : VersionContinuationToken ? ): List <S3TreeNode > {
132
- if (showHistory) {
154
+ if (! showHistory) {
155
+ return emptyList()
156
+ }
157
+
158
+ try {
133
159
val response = runBlocking {
134
160
bucket.listObjectVersions(key, continuationMarker?.keyMarker, continuationMarker?.versionId)
135
161
}
136
162
137
- return mutableListOf< S3TreeNode >(). apply {
163
+ return buildList {
138
164
response?.versions()
139
165
?.filter { it.key() == key && it.versionId() != NOT_VERSIONED_VERSION_ID }
140
166
?.map { S3TreeObjectVersionNode (this @S3TreeObjectNode, it.versionId(), it.size(), it.lastModified()) }
@@ -154,9 +180,27 @@ class S3TreeObjectNode(parent: S3TreeDirectoryNode, key: String, override val si
154
180
)
155
181
}
156
182
}
183
+ } catch (e: Exception ) {
184
+ LOG .error(e) { " Loading objects failed!" }
185
+ return buildList {
186
+ if (continuationMarker != null ) {
187
+ add(
188
+ S3TreeErrorContinuationNode (
189
+ bucket,
190
+ this @S3TreeObjectNode,
191
+ this @S3TreeObjectNode.key,
192
+ continuationMarker
193
+ )
194
+ )
195
+ } else {
196
+ add(S3TreeErrorNode (bucket, this @S3TreeObjectNode))
197
+ }
198
+ }
157
199
}
200
+ }
158
201
159
- return emptyList()
202
+ companion object {
203
+ private val LOG = getLogger<S3TreeObjectNode >()
160
204
}
161
205
}
162
206
@@ -190,7 +234,7 @@ class S3TreeObjectVersionNode(parent: S3TreeObjectNode, override val versionId:
190
234
override fun toString (): String = " S3TreeObjectVersionNode(key='$key ', versionId='$versionId ')"
191
235
}
192
236
193
- class S3TreeContinuationNode <T >(
237
+ open class S3TreeContinuationNode <T >(
194
238
bucket : S3VirtualBucket ,
195
239
private val parentNode : S3LazyLoadParentNode <T >,
196
240
key : String ,
@@ -208,3 +252,27 @@ class S3TreeContinuationNode<T>(
208
252
209
253
override fun getEqualityObjects (): Array <Any ?> = arrayOf(bucket, key, continuationMarker)
210
254
}
255
+
256
+ class S3TreeErrorContinuationNode <T >(
257
+ bucket : S3VirtualBucket ,
258
+ parentNode : S3LazyLoadParentNode <T >,
259
+ key : String ,
260
+ continuationMarker : T
261
+ ) : S3TreeContinuationNode<T>(bucket, parentNode, key, continuationMarker) {
262
+ init {
263
+ icon = AllIcons .General .Error
264
+ }
265
+
266
+ override fun displayName (): String = message(" s3.load_more_failed" )
267
+ }
268
+
269
+ class S3TreeErrorNode (
270
+ bucket : S3VirtualBucket ,
271
+ parentNode : S3LazyLoadParentNode <* >
272
+ ) : S3TreeNode(bucket, parentNode, " ${parentNode.key} error" ) {
273
+ init {
274
+ icon = AllIcons .General .Error
275
+ }
276
+
277
+ override fun displayName (): String = message(" s3.error_loading" )
278
+ }
0 commit comments