54
54
import stroom .ui .config .shared .SourceConfig ;
55
55
import stroom .util .NullSafe ;
56
56
import stroom .util .date .DateUtil ;
57
+ import stroom .util .io .FileUtil ;
57
58
import stroom .util .io .StreamUtil ;
59
+ import stroom .util .io .TempDirProvider ;
58
60
import stroom .util .logging .LambdaLogger ;
59
61
import stroom .util .logging .LambdaLoggerFactory ;
60
62
import stroom .util .logging .LogUtil ;
65
67
import stroom .util .shared .ResourceGeneration ;
66
68
import stroom .util .shared .ResourceKey ;
67
69
import stroom .util .shared .ResultPage ;
70
+ import stroom .util .zip .ZipUtil ;
68
71
69
72
import jakarta .inject .Inject ;
70
73
import jakarta .inject .Provider ;
71
74
75
+ import java .io .IOException ;
76
+ import java .nio .file .Files ;
72
77
import java .nio .file .Path ;
73
78
import java .text .NumberFormat ;
74
79
import java .util .ArrayList ;
75
80
import java .util .Collections ;
76
81
import java .util .List ;
77
82
import java .util .Map ;
78
83
import java .util .Set ;
84
+ import java .util .UUID ;
79
85
import java .util .stream .Collectors ;
86
+ import java .util .stream .Stream ;
80
87
81
88
class DataServiceImpl implements DataService {
82
89
@@ -88,6 +95,7 @@ class DataServiceImpl implements DataService {
88
95
private final DocRefInfoService docRefInfoService ;
89
96
private final MetaService metaService ;
90
97
private final AttributeMapFactory attributeMapFactory ;
98
+ private final TempDirProvider tempDirProvider ;
91
99
private final SecurityContext securityContext ;
92
100
private final FeedStore feedStore ;
93
101
@@ -115,7 +123,8 @@ class DataServiceImpl implements DataService {
115
123
final PipelineDataCache pipelineDataCache ,
116
124
final PipelineScopeRunnable pipelineScopeRunnable ,
117
125
final SourceConfig sourceConfig ,
118
- final TaskContextFactory taskContextFactory ) {
126
+ final TaskContextFactory taskContextFactory ,
127
+ final TempDirProvider tempDirProvider ) {
119
128
120
129
this .resourceStore = resourceStore ;
121
130
this .dataUploadTaskHandlerProvider = dataUploadTaskHandler ;
@@ -125,6 +134,7 @@ class DataServiceImpl implements DataService {
125
134
this .attributeMapFactory = attributeMapFactory ;
126
135
this .securityContext = securityContext ;
127
136
this .feedStore = feedStore ;
137
+ this .tempDirProvider = tempDirProvider ;
128
138
129
139
this .dataFetcher = new DataFetcher (streamStore ,
130
140
feedProperties ,
@@ -148,28 +158,53 @@ public ResourceGeneration download(final FindMetaCriteria criteria) {
148
158
return securityContext .secureResult (AppPermission .EXPORT_DATA_PERMISSION , () -> {
149
159
// Import file.
150
160
final ResourceKey resourceKey = resourceStore .createTempFile ("StroomData.zip" );
151
- final Path file = resourceStore .getTempFile (resourceKey );
152
- String fileName = file .getFileName ().toString ();
153
- int index = fileName .lastIndexOf ("." );
154
- if (index != -1 ) {
155
- fileName = fileName .substring (0 , index );
156
- }
161
+ final Path tempFile = resourceStore .getTempFile (resourceKey );
162
+ final Path outputDir = tempDirProvider .get ().resolve (UUID .randomUUID ().toString ());
163
+ try {
164
+ final DataDownloadSettings settings = new DataDownloadSettings ();
165
+ final DataDownloadResult result = dataDownloadTaskHandlerProvider .downloadData (
166
+ criteria ,
167
+ outputDir ,
168
+ "data" ,
169
+ settings );
170
+
171
+ if (result .getRecordsWritten () == 0 ) {
172
+ if (result .getMessageList () != null && !result .getMessageList ().isEmpty ()) {
173
+ throw new RuntimeException ("Download failed with errors: " +
174
+ result .getMessageList ().stream ()
175
+ .map (Message ::getMessage )
176
+ .collect (Collectors .joining (", " )));
177
+ }
178
+ }
179
+
180
+ try {
181
+ // Find out how many files were written.
182
+ final List <Path > list ;
183
+ try (final Stream <Path > stream = Files .list (outputDir )) {
184
+ list = stream .toList ();
185
+ }
157
186
158
- final DataDownloadSettings settings = new DataDownloadSettings ();
159
- final DataDownloadResult result = dataDownloadTaskHandlerProvider .downloadData (criteria ,
160
- file .getParent (),
161
- fileName ,
162
- settings );
163
-
164
- if (result .getRecordsWritten () == 0 ) {
165
- if (result .getMessageList () != null && !result .getMessageList ().isEmpty ()) {
166
- throw new RuntimeException ("Download failed with errors: " +
167
- result .getMessageList ().stream ()
168
- .map (Message ::getMessage )
169
- .collect (Collectors .joining (", " )));
187
+ if (list .size () == 1 ) {
188
+ // If we have only 1 file then just move it to the temp file.
189
+ Files .move (list .getFirst (), tempFile );
190
+ } else if (list .size () > 1 ) {
191
+ // If we have more than 1 file then zip them all.
192
+ ZipUtil .zip (tempFile , outputDir );
193
+ } else {
194
+ throw new RuntimeException ("Download failed with no files written" );
195
+ }
196
+ } catch (final IOException e ) {
197
+ throw new RuntimeException ("Download failed with errors: " + e .getMessage ());
198
+ }
199
+
200
+ return new ResourceGeneration (resourceKey , result .getMessageList ());
201
+ } finally {
202
+ try {
203
+ FileUtil .deleteDir (outputDir );
204
+ } catch (final RuntimeException e ) {
205
+ LOGGER .error (e ::getMessage , e );
170
206
}
171
207
}
172
- return new ResourceGeneration (resourceKey , result .getMessageList ());
173
208
});
174
209
}
175
210
@@ -191,11 +226,11 @@ public ResourceKey upload(final UploadDataRequest request) {
191
226
return securityContext .secureResult (AppPermission .IMPORT_DATA_PERMISSION , () -> {
192
227
try {
193
228
// Import file.
194
- final Path file = resourceStore .getTempFile (request .getKey ());
229
+ final Path tempFile = resourceStore .getTempFile (request .getKey ());
195
230
196
231
dataUploadTaskHandlerProvider .uploadData (
197
232
request .getFileName (),
198
- file ,
233
+ tempFile ,
199
234
request .getFeedName (),
200
235
request .getStreamTypeName (),
201
236
request .getEffectiveMs (),
@@ -245,10 +280,10 @@ public List<DataInfoSection> info(final long id) {
245
280
sortedKeys .forEach (key -> {
246
281
final String value = attributeMap .get (key );
247
282
if (value != null &&
248
- // We are going to add retention entries separately.
249
- !DataRetentionFields .RETENTION_AGE .equals (key ) &&
250
- !DataRetentionFields .RETENTION_UNTIL .equals (key ) &&
251
- !DataRetentionFields .RETENTION_RULE .equals (key )) {
283
+ // We are going to add retention entries separately.
284
+ !DataRetentionFields .RETENTION_AGE .equals (key ) &&
285
+ !DataRetentionFields .RETENTION_UNTIL .equals (key ) &&
286
+ !DataRetentionFields .RETENTION_RULE .equals (key )) {
252
287
253
288
if (MetaFields .DURATION .getFldName ().equals (key )) {
254
289
entries .add (new DataInfoSection .Entry (key , convertDuration (value )));
@@ -323,10 +358,7 @@ private String convertDuration(final String value) {
323
358
private String convertTime (final String value ) {
324
359
try {
325
360
long valLong = Long .parseLong (value );
326
- return DateUtil .createNormalDateTimeString (valLong )
327
- + " ("
328
- + valLong
329
- + ")" ;
361
+ return DateUtil .createNormalDateTimeString (valLong ) + " (" + valLong + ")" ;
330
362
} catch (RuntimeException e ) {
331
363
// Ignore.
332
364
}
@@ -338,10 +370,7 @@ private String convertSize(final String value) {
338
370
final long valLong = Long .parseLong (value );
339
371
final String iecByteSizeStr = ModelStringUtil .formatIECByteSizeString (valLong );
340
372
if (valLong >= 1024 ) {
341
- return iecByteSizeStr
342
- + " ("
343
- + NumberFormat .getIntegerInstance ().format (valLong )
344
- + ")" ;
373
+ return iecByteSizeStr + " (" + NumberFormat .getIntegerInstance ().format (valLong ) + ")" ;
345
374
} else {
346
375
return iecByteSizeStr ;
347
376
}
0 commit comments