• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IQSS / dataverse / #24529

11 Feb 2025 10:59PM CUT coverage: 22.702% (-0.05%) from 22.749%
#24529

Pull #11193

github

GPortas
Removed: logs from AuthenticationServiceBean
Pull Request #11193: Keycloak SPI for Builtin Users Authentication

0 of 5 new or added lines in 2 files covered. (0.0%)

269 existing lines in 4 files now uncovered.

19910 of 87701 relevant lines covered (22.7%)

0.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.82
/src/main/java/edu/harvard/iq/dataverse/dataaccess/FileAccessIO.java
1
/*
2
   Copyright (C) 2005-2012, by the President and Fellows of Harvard College.
3

4
   Licensed under the Apache License, Version 2.0 (the "License");
5
   you may not use this file except in compliance with the License.
6
   You may obtain a copy of the License at
7

8
         http://www.apache.org/licenses/LICENSE-2.0
9

10
   Unless required by applicable law or agreed to in writing, software
11
   distributed under the License is distributed on an "AS IS" BASIS,
12
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
   See the License for the specific language governing permissions and
14
   limitations under the License.
15

16
   Dataverse Network - A web application to share, preserve and analyze research data.
17
   Developed at the Institute for Quantitative Social Science, Harvard University.
18
   Version 3.0.
19
*/
20

21
package edu.harvard.iq.dataverse.dataaccess;
22

23
// java core imports:
24
import java.io.IOException;
25
import java.io.File;
26
import java.io.InputStream;
27
import java.io.OutputStream; 
28
import java.io.FileInputStream;
29
import java.io.FileOutputStream;
30
// NIO imports: 
31
import java.nio.file.Files;
32
import java.nio.file.InvalidPathException;
33
import java.nio.file.Path;
34
import java.nio.file.Paths;
35
import java.util.List;
36
import java.util.function.Predicate;
37
import java.util.logging.Logger;
38
import java.util.stream.Collectors;
39

40
// Dataverse imports:
41
import edu.harvard.iq.dataverse.DataFile;
42
import edu.harvard.iq.dataverse.Dataset;
43
import edu.harvard.iq.dataverse.Dataverse;
44
import edu.harvard.iq.dataverse.DvObject;
45
import edu.harvard.iq.dataverse.datavariable.DataVariable;
46
import java.io.FileNotFoundException;
47
import java.nio.channels.Channel;
48
import java.nio.file.DirectoryStream;
49
import java.nio.file.StandardCopyOption;
50
import java.util.ArrayList;
51

52

53
public class FileAccessIO<T extends DvObject> extends StorageIO<T> {
54

55
    private static final Logger logger = Logger.getLogger("edu.harvard.iq.dataverse.dataaccess.FileAccessIO");
1✔
56
    public static final String DIRECTORY = "directory";
57

58

59
    public FileAccessIO() {
60
        // Constructor only for testing
61
        super(null, null, null);
1✔
62
    }
1✔
63

64
    public FileAccessIO(T dvObject, DataAccessRequest req, String driverId ) {
65

66
        super(dvObject, req, driverId);
1✔
67

68
        this.setIsLocalFile(true);
1✔
69
    }
1✔
70
    
71
    // "Direct" File Access IO, opened on a physical file not associated with
72
    // a specific DvObject
73
    public FileAccessIO(String storageLocation, String driverId) {
74
        super(storageLocation, driverId);
1✔
75
        this.setIsLocalFile(true);
1✔
76
        logger.fine("Storage path: " + storageLocation);
1✔
77
        physicalPath = Paths.get(storageLocation);
1✔
78
    }
1✔
79
    
80
    private Path physicalPath = null; 
1✔
81
    
82
    @Override
83
    public void open (DataAccessOption... options) throws IOException {
84
        DataFile dataFile;
85
        Dataset dataset;
86
        Dataverse dataverse = null;
1✔
87
        DataAccessRequest req = this.getRequest();
1✔
88
        
89
        if (isWriteAccessRequested(options)) {
1✔
90
            isWriteAccess = true;
1✔
91
            isReadAccess = false;
1✔
92
        } else {
93
            isWriteAccess = false;
1✔
94
            isReadAccess = true;
1✔
95
        }
96
        
97
        if (dvObject instanceof DataFile) {
1✔
98
            dataFile = this.getDataFile();
1✔
99
            String storageIdentifier = dataFile.getStorageIdentifier();
1✔
100
            if (req != null && req.getParameter("noVarHeader") != null) {
1✔
101
                this.setNoVarHeader(true);
×
102
            }
103

104
            if (storageIdentifier == null || "".equals(storageIdentifier)) {
1✔
105
                throw new IOException("Data Access: No local storage identifier defined for this datafile.");
×
106
            }
107

108
            if (isReadAccess) {
1✔
109
                FileInputStream fin = openLocalFileAsInputStream();
1✔
110

111
                if (fin == null) {
1✔
112
                    throw new IOException ("Failed to open local file "+getStorageLocation());
1✔
113
                }
114

115
                this.setInputStream(fin);
1✔
116
                setChannel(fin.getChannel());
1✔
117
                this.setSize(retrieveSizeFromMedia());
1✔
118

119
                if (dataFile.getContentType() != null
1✔
120
                        && dataFile.getContentType().equals("text/tab-separated-values")
1✔
121
                        && dataFile.isTabularData()
×
122
                        && dataFile.getDataTable() != null
×
123
                        && (!this.noVarHeader())
×
124
                        && (!dataFile.getDataTable().isStoredWithVariableHeader())) {
×
125

126
                    List<DataVariable> datavariables = dataFile.getDataTable().getDataVariables();
×
127
                    String varHeaderLine = generateVariableHeader(datavariables);
×
128
                    this.setVarHeader(varHeaderLine);
×
129
                }
130
            } else if (isWriteAccess) {
1✔
131
                // Creates a new directory as needed for a dataset.
132
                Path datasetPath=Paths.get(getDatasetDirectory());
×
133
                if (datasetPath != null && !Files.exists(datasetPath)) {
×
134
                    Files.createDirectories(datasetPath);
×
135
                }
136
                FileOutputStream fout = openLocalFileAsOutputStream();
×
137

138
                if (fout == null) {
×
139
                    throw new IOException ("Failed to open local file "+getStorageLocation()+" for writing.");
×
140
                }
141

142
                this.setOutputStream(fout);
×
143
                setChannel(fout.getChannel());
×
144
                if (!storageIdentifier.startsWith(this.driverId + DataAccess.SEPARATOR)) {
×
145
                    dvObject.setStorageIdentifier(this.driverId + DataAccess.SEPARATOR + storageIdentifier);
×
146
                }
147
            }
148

149
            this.setMimeType(dataFile.getContentType());
1✔
150

151
            try {
152
                this.setFileName(dataFile.getFileMetadata().getLabel());
1✔
153
            } catch (Exception ex) {
×
154
                this.setFileName("unknown");
×
155
            }
1✔
156
        } else if (dvObject instanceof Dataset) {
1✔
157
            //This case is for uploading a dataset related auxiliary file 
158
            //e.g. image thumbnails/metadata exports
159
            dataset = this.getDataset();
1✔
160
            if (isReadAccess) {
1✔
161
                //TODO: Not necessary for dataset as there is no files associated with this
162
              //  FileInputStream fin = openLocalFileAsInputStream();
163
//                Path path= dataset.getFileSystemDirectory();                    
164
//                if (path == null) {
165
//                    throw new IOException("Failed to locate Dataset"+dataset.getIdentifier());
166
//                }
167
//
168
//                this.setInputStream(fin);  
169
              } else if (isWriteAccess) {
1✔
170
                //this checks whether a directory for a dataset exists 
171
                  Path datasetPath=Paths.get(getDatasetDirectory());
1✔
172
                  if (datasetPath != null && !Files.exists(datasetPath)) {
1✔
173
                      Files.createDirectories(datasetPath);
1✔
174
                  }
175
                dataset.setStorageIdentifier(this.driverId + DataAccess.SEPARATOR + dataset.getAuthorityForFileStorage() + "/" + dataset.getIdentifierForFileStorage());
1✔
176
            }
1✔
177

178
        } else if (dvObject instanceof Dataverse) {
1✔
179
            dataverse = this.getDataverse();
×
180
        } else {
181
            logger.fine("Overlay case: FileAccessIO open for : " + physicalPath.toString());
1✔
182
            Path datasetPath= physicalPath.getParent();
1✔
183
            if (datasetPath != null && !Files.exists(datasetPath)) {
1✔
184
                Files.createDirectories(datasetPath);
1✔
185
            }
186
            //throw new IOException("Data Access: Invalid DvObject type");
187
        }
188
        // This "status" is a leftover from 3.6; we don't have a use for it 
189
        // in 4.0 yet; and we may not need it at all. 
190
        // -- L.A. 4.0.2
191
        /*this.setStatus(200);*/
192
    }
1✔
193
    
194
    @Override
195
    public void savePath(Path fileSystemPath) throws IOException {
196
        
197
        // Since this is a local fileystem file, we can use the
198
        // quick NIO Files.copy method: 
199
        
200
        Path outputPath = getFileSystemPath();
1✔
201

202
        if (outputPath == null) {
1✔
203
            throw new FileNotFoundException("FileAccessIO: Could not locate aux file for writing.");
×
204
        }
205
        Files.copy(fileSystemPath, outputPath, StandardCopyOption.REPLACE_EXISTING);
1✔
206
        long newFileSize = outputPath.toFile().length();
1✔
207

208
        // if it has worked successfully, we also need to reset the size
209
        // of the object. 
210
        setSize(newFileSize);
1✔
211
    }
1✔
212
    
213
    @Override
214
    public void saveInputStream(InputStream inputStream, Long filesize) throws IOException {
215
        saveInputStream(inputStream);
×
216
    }
×
217
    
218
    @Override
219
    public void saveInputStream(InputStream inputStream) throws IOException {
220
        // Since this is a local fileystem file, we can use the
221
        // quick NIO Files.copy method: 
222

223
        File outputFile = getFileSystemPath().toFile();
1✔
224

225
        if (outputFile == null) {
1✔
226
            throw new FileNotFoundException("FileAccessIO: Could not locate file for writing.");
×
227
        }
228
        
229
        try (OutputStream outputStream = new FileOutputStream(outputFile)) {
1✔
230
            int read;
231
            byte[] bytes = new byte[1024];
1✔
232
            while ((read = inputStream.read(bytes)) != -1) {
1✔
233
                outputStream.write(bytes, 0, read);
1✔
234
            }
235
        }
236
        inputStream.close();
1✔
237

238
        // if it has worked successfully, we also need to reset the size
239
        // of the object. 
240
        setSize(outputFile.length());
1✔
241
    }
1✔
242
    
243
    @Override
244
    public Channel openAuxChannel(String auxItemTag, DataAccessOption... options) throws IOException {
245
      
246
        Path auxPath = getAuxObjectAsPath(auxItemTag);
1✔
247

248
        if (isWriteAccessRequested(options)) {
1✔
249
            if (((dvObject instanceof Dataset) || isDirectAccess()) && !this.canWrite()) {
×
250
                // If this is a dataset-level auxilary file (a cached metadata export,
251
                // dataset logo, etc.) there's a chance that no "real" files 
252
                // have been saved for this dataset yet, and thus the filesystem 
253
                // directory does not exist yet. Let's force a proper .open() on 
254
                // this StorageIO, that will ensure it is created:
255
                open(DataAccessOption.WRITE_ACCESS);
×
256
            }
257

258
            FileOutputStream auxOut = new FileOutputStream(auxPath.toFile());
×
259

260
            if (auxOut == null) {
×
261
                throw new IOException("Failed to open Auxiliary File " + dvObject.getStorageIdentifier() + "." + auxItemTag + " for writing.");
×
262
            }
263

264
            return auxOut.getChannel();
×
265
        }
266
        
267
        // Read access requested.
268
        // Check if this Aux object is cached; and if so, open for reading:
269

270
        if (!auxPath.toFile().exists()) {
1✔
271
            throw new FileNotFoundException("Auxiliary File " + dvObject.getStorageIdentifier() + "." + auxItemTag + " does not exist.");
×
272
        }
273

274
        FileInputStream auxIn = new FileInputStream(auxPath.toFile());
1✔
275

276
        if (auxIn == null) {
1✔
277
            throw new IOException("Failed to open Auxiliary File " + dvObject.getStorageIdentifier() + "." + auxItemTag + " for reading");
×
278
        }
279

280
        return auxIn.getChannel();
1✔
281

282
    }
283
    
284
    @Override
285
    public boolean isAuxObjectCached(String auxItemTag) throws IOException {
286
        // Check if the file exists:
287
        
288
        Path auxPath = getAuxObjectAsPath(auxItemTag);
1✔
289
        
290
        return auxPath.toFile().exists();
1✔
291
    }
292
    
293
    @Override
294
    public long getAuxObjectSize(String auxItemTag) throws IOException {
295
        Path auxPath = getAuxObjectAsPath(auxItemTag);
1✔
296
        
297
        if (!auxPath.toFile().exists()) {
1✔
298
            throw new FileNotFoundException ("Aux file does not exist.");
×
299
        }
300
        
301
        return auxPath.toFile().length();
1✔
302
    }
303
    
304
    @Override
305
    public Path getAuxObjectAsPath(String auxItemTag) throws IOException {
306

307
        if (auxItemTag == null || "".equals(auxItemTag)) {
1✔
308
            throw new IOException("Null or invalid Auxiliary Object Tag.");
×
309
        }
310
        if(isDirectAccess()) {
1✔
311
            //includes overlay case
312
            return Paths.get(physicalPath.toString() + "." + auxItemTag);
1✔
313
        }
314
        String datasetDirectory = getDatasetDirectory();
1✔
315
        
316
        if (dvObject.getStorageIdentifier() == null || "".equals(dvObject.getStorageIdentifier())) {
1✔
317
            throw new IOException("Data Access: No local storage identifier defined for this datafile.");
×
318
        }
319
        Path auxPath = null;
1✔
320
        if (dvObject instanceof DataFile) {
1✔
321
            auxPath = Paths.get(datasetDirectory, stripDriverId(dvObject.getStorageIdentifier()) + "." + auxItemTag);
1✔
322
        } else if (dvObject instanceof Dataset) {
1✔
323
            auxPath = Paths.get(datasetDirectory, auxItemTag);
1✔
324
        } else if (dvObject instanceof Dataverse) {
×
325
        } else {
326
            throw new IOException("Aux path could not be generated for " + auxItemTag);
×
327
        } 
328
        
329
        if (auxPath == null) {
1✔
330
            throw new IOException("Invalid Path location for the auxiliary file " + dvObject.getStorageIdentifier() + "." + auxItemTag);
×
331
        }
332
        
333
        return auxPath;
1✔
334
    }
335
    
336

337
    @Override 
338
    public void backupAsAux(String auxItemTag) throws IOException {
339
        Path auxPath = getAuxObjectAsPath(auxItemTag);
1✔
340
        
341
        Files.move(getFileSystemPath(), auxPath, StandardCopyOption.REPLACE_EXISTING);
1✔
342
    }
1✔
343
    
344
    @Override 
345
    public void revertBackupAsAux(String auxItemTag) throws IOException {
346
        Path auxPath = getAuxObjectAsPath(auxItemTag);
×
347
        Files.move(auxPath, getFileSystemPath(), StandardCopyOption.REPLACE_EXISTING);
×
348
    }
×
349
    
350
    // this method copies a local filesystem Path into this DataAccess Auxiliary location:
351
    @Override
352
    public void savePathAsAux(Path fileSystemPath, String auxItemTag) throws IOException {
353
        if (dvObject instanceof Dataset && !this.canWrite()) {
1✔
354
            // see the comment in openAuxChannel()
355
            open(DataAccessOption.WRITE_ACCESS);
1✔
356
        }
357
        // quick Files.copy method: 
358
        try {
359
            Path auxPath = getAuxObjectAsPath(auxItemTag);
1✔
360
            Files.copy(fileSystemPath, auxPath, StandardCopyOption.REPLACE_EXISTING);
1✔
361
        } catch (IOException ex) {
×
362
        }
1✔
363
    }
1✔
364
    
365
    @Override
366
    public void saveInputStreamAsAux(InputStream inputStream, String auxItemTag, Long filesize) throws IOException {
367
        saveInputStreamAsAux(inputStream, auxItemTag);
×
368
    }
×
369
    
370
    @Override
371
    public void saveInputStreamAsAux(InputStream inputStream, String auxItemTag) throws IOException {
372
        if (dvObject instanceof Dataset && !this.canWrite()) {
1✔
373
            // see the comment in openAuxChannel()
374
            open(DataAccessOption.WRITE_ACCESS);
1✔
375
        }
376
        // Since this is a local fileystem file, we can use the
377
        // quick NIO Files.copy method: 
378

379
        File outputFile = getAuxObjectAsPath(auxItemTag).toFile();
1✔
380

381
        if (outputFile == null) {
1✔
382
            throw new FileNotFoundException("FileAccessIO: Could not locate aux file for writing.");
×
383
        }
384
        
385
        try (OutputStream outputStream = new FileOutputStream(outputFile)) {
1✔
386
            int read;
387
            byte[] bytes = new byte[1024];
1✔
388
            while ((read = inputStream.read(bytes)) != -1) {
1✔
389
                outputStream.write(bytes, 0, read);
1✔
390
            }
391
        }
392
        inputStream.close();
1✔
393
    }
1✔
394
    
395
    @Override
396
    public List<String>listAuxObjects() throws IOException {
397
        if (this.getDataFile() == null) {
1✔
398
            throw new IOException("This FileAccessIO object hasn't been properly initialized.");
×
399
        }
400
        
401
        List<Path> cachedFiles = listCachedFiles();
1✔
402
        
403
        if (cachedFiles == null) {
1✔
404
            return null;
×
405
        }
406
        
407
        List<String> cachedFileNames = new ArrayList<>();
1✔
408
        String baseName = stripDriverId(this.getDataFile().getStorageIdentifier()) + ".";
1✔
409
        for (Path auxPath : cachedFiles) {
1✔
410
            cachedFileNames.add(auxPath.getFileName().toString().substring(baseName.length()));
×
411
        }
×
412
        
413
        return cachedFileNames;
1✔
414
    }
415
    
416
    @Override
417
    public void deleteAuxObject(String auxItemTag) throws IOException {
418
        Path auxPath = getAuxObjectAsPath(auxItemTag);
1✔
419
        Files.delete(auxPath);
1✔
420
    }
1✔
421
    
422
    @Override
423
    public void deleteAllAuxObjects() throws IOException {
424
        List<Path> cachedFiles = listCachedFiles();
1✔
425
        
426
        if (cachedFiles == null) {
1✔
427
            return;
×
428
        }
429
        
430
        for (Path auxPath : cachedFiles) {
1✔
431
            Files.delete(auxPath);
×
432
        }
×
433
        
434
    }
1✔
435

436

437
    @Override
438
    public String getStorageLocation() {
439
        // For a local file, the "storage location" is a complete, absolute
440
        // filesystem path, with the "<driverId>://" prefix:
441
        
442
        try {
443
            Path testPath = getFileSystemPath();
1✔
444
            if (testPath != null) {
1✔
445
                return this.driverId + DataAccess.SEPARATOR + testPath.toString();
1✔
446
            }
447
        } catch (IOException ioex) {
×
448
            // just return null, below:
449
        }
×
450

451
        return null; 
×
452
    }
453
    
454
    @Override
455
    public Path getFileSystemPath() throws IOException {
456
        if (physicalPath != null) {
1✔
457
            return physicalPath;
1✔
458
        }
459
        
460
        String datasetDirectory = getDatasetDirectory(); 
1✔
461
        
462
        if (dvObject.getStorageIdentifier() == null || "".equals(dvObject.getStorageIdentifier())) {
1✔
463
            throw new IOException("Data Access: No local storage identifier defined for this datafile.");
×
464
        }
465

466
        physicalPath = Paths.get(datasetDirectory, stripDriverId(dvObject.getStorageIdentifier()));
1✔
467
        return physicalPath;
1✔
468

469
    }
470
    
471
    @Override
472
    public boolean exists() throws IOException {
473
        if (getFileSystemPath() == null) {
1✔
474
            throw new FileNotFoundException("FileAccessIO: invalid Access IO object.");
×
475
        }
476
        
477
        return getFileSystemPath().toFile().exists();
1✔
478
    }
479
    
480
    /*@Override
481
    public void delete() throws IOException {
482
        Path victim = getFileSystemPath();
483
        
484
        if (victim != null) {
485
            Files.delete(victim);
486
        } else {
487
            throw new IOException("Could not locate physical file location for the Filesystem object.");
488
        }
489
    }*/
490
    
491
    @Override
492
    public void delete() throws IOException {
493
        if (!isDirectAccess()) {
×
494
            throw new IOException("Direct Access IO must be used to permanently delete stored file objects");
×
495
        }
496

497
        if (physicalPath == null) {
×
498
            throw new IOException("Attempted delete on an unspecified physical path");
×
499
        }
500
        
501
        deleteAllAuxObjects();
×
502
        
503
        Files.delete(physicalPath);
×
504

505
    }
×
506
    
507
    // Auxilary helper methods, filesystem access-specific:
508
    
509
    public FileInputStream openLocalFileAsInputStream () {
510
        FileInputStream in;
511

512
        try {
513
            in = new FileInputStream(getFileSystemPath().toFile());
1✔
514
        } catch (IOException ex) {
1✔
515
            // We don't particularly care what the reason why we have
516
            // failed to access the file was.
517
            // From the point of view of the download subsystem, it's a
518
            // binary operation -- it's either successfull or not.
519
            // If we can't access it for whatever reason, we are saying
520
            // it's 404 NOT FOUND in our HTTP response.
521
            // TODO: no, we should probably provide some kind of diagnostics. 
522
            // -- L.A. 4.0.2
523
            return null;
1✔
524
        }
1✔
525

526
        return in;
1✔
527
    }
528
    
529
    public FileOutputStream openLocalFileAsOutputStream () {
530
        FileOutputStream out;
531

532
        try {
533
            out = new FileOutputStream(getFileSystemPath().toFile());
1✔
534
        } catch (IOException ex) {
×
535
            // We don't particularly care what the reason why we have
536
            // failed to access the file was.
537
            // From the point of view of the download subsystem, it's a
538
            // binary operation -- it's either successfull or not.
539
            // If we can't access it for whatever reason, we are saying
540
            // it's 404 NOT FOUND in our HTTP response.
541
            // TODO: no, we should probably provide some kind of diagnostics. 
542
            // -- L.A. 4.0.2
543
            return null;
×
544
        }
1✔
545

546
        return out;
1✔
547
    }
548
    
549
    private String getDatasetDirectory() throws IOException {
550
        if (isDirectAccess()) {
1✔
551
            throw new IOException("No DvObject defined in the Data Access Object");
×
552
        }
553
        
554
        String authorityForFS = null;
1✔
555
        String identifierForFS = null;
1✔
556
        if (dvObject instanceof Dataset) {
1✔
557
            authorityForFS = this.getDataset().getAuthorityForFileStorage();
1✔
558
            identifierForFS = this.getDataset().getIdentifierForFileStorage();
1✔
559
        } else if (dvObject instanceof DataFile) {
1✔
560
            authorityForFS = this.getDataFile().getOwner().getAuthorityForFileStorage();
1✔
561
            identifierForFS = this.getDataFile().getOwner().getIdentifierForFileStorage();
1✔
562
        } else if (dvObject instanceof Dataverse) {
×
563
            throw new IOException("FileAccessIO: Dataverses are not a supported dvObject");
×
564
        }
565
        
566
        if (authorityForFS == null || identifierForFS == null) {
1✔
567
            throw new IOException("Could not determine the filesystem directory of the parent dataset.");
×
568
        }
569
        
570
        // Determine the final directory tree. As of JDK 16, the first component of the path MUST be non-null
571
        // (we check for that via the setting), but also the others make no sense if they are null.
572
        String datasetDirectory = Paths.get(getFilesRootDirectory(), authorityForFS, identifierForFS).toString();
1✔
573

574
        if (dvObject.getStorageIdentifier() == null || dvObject.getStorageIdentifier().isEmpty()) {
1✔
575
            throw new IOException("Data Access: No local storage identifier defined for this datafile.");
×
576
        }
577

578
        return datasetDirectory;
1✔
579
    }
580
    
581
    
582
    protected String getFilesRootDirectory() {
583
        String filesRootDirectory = getConfigParam(DIRECTORY, "/tmp/files");
1✔
584
        return filesRootDirectory;
1✔
585
    }
586
    
587
    private List<Path> listCachedFiles() throws IOException {
588
        List<Path> auxItems = new ArrayList<>();
1✔
589

590
        // cached files for a given datafiles are stored on the filesystem
591
        // as <filesystemname>.*; for example, <filename>.thumb64 or 
592
        // <filename>.RData.
593
        
594
        String baseName; 
595
        Path datasetDirectoryPath; 
596
        
597
        if (isDirectAccess()) {
1✔
598
            baseName = physicalPath.getFileName().toString();
×
599
            datasetDirectoryPath = physicalPath.getParent();
×
600
            
601
        } else {
602
            if (this.getDataFile() == null || this.getDataFile().getStorageIdentifier() == null || this.getDataFile().getStorageIdentifier().isEmpty()) {
1✔
603
                throw new IOException("Null or invalid DataFile in FileAccessIO object.");
×
604
            }
605
        
606
            baseName = stripDriverId(this.getDataFile().getStorageIdentifier());
1✔
607

608
            datasetDirectoryPath = Paths.get(getDatasetDirectory());
1✔
609
        }
610

611
        if (datasetDirectoryPath == null) {
1✔
612
            throw new IOException("Could not determine the filesystem directory of the parent dataset.");
×
613
        }
614
        
615
        DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
1✔
616
            @Override
617
            public boolean accept(Path file) throws IOException {
618
                return (file.getFileName() != null
1✔
619
                        && file.getFileName().toString().startsWith(baseName + "."));
1✔
620
            }
621
        };
622

623
        DirectoryStream<Path> dirStream = Files.newDirectoryStream(datasetDirectoryPath, filter);
1✔
624
        
625
        if (dirStream != null) {
1✔
626
            for (Path filePath : dirStream) {
1✔
627
                auxItems.add(filePath);
×
628
            }
×
629
        }   
630

631
        dirStream.close();
1✔
632
        
633
        return auxItems;
1✔
634
    }
635

636
    @Override
637
    public InputStream getAuxFileAsInputStream(String auxItemTag) throws IOException {
638
        InputStream in = null;
1✔
639

640
        if(this.isAuxObjectCached(auxItemTag))
1✔
641
        {
642
            Path path=getAuxObjectAsPath(auxItemTag);
1✔
643
            in=Files.newInputStream(path);
1✔
644
        }
645
        return in;
1✔
646
    }
647
    private String stripDriverId(String storageIdentifier) {
648
        int separatorIndex = storageIdentifier.indexOf(DataAccess.SEPARATOR);
1✔
649
        if(separatorIndex>0) {
1✔
650
            return storageIdentifier.substring(separatorIndex + DataAccess.SEPARATOR.length());
1✔
651
        }
652
        return storageIdentifier;
1✔
653
    }
654
    
655
    //Confirm inputs are of the form of a relative file path that doesn't contain . or ..
656
    protected static boolean isValidIdentifier(String driverId, String storageId) {
657
        String pathString = storageId.substring(storageId.lastIndexOf("//") + 2);
1✔
658
        String basePath = "/tmp/";
1✔
659
        try {
660
            String rawPathString = basePath + pathString;
1✔
661
            Path normalized = Paths.get(rawPathString).normalize();
1✔
662
            if(!rawPathString.equals(normalized.toString())) {
1✔
663
                logger.warning("Non-normalized path in submitted identifier " + storageId);
1✔
664
                return false;
1✔
665
            }
666
            logger.fine(normalized.getFileName().toString());
1✔
667
            if (!usesStandardNamePattern(normalized.getFileName().toString())) {
1✔
UNCOV
668
                logger.warning("Unacceptable file name in submitted identifier: " + storageId);
×
UNCOV
669
                return false;
×
670
            }
671

672
        } catch (InvalidPathException ipe) {
×
673
            logger.warning("Invalid Path in submitted identifier " + storageId);
×
674
            return false;
×
675
        }
1✔
676
        return true;
1✔
677
    }
678

679
    private List<String> listAllFiles() throws IOException {
680
        Dataset dataset = this.getDataset();
×
681
        if (dataset == null) {
×
682
            throw new IOException("This FileAccessIO object hasn't been properly initialized.");
×
683
        }
684

685
        Path datasetDirectoryPath = Paths.get(dataset.getAuthorityForFileStorage(), dataset.getIdentifierForFileStorage());
×
686
        if (datasetDirectoryPath == null) {
×
687
            throw new IOException("Could not determine the filesystem directory of the dataset.");
×
688
        }
689

690
        DirectoryStream<Path> dirStream = Files.newDirectoryStream(Paths.get(this.getFilesRootDirectory(), datasetDirectoryPath.toString()));
×
691
        
692
        List<String> res = new ArrayList<>();
×
693
        if (dirStream != null) {
×
694
            for (Path filePath : dirStream) {
×
695
                res.add(filePath.getFileName().toString());
×
696
            }
×
697
            dirStream.close();
×
698
        }
699
        
700
        return res;
×
701
    }
702
    
703
    private void deleteFile(String fileName) throws IOException {
704
        Dataset dataset = this.getDataset();
×
705
        if (dataset == null) {
×
706
            throw new IOException("This FileAccessIO object hasn't been properly initialized.");
×
707
        }
708

709
        Path datasetDirectoryPath = Paths.get(dataset.getAuthorityForFileStorage(), dataset.getIdentifierForFileStorage());
×
710
        if (datasetDirectoryPath == null) {
×
711
            throw new IOException("Could not determine the filesystem directory of the dataset.");
×
712
        }
713

714
        Path p = Paths.get(this.getFilesRootDirectory(), datasetDirectoryPath.toString(), fileName);
×
715
        Files.delete(p);
×
716
    }
×
717

718
    @Override
719
    public List<String> cleanUp(Predicate<String> filter, boolean dryRun) throws IOException {
720
        List<String> toDelete = this.listAllFiles().stream().filter(filter).collect(Collectors.toList());
×
721
        if (dryRun) {
×
722
            return toDelete;
×
723
        }
724
        for (String f : toDelete) {
×
725
            this.deleteFile(f);
×
726
        }
×
727
        return toDelete;
×
728
    }
729

730
    @Override
731
    public long retrieveSizeFromMedia() {
732
        long fileSize = -1;
1✔
733
        try {
734
            File testFile = getFileSystemPath().toFile();
1✔
735
            if (testFile != null) {
1✔
736
                fileSize = testFile.length();
1✔
737
            }
738
            return fileSize;
1✔
739
        } catch (IOException ex) {
×
740
            return -1;
×
741
        }
742
    }
743

744
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc