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

kit-data-manager / ro-crate-java / #348

15 Apr 2025 08:24AM UTC coverage: 86.955%. First build
#348

Pull #233

github

web-flow
Merge pull request #244 from kit-data-manager/renovate/commons-io-commons-io-2.x

chore(deps): update dependency commons-io:commons-io to v2.19.0
Pull Request #233: Version 2.1.0

521 of 659 new or added lines in 18 files covered. (79.06%)

1873 of 2154 relevant lines covered (86.95%)

0.87 hits per line

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

82.22
/src/main/java/edu/kit/datamanager/ro_crate/reader/ZipStreamReader.java
1
package edu.kit.datamanager.ro_crate.reader;
2

3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import com.fasterxml.jackson.databind.node.ObjectNode;
5
import edu.kit.datamanager.ro_crate.objectmapper.MyObjectMapper;
6
import java.io.File;
7
import java.io.FileOutputStream;
8
import java.io.IOException;
9
import java.io.InputStream;
10
import java.io.OutputStream;
11
import java.nio.file.Path;
12
import java.util.UUID;
13
import net.lingala.zip4j.io.inputstream.ZipInputStream;
14
import net.lingala.zip4j.model.LocalFileHeader;
15
import org.apache.commons.io.FileUtils;
16

17
/**
18
 *
19
 * @author jejkal
20
 */
21
public class ZipStreamReader implements StreamReaderStrategy {
22

23
    protected final String ID = UUID.randomUUID().toString();
1✔
24
    protected Path temporaryFolder = Path.of(String.format("./.tmp/ro-crate-java/zipStreamReader/%s/", ID));
1✔
25
    protected boolean isExtracted = false;
1✔
26

27
    /**
28
     * Crates a ZipStreamReader with the default configuration as described in
29
     * the class documentation.
30
     */
31
    public ZipStreamReader() {
1✔
32
    }
1✔
33

34
    /**
35
     * Creates a ZipStreamReader which will extract the contents temporary to
36
     * the given location instead of the default location.
37
     *
38
     * @param folderPath the custom directory to extract content to for
39
     * temporary access.
40
     * @param shallAddUuidSubfolder if true, the reader will extract into
41
     * subdirectories of the given directory. These subdirectories will have
42
     * UUIDs as their names.
43
     */
44
    public ZipStreamReader(Path folderPath, boolean shallAddUuidSubfolder) {
1✔
45
        if (shallAddUuidSubfolder) {
1✔
46
            this.temporaryFolder = folderPath.resolve(ID);
1✔
47
        } else {
48
            this.temporaryFolder = folderPath;
1✔
49
        }
50
    }
1✔
51

52
    /**
53
     * @return the identifier which may be used as the name for a subfolder in
54
     * the temporary directory.
55
     */
56
    public String getID() {
57
        return ID;
1✔
58
    }
59

60
    /**
61
     * @return the folder (considered temporary) where the zipped crate will be
62
     * or has been extracted to.
63
     */
64
    public Path getTemporaryFolder() {
65
        return temporaryFolder;
1✔
66
    }
67

68
    /**
69
     * @return whether the crate has already been extracted into the temporary
70
     * folder.
71
     */
72
    public boolean isExtracted() {
73
        return isExtracted;
1✔
74
    }
75

76
    /**Read the create metadata and content from the provided input stream.
77
     * 
78
     * @param stream The input stream.
79
     */
80
    private void readCrate(InputStream stream) {
81
        try {
82
            File folder = temporaryFolder.toFile();
1✔
83
            // ensure the directory is clean
84
            if (folder.exists()) {
1✔
85
                if (folder.isDirectory()) {
1✔
86
                    FileUtils.cleanDirectory(folder);
1✔
NEW
87
                } else if (folder.isFile()) {
×
NEW
88
                    FileUtils.delete(folder);
×
89
                }
90
            } else {
91
                FileUtils.forceMkdir(folder);
1✔
92
            }
93

94
            LocalFileHeader localFileHeader;
95
            int readLen;
96
            byte[] readBuffer = new byte[4096];
1✔
97

98
            try (ZipInputStream zipInputStream = new ZipInputStream(stream)) {
1✔
99
                while ((localFileHeader = zipInputStream.getNextEntry()) != null) {
1✔
100
                    File extractedFile = new File(folder, localFileHeader.getFileName());
1✔
101
                    try (OutputStream outputStream = new FileOutputStream(extractedFile)) {
1✔
102
                        while ((readLen = zipInputStream.read(readBuffer)) != -1) {
1✔
103
                            outputStream.write(readBuffer, 0, readLen);
1✔
104
                        }
105
                    }
106
                }
1✔
107
            }
108
            this.isExtracted = true;
1✔
109
            // register deletion on exit
110
            FileUtils.forceDeleteOnExit(folder);
1✔
NEW
111
        } catch (IOException ex) {
×
NEW
112
            logger.error("Failed to read crate from input stream.", ex);
×
113
        }
1✔
114
    }
1✔
115

116
    @Override
117
    public ObjectNode readMetadataJson(InputStream stream) {
118
        if (!isExtracted) {
1✔
119
            this.readCrate(stream);
1✔
120
        }
121

122
        ObjectMapper objectMapper = MyObjectMapper.getMapper();
1✔
123
        File jsonMetadata = temporaryFolder.resolve("ro-crate-metadata.json").toFile();
1✔
124

125
        try {
126
            return objectMapper.readTree(jsonMetadata).deepCopy();
1✔
NEW
127
        } catch (IOException e) {
×
NEW
128
            logger.error("Failed to deserialize crate metadata.", e);
×
NEW
129
            return null;
×
130
        }
131
    }
132

133
    @Override
134
    public File readContent(InputStream stream) {
135
        if (!isExtracted) {
1✔
NEW
136
            this.readCrate(stream);
×
137
        }
138
        return temporaryFolder.toFile();
1✔
139
    }
140
}
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