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

valkyrjaio / valkyrja-java / 27862494301

20 Jun 2026 06:10AM UTC coverage: 99.835%. First build
27862494301

Pull #27

github

web-flow
Merge 138e8698f into 9d8ae9377
Pull Request #27: [Tests] Reach 100% branch coverage

1578 of 1582 branches covered (99.75%)

Branch coverage included in aggregate %.

47 of 54 new or added lines in 17 files covered. (87.04%)

5702 of 5710 relevant lines covered (99.86%)

4.35 hits per line

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

97.98
/src/main/java/io/valkyrja/http/message/file/UploadedFile.java
1
/*
2
 * This file is part of the Valkyrja Framework package.
3
 *
4
 * (c) Melech Mizrachi <melechmizrachi@gmail.com>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9

10
package io.valkyrja.http.message.file;
11

12
import io.valkyrja.http.message.file.contract.UploadedFileContract;
13
import io.valkyrja.http.message.file.throwable.exception.UploadedFileAlreadyMovedException;
14
import io.valkyrja.http.message.file.throwable.exception.UploadedFileInvalidDirectoryException;
15
import io.valkyrja.http.message.file.throwable.exception.UploadedFileInvalidUploadedFileException;
16
import io.valkyrja.http.message.file.throwable.exception.UploadedFileMoveFailureException;
17
import io.valkyrja.http.message.file.throwable.exception.UploadedFileUnableToWriteFileException;
18
import io.valkyrja.http.message.stream.Stream;
19
import io.valkyrja.http.message.stream.contract.StreamContract;
20
import java.io.File;
21
import java.io.FileOutputStream;
22
import java.io.IOException;
23
import java.nio.charset.StandardCharsets;
24
import java.nio.file.Files;
25
import java.nio.file.Path;
26
import java.nio.file.Paths;
27
import org.jspecify.annotations.Nullable;
28

29
public class UploadedFile implements UploadedFileContract {
30

31
    protected boolean hasBeenMoved = false;
3✔
32

33
    protected @Nullable String file;
34
    protected @Nullable StreamContract stream;
35
    protected int size;
36
    protected String fileName;
37
    protected String mediaType;
38

39
    public UploadedFile(
40
            @Nullable String file,
41
            @Nullable StreamContract stream,
42
            int size,
43
            @Nullable String fileName,
44
            @Nullable String mediaType) {
2✔
45
        if (file == null && stream == null) {
4✔
46
            throw new UploadedFileInvalidUploadedFileException(
5✔
47
                    "One of file or stream are required");
48
        }
49

50
        this.file = file;
3✔
51
        this.stream = stream;
3✔
52
        this.size = size;
3✔
53
        this.fileName = fileName != null ? fileName : "";
7✔
54
        this.mediaType = mediaType != null ? mediaType : "";
7✔
55
    }
1✔
56

57
    @Override
58
    public StreamContract getStream() {
59
        validateHasNotBeenMoved("Cannot retrieve stream after it has already been moved");
3✔
60

61
        if (this.stream != null) {
3✔
62
            return this.stream;
3✔
63
        }
64

65
        if (this.file == null) {
3!
NEW
66
            throw new UploadedFileInvalidUploadedFileException(
×
67
                    "One of file or stream are required");
68
        }
69

70
        this.stream = new Stream();
5✔
71

72
        try {
73
            byte[] bytes = Files.readAllBytes(Paths.get(this.file));
7✔
74
            this.stream.write(new String(bytes, StandardCharsets.UTF_8));
9✔
75
            this.stream.rewind();
3✔
76
        } catch (IOException e) {
1✔
77
            throw new UploadedFileInvalidUploadedFileException("Unable to read file: " + this.file);
7✔
78
        }
1✔
79

80
        return this.stream;
3✔
81
    }
82

83
    @Override
84
    public void moveTo(String targetPath) {
85
        validateHasNotBeenMoved();
2✔
86

87
        String targetDirectory = getDirectoryName(targetPath);
4✔
88

89
        validateMoveToTargetDirectory(targetDirectory);
3✔
90

91
        writeStream(targetPath);
3✔
92

93
        // writeStream() resolves the stream via getStream(), so it is always present here.
94
        this.stream.close();
3✔
95

96
        if (this.file != null && new File(this.file).isFile()) {
10✔
97
            try {
98
                Files.delete(Paths.get(this.file));
6✔
99
            } catch (IOException e) {
1✔
100
                throw new UploadedFileMoveFailureException(
7✔
101
                        "Unable to delete original file: " + this.file);
102
            }
1✔
103
        }
104

105
        this.hasBeenMoved = true;
3✔
106
    }
1✔
107

108
    @Override
109
    public boolean hasSize() {
110
        return this.size != 0;
7✔
111
    }
112

113
    @Override
114
    public int getSize() {
115
        return this.size;
3✔
116
    }
117

118
    @Override
119
    public boolean hasClientFilename() {
120
        return !this.fileName.isEmpty();
8✔
121
    }
122

123
    @Override
124
    public String getClientFilename() {
125
        return this.fileName;
3✔
126
    }
127

128
    @Override
129
    public boolean hasClientMediaType() {
130
        return !this.mediaType.isEmpty();
8✔
131
    }
132

133
    @Override
134
    public String getClientMediaType() {
135
        return this.mediaType;
3✔
136
    }
137

138
    protected void validateHasNotBeenMoved() {
139
        validateHasNotBeenMoved(null);
3✔
140
    }
1✔
141

142
    protected void validateHasNotBeenMoved(@Nullable String message) {
143
        if (this.hasBeenMoved) {
3✔
144
            throw new UploadedFileAlreadyMovedException(
2✔
145
                    message != null ? message : "Cannot move file after it has already been moved");
7✔
146
        }
147
    }
1✔
148

149
    protected void validateMoveToTargetDirectory(String targetDirectory) {
150
        File dir = new File(targetDirectory);
5✔
151

152
        if (!dir.isDirectory() || !dir.canWrite()) {
6✔
153
            throw new UploadedFileInvalidDirectoryException(
6✔
154
                    "The target directory `"
155
                            + targetDirectory
156
                            + "` does not exists or is not writable");
157
        }
158
    }
1✔
159

160
    protected void writeStream(String path) {
161
        try (FileOutputStream out = new FileOutputStream(path)) {
5✔
162
            StreamContract s = getStream();
3✔
163
            s.rewind();
2✔
164

165
            while (!s.eof()) {
3✔
166
                String chunk = s.read(4096);
4✔
167
                out.write(chunk.getBytes(StandardCharsets.UTF_8));
5✔
168
            }
1✔
169
        } catch (IOException e) {
1✔
170
            throw new UploadedFileUnableToWriteFileException("Unable to write to designated path");
5✔
171
        }
1✔
172
    }
1✔
173

174
    protected String getDirectoryName(String path) {
175
        Path p = Paths.get(path);
5✔
176
        Path parent = p.getParent();
3✔
177
        return parent != null ? parent.toString() : ".";
7✔
178
    }
179
}
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

© 2026 Coveralls, Inc