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

valkyrjaio / valkyrja-java / 27862613065

20 Jun 2026 06:15AM UTC coverage: 99.835%. First build
27862613065

Pull #27

github

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

1578 of 1582 branches covered (99.75%)

Branch coverage included in aggregate %.

46 of 53 new or added lines in 17 files covered. (86.79%)

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 java.util.Objects;
28
import org.jspecify.annotations.Nullable;
29

30
public class UploadedFile implements UploadedFileContract {
31

32
    protected boolean hasBeenMoved = false;
3✔
33

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

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

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

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

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

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

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

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

81
        return this.stream;
3✔
82
    }
83

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

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

90
        validateMoveToTargetDirectory(targetDirectory);
3✔
91

92
        writeStream(targetPath);
3✔
93

94
        // writeStream() resolves the stream via getStream(), so it is always present here.
95
        Objects.requireNonNull(this.stream).close();
5✔
96

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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