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

valkyrjaio / valkyrja-java / 27861926414

20 Jun 2026 05:45AM UTC coverage: 99.508%. First build
27861926414

Pull #27

github

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

1568 of 1596 branches covered (98.25%)

Branch coverage included in aggregate %.

56 of 63 new or added lines in 17 files covered. (88.89%)

5713 of 5721 relevant lines covered (99.86%)

4.35 hits per line

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

96.08
/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
        if (this.stream != null) {
3!
94
            this.stream.close();
3✔
95
        }
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