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

ebourg / jsign / #425

06 Oct 2026 08:28PM UTC coverage: 82.133% (+0.06%) from 82.076%
#425

push

ebourg
No longer map MSI files into memory (Fixes #365)

41 of 43 new or added lines in 3 files covered. (95.35%)

1 existing line in 1 file now uncovered.

6316 of 7690 relevant lines covered (82.13%)

0.82 hits per line

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

93.94
/jsign-core/src/main/java/net/jsign/msi/UnmappedFileDataSource.java
1
/*
2
 * Copyright 2026 Emmanuel Bourg
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

17
package net.jsign.msi;
18

19
import java.io.File;
20
import java.io.IOException;
21
import java.nio.ByteBuffer;
22
import java.util.IdentityHashMap;
23
import java.util.LinkedHashMap;
24
import java.util.Map;
25

26
import org.apache.poi.poifs.nio.FileBackedDataSource;
27

28
/**
29
 * POI data source modifying the file without mapping it in memory.
30
 *
31
 * @since 8.0
32
 */
33
class UnmappedFileDataSource extends FileBackedDataSource {
34

35
    /** The blocks modified by POI, by position in the file */
36
    private final Map<Long, ByteBuffer> blocks = new LinkedHashMap<>();
1 ✔
37

38
    /** The position of the blocks held */
39
    private final Map<ByteBuffer, Long> positions = new IdentityHashMap<>();
1 ✔
40

41
    UnmappedFileDataSource(File file) throws IOException {
42
        super(file, false);
1 ✔
43
    }
1 ✔
44

45
    @Override
46
    public ByteBuffer read(int length, long position) throws IOException {
47
        ByteBuffer block = blocks.get(position);
1 ✔
48

49
        if (block == null) {
1 ✔
50
            if (position >= size()) {
1 ✔
51
                throw new IndexOutOfBoundsException("Position " + position + " past the end of the file");
1 ✔
52
            }
53

54
            block = ByteBuffer.allocate(length);
1 ✔
55
            getChannel().read(block, position);
1 ✔
56

57
            blocks.put(position, block);
1 ✔
58
            positions.put(block, position);
1 ✔
59
        }
60

61
        block.position(0);
1 ✔
62
        block.limit(block.capacity());
1 ✔
63

64
        return block;
1 ✔
65
    }
66

67
    @Override
68
    public void releaseBuffer(ByteBuffer block) {
69
        Long position = positions.remove(block);
1 ✔
70
        if (position != null) {
1 ✔
71
            blocks.remove(position);
1 ✔
72
            try {
73
                writeBlock(block, position);
1 ✔
NEW
74
            } catch (IOException e) {
×
NEW
75
                throw new RuntimeException("Unable to write the block at the position " + position, e);
×
76
            }
1 ✔
77
        }
78
    }
1 ✔
79

80
    /**
81
     * Writes the blocks still held to the file.
82
     */
83
    void flush() throws IOException {
84
        for (Map.Entry<Long, ByteBuffer> entry : blocks.entrySet()) {
1 ✔
85
            writeBlock(entry.getValue(), entry.getKey());
1 ✔
86
        }
1 ✔
87

88
        blocks.clear();
1 ✔
89
        positions.clear();
1 ✔
90
    }
1 ✔
91

92
    private void writeBlock(ByteBuffer block, long position) throws IOException {
93
        block.position(0);
1 ✔
94
        block.limit(block.capacity());
1 ✔
95
        write(block, position);
1 ✔
96
    }
1 ✔
97
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc