FileReader.java

1
package com.renomad.minum.utils;
2
3
import com.renomad.minum.logging.ILogger;
4
5
import java.io.ByteArrayOutputStream;
6
import java.io.IOException;
7
import java.io.RandomAccessFile;
8
import java.nio.ByteBuffer;
9
import java.nio.channels.FileChannel;
10
import java.util.Map;
11
import java.util.concurrent.locks.ReentrantLock;
12
13
import static com.renomad.minum.utils.FileUtils.checkForBadFilePatterns;
14
15
/**
16
 * Reads files from disk, optionally storing into a LRU cache.
17
 */
18
public final class FileReader implements IFileReader {
19
20
    private final Map<String, byte[]> lruCache;
21
    private final boolean useCacheForStaticFiles;
22
    private final ILogger logger;
23
    private final ReentrantLock cacheLock = new ReentrantLock();
24
25
    public FileReader(Map<String, byte[]> lruCache, boolean useCacheForStaticFiles, ILogger logger) {
26
        this.lruCache = lruCache;
27
        this.useCacheForStaticFiles = useCacheForStaticFiles;
28
        this.logger = logger;
29
    }
30
31
    @Override
32
    public byte[] readFile(String path) throws IOException {
33 2 1. readFile : negated conditional → KILLED
2. readFile : negated conditional → KILLED
        if (useCacheForStaticFiles && lruCache.containsKey(path)) {
34 1 1. readFile : removed call to java/util/concurrent/locks/ReentrantLock::lock → KILLED
            cacheLock.lock();
35
            try {
36 1 1. readFile : replaced return value with null for com/renomad/minum/utils/FileReader::readFile → KILLED
                return lruCache.get(path);
37
            } finally {
38 1 1. readFile : removed call to java/util/concurrent/locks/ReentrantLock::unlock → TIMED_OUT
                cacheLock.unlock();
39
            }
40
        }
41 1 1. readFile : removed call to com/renomad/minum/utils/FileUtils::checkForBadFilePatterns → KILLED
        checkForBadFilePatterns(path);
42 1 1. readFile : replaced return value with null for com/renomad/minum/utils/FileReader::readFile → KILLED
        return readTheFile(path, logger, useCacheForStaticFiles, lruCache);
43
    }
44
45
    byte[] readTheFile(String path, ILogger logger, boolean useCacheForStaticFiles, Map<String, byte[]> lruCache) throws IOException {
46
        try (RandomAccessFile reader = new RandomAccessFile(path, "r");
47
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
48
            FileChannel channel = reader.getChannel();
49
            int bufferSize = 8 * 1024;
50 2 1. readTheFile : changed conditional boundary → TIMED_OUT
2. readTheFile : negated conditional → KILLED
            if (bufferSize > channel.size()) {
51
                bufferSize = (int) channel.size();
52
            }
53
            ByteBuffer buff = ByteBuffer.allocate(bufferSize);
54
55 2 1. readTheFile : negated conditional → TIMED_OUT
2. readTheFile : changed conditional boundary → TIMED_OUT
            while (channel.read(buff) > 0) {
56 1 1. readTheFile : removed call to java/io/ByteArrayOutputStream::write → KILLED
                out.write(buff.array(), 0, buff.position());
57
                buff.clear();
58
            }
59
60
            byte[] bytes = out.toByteArray();
61 1 1. readTheFile : negated conditional → KILLED
            if (bytes.length == 0) {
62
                logger.logTrace(() -> path + " filesize was 0, returning empty byte array");
63
                return new byte[0];
64
            } else {
65
                String s = path + " filesize was " + bytes.length + " bytes.";
66
                logger.logTrace(() -> s);
67
68
                if (useCacheForStaticFiles) {
69
                    logger.logDebug(() -> "Storing " + path + " in the cache");
70
                    cacheLock.lock();
71
                    try {
72
                        lruCache.put(path, bytes);
73
                    } finally {
74
                        cacheLock.unlock();
75
                    }
76
                }
77
                return bytes;
78
            }
79
        }
80
    }
81
82
    /**
83
     * Returns the lock used to prevent concurrent modification
84
     * exceptions when mutating the LRU cache data.
85
     * <br>
86
     * This may be useful if you need to access the LRU cache,
87
     * which, owing to how a least-recently-used cache works,
88
     * will cause the data to mutate, and which requires to
89
     * be protected with locks.
90
     */
91
    public ReentrantLock getCacheLock() {
92 1 1. getCacheLock : replaced return value with null for com/renomad/minum/utils/FileReader::getCacheLock → KILLED
        return cacheLock;
93
    }
94
}

Mutations

33

1.1
Location : readFile
Killed by : com.renomad.minum.utils.FileReaderTests
negated conditional → KILLED

2.2
Location : readFile
Killed by : com.renomad.minum.utils.FileReaderTests
negated conditional → KILLED

34

1.1
Location : readFile
Killed by : com.renomad.minum.utils.FileReaderTests
removed call to java/util/concurrent/locks/ReentrantLock::lock → KILLED

36

1.1
Location : readFile
Killed by : com.renomad.minum.utils.FileReaderTests
replaced return value with null for com/renomad/minum/utils/FileReader::readFile → KILLED

38

1.1
Location : readFile
Killed by : none
removed call to java/util/concurrent/locks/ReentrantLock::unlock → TIMED_OUT

41

1.1
Location : readFile
Killed by : com.renomad.minum.utils.FileReaderTests
removed call to com/renomad/minum/utils/FileUtils::checkForBadFilePatterns → KILLED

42

1.1
Location : readFile
Killed by : com.renomad.minum.utils.FileReaderTests
replaced return value with null for com/renomad/minum/utils/FileReader::readFile → KILLED

50

1.1
Location : readTheFile
Killed by : com.renomad.minum.FunctionalTests.test_EdgeCase_IOExceptionThrown_WebFramework(com.renomad.minum.FunctionalTests)
negated conditional → KILLED

2.2
Location : readTheFile
Killed by : none
changed conditional boundary → TIMED_OUT

55

1.1
Location : readTheFile
Killed by : none
negated conditional → TIMED_OUT

2.2
Location : readTheFile
Killed by : none
changed conditional boundary → TIMED_OUT

56

1.1
Location : readTheFile
Killed by : com.renomad.minum.utils.FileReaderTests
removed call to java/io/ByteArrayOutputStream::write → KILLED

61

1.1
Location : readTheFile
Killed by : com.renomad.minum.utils.FileReaderTests
negated conditional → KILLED

92

1.1
Location : getCacheLock
Killed by : com.renomad.minum.utils.FileReaderTests
replaced return value with null for com/renomad/minum/utils/FileReader::getCacheLock → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0