Thanks IntelliJ. ThintelliJ.

This commit is contained in:
comp500 2019-08-07 13:21:15 +01:00
parent 794b817eff
commit bd95bc15ad
14 changed files with 167 additions and 164 deletions

2
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,2 @@
# Default ignored files
/workspace.xml

18
.idea/gradle.xml generated Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="11" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>

5
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK" />
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,5 @@
package link.infra.packwiz.installer;
class DownloadTask {
}

View File

@ -1,22 +1,14 @@
package link.infra.packwiz.installer; package link.infra.packwiz.installer;
import java.awt.EventQueue;
import java.awt.GraphicsEnvironment;
import java.net.URI;
import java.net.URISyntaxException;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import link.infra.packwiz.installer.ui.CLIHandler; import link.infra.packwiz.installer.ui.CLIHandler;
import link.infra.packwiz.installer.ui.IUserInterface; import link.infra.packwiz.installer.ui.IUserInterface;
import link.infra.packwiz.installer.ui.InstallWindow; import link.infra.packwiz.installer.ui.InstallWindow;
import org.apache.commons.cli.*;
import javax.swing.*;
import java.awt.*;
import java.net.URI;
import java.net.URISyntaxException;
public class Main { public class Main {
@ -28,13 +20,11 @@ public class Main {
this.startup(args); this.startup(args);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
public void run() { JOptionPane.showMessageDialog(null,
JOptionPane.showMessageDialog(null, "A fatal error occurred: \n" + e.getClass().getCanonicalName() + ": " + e.getMessage(),
"A fatal error occurred: \n" + e.getClass().getCanonicalName() + ": " + e.getMessage(), "packwiz-installer", JOptionPane.ERROR_MESSAGE);
"packwiz-installer", JOptionPane.ERROR_MESSAGE); System.exit(1);
System.exit(1);
}
}); });
// In case the eventqueue is broken, exit after 1 minute // In case the eventqueue is broken, exit after 1 minute
try { try {
@ -127,14 +117,12 @@ public class Main {
} catch (Exception e) { } catch (Exception e) {
// TODO: better error message? // TODO: better error message?
ui.handleExceptionAndExit(e); ui.handleExceptionAndExit(e);
return;
} }
} }
}); });
} catch (Exception e) { } catch (Exception e) {
// TODO: better error message? // TODO: better error message?
ui.handleExceptionAndExit(e); ui.handleExceptionAndExit(e);
return;
} }
} }

View File

@ -1,10 +1,8 @@
package link.infra.packwiz.installer; package link.infra.packwiz.installer;
import javax.swing.*;
import java.util.Arrays; import java.util.Arrays;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
public class RequiresBootstrap { public class RequiresBootstrap {
public static void main(String[] args) { public static void main(String[] args) {
@ -15,10 +13,10 @@ public class RequiresBootstrap {
if (Arrays.stream(args).map(str -> { if (Arrays.stream(args).map(str -> {
if (str == null) return ""; if (str == null) return "";
if (str.startsWith("--")) { if (str.startsWith("--")) {
return str.substring(2, str.length()); return str.substring(2);
} }
if (str.startsWith("-")) { if (str.startsWith("-")) {
return str.substring(1, str.length()); return str.substring(1);
} }
return ""; return "";
}).anyMatch(str -> str.equals("g") || str.equals("no-gui"))) { }).anyMatch(str -> str.equals("g") || str.equals("no-gui"))) {

View File

@ -1,36 +1,11 @@
package link.infra.packwiz.installer; package link.infra.packwiz.installer;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException; import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import com.moandjiezana.toml.Toml; import com.moandjiezana.toml.Toml;
import link.infra.packwiz.installer.metadata.IndexFile; import link.infra.packwiz.installer.metadata.IndexFile;
import link.infra.packwiz.installer.metadata.ManifestFile; import link.infra.packwiz.installer.metadata.ManifestFile;
import link.infra.packwiz.installer.metadata.PackFile; import link.infra.packwiz.installer.metadata.PackFile;
@ -44,6 +19,16 @@ import okio.Buffer;
import okio.Okio; import okio.Okio;
import okio.Source; import okio.Source;
import java.io.*;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
public class UpdateManager { public class UpdateManager {
public final Options opts; public final Options opts;
@ -84,8 +69,8 @@ public class UpdateManager {
return true; return true;
} }
if (this.depSides != null) { if (this.depSides != null) {
for (int i = 0; i < this.depSides.length; i++) { for (Side depSide : this.depSides) {
if (this.depSides[i].equals(tSide)) { if (depSide.equals(tSide)) {
return true; return true;
} }
} }
@ -96,7 +81,7 @@ public class UpdateManager {
public static Side from(String name) { public static Side from(String name) {
String lowerName = name.toLowerCase(); String lowerName = name.toLowerCase();
for (Side side : Side.values()) { for (Side side : Side.values()) {
if (side.sideName == lowerName) { if (side.sideName.equals(lowerName)) {
return side; return side;
} }
} }
@ -150,9 +135,7 @@ public class UpdateManager {
List<URI> invalidatedUris = new ArrayList<>(); List<URI> invalidatedUris = new ArrayList<>();
if (manifest.cachedFiles != null) { if (manifest.cachedFiles != null) {
Iterator<Map.Entry<URI, ManifestFile.File>> it = manifest.cachedFiles.entrySet().iterator(); for (Map.Entry<URI, ManifestFile.File> entry : manifest.cachedFiles.entrySet()) {
while (it.hasNext()) {
Map.Entry<URI, ManifestFile.File> entry = it.next();
if (entry.getValue().cachedLocation != null) { if (entry.getValue().cachedLocation != null) {
if (!Files.exists(Paths.get(opts.packFolder, entry.getValue().cachedLocation))) { if (!Files.exists(Paths.get(opts.packFolder, entry.getValue().cachedLocation))) {
URI fileUri = entry.getKey(); URI fileUri = entry.getKey();
@ -225,7 +208,7 @@ public class UpdateManager {
} }
if (manifest.cachedFiles == null) { if (manifest.cachedFiles == null) {
manifest.cachedFiles = new HashMap<URI, ManifestFile.File>(); manifest.cachedFiles = new HashMap<>();
} }
ui.submitProgress(new InstallProgress("Checking local files...")); ui.submitProgress(new InstallProgress("Checking local files..."));
@ -233,7 +216,7 @@ public class UpdateManager {
while (it.hasNext()) { while (it.hasNext()) {
Map.Entry<URI, ManifestFile.File> entry = it.next(); Map.Entry<URI, ManifestFile.File> entry = it.next();
if (entry.getValue().cachedLocation != null) { if (entry.getValue().cachedLocation != null) {
if (!indexFile.files.stream().anyMatch(f -> f.file.equals(entry.getKey()))) { if (indexFile.files.stream().noneMatch(f -> f.file.equals(entry.getKey()))) {
// File has been removed from the index // File has been removed from the index
try { try {
Files.deleteIfExists(Paths.get(opts.packFolder, entry.getValue().cachedLocation)); Files.deleteIfExists(Paths.get(opts.packFolder, entry.getValue().cachedLocation));
@ -248,12 +231,11 @@ public class UpdateManager {
ui.submitProgress(new InstallProgress("Comparing new files...")); ui.submitProgress(new InstallProgress("Comparing new files..."));
// TODO: progress bar // TODO: progress bar
ConcurrentLinkedQueue<Exception> exceptionQueue = new ConcurrentLinkedQueue<Exception>(); ConcurrentLinkedQueue<Exception> exceptionQueue = new ConcurrentLinkedQueue<>();
List<IndexFile.File> newFiles = indexFile.files.stream().map(f -> { List<IndexFile.File> newFiles = indexFile.files.stream().peek(f -> {
if (f.hashFormat == null || f.hashFormat.length() == 0) { if (f.hashFormat == null || f.hashFormat.length() == 0) {
f.hashFormat = indexFile.hashFormat; f.hashFormat = indexFile.hashFormat;
} }
return f;
}).filter(f -> { }).filter(f -> {
if (invalidatedUris.contains(f.file)) { if (invalidatedUris.contains(f.file)) {
return true; return true;
@ -267,13 +249,12 @@ public class UpdateManager {
return false; return false;
} }
return cachedFile == null || !newHash.equals(cachedFile.hash); return cachedFile == null || !newHash.equals(cachedFile.hash);
}).parallel().map(f -> { }).parallel().peek(f -> {
try { try {
f.downloadMeta(indexFile, indexUri); f.downloadMeta(indexFile, indexUri);
} catch (Exception e) { } catch (Exception e) {
exceptionQueue.add(e); exceptionQueue.add(e);
} }
return f;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
for (Exception e : exceptionQueue) { for (Exception e : exceptionQueue) {
@ -284,81 +265,78 @@ public class UpdateManager {
// TODO: present options // TODO: present options
// TODO: all options should be presented, not just new files!!!!!!! // TODO: all options should be presented, not just new files!!!!!!!
// and options should be readded to newFiles after option -> true // and options should be readded to newFiles after option -> true
newFiles.stream().filter(f -> f.linkedFile != null).filter(f -> f.linkedFile.option != null).map(f -> { newFiles.stream().filter(f -> f.linkedFile != null).filter(f -> f.linkedFile.option != null).map(f ->
return "option: " + (f.linkedFile.option.description == null ? "null" : f.linkedFile.option.description); "option: " + (f.linkedFile.option.description == null ? "null" : f.linkedFile.option.description)
}).forEachOrdered(desc -> { ).forEachOrdered(desc -> {
System.out.println(desc); System.out.println(desc);
}); });
// TODO: different thread pool type? // TODO: different thread pool type?
ExecutorService threadPool = Executors.newFixedThreadPool(10); ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletionService<DownloadCompletion> completionService = new ExecutorCompletionService<DownloadCompletion>( CompletionService<DownloadCompletion> completionService = new ExecutorCompletionService<>(threadPool);
threadPool);
for (IndexFile.File f : newFiles) { for (IndexFile.File f : newFiles) {
ManifestFile.File cachedFile = manifest.cachedFiles.get(f.file); ManifestFile.File cachedFile = manifest.cachedFiles.get(f.file);
completionService.submit(new Callable<DownloadCompletion>() { completionService.submit(() -> {
public DownloadCompletion call() { DownloadCompletion dc = new DownloadCompletion();
DownloadCompletion dc = new DownloadCompletion(); dc.file = f;
dc.file = f;
if (cachedFile != null && cachedFile.linkedFileHash != null && f.linkedFile != null) { if (cachedFile != null && cachedFile.linkedFileHash != null && f.linkedFile != null) {
try { try {
if (cachedFile.linkedFileHash.equals(f.linkedFile.getHash())) { if (cachedFile.linkedFileHash.equals(f.linkedFile.getHash())) {
// Do nothing, the file didn't change // Do nothing, the file didn't change
// TODO: but if the hash of the metafile changed, what did change????? // TODO: but if the hash of the metafile changed, what did change?????
// should this be checked somehow?? // should this be checked somehow??
return dc;
}
} catch (Exception e) {}
}
Path destPath = Paths.get(opts.packFolder, f.getDestURI().toString());
// Don't update files marked with preserve if they already exist on disk
if (f.preserve) {
if (Files.exists(destPath)) {
return dc; return dc;
} }
} } catch (Exception ignored) {}
}
try { Path destPath = Paths.get(opts.packFolder, f.getDestURI().toString());
Hash hash;
String fileHashFormat;
if (f.linkedFile != null) {
hash = f.linkedFile.getHash();
fileHashFormat = f.linkedFile.download.hashFormat;
} else {
hash = f.getHash();
fileHashFormat = f.hashFormat;
}
Source src = f.getSource(indexUri); // Don't update files marked with preserve if they already exist on disk
GeneralHashingSource fileSource = HashUtils.getHasher(fileHashFormat).getHashingSource(src); if (f.preserve) {
Buffer data = new Buffer(); if (Files.exists(destPath)) {
Okio.buffer(fileSource).readAll(data);
if (fileSource.hashIsEqual(hash)) {
Files.createDirectories(destPath.getParent());
Files.copy(data.inputStream(), destPath, StandardCopyOption.REPLACE_EXISTING);
} else {
System.out.println("Invalid hash for " + f.getDestURI().toString());
System.out.println("Calculated: " + fileSource.getHash());
System.out.println("Expected: " + hash);
dc.err = new Exception("Hash invalid!");
}
if (cachedFile != null && !destPath.equals(Paths.get(opts.packFolder, cachedFile.cachedLocation))) {
// Delete old file if location changes
Files.delete(Paths.get(opts.packFolder, cachedFile.cachedLocation));
}
return dc;
} catch (Exception e) {
dc.err = e;
return dc; return dc;
} }
} }
try {
Hash hash;
String fileHashFormat;
if (f.linkedFile != null) {
hash = f.linkedFile.getHash();
fileHashFormat = f.linkedFile.download.hashFormat;
} else {
hash = f.getHash();
fileHashFormat = f.hashFormat;
}
Source src = f.getSource(indexUri);
GeneralHashingSource fileSource = HashUtils.getHasher(fileHashFormat).getHashingSource(src);
Buffer data = new Buffer();
Okio.buffer(fileSource).readAll(data);
if (fileSource.hashIsEqual(hash)) {
Files.createDirectories(destPath.getParent());
Files.copy(data.inputStream(), destPath, StandardCopyOption.REPLACE_EXISTING);
} else {
System.out.println("Invalid hash for " + f.getDestURI().toString());
System.out.println("Calculated: " + fileSource.getHash());
System.out.println("Expected: " + hash);
dc.err = new Exception("Hash invalid!");
}
if (cachedFile != null && !destPath.equals(Paths.get(opts.packFolder, cachedFile.cachedLocation))) {
// Delete old file if location changes
Files.delete(Paths.get(opts.packFolder, cachedFile.cachedLocation));
}
return dc;
} catch (Exception e) {
dc.err = e;
return dc;
}
}); });
} }

View File

@ -1,13 +1,8 @@
package link.infra.packwiz.installer.metadata; package link.infra.packwiz.installer.metadata;
import java.net.URI;
import java.nio.file.Paths;
import java.util.List;
import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import com.moandjiezana.toml.Toml; import com.moandjiezana.toml.Toml;
import link.infra.packwiz.installer.metadata.hash.GeneralHashingSource; import link.infra.packwiz.installer.metadata.hash.GeneralHashingSource;
import link.infra.packwiz.installer.metadata.hash.Hash; import link.infra.packwiz.installer.metadata.hash.Hash;
import link.infra.packwiz.installer.metadata.hash.HashUtils; import link.infra.packwiz.installer.metadata.hash.HashUtils;
@ -15,6 +10,10 @@ import link.infra.packwiz.installer.request.HandlerManager;
import okio.Okio; import okio.Okio;
import okio.Source; import okio.Source;
import java.net.URI;
import java.nio.file.Paths;
import java.util.List;
public class IndexFile { public class IndexFile {
@SerializedName("hash-format") @SerializedName("hash-format")
public String hashFormat; public String hashFormat;
@ -69,6 +68,7 @@ public class IndexFile {
public Hash getHash() throws Exception { public Hash getHash() throws Exception {
if (hash == null) { if (hash == null) {
// TODO: should these be more specific exceptions (e.g. IndexFileException?!)
throw new Exception("Index file doesn't have a hash"); throw new Exception("Index file doesn't have a hash");
} }
if (hashFormat == null) { if (hashFormat == null) {
@ -90,7 +90,8 @@ public class IndexFile {
if (file != null) { if (file != null) {
return Paths.get(file.getPath()).getFileName().toString(); return Paths.get(file.getPath()).getFileName().toString();
} }
return file.getPath(); // TODO: throw some kind of exception?
return "Invalid file";
} }
public URI getDestURI() { public URI getDestURI() {

View File

@ -48,7 +48,7 @@ public class HashingSourceHasher implements IHasher {
if (value != null) { if (value != null) {
return value.equals(objHash.value); return value.equals(objHash.value);
} else { } else {
return objHash.value == null ? true : false; return objHash.value == null;
} }
} }

View File

@ -1,10 +1,10 @@
package link.infra.packwiz.installer.metadata.hash; package link.infra.packwiz.installer.metadata.hash;
import java.io.IOException;
import okio.Buffer; import okio.Buffer;
import okio.Source; import okio.Source;
import java.io.IOException;
public class Murmur2Hasher implements IHasher { public class Murmur2Hasher implements IHasher {
private class Murmur2GeneralHashingSource extends GeneralHashingSource { private class Murmur2GeneralHashingSource extends GeneralHashingSource {
Murmur2Hash value; Murmur2Hash value;
@ -40,8 +40,7 @@ public class Murmur2Hasher implements IHasher {
private byte[] computeNormalizedArray(byte[] input) { private byte[] computeNormalizedArray(byte[] input) {
byte[] output = new byte[input.length]; byte[] output = new byte[input.length];
int num = 0; int num = 0;
for (int i = 0; i < input.length; i++) { for (byte b : input) {
byte b = input[i];
if (!(b == 9 || b == 10 || b == 13 || b == 32)) { if (!(b == 9 || b == 10 || b == 13 || b == 32)) {
output[num] = b; output[num] = b;
num++; num++;
@ -54,7 +53,7 @@ public class Murmur2Hasher implements IHasher {
} }
private class Murmur2Hash extends Hash { private static class Murmur2Hash extends Hash {
int value; int value;
private Murmur2Hash(String value) { private Murmur2Hash(String value) {
// Parsing as long then casting to int converts values gt int max value but lt uint max value // Parsing as long then casting to int converts values gt int max value but lt uint max value

View File

@ -1,17 +1,17 @@
package link.infra.packwiz.installer.request; package link.infra.packwiz.installer.request;
import java.net.URI;
import okio.Source; import okio.Source;
import java.net.URI;
/** /**
* IRequestHandler handles requests for locations specified in modpack metadata. * IRequestHandler handles requests for locations specified in modpack metadata.
*/ */
public interface IRequestHandler { public interface IRequestHandler {
public boolean matchesHandler(URI loc); boolean matchesHandler(URI loc);
public default URI getNewLoc(URI loc) { default URI getNewLoc(URI loc) {
return loc; return loc;
} }
@ -22,6 +22,6 @@ public interface IRequestHandler {
* @return The Source containing the data of the file * @return The Source containing the data of the file
* @throws Exception * @throws Exception
*/ */
public Source getFileSource(URI loc) throws Exception; Source getFileSource(URI loc) throws Exception;
} }

View File

@ -19,14 +19,17 @@ public class RequestHandlerGithub extends RequestHandlerZip {
} }
// TODO: is caching really needed, if HTTPURLConnection follows redirects correctly? // TODO: is caching really needed, if HTTPURLConnection follows redirects correctly?
private Map<String, URI> zipUriMap = new HashMap<String, URI>(); private Map<String, URI> zipUriMap = new HashMap<>();
final ReentrantReadWriteLock zipUriLock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock zipUriLock = new ReentrantReadWriteLock();
private static Pattern repoMatcherPattern = Pattern.compile("/([\\w.-]+/[\\w.-]+).*"); private static Pattern repoMatcherPattern = Pattern.compile("/([\\w.-]+/[\\w.-]+).*");
private String getRepoName(URI loc) { private String getRepoName(URI loc) {
Matcher matcher = repoMatcherPattern.matcher(loc.getPath()); Matcher matcher = repoMatcherPattern.matcher(loc.getPath());
matcher.matches(); if (matcher.matches()) {
return matcher.group(1); return matcher.group(1);
} else {
return null;
}
} }
@Override @Override
@ -57,8 +60,11 @@ public class RequestHandlerGithub extends RequestHandlerZip {
private String getBranch(URI loc) { private String getBranch(URI loc) {
Matcher matcher = branchMatcherPattern.matcher(loc.getPath()); Matcher matcher = branchMatcherPattern.matcher(loc.getPath());
matcher.matches(); if (matcher.matches()) {
return matcher.group(1); return matcher.group(1);
} else {
return null;
}
} }
@Override @Override

View File

@ -1,5 +1,10 @@
package link.infra.packwiz.installer.request.handlers; package link.infra.packwiz.installer.request.handlers;
import okio.Buffer;
import okio.BufferedSource;
import okio.Okio;
import okio.Source;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
@ -11,14 +16,9 @@ import java.util.function.Predicate;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import okio.Buffer;
import okio.BufferedSource;
import okio.Okio;
import okio.Source;
public abstract class RequestHandlerZip extends RequestHandlerHTTP { public abstract class RequestHandlerZip extends RequestHandlerHTTP {
protected final boolean modeHasFolder; private final boolean modeHasFolder;
public RequestHandlerZip(boolean modeHasFolder) { public RequestHandlerZip(boolean modeHasFolder) {
this.modeHasFolder = modeHasFolder; this.modeHasFolder = modeHasFolder;
@ -35,14 +35,14 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
private class ZipReader { private class ZipReader {
private final ZipInputStream zis; private final ZipInputStream zis;
private final Map<URI, Buffer> readFiles = new HashMap<URI, Buffer>(); private final Map<URI, Buffer> readFiles = new HashMap<>();
// Write lock implies access to ZipInputStream - only 1 thread must read at a time! // Write lock implies access to ZipInputStream - only 1 thread must read at a time!
final ReentrantLock filesLock = new ReentrantLock(); final ReentrantLock filesLock = new ReentrantLock();
private ZipEntry entry; private ZipEntry entry;
private final BufferedSource zipSource; private final BufferedSource zipSource;
public ZipReader(Source zip) { ZipReader(Source zip) {
zis = new ZipInputStream(Okio.buffer(zip).inputStream()); zis = new ZipInputStream(Okio.buffer(zip).inputStream());
zipSource = Okio.buffer(Okio.source(zis)); zipSource = Okio.buffer(Okio.source(zis));
} }
@ -71,7 +71,7 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
} }
} }
public Source getFileSource(URI loc) throws Exception { Source getFileSource(URI loc) throws Exception {
filesLock.lock(); filesLock.lock();
// Assume files are only read once, allow GC by removing // Assume files are only read once, allow GC by removing
Buffer file = readFiles.remove(loc); Buffer file = readFiles.remove(loc);
@ -82,13 +82,10 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
file = findFile(loc); file = findFile(loc);
filesLock.unlock(); filesLock.unlock();
if (file != null) { return file;
return file;
}
return null;
} }
public URI findInZip(Predicate<URI> matches) throws Exception { URI findInZip(Predicate<URI> matches) throws Exception {
filesLock.lock(); filesLock.lock();
for (URI file : readFiles.keySet()) { for (URI file : readFiles.keySet()) {
if (matches.test(file)) { if (matches.test(file)) {
@ -115,8 +112,8 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
} }
private final Map<URI, ZipReader> cache = new HashMap<URI, ZipReader>(); private final Map<URI, ZipReader> cache = new HashMap<>();
final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
protected abstract URI getZipUri(URI loc) throws Exception; protected abstract URI getZipUri(URI loc) throws Exception;