Modpack updates
This commit is contained in:
@@ -17,16 +17,22 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.GameBuilder;
|
||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Install a downloaded CurseForge modpack.
|
||||
@@ -40,6 +46,8 @@ public final class CurseInstallTask extends Task {
|
||||
private final File zipFile;
|
||||
private final CurseManifest manifest;
|
||||
private final String name;
|
||||
private final File run;
|
||||
private final ModpackConfiguration<CurseManifest> config;
|
||||
private final List<Task> dependents = new LinkedList<>();
|
||||
private final List<Task> dependencies = new LinkedList<>();
|
||||
|
||||
@@ -57,10 +65,11 @@ public final class CurseInstallTask extends Task {
|
||||
this.zipFile = zipFile;
|
||||
this.manifest = manifest;
|
||||
this.name = name;
|
||||
this.repository = dependencyManager.getGameRepository();
|
||||
this.run = repository.getRunDirectory(name);
|
||||
|
||||
repository = dependencyManager.getGameRepository();
|
||||
|
||||
if (repository.hasVersion(name))
|
||||
File json = new File(run, "modpack.json");
|
||||
if (repository.hasVersion(name) && !json.exists())
|
||||
throw new IllegalArgumentException("Version " + name + " already exists.");
|
||||
|
||||
GameBuilder builder = dependencyManager.gameBuilder().name(name).gameVersion(manifest.getMinecraft().getGameVersion());
|
||||
@@ -68,6 +77,15 @@ public final class CurseInstallTask extends Task {
|
||||
if (modLoader.getId().startsWith("forge-"))
|
||||
builder.version("forge", modLoader.getId().substring("forge-".length()));
|
||||
dependents.add(builder.buildAsync());
|
||||
|
||||
ModpackConfiguration<CurseManifest> config = null;
|
||||
try {
|
||||
if (json.exists())
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<CurseManifest>>(){}.getType());
|
||||
} catch (JsonParseException | IOException ignore) {
|
||||
}
|
||||
this.config = config;
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, manifest.getOverrides(), Constants.truePredicate(), config));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,10 +100,17 @@ public final class CurseInstallTask extends Task {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
File run = repository.getRunDirectory(name);
|
||||
CompressingUtils.unzip(zipFile, run, manifest.getOverrides());
|
||||
if (config != null)
|
||||
for (CurseManifestFile oldCurseManifestFile : config.getManifest().getFiles()) {
|
||||
if (oldCurseManifestFile.getFileName() == null) continue;
|
||||
File oldFile = new File(run, "mods/" + oldCurseManifestFile.getFileName());
|
||||
if (!oldFile.exists()) continue;
|
||||
if (manifest.getFiles().stream().noneMatch(oldCurseManifestFile::equals))
|
||||
oldFile.delete();
|
||||
}
|
||||
|
||||
dependencies.add(new CurseCompletionTask(dependencyManager, name));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, manifest.getOverrides(), false, manifest, new File(run, "modpack.json")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jackhuang.hmcl.util.NetworkUtils;
|
||||
import org.jackhuang.hmcl.util.Validation;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -84,4 +85,18 @@ public final class CurseManifestFile implements Validation {
|
||||
public CurseManifestFile setFileName(String fileName) {
|
||||
return new CurseManifestFile(projectID, fileID, fileName, required);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CurseManifestFile that = (CurseManifestFile) o;
|
||||
return projectID == that.projectID &&
|
||||
fileID == that.fileID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(projectID, fileID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,5 +17,57 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
public class MinecraftInstanceTask {
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.DigestUtils;
|
||||
import org.jackhuang.hmcl.util.FileUtils;
|
||||
import org.jackhuang.hmcl.util.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class MinecraftInstanceTask<T> extends Task {
|
||||
|
||||
private final File zipFile;
|
||||
private final String subDirectory;
|
||||
private final File jsonFile;
|
||||
private final T manifest;
|
||||
|
||||
public MinecraftInstanceTask(File zipFile, String subDirectory, T manifest, File jsonFile) {
|
||||
this.zipFile = zipFile;
|
||||
this.subDirectory = subDirectory;
|
||||
this.manifest = manifest;
|
||||
this.jsonFile = jsonFile;
|
||||
|
||||
if (!zipFile.exists())
|
||||
throw new IllegalArgumentException("File " + zipFile + " does not exist. Cannot parse this modpack.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
Map<String, ModpackConfiguration.FileInformation> overrides = new HashMap<>();
|
||||
|
||||
byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
|
||||
try (ZipArchiveInputStream zip = new ZipArchiveInputStream(new FileInputStream(zipFile), null, true, true)) {
|
||||
ArchiveEntry entry;
|
||||
while ((entry = zip.getNextEntry()) != null) {
|
||||
String path = entry.getName();
|
||||
if (!path.startsWith(subDirectory) || entry.isDirectory())
|
||||
continue;
|
||||
path = path.substring(subDirectory.length());
|
||||
if (path.startsWith("/") || path.startsWith("\\"))
|
||||
path = path.substring(1);
|
||||
|
||||
overrides.put(path, new ModpackConfiguration.FileInformation(
|
||||
path, DigestUtils.sha1Hex(zip)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
FileUtils.writeText(jsonFile, Constants.GSON.toJson(new ModpackConfiguration<>(manifest, overrides)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
import org.jackhuang.hmcl.util.Validation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
@Immutable
|
||||
public final class ModpackConfiguration<T> implements Validation {
|
||||
|
||||
private final T manifest;
|
||||
|
||||
private final Map<String, FileInformation> overrides;
|
||||
|
||||
public ModpackConfiguration() {
|
||||
this(null, Collections.emptyMap());
|
||||
}
|
||||
|
||||
public ModpackConfiguration(T manifest, Map<String, FileInformation> overrides) {
|
||||
this.manifest = manifest;
|
||||
this.overrides = overrides;
|
||||
}
|
||||
|
||||
public T getManifest() {
|
||||
return manifest;
|
||||
}
|
||||
|
||||
public ModpackConfiguration<T> setManifest(T manifest) {
|
||||
return new ModpackConfiguration<>(manifest, overrides);
|
||||
}
|
||||
|
||||
public ModpackConfiguration<T> setOverrides(Map<String, FileInformation> overrides) {
|
||||
return new ModpackConfiguration<>(manifest, overrides);
|
||||
}
|
||||
|
||||
public Map<String, FileInformation> getOverrides() {
|
||||
return Collections.unmodifiableMap(overrides);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws JsonParseException {
|
||||
if (manifest == null)
|
||||
throw new JsonParseException("MinecraftInstanceConfiguration missing `manifest`");
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class FileInformation implements Validation {
|
||||
private final String location; // relative
|
||||
private final String hash;
|
||||
private final String downloadURL;
|
||||
|
||||
public FileInformation() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public FileInformation(String location, String hash) {
|
||||
this(location, hash, null);
|
||||
}
|
||||
|
||||
public FileInformation(String location, String hash, String downloadURL) {
|
||||
this.location = location;
|
||||
this.hash = hash;
|
||||
this.downloadURL = downloadURL;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public String getDownloadURL() {
|
||||
return downloadURL;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws JsonParseException {
|
||||
if (location == null)
|
||||
throw new JsonParseException("FileInformation missing `location`.");
|
||||
if (hash == null)
|
||||
throw new JsonParseException("FileInformation missing file hash code.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.DigestUtils;
|
||||
import org.jackhuang.hmcl.util.FileUtils;
|
||||
import org.jackhuang.hmcl.util.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ModpackInstallTask<T> extends Task {
|
||||
|
||||
private final File modpackFile;
|
||||
private final File dest;
|
||||
private final String subDirectory;
|
||||
private final Map<String, ModpackConfiguration.FileInformation> overrides;
|
||||
private final Predicate<String> callback;
|
||||
|
||||
public ModpackInstallTask(File modpackFile, File dest, String subDirectory, Predicate<String> callback, ModpackConfiguration<T> oldConfiguration) {
|
||||
this.modpackFile = modpackFile;
|
||||
this.dest = dest;
|
||||
this.subDirectory = subDirectory;
|
||||
this.callback = callback;
|
||||
|
||||
if (oldConfiguration == null)
|
||||
overrides = Collections.emptyMap();
|
||||
else
|
||||
overrides = oldConfiguration.getOverrides();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
Set<String> entries = new HashSet<>();
|
||||
byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
|
||||
if (!FileUtils.makeDirectory(dest))
|
||||
throw new IOException("Unable to make directory " + dest);
|
||||
try (ZipArchiveInputStream zipStream = new ZipArchiveInputStream(new FileInputStream(modpackFile), null, true, true)) {
|
||||
ArchiveEntry entry;
|
||||
while ((entry = zipStream.getNextEntry()) != null) {
|
||||
String path = entry.getName();
|
||||
|
||||
if (!path.startsWith(subDirectory))
|
||||
continue;
|
||||
path = path.substring(subDirectory.length());
|
||||
if (path.startsWith("/") || path.startsWith("\\"))
|
||||
path = path.substring(1);
|
||||
File entryFile = new File(dest, path);
|
||||
|
||||
if (callback != null)
|
||||
if (!callback.test(path))
|
||||
continue;
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!FileUtils.makeDirectory(entryFile))
|
||||
throw new IOException("Unable to make directory: " + entryFile);
|
||||
} else {
|
||||
if (!FileUtils.makeDirectory(entryFile.getAbsoluteFile().getParentFile()))
|
||||
throw new IOException("Unable to make parent directory for file " + entryFile);
|
||||
|
||||
entries.add(path);
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(IOUtils.DEFAULT_BUFFER_SIZE);
|
||||
IOUtils.copyTo(zipStream, os, buf);
|
||||
byte[] data = os.toByteArray();
|
||||
|
||||
if (!overrides.containsKey(path) || entryFile.exists()) {
|
||||
String oldHash = DigestUtils.sha1Hex(new FileInputStream(entryFile));
|
||||
String newHash = DigestUtils.sha1Hex(new ByteArrayInputStream(data));
|
||||
if (!oldHash.equals(newHash)) {
|
||||
try (FileOutputStream fos = new FileOutputStream(entryFile)) {
|
||||
IOUtils.copyTo(new ByteArrayInputStream(data), fos, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String path : overrides.keySet()) {
|
||||
File original = new File(dest, path);
|
||||
if (original.exists() && !entries.contains(path))
|
||||
original.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
@@ -25,12 +27,10 @@ import org.jackhuang.hmcl.game.Arguments;
|
||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.CompressingUtils;
|
||||
import org.jackhuang.hmcl.util.Constants;
|
||||
import org.jackhuang.hmcl.util.IOUtils;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -57,14 +57,24 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
this.name = name;
|
||||
this.repository = dependencyManager.getGameRepository();
|
||||
this.run = repository.getRunDirectory(name);
|
||||
|
||||
if (repository.hasVersion(name))
|
||||
|
||||
File json = new File(run, "modpack.json");
|
||||
if (repository.hasVersion(name) && !json.exists())
|
||||
throw new IllegalArgumentException("Version " + name + " already exists.");
|
||||
dependents.add(dependencyManager.gameBuilder().name(name).gameVersion(manifest.getGameVersion()).buildAsync());
|
||||
onDone().register(event -> {
|
||||
if (event.isFailed())
|
||||
repository.removeVersionFromDisk(name);
|
||||
});
|
||||
|
||||
ModpackConfiguration<MultiMCInstanceConfiguration> config = null;
|
||||
try {
|
||||
if (json.exists())
|
||||
config = Constants.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<MultiMCInstanceConfiguration>>(){}.getType());
|
||||
} catch (JsonParseException | IOException ignore) {
|
||||
}
|
||||
|
||||
dependents.add(new ModpackInstallTask<>(zipFile, run, manifest.getName() + "/minecraft/", Constants.truePredicate(), config));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,8 +90,7 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
Version version = Objects.requireNonNull(repository.readVersionJson(name));
|
||||
CompressingUtils.unzip(zipFile, run, manifest.getName() + "/minecraft/", null, false, true);
|
||||
|
||||
|
||||
try (ZipFile zip = new ZipFile(zipFile)) {
|
||||
for (ZipArchiveEntry entry : Lang.asIterable(zip.getEntries())) {
|
||||
// ensure that this entry is in folder 'patches' and is a json file.
|
||||
@@ -99,8 +108,9 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies.add(new VersionJsonSaveTask(repository, version));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, manifest.getName() + "/minecraft/", manifest, new File(run, "modpack.json")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -107,6 +107,10 @@ public class FileDownloadTask extends Task {
|
||||
return url;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
URL currentURL = url;
|
||||
@@ -189,12 +193,12 @@ public class FileDownloadTask extends Task {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
} else {
|
||||
if (file.exists())
|
||||
file.delete();
|
||||
if (file.exists() || !file.delete())
|
||||
throw new IOException("Unable to delete existent file " + file);
|
||||
if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile()))
|
||||
throw new IOException("Cannot make parent directory " + file);
|
||||
throw new IOException("Unable to make parent directory " + file);
|
||||
if (!temp.renameTo(file))
|
||||
throw new IOException("Cannot move temp file to " + file);
|
||||
throw new IOException("Unable move temp file to " + file);
|
||||
}
|
||||
|
||||
if (downloaded != contentLength)
|
||||
|
||||
@@ -52,6 +52,16 @@ public abstract class Task {
|
||||
this.significance = significance;
|
||||
}
|
||||
|
||||
private TaskState state = TaskState.READY;
|
||||
|
||||
public TaskState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
void setState(TaskState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* The scheduler that decides how this task runs.
|
||||
*/
|
||||
@@ -111,14 +121,14 @@ public abstract class Task {
|
||||
/**
|
||||
* The collection of sub-tasks that should execute **before** this task running.
|
||||
*/
|
||||
public Collection<Task> getDependents() {
|
||||
public Collection<? extends Task> getDependents() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* The collection of sub-tasks that should execute **after** this task running.
|
||||
*/
|
||||
public Collection<Task> getDependencies() {
|
||||
public Collection<? extends Task> getDependencies() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@@ -298,4 +308,11 @@ public abstract class Task {
|
||||
return this == MAJOR;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TaskState {
|
||||
READY,
|
||||
RUNNING,
|
||||
SUCCEEDED,
|
||||
FAILED
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ public final class TaskExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean executeTasks(Collection<Task> tasks) throws InterruptedException {
|
||||
private boolean executeTasks(Collection<? extends Task> tasks) throws InterruptedException {
|
||||
if (tasks.isEmpty())
|
||||
return true;
|
||||
|
||||
@@ -140,8 +140,12 @@ public final class TaskExecutor {
|
||||
}
|
||||
|
||||
private boolean executeTask(Task task) {
|
||||
if (canceled)
|
||||
if (canceled) {
|
||||
task.setState(Task.TaskState.FAILED);
|
||||
return false;
|
||||
}
|
||||
|
||||
task.setState(Task.TaskState.RUNNING);
|
||||
|
||||
if (task.getSignificance().shouldLog())
|
||||
Logging.LOG.log(Level.FINE, "Executing task: {0}", task.getName());
|
||||
@@ -165,7 +169,7 @@ public final class TaskExecutor {
|
||||
|
||||
if (!executeTasks(task.getDependencies()) && task.isRelyingOnDependencies()) {
|
||||
Logging.LOG.severe("Subtasks failed for " + task.getName());
|
||||
return false;
|
||||
throw new SilentException();
|
||||
}
|
||||
|
||||
flag = true;
|
||||
@@ -182,10 +186,8 @@ public final class TaskExecutor {
|
||||
task.onDone().fireEvent(new TaskEvent(this, task, true));
|
||||
taskListeners.forEach(it -> it.onFailed(task, e));
|
||||
}
|
||||
} catch (SilentException e) {
|
||||
} catch (SilentException | RejectedExecutionException e) {
|
||||
// do nothing
|
||||
} catch (RejectedExecutionException e) {
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
lastException = e;
|
||||
Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e);
|
||||
@@ -194,6 +196,7 @@ public final class TaskExecutor {
|
||||
} finally {
|
||||
task.setVariables(null);
|
||||
}
|
||||
task.setState(flag ? Task.TaskState.SUCCEEDED : Task.TaskState.FAILED);
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class CompressingUtils {
|
||||
* @param sourceDir the source directory or a file.
|
||||
* @param zipFile the location of dest zip file.
|
||||
* @param pathNameCallback callback(pathName, isDirectory) returns your modified pathName
|
||||
* @throws IOException
|
||||
* @throws IOException if there is filesystem error.
|
||||
*/
|
||||
public static void zip(File sourceDir, File zipFile, BiFunction<String, Boolean, String> pathNameCallback) throws IOException {
|
||||
try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(new FileOutputStream(zipFile))) {
|
||||
@@ -71,6 +71,8 @@ public final class CompressingUtils {
|
||||
File[] files = src.isDirectory() ? src.listFiles() : new File[] { src };
|
||||
String pathName;// the relative path (relative to the root directory to be compressed)
|
||||
byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
|
||||
|
||||
if (files == null) return;
|
||||
for (File file : files)
|
||||
if (file.isDirectory()) {
|
||||
pathName = file.getPath().substring(basePath.length() + 1) + "/";
|
||||
@@ -152,48 +154,39 @@ public final class CompressingUtils {
|
||||
* @param callback will be called for every entry in the zip file, returns false if you dont want this file being uncompressed.
|
||||
* @param ignoreExistentFile true if skip all existent files.
|
||||
* @param allowStoredEntriesWithDataDescriptor whether the zip stream will try to read STORED entries that use a data descriptor
|
||||
* @throws IOException
|
||||
* @throws IOException if zip file is malformed or filesystem error.
|
||||
*/
|
||||
public static void unzip(File src, File dest, String subDirectory, Predicate<String> callback, boolean ignoreExistentFile, boolean allowStoredEntriesWithDataDescriptor) throws IOException {
|
||||
byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
|
||||
dest.mkdirs();
|
||||
try (ZipArchiveInputStream zipFile = new ZipArchiveInputStream(new FileInputStream(src), null, true, allowStoredEntriesWithDataDescriptor)) {
|
||||
if (src.exists()) {
|
||||
String strPath, gbkPath, strtemp;
|
||||
strPath = dest.getAbsolutePath();
|
||||
ArchiveEntry zipEnt;
|
||||
while ((zipEnt = zipFile.getNextEntry()) != null) {
|
||||
gbkPath = zipEnt.getName();
|
||||
if (!FileUtils.makeDirectory(dest))
|
||||
throw new IOException("Unable to make directory " + dest);
|
||||
try (ZipArchiveInputStream zipStream = new ZipArchiveInputStream(new FileInputStream(src), null, true, allowStoredEntriesWithDataDescriptor)) {
|
||||
ArchiveEntry entry;
|
||||
while ((entry = zipStream.getNextEntry()) != null) {
|
||||
String path = entry.getName();
|
||||
|
||||
if (!gbkPath.startsWith(subDirectory))
|
||||
if (!path.startsWith(subDirectory))
|
||||
continue;
|
||||
path = path.substring(subDirectory.length());
|
||||
if (path.startsWith("/") || path.startsWith("\\"))
|
||||
path = path.substring(1);
|
||||
File entryFile = new File(dest, path);
|
||||
|
||||
if (callback != null)
|
||||
if (!callback.test(path))
|
||||
continue;
|
||||
gbkPath = gbkPath.substring(subDirectory.length());
|
||||
if (gbkPath.startsWith("/") || gbkPath.startsWith("\\"))
|
||||
gbkPath = gbkPath.substring(1);
|
||||
strtemp = strPath + File.separator + gbkPath;
|
||||
|
||||
if (callback != null)
|
||||
if (!callback.test(gbkPath))
|
||||
continue;
|
||||
if (entry.isDirectory()) {
|
||||
if (!FileUtils.makeDirectory(entryFile))
|
||||
throw new IOException("Unable to make directory: " + entryFile);
|
||||
} else {
|
||||
if (!FileUtils.makeDirectory(entryFile.getAbsoluteFile().getParentFile()))
|
||||
throw new IOException("Unable to make parent directory for file " + entryFile);
|
||||
|
||||
if (zipEnt.isDirectory()) {
|
||||
File dir = new File(strtemp);
|
||||
dir.mkdirs();
|
||||
} else {
|
||||
// create directories
|
||||
String strsubdir = gbkPath;
|
||||
for (int i = 0; i < strsubdir.length(); i++)
|
||||
if (strsubdir.substring(i, i + 1).equalsIgnoreCase("/")) {
|
||||
String temp = strPath + File.separator + strsubdir.substring(0, i);
|
||||
File subdir = new File(temp);
|
||||
if (!subdir.exists())
|
||||
subdir.mkdir();
|
||||
}
|
||||
if (ignoreExistentFile && new File(strtemp).exists())
|
||||
continue;
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(strtemp))) {
|
||||
IOUtils.copyTo(zipFile, fos, buf);
|
||||
}
|
||||
if (ignoreExistentFile && entryFile.exists())
|
||||
continue;
|
||||
try (FileOutputStream fos = new FileOutputStream(entryFile)) {
|
||||
IOUtils.copyTo(zipStream, fos, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
@@ -86,4 +87,11 @@ public final class Constants {
|
||||
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory.INSTANCE)
|
||||
.create();
|
||||
|
||||
public static <T> Predicate<T> truePredicate() {
|
||||
return s -> true;
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> falsePredicate() {
|
||||
return s -> false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user