Try to fix ConcurrentModificationException

This commit is contained in:
huanghongxun 2019-08-25 15:35:17 +08:00
parent 93837a28fa
commit a9feb65fc8
16 changed files with 40 additions and 26 deletions

View File

@ -25,6 +25,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.Zipper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -75,7 +76,7 @@ public class HMCLModpackExportTask extends Task<Void> {
Version mv = repository.getResolvedVersion(version);
String gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version))
.orElseThrow(() -> new IllegalStateException("Cannot parse the version of " + version));
.orElseThrow(() -> new IOException("Cannot parse the version of " + version));
zip.putTextFile(JsonUtils.GSON.toJson(mv.setJar(gameVersion)), "minecraft/pack.json"); // Making "jar" to gameVersion is to be compatible with old HMCL.
zip.putTextFile(JsonUtils.GSON.toJson(modpack.setGameVersion(gameVersion)), "modpack.json"); // Newer HMCL only reads 'gameVersion' field.
}

View File

@ -123,7 +123,7 @@ public final class ModpackHelper {
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)
.whenComplete(Schedulers.defaultScheduler(), success, failure)
.thenComposeAsync(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name));
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
else throw new IllegalArgumentException("Unrecognized modpack: " + modpack);
}
public static Task<Void> getUpdateTask(Profile profile, File zipFile, Charset charset, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException, MismatchedModpackTypeException {

View File

@ -18,9 +18,11 @@
package org.jackhuang.hmcl.ui.download;
import javafx.scene.Node;
import org.jackhuang.hmcl.download.DefaultDependencyManager;
import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.download.RemoteVersion;
import org.jackhuang.hmcl.download.VersionMismatchException;
import org.jackhuang.hmcl.download.fabric.FabricInstallTask;
import org.jackhuang.hmcl.download.game.LibraryDownloadException;
import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask;
import org.jackhuang.hmcl.game.Version;
@ -114,9 +116,10 @@ public final class InstallerWizardProvider implements WizardProvider {
} else {
Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageType.ERROR, next);
}
} else if (exception instanceof OptiFineInstallTask.UnsupportedOptiFineInstallationException) {
} else if (exception instanceof OptiFineInstallTask.UnsupportedOptiFineInstallationException ||
exception instanceof FabricInstallTask.UnsupportedFabricInstallationException) {
Controllers.dialog(i18n("install.failed.optifine_conflict"), i18n("install.failed"), MessageType.ERROR, next);
} else if (exception instanceof UnsupportedOperationException) {
} else if (exception instanceof DefaultDependencyManager.UnsupportedLibraryInstallerException) {
Controllers.dialog(i18n("install.failed.install_online"), i18n("install.failed"), MessageType.ERROR, next);
} else if (exception instanceof VersionMismatchException) {
VersionMismatchException e = ((VersionMismatchException) exception);

View File

@ -132,7 +132,7 @@ install.failed.downloading=Failed to install due to some files not downloaded su
install.failed.downloading.detail=Failed to download file: %s
install.failed.downloading.timeout=Download timed out: %s
install.failed.install_online=Unable to recognize what you provided installer file is
install.failed.optifine_conflict=OptiFine and Forge are both installed simultaneously on Minecraft 1.13
install.failed.optifine_conflict=Fabric, OptiFine and Forge are both installed simultaneously on Minecraft 1.13
install.failed.version_mismatch=The library requires game version %s, but actual version is %s.
install.installer.choose=Choose a %s version
install.installer.fabric=Fabric

View File

@ -94,7 +94,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
VersionList<?> versionList = getVersionList(libraryId);
return versionList.loadAsync(gameVersion, getDownloadProvider())
.thenComposeAsync(() -> installLibraryAsync(baseVersion, versionList.getVersion(gameVersion, libraryVersion)
.orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion))));
.orElseThrow(() -> new IOException("Remote library " + libraryId + " has no version " + libraryVersion))));
}
@Override
@ -126,12 +126,15 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
} catch (IOException ignore) {
}
throw new UnsupportedOperationException("Library cannot be recognized");
throw new UnsupportedLibraryInstallerException();
})
.thenApplyAsync(oldVersion::addPatch)
.thenComposeAsync(repository::save);
}
public static class UnsupportedLibraryInstallerException extends Exception {
}
/**
* Remove installed library.
* Will try to remove libraries and patches.

View File

@ -65,7 +65,7 @@ public final class FabricInstallTask extends Task<Version> {
}
@Override
public void preExecute() {
public void preExecute() throws Exception {
if (!Objects.equals("net.minecraft.client.main.Main", version.resolve(dependencyManager.getGameRepository()).getMainClass()))
throw new UnsupportedFabricInstallationException();
}
@ -128,6 +128,6 @@ public final class FabricInstallTask extends Task<Version> {
return new Version("net.fabricmc", loaderVersion, 30000, arguments, mainClass, libraries);
}
public static class UnsupportedFabricInstallationException extends UnsupportedOperationException {
public static class UnsupportedFabricInstallationException extends Exception {
}
}

View File

@ -38,6 +38,7 @@ import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.SystemUtils;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
@ -233,7 +234,7 @@ public class ForgeNewInstallTask extends Task<Version> {
List<String> args = processor.getArgs().stream().map(arg -> {
String parsed = parseLiteral(arg, data, ExceptionalFunction.identity());
if (parsed == null)
throw new IllegalStateException("Invalid forge installation configuration");
throw new IOException("Invalid forge installation configuration");
return parsed;
}).collect(Collectors.toList());
@ -242,7 +243,7 @@ public class ForgeNewInstallTask extends Task<Version> {
LOG.info("Executing external processor " + processor.getJar().toString() + ", command line: " + new CommandBuilder().addAll(command).toString());
int exitCode = SystemUtils.callExternalProcess(command);
if (exitCode != 0)
throw new IllegalStateException("Game processor exited abnormally");
throw new IOException("Game processor exited abnormally");
for (Map.Entry<String, String> entry : outputs.entrySet()) {
Path artifact = Paths.get(entry.getKey());

View File

@ -24,6 +24,7 @@ import org.jackhuang.hmcl.task.GetTask;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
@ -61,9 +62,9 @@ public final class VersionJsonDownloadTask extends Task<String> {
}
@Override
public void execute() {
public void execute() throws IOException {
RemoteVersion remoteVersion = gameVersionList.getVersion(gameVersion, gameVersion)
.orElseThrow(() -> new IllegalStateException("Cannot find specific version " + gameVersion + " in remote repository"));
.orElseThrow(() -> new IOException("Cannot find specific version " + gameVersion + " in remote repository"));
String jsonURL = dependencyManager.getDownloadProvider().injectURL(remoteVersion.getUrl());
dependencies.add(new GetTask(NetworkUtils.toURL(jsonURL)).storeTo(this::setResult));
}

View File

@ -149,7 +149,7 @@ public final class OptiFineInstallTask extends Task<Version> {
gameRepository.getLibraryFile(version, optiFineLibrary).toString()
);
if (exitCode != 0)
throw new IllegalStateException("OptiFine patcher failed");
throw new IOException("OptiFine patcher failed");
} else {
FileUtils.copyFile(dest, gameRepository.getLibraryFile(version, optiFineLibrary).toPath());
}
@ -188,7 +188,7 @@ public final class OptiFineInstallTask extends Task<Version> {
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult()));
}
public static class UnsupportedOptiFineInstallationException extends UnsupportedOperationException {
public static class UnsupportedOptiFineInstallationException extends Exception {
}
/**

View File

@ -20,6 +20,7 @@ package org.jackhuang.hmcl.event;
import org.jackhuang.hmcl.util.Logging;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
*
@ -27,12 +28,11 @@ import java.util.HashMap;
*/
public final class EventBus {
private final HashMap<Class<?>, EventManager<?>> events = new HashMap<>();
private final ConcurrentHashMap<Class<?>, EventManager<?>> events = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
public <T extends Event> EventManager<T> channel(Class<T> clazz) {
if (!events.containsKey(clazz))
events.put(clazz, new EventManager<>());
events.putIfAbsent(clazz, new EventManager<>());
return (EventManager<T>) events.get(clazz);
}

View File

@ -22,6 +22,7 @@ import org.jackhuang.hmcl.util.SimpleMultimap;
import java.lang.ref.WeakReference;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Consumer;
/**
@ -31,7 +32,7 @@ import java.util.function.Consumer;
public final class EventManager<T extends Event> {
private final SimpleMultimap<EventPriority, Consumer<T>> handlers
= new SimpleMultimap<>(() -> new EnumMap<>(EventPriority.class), HashSet::new);
= new SimpleMultimap<>(() -> new EnumMap<>(EventPriority.class), CopyOnWriteArraySet::new);
public Consumer<T> registerWeak(Consumer<T> consumer) {
register(new WeakListener(consumer));

View File

@ -54,6 +54,6 @@ public final class AssetObject implements Validation {
@Override
public void validate() throws JsonParseException {
if (StringUtils.isBlank(hash) || hash.length() < 2)
throw new IllegalStateException("AssetObject hash cannot be blank.");
throw new JsonParseException("AssetObject hash cannot be blank.");
}
}

View File

@ -91,7 +91,7 @@ public class World {
private void loadFromZipImpl(Path root) throws IOException {
Path levelDat = root.resolve("level.dat");
if (!Files.exists(levelDat))
throw new IllegalArgumentException("Not a valid world zip file since level.dat cannot be found.");
throw new IOException("Not a valid world zip file since level.dat cannot be found.");
getWorldName(levelDat);
}
@ -116,6 +116,9 @@ public class World {
CompoundTag nbt = parseLevelDat(levelDat);
CompoundTag data = nbt.get("Data");
if (data == null)
throw new IOException("level.dat missing Data");
if (data.get("LevelName") instanceof StringTag)
worldName = data.<StringTag>get("LevelName").getValue();
else
@ -209,7 +212,7 @@ public class World {
return Files.list(savesDir).flatMap(world -> {
try {
return Stream.of(new World(world));
} catch (IOException | IllegalArgumentException e) {
} catch (IOException e) {
Logging.LOG.log(Level.WARNING, "Failed to read world " + world, e);
return Stream.empty();
}

View File

@ -27,6 +27,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.Zipper;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
@ -80,7 +81,7 @@ public class MultiMCModpackExportTask extends Task<Void> {
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(repository.getResolvedPreservingPatchesVersion(versionId));
String gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(versionId))
.orElseThrow(() -> new IllegalStateException("Cannot parse the version of " + versionId));
.orElseThrow(() -> new IOException("Cannot parse the version of " + versionId));
List<MultiMCManifest.MultiMCManifestComponent> components = new ArrayList<>();
components.add(new MultiMCManifest.MultiMCManifestComponent(true, false, "net.minecraft", gameVersion));
analyzer.getVersion(FORGE).ifPresent(forgeVersion ->

View File

@ -292,7 +292,7 @@ public class FileDownloadTask extends Task<Void> {
}
if (downloaded != contentLength)
throw new IllegalStateException("Unexpected file size: " + downloaded + ", expected: " + contentLength);
throw new IOException("Unexpected file size: " + downloaded + ", expected: " + contentLength);
// Integrity check
if (integrityCheck != null) {
@ -312,7 +312,7 @@ public class FileDownloadTask extends Task<Void> {
}
return;
} catch (IOException | IllegalStateException e) {
} catch (IOException e) {
if (temp != null)
temp.toFile().delete();
exception = e;

View File

@ -64,7 +64,7 @@ public final class TaskExecutor {
Logging.LOG.log(Level.WARNING, "An exception occurred in task execution", exception);
Throwable resolvedException = resolveException(exception);
if (resolvedException instanceof RuntimeException) {
if (resolvedException instanceof RuntimeException && !(resolvedException instanceof CancellationException)) {
// Track uncaught RuntimeException which are thrown mostly by our mistake
if (uncaughtExceptionHandler != null)
uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), resolvedException);