mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-26 04:25:31 +01:00
Add storages command
This commit is contained in:
parent
0fce08dd62
commit
004f296b5e
@ -38,15 +38,13 @@
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import de.bluecolored.bluemap.common.config.ConfigurationException;
|
||||
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||
import de.bluecolored.bluemap.common.plugin.PluginState;
|
||||
import de.bluecolored.bluemap.common.plugin.text.Text;
|
||||
import de.bluecolored.bluemap.common.plugin.text.TextColor;
|
||||
import de.bluecolored.bluemap.common.plugin.text.TextFormat;
|
||||
import de.bluecolored.bluemap.common.rendermanager.MapPurgeTask;
|
||||
import de.bluecolored.bluemap.common.rendermanager.MapUpdateTask;
|
||||
import de.bluecolored.bluemap.common.rendermanager.RenderTask;
|
||||
import de.bluecolored.bluemap.common.rendermanager.WorldRegionRenderTask;
|
||||
import de.bluecolored.bluemap.common.rendermanager.*;
|
||||
import de.bluecolored.bluemap.common.serverinterface.CommandSource;
|
||||
import de.bluecolored.bluemap.core.BlueMap;
|
||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||
@ -54,15 +52,13 @@
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.map.BmMap;
|
||||
import de.bluecolored.bluemap.core.map.MapRenderState;
|
||||
import de.bluecolored.bluemap.core.storage.Storage;
|
||||
import de.bluecolored.bluemap.core.world.Block;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@ -88,26 +84,22 @@ public Commands(Plugin plugin, CommandDispatcher<S> dispatcher, Function<S, Comm
|
||||
|
||||
public void init() {
|
||||
// commands
|
||||
LiteralCommandNode<S> baseCommand =
|
||||
literal("bluemap")
|
||||
LiteralCommandNode<S> baseCommand = literal("bluemap")
|
||||
.requires(requirementsUnloaded("bluemap.status"))
|
||||
.executes(this::statusCommand)
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> versionCommand =
|
||||
literal("version")
|
||||
LiteralCommandNode<S> versionCommand = literal("version")
|
||||
.requires(requirementsUnloaded("bluemap.version"))
|
||||
.executes(this::versionCommand)
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> helpCommand =
|
||||
literal("help")
|
||||
LiteralCommandNode<S> helpCommand = literal("help")
|
||||
.requires(requirementsUnloaded("bluemap.help"))
|
||||
.executes(this::helpCommand)
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> reloadCommand =
|
||||
literal("reload")
|
||||
LiteralCommandNode<S> reloadCommand = literal("reload")
|
||||
.requires(requirementsUnloaded("bluemap.reload"))
|
||||
.executes(context -> this.reloadCommand(context, false))
|
||||
|
||||
@ -116,8 +108,7 @@ public void init() {
|
||||
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> debugCommand =
|
||||
literal("debug")
|
||||
LiteralCommandNode<S> debugCommand = literal("debug")
|
||||
.requires(requirementsUnloaded("bluemap.debug"))
|
||||
|
||||
.then(literal("block")
|
||||
@ -147,31 +138,27 @@ public void init() {
|
||||
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> stopCommand =
|
||||
literal("stop")
|
||||
LiteralCommandNode<S> stopCommand = literal("stop")
|
||||
.requires(requirements("bluemap.stop"))
|
||||
.executes(this::stopCommand)
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> startCommand =
|
||||
literal("start")
|
||||
LiteralCommandNode<S> startCommand = literal("start")
|
||||
.requires(requirements("bluemap.start"))
|
||||
.executes(this::startCommand)
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> freezeCommand =
|
||||
literal("freeze")
|
||||
LiteralCommandNode<S> freezeCommand = literal("freeze")
|
||||
.requires(requirements("bluemap.freeze"))
|
||||
.then(argument("map", StringArgumentType.string()).suggests(new MapSuggestionProvider<>(plugin))
|
||||
.executes(this::freezeCommand))
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> unfreezeCommand =
|
||||
literal("unfreeze")
|
||||
.requires(requirements("bluemap.freeze"))
|
||||
.then(argument("map", StringArgumentType.string()).suggests(new MapSuggestionProvider<>(plugin))
|
||||
.executes(this::unfreezeCommand))
|
||||
.build();
|
||||
LiteralCommandNode<S> unfreezeCommand = literal("unfreeze")
|
||||
.requires(requirements("bluemap.freeze"))
|
||||
.then(argument("map", StringArgumentType.string()).suggests(new MapSuggestionProvider<>(plugin))
|
||||
.executes(this::unfreezeCommand))
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> forceUpdateCommand =
|
||||
addRenderArguments(
|
||||
@ -187,33 +174,42 @@ public void init() {
|
||||
this::updateCommand
|
||||
).build();
|
||||
|
||||
LiteralCommandNode<S> purgeCommand =
|
||||
literal("purge")
|
||||
.requires(requirements("bluemap.purge"))
|
||||
.then(argument("map", StringArgumentType.string()).suggests(new MapSuggestionProvider<>(plugin))
|
||||
.executes(this::purgeCommand))
|
||||
.build();
|
||||
LiteralCommandNode<S> purgeCommand = literal("purge")
|
||||
.requires(requirements("bluemap.purge"))
|
||||
.then(argument("map", StringArgumentType.string()).suggests(new MapSuggestionProvider<>(plugin))
|
||||
.executes(this::purgeCommand))
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> cancelCommand =
|
||||
literal("cancel")
|
||||
LiteralCommandNode<S> cancelCommand = literal("cancel")
|
||||
.requires(requirements("bluemap.cancel"))
|
||||
.executes(this::cancelCommand)
|
||||
.then(argument("task-ref", StringArgumentType.string()).suggests(new TaskRefSuggestionProvider<>(helper))
|
||||
.executes(this::cancelCommand))
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> worldsCommand =
|
||||
literal("worlds")
|
||||
LiteralCommandNode<S> worldsCommand = literal("worlds")
|
||||
.requires(requirements("bluemap.status"))
|
||||
.executes(this::worldsCommand)
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> mapsCommand =
|
||||
literal("maps")
|
||||
LiteralCommandNode<S> mapsCommand = literal("maps")
|
||||
.requires(requirements("bluemap.status"))
|
||||
.executes(this::mapsCommand)
|
||||
.build();
|
||||
|
||||
LiteralCommandNode<S> storagesCommand = literal("storages")
|
||||
.requires(requirements("bluemap.status"))
|
||||
.executes(this::storagesCommand)
|
||||
|
||||
.then(argument("storage", StringArgumentType.string()).suggests(new StorageSuggestionProvider<>(plugin))
|
||||
.executes(this::storagesInfoCommand)
|
||||
|
||||
.then(literal("delete")
|
||||
.then(argument("map", StringArgumentType.string())
|
||||
.executes(this::storagesDeleteMapCommand))))
|
||||
|
||||
.build();
|
||||
|
||||
// command tree
|
||||
dispatcher.getRoot().addChild(baseCommand);
|
||||
baseCommand.addChild(versionCommand);
|
||||
@ -230,6 +226,7 @@ public void init() {
|
||||
baseCommand.addChild(purgeCommand);
|
||||
baseCommand.addChild(worldsCommand);
|
||||
baseCommand.addChild(mapsCommand);
|
||||
baseCommand.addChild(storagesCommand);
|
||||
}
|
||||
|
||||
private <B extends ArgumentBuilder<S, B>> B addRenderArguments(B builder, Command<S> command) {
|
||||
@ -862,4 +859,91 @@ public int mapsCommand(CommandContext<S> context) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int storagesCommand(CommandContext<S> context) {
|
||||
CommandSource source = commandSourceInterface.apply(context.getSource());
|
||||
|
||||
source.sendMessage(Text.of(TextColor.BLUE, "Storages loaded by BlueMap:"));
|
||||
for (var entry : plugin.getBlueMap().getConfigs().getStorageConfigs().entrySet()) {
|
||||
source.sendMessage(Text.of(TextColor.GRAY, " - ", TextColor.WHITE, entry.getKey())
|
||||
.setHoverText(Text.of(entry.getValue().getStorageType().name()))
|
||||
.setClickAction(Text.ClickAction.RUN_COMMAND, "/bluemap storages " + entry.getKey())
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int storagesInfoCommand(CommandContext<S> context) {
|
||||
CommandSource source = commandSourceInterface.apply(context.getSource());
|
||||
String storageId = context.getArgument("storage", String.class);
|
||||
|
||||
Storage storage;
|
||||
try {
|
||||
storage = plugin.getBlueMap().getStorage(storageId);
|
||||
} catch (ConfigurationException ex) {
|
||||
source.sendMessage(Text.of(TextColor.RED, ex.getMessage()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
Collection<String> mapIds;
|
||||
try {
|
||||
mapIds = storage.collectMapIds();
|
||||
} catch (IOException ex) {
|
||||
source.sendMessage(Text.of(TextColor.RED, "There was an unexpected exception trying to access this storage. Please check the console for more details..."));
|
||||
Logger.global.logError("Unexpected exception trying to load mapId's from storage '" + storageId + "'!", ex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
source.sendMessage(Text.of(TextColor.BLUE, "Storage '", storageId, "':"));
|
||||
if (mapIds.isEmpty()) {
|
||||
source.sendMessage(Text.of(TextColor.GRAY, " <empty storage>"));
|
||||
} else {
|
||||
for (String mapId : mapIds) {
|
||||
BmMap map = plugin.getMaps().get(mapId);
|
||||
boolean isLoaded = map != null && map.getStorage().equals(storage);
|
||||
|
||||
if (isLoaded) {
|
||||
source.sendMessage(Text.of(TextColor.GRAY, " - ", TextColor.WHITE, mapId, TextColor.GREEN, TextFormat.ITALIC, " (loaded)"));
|
||||
} else {
|
||||
source.sendMessage(Text.of(TextColor.GRAY, " - ", TextColor.WHITE, mapId, TextColor.DARK_GRAY, TextFormat.ITALIC, " (unloaded/static/remote)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int storagesDeleteMapCommand(CommandContext<S> context) {
|
||||
CommandSource source = commandSourceInterface.apply(context.getSource());
|
||||
String storageId = context.getArgument("storage", String.class);
|
||||
String mapId = context.getArgument("map", String.class);
|
||||
|
||||
Storage storage;
|
||||
try {
|
||||
storage = plugin.getBlueMap().getStorage(storageId);
|
||||
} catch (ConfigurationException ex) {
|
||||
source.sendMessage(Text.of(TextColor.RED, ex.getMessage()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BmMap map = plugin.getMaps().get(mapId);
|
||||
boolean isLoaded = map != null && map.getStorage().equals(storage);
|
||||
if (isLoaded) {
|
||||
Text purgeCommand = Text.of(TextColor.WHITE, "/bluemap purge " + mapId)
|
||||
.setClickAction(Text.ClickAction.SUGGEST_COMMAND, "/bluemap purge " + mapId);
|
||||
source.sendMessage(Text.of(TextColor.RED, "Can't delete a loaded map!\n" +
|
||||
"Unload the map by removing it's config-file first,\n" +
|
||||
"or use ", purgeCommand, " if you want to purge it."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// delete map
|
||||
StorageDeleteTask deleteTask = new StorageDeleteTask(storage, mapId);
|
||||
|
||||
plugin.getRenderManager().scheduleRenderTaskNext(deleteTask);
|
||||
source.sendMessage(Text.of(TextColor.GREEN, "Created new Task to delete map '" + mapId + "' from storage '" + storageId + "'"));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.common.plugin.commands;
|
||||
|
||||
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class StorageSuggestionProvider<S> extends AbstractSuggestionProvider<S> {
|
||||
|
||||
private final Plugin plugin;
|
||||
|
||||
public StorageSuggestionProvider(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getPossibleValues() {
|
||||
return plugin.getBlueMap().getConfigs().getStorageConfigs().keySet();
|
||||
}
|
||||
|
||||
}
|
@ -28,7 +28,7 @@
|
||||
|
||||
public class TaskRefSuggestionProvider<S> extends AbstractSuggestionProvider<S> {
|
||||
|
||||
private CommandHelper helper;
|
||||
private final CommandHelper helper;
|
||||
|
||||
public TaskRefSuggestionProvider(CommandHelper helper) {
|
||||
this.helper = helper;
|
||||
|
@ -24,16 +24,15 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.common.plugin.commands;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import de.bluecolored.bluemap.core.map.BmMap;
|
||||
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class WorldOrMapSuggestionProvider<S> extends AbstractSuggestionProvider<S> {
|
||||
|
||||
private Plugin plugin;
|
||||
private final Plugin plugin;
|
||||
|
||||
public WorldOrMapSuggestionProvider(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
@ -50,6 +50,7 @@ public void doWork() throws Exception {
|
||||
if (!this.hasMoreWork) return;
|
||||
this.hasMoreWork = false;
|
||||
}
|
||||
if (this.cancelled) return;
|
||||
|
||||
// save lowres-tile-manager to clear/flush any buffered data
|
||||
this.map.getLowresTileManager().save();
|
||||
@ -97,7 +98,7 @@ public boolean contains(RenderTask task) {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Purge Map " + map.getId();
|
||||
return "Purge map " + map.getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.common.rendermanager;
|
||||
|
||||
import de.bluecolored.bluemap.api.debug.DebugDump;
|
||||
import de.bluecolored.bluemap.core.storage.Storage;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class StorageDeleteTask implements RenderTask {
|
||||
|
||||
private final Storage storage;
|
||||
private final String mapId;
|
||||
|
||||
private volatile double progress;
|
||||
private volatile boolean hasMoreWork;
|
||||
private volatile boolean cancelled;
|
||||
|
||||
public StorageDeleteTask(Storage storage, String mapId) {
|
||||
this.storage = Objects.requireNonNull(storage);
|
||||
this.mapId = Objects.requireNonNull(mapId);
|
||||
this.progress = 0d;
|
||||
this.hasMoreWork = true;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWork() throws Exception {
|
||||
synchronized (this) {
|
||||
if (!this.hasMoreWork) return;
|
||||
this.hasMoreWork = false;
|
||||
}
|
||||
if (this.cancelled) return;
|
||||
|
||||
// purge the map
|
||||
storage.purgeMap(mapId, progressInfo -> {
|
||||
this.progress = progressInfo.getProgress();
|
||||
return !this.cancelled;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreWork() {
|
||||
return this.hasMoreWork && !this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DebugDump
|
||||
public double estimateProgress() {
|
||||
return this.progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
this.cancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(RenderTask task) {
|
||||
if (task == this) return true;
|
||||
if (task instanceof StorageDeleteTask) {
|
||||
StorageDeleteTask sTask = (StorageDeleteTask) task;
|
||||
return storage.equals(sTask.storage) && mapId.equals(sTask.mapId);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Delete map " + mapId;
|
||||
}
|
||||
|
||||
}
|
@ -58,8 +58,6 @@ public abstract class Storage implements Closeable {
|
||||
|
||||
public abstract Collection<String> collectMapIds() throws IOException;
|
||||
|
||||
public abstract long estimateMapSize(String mapId) throws IOException;
|
||||
|
||||
public MapStorage mapStorage(final String mapId) {
|
||||
return new MapStorage(mapId);
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
import de.bluecolored.bluemap.core.storage.*;
|
||||
import de.bluecolored.bluemap.core.util.DeletingPathVisitor;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
import de.bluecolored.bluemap.core.util.SizeCollectingPathVisitor;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
@ -227,13 +226,6 @@ public Collection<String> collectMapIds() throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateMapSize(String mapId) throws IOException {
|
||||
SizeCollectingPathVisitor visitor = new SizeCollectingPathVisitor();
|
||||
Files.walkFileTree(getFilePath(mapId), visitor);
|
||||
return visitor.getSize();
|
||||
}
|
||||
|
||||
public Path getFilePath(String mapId, int lod, Vector2i tile){
|
||||
String path = "x" + tile.getX() + "z" + tile.getY();
|
||||
char[] cs = path.toCharArray();
|
||||
|
@ -417,12 +417,20 @@ public void purgeMap(String mapId, Function<ProgressInfo, Boolean> onProgress) t
|
||||
|
||||
@Override
|
||||
public Collection<String> collectMapIds() throws IOException {
|
||||
return Collections.emptyList(); //TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateMapSize(String mapId) throws IOException {
|
||||
return 0; //TODO
|
||||
try {
|
||||
return recoveringConnection(connection -> {
|
||||
ResultSet result = executeQuery(connection,
|
||||
"SELECT `map_id` FROM `bluemap_map`"
|
||||
);
|
||||
Collection<String> mapIds = new ArrayList<>();
|
||||
while (result.next()) {
|
||||
mapIds.add(result.getString("map_id"));
|
||||
}
|
||||
return mapIds;
|
||||
}, 2);
|
||||
} catch (SQLException ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedAssignment")
|
||||
|
Loading…
Reference in New Issue
Block a user