mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 00:51:01 +03:00
Перевод конфигов на Json часть 1
Не комплируется
This commit is contained in:
parent
d2916d180d
commit
49b085278c
34 changed files with 134 additions and 1514 deletions
|
@ -50,105 +50,56 @@
|
|||
import java.util.zip.CRC32;
|
||||
|
||||
public final class LaunchServer implements Runnable, AutoCloseable {
|
||||
public static final class Config extends ConfigObject {
|
||||
public final int port;
|
||||
public static final class Config {
|
||||
public int port;
|
||||
|
||||
// Handlers & Providers
|
||||
|
||||
public final AuthHandler[] authHandler;
|
||||
public AuthHandler[] authHandler;
|
||||
|
||||
public final AuthProvider[] authProvider;
|
||||
public AuthProvider[] authProvider;
|
||||
|
||||
public final TextureProvider textureProvider;
|
||||
public TextureProvider textureProvider;
|
||||
|
||||
public final HWIDHandler hwidHandler;
|
||||
public HWIDHandler hwidHandler;
|
||||
|
||||
// Misc options
|
||||
public final int threadCount;
|
||||
public int threadCount;
|
||||
|
||||
public final int threadCoreCount;
|
||||
public int threadCoreCount;
|
||||
|
||||
public final ExeConf launch4j;
|
||||
public ExeConf launch4j;
|
||||
|
||||
public final PostBuildTransformConf buildPostTransform;
|
||||
public PostBuildTransformConf buildPostTransform;
|
||||
|
||||
public final boolean compress;
|
||||
public boolean compress;
|
||||
|
||||
public final int authRateLimit;
|
||||
public int authRateLimit;
|
||||
|
||||
public final int authRateLimitMilis;
|
||||
public int authRateLimitMilis;
|
||||
|
||||
public final ListConfigEntry authLimitExclusions;
|
||||
public String[] authLimitExclusions;
|
||||
|
||||
public final String authRejectString;
|
||||
public String authRejectString;
|
||||
|
||||
public final String projectName;
|
||||
public String projectName;
|
||||
|
||||
public final String whitelistRejectString;
|
||||
public String whitelistRejectString;
|
||||
|
||||
public final boolean genMappings;
|
||||
public final boolean isUsingWrapper;
|
||||
public final boolean isDownloadJava;
|
||||
public boolean genMappings;
|
||||
public boolean isUsingWrapper;
|
||||
public boolean isDownloadJava;
|
||||
|
||||
public ListConfigEntry mirrors;
|
||||
public final String binaryName;
|
||||
private final StringConfigEntry address;
|
||||
private final String bindAddress;
|
||||
public final LauncherConfig.LauncherEnvironment env;
|
||||
public final boolean isWarningMissArchJava;
|
||||
|
||||
private Config(BlockConfigEntry block, Path coredir, LaunchServer server) {
|
||||
super(block);
|
||||
address = block.getEntry("address", StringConfigEntry.class);
|
||||
port = VerifyHelper.verifyInt(block.getEntryValue("port", IntegerConfigEntry.class),
|
||||
VerifyHelper.range(0, 65535), "Illegal LaunchServer port");
|
||||
threadCoreCount = block.hasEntry("threadCoreCacheSize") ? VerifyHelper.verifyInt(block.getEntryValue("threadCoreCacheSize", IntegerConfigEntry.class),
|
||||
VerifyHelper.range(0, 100), "Illegal LaunchServer inital thread pool cache size") : 0;
|
||||
int internalThreadCount = block.hasEntry("threadCacheSize") ? VerifyHelper.verifyInt(block.getEntryValue("threadCacheSize", IntegerConfigEntry.class),
|
||||
VerifyHelper.range(2, 100), "Illegal LaunchServer thread pool cache size") : (JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors() >= 4 ? JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors() / 2 : JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors());
|
||||
threadCount = threadCoreCount > internalThreadCount ? threadCoreCount : internalThreadCount;
|
||||
authRateLimit = VerifyHelper.verifyInt(block.getEntryValue("authRateLimit", IntegerConfigEntry.class),
|
||||
VerifyHelper.range(0, 1000000), "Illegal authRateLimit");
|
||||
authRateLimitMilis = VerifyHelper.verifyInt(block.getEntryValue("authRateLimitMilis", IntegerConfigEntry.class),
|
||||
VerifyHelper.range(10, 10000000), "Illegal authRateLimitMillis");
|
||||
authLimitExclusions = block.hasEntry("authLimitExclusions") ? block.getEntry("authLimitExclusions", ListConfigEntry.class) : null;
|
||||
bindAddress = block.hasEntry("bindAddress") ?
|
||||
block.getEntryValue("bindAddress", StringConfigEntry.class) : getAddress();
|
||||
authRejectString = block.hasEntry("authRejectString") ?
|
||||
block.getEntryValue("authRejectString", StringConfigEntry.class) : "Вы превысили лимит авторизаций. Подождите некоторое время перед повторной попыткой";
|
||||
whitelistRejectString = block.hasEntry("whitelistRejectString") ?
|
||||
block.getEntryValue("whitelistRejectString", StringConfigEntry.class) : "Вас нет в белом списке";
|
||||
|
||||
// Set handlers & providers
|
||||
authHandler = new AuthHandler[1];
|
||||
authHandler[0] = AuthHandler.newHandler(block.getEntryValue("authHandler", StringConfigEntry.class),
|
||||
block.getEntry("authHandlerConfig", BlockConfigEntry.class));
|
||||
authProvider = new AuthProvider[1];
|
||||
authProvider[0] = AuthProvider.newProvider(block.getEntryValue("authProvider", StringConfigEntry.class),
|
||||
block.getEntry("authProviderConfig", BlockConfigEntry.class), server);
|
||||
textureProvider = TextureProvider.newProvider(block.getEntryValue("textureProvider", StringConfigEntry.class),
|
||||
block.getEntry("textureProviderConfig", BlockConfigEntry.class));
|
||||
hwidHandler = HWIDHandler.newHandler(block.getEntryValue("hwidHandler", StringConfigEntry.class),
|
||||
block.getEntry("hwidHandlerConfig", BlockConfigEntry.class));
|
||||
|
||||
// Set misc config
|
||||
genMappings = block.getEntryValue("proguardPrintMappings", BooleanConfigEntry.class);
|
||||
mirrors = block.getEntry("mirrors", ListConfigEntry.class);
|
||||
launch4j = new ExeConf(block.getEntry("launch4J", BlockConfigEntry.class));
|
||||
buildPostTransform = new PostBuildTransformConf(block.getEntry("buildExtendedOperation", BlockConfigEntry.class), coredir);
|
||||
binaryName = block.getEntryValue("binaryName", StringConfigEntry.class);
|
||||
projectName = block.hasEntry("projectName") ? block.getEntryValue("projectName", StringConfigEntry.class) : "Minecraft";
|
||||
compress = block.getEntryValue("compress", BooleanConfigEntry.class);
|
||||
|
||||
isUsingWrapper = block.getEntryValue("isUsingWrapper", BooleanConfigEntry.class);
|
||||
isDownloadJava = block.getEntryValue("isDownloadJava", BooleanConfigEntry.class);
|
||||
isWarningMissArchJava = block.getEntryValue("isWarningMissArchJava", BooleanConfigEntry.class);
|
||||
env = LauncherConfig.LauncherEnvironment.STD;
|
||||
}
|
||||
public String[] mirrors;
|
||||
public String binaryName;
|
||||
private String address;
|
||||
private String bindAddress;
|
||||
public LauncherConfig.LauncherEnvironment env;
|
||||
public boolean isWarningMissArchJava;
|
||||
|
||||
|
||||
public String getAddress() {
|
||||
return address.getValue();
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
|
@ -163,7 +114,7 @@ public SocketAddress getSocketAddress() {
|
|||
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address.setValue(address);
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
|
||||
|
@ -172,40 +123,18 @@ public void verify() {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ExeConf extends ConfigObject {
|
||||
public final boolean enabled;
|
||||
public final String productName;
|
||||
public final String productVer;
|
||||
public final String fileDesc;
|
||||
public final String fileVer;
|
||||
public final String internalName;
|
||||
public final String copyright;
|
||||
public final String trademarks;
|
||||
public static class ExeConf {
|
||||
public boolean enabled;
|
||||
public String productName;
|
||||
public String productVer;
|
||||
public String fileDesc;
|
||||
public String fileVer;
|
||||
public String internalName;
|
||||
public String copyright;
|
||||
public String trademarks;
|
||||
|
||||
public final String txtFileVersion;
|
||||
public final String txtProductVersion;
|
||||
|
||||
private ExeConf(BlockConfigEntry block) {
|
||||
super(block);
|
||||
enabled = block.getEntryValue("enabled", BooleanConfigEntry.class);
|
||||
productName = block.hasEntry("productName") ? block.getEntryValue("productName", StringConfigEntry.class)
|
||||
: "sashok724's Launcher v3 mod by Gravit";
|
||||
productVer = block.hasEntry("productVer") ? block.getEntryValue("productVer", StringConfigEntry.class)
|
||||
: "1.0.0.0";
|
||||
fileDesc = block.hasEntry("fileDesc") ? block.getEntryValue("fileDesc", StringConfigEntry.class)
|
||||
: "sashok724's Launcher v3 mod by Gravit";
|
||||
fileVer = block.hasEntry("fileVer") ? block.getEntryValue("fileVer", StringConfigEntry.class) : "1.0.0.0";
|
||||
internalName = block.hasEntry("internalName") ? block.getEntryValue("internalName", StringConfigEntry.class)
|
||||
: "Launcher";
|
||||
copyright = block.hasEntry("copyright") ? block.getEntryValue("copyright", StringConfigEntry.class)
|
||||
: "© sashok724 LLC";
|
||||
trademarks = block.hasEntry("trademarks") ? block.getEntryValue("trademarks", StringConfigEntry.class)
|
||||
: "This product is licensed under MIT License";
|
||||
txtFileVersion = block.hasEntry("txtFileVersion") ? block.getEntryValue("txtFileVersion", StringConfigEntry.class)
|
||||
: String.format("%s, build %d", Launcher.getVersion().getVersionString(), Launcher.getVersion().build);
|
||||
txtProductVersion = block.hasEntry("txtProductVersion") ? block.getEntryValue("txtProductVersion", StringConfigEntry.class)
|
||||
: String.format("%s, build %d", Launcher.getVersion().getVersionString(), Launcher.getVersion().build);
|
||||
}
|
||||
public String txtFileVersion;
|
||||
public String txtProductVersion;
|
||||
}
|
||||
|
||||
private final class ProfilesFileVisitor extends SimpleFileVisitor<Path> {
|
||||
|
@ -232,17 +161,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
|||
}
|
||||
}
|
||||
|
||||
public static class PostBuildTransformConf extends ConfigObject {
|
||||
public final boolean enabled;
|
||||
public static class PostBuildTransformConf {
|
||||
public boolean enabled;
|
||||
public List<String> script;
|
||||
|
||||
private PostBuildTransformConf(BlockConfigEntry block, Path coredir) {
|
||||
super(block);
|
||||
enabled = block.getEntryValue("enabled", BooleanConfigEntry.class);
|
||||
script = new ArrayList<>(1);
|
||||
if (block.hasEntry("script"))
|
||||
block.getEntry("script", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(script::add);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
|
@ -399,7 +320,7 @@ public LaunchServer(Path dir) throws IOException, InvalidKeySpecException {
|
|||
mirrorManager = new MirrorManager();
|
||||
GarbageManager.registerNeedGC(sessionManager);
|
||||
GarbageManager.registerNeedGC(limiter);
|
||||
config.mirrors.stream(StringConfigEntry.class).forEach(s -> {
|
||||
Arrays.stream(config.mirrors).forEach(s -> {
|
||||
try {
|
||||
mirrorManager.addMirror(s);
|
||||
} catch (MalformedURLException e) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package ru.gravit.launchserver.auth.handler;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
@ -12,8 +10,8 @@
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class AuthHandler extends ConfigObject implements AutoCloseable {
|
||||
private static final Map<String, Adapter<AuthHandler>> AUTH_HANDLERS = new ConcurrentHashMap<>(4);
|
||||
public abstract class AuthHandler implements AutoCloseable {
|
||||
private static final Map<String, Class> AUTH_HANDLERS = new ConcurrentHashMap<>(4);
|
||||
private static boolean registredHandl = false;
|
||||
|
||||
|
||||
|
@ -22,14 +20,7 @@ public static UUID authError(String message) throws AuthException {
|
|||
}
|
||||
|
||||
|
||||
public static AuthHandler newHandler(String name, BlockConfigEntry block) {
|
||||
Adapter<AuthHandler> authHandlerAdapter = VerifyHelper.getMapValue(AUTH_HANDLERS, name,
|
||||
String.format("Unknown auth handler: '%s'", name));
|
||||
return authHandlerAdapter.convert(block);
|
||||
}
|
||||
|
||||
|
||||
public static void registerHandler(String name, Adapter<AuthHandler> adapter) {
|
||||
public static void registerHandler(String name, Class adapter) {
|
||||
VerifyHelper.verifyIDName(name);
|
||||
VerifyHelper.putIfAbsent(AUTH_HANDLERS, name, Objects.requireNonNull(adapter, "adapter"),
|
||||
String.format("Auth handler has been already registered: '%s'", name));
|
||||
|
@ -37,22 +28,16 @@ public static void registerHandler(String name, Adapter<AuthHandler> adapter) {
|
|||
|
||||
public static void registerHandlers() {
|
||||
if (!registredHandl) {
|
||||
registerHandler("null", NullAuthHandler::new);
|
||||
registerHandler("memory", MemoryAuthHandler::new);
|
||||
registerHandler("null", NullAuthHandler.class);
|
||||
registerHandler("memory", MemoryAuthHandler.class);
|
||||
|
||||
// Auth handler that doesn't do nothing :D
|
||||
registerHandler("binaryFile", BinaryFileAuthHandler::new);
|
||||
registerHandler("textFile", TextFileAuthHandler::new);
|
||||
registerHandler("mysql", MySQLAuthHandler::new);
|
||||
registerHandler("binaryFile", BinaryFileAuthHandler.class);
|
||||
registerHandler("mysql", MySQLAuthHandler.class);
|
||||
registredHandl = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected AuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
public abstract UUID auth(AuthProviderResult authResult) throws IOException;
|
||||
|
||||
public abstract UUID checkServer(String username, String serverID) throws IOException;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -11,9 +10,6 @@
|
|||
import java.util.UUID;
|
||||
|
||||
public final class BinaryFileAuthHandler extends FileAuthHandler {
|
||||
public BinaryFileAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readAuthFile() throws IOException {
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package ru.gravit.launchserver.auth.handler;
|
||||
|
||||
import ru.gravit.launcher.NeedGarbageCollection;
|
||||
import ru.gravit.launcher.managers.GarbageManager;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
@ -37,13 +34,6 @@ public Entry(UUID uuid, String username, String accessToken, String serverID) {
|
|||
private final Map<String, UUID> usernamesCache = new HashMap<>(1024);
|
||||
|
||||
|
||||
protected CachedAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
if (block.hasEntry("garbage"))
|
||||
if (block.getEntryValue("garbage", BooleanConfigEntry.class)) GarbageManager.registerNeedGC(this);
|
||||
}
|
||||
|
||||
|
||||
protected void addEntry(Entry entry) {
|
||||
Entry previous = entryCache.put(entry.uuid, entry);
|
||||
if (previous != null)
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launcher.serialize.stream.StreamObject;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.*;
|
||||
|
@ -96,12 +93,12 @@ public void write(HOutput output) throws IOException {
|
|||
}
|
||||
|
||||
|
||||
public final Path file;
|
||||
public Path file;
|
||||
|
||||
public final Path fileTmp;
|
||||
public Path fileTmp;
|
||||
|
||||
|
||||
public final boolean offlineUUIDs;
|
||||
public boolean offlineUUIDs;
|
||||
// Instance
|
||||
private final SecureRandom random = SecurityHelper.newRandom();
|
||||
|
||||
|
@ -112,24 +109,6 @@ public void write(HOutput output) throws IOException {
|
|||
private final Map<String, UUID> usernamesMap = new HashMap<>(256);
|
||||
|
||||
|
||||
protected FileAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
file = IOHelper.toPath(block.getEntryValue("file", StringConfigEntry.class));
|
||||
fileTmp = IOHelper.toPath(block.getEntryValue("file", StringConfigEntry.class) + ".tmp");
|
||||
offlineUUIDs = block.getEntryValue("offlineUUIDs", BooleanConfigEntry.class);
|
||||
|
||||
// Read auth handler file
|
||||
if (IOHelper.isFile(file)) {
|
||||
LogHelper.info("Reading auth handler file: '%s'", file);
|
||||
try {
|
||||
readAuthFile();
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected final void addAuth(UUID uuid, Entry entry) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package ru.gravit.launchserver.auth.handler;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -29,11 +27,6 @@ private static UUID toUUID(String username) {
|
|||
return new UUID(buffer.getLong(), buffer.getLong()); // MOST, LEAST
|
||||
}
|
||||
|
||||
public MemoryAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
LogHelper.warning("Usage of MemoryAuthHandler isn't recommended!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package ru.gravit.launchserver.auth.handler;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
|
@ -13,44 +10,17 @@
|
|||
import java.util.UUID;
|
||||
|
||||
public final class MySQLAuthHandler extends CachedAuthHandler {
|
||||
private final MySQLSourceConfig mySQLHolder;
|
||||
private final String uuidColumn;
|
||||
private final String usernameColumn;
|
||||
private final String accessTokenColumn;
|
||||
private final String serverIDColumn;
|
||||
private MySQLSourceConfig mySQLHolder;
|
||||
private String uuidColumn;
|
||||
private String usernameColumn;
|
||||
private String accessTokenColumn;
|
||||
private String serverIDColumn;
|
||||
|
||||
// Prepared SQL queries
|
||||
private final String queryByUUIDSQL;
|
||||
private final String queryByUsernameSQL;
|
||||
private final String updateAuthSQL;
|
||||
private final String updateServerIDSQL;
|
||||
|
||||
public MySQLAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
mySQLHolder = new MySQLSourceConfig("authHandlerPool", block);
|
||||
|
||||
// Read query params
|
||||
String table = VerifyHelper.verifyIDName(
|
||||
block.getEntryValue("table", StringConfigEntry.class));
|
||||
uuidColumn = VerifyHelper.verifyIDName(
|
||||
block.getEntryValue("uuidColumn", StringConfigEntry.class));
|
||||
usernameColumn = VerifyHelper.verifyIDName(
|
||||
block.getEntryValue("usernameColumn", StringConfigEntry.class));
|
||||
accessTokenColumn = VerifyHelper.verifyIDName(
|
||||
block.getEntryValue("accessTokenColumn", StringConfigEntry.class));
|
||||
serverIDColumn = VerifyHelper.verifyIDName(
|
||||
block.getEntryValue("serverIDColumn", StringConfigEntry.class));
|
||||
|
||||
// Prepare SQL queries
|
||||
queryByUUIDSQL = String.format("SELECT %s, %s, %s, %s FROM %s WHERE %s=? LIMIT 1",
|
||||
uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, table, uuidColumn);
|
||||
queryByUsernameSQL = String.format("SELECT %s, %s, %s, %s FROM %s WHERE %s=? LIMIT 1",
|
||||
uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, table, usernameColumn);
|
||||
updateAuthSQL = String.format("UPDATE %s SET %s=?, %s=?, %s=NULL WHERE %s=? LIMIT 1",
|
||||
table, usernameColumn, accessTokenColumn, serverIDColumn, uuidColumn);
|
||||
updateServerIDSQL = String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1",
|
||||
table, serverIDColumn, uuidColumn);
|
||||
}
|
||||
private String queryByUUIDSQL;
|
||||
private String queryByUsernameSQL;
|
||||
private String updateAuthSQL;
|
||||
private String updateServerIDSQL;
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ru.gravit.launchserver.auth.handler;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
|
@ -11,10 +10,6 @@
|
|||
public final class NullAuthHandler extends AuthHandler {
|
||||
private volatile AuthHandler handler;
|
||||
|
||||
public NullAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID auth(AuthProviderResult authResult) throws IOException {
|
||||
return getHandler().auth(authResult);
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
package ru.gravit.launchserver.auth.handler;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.TextConfigReader;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigWriter;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry.Type;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class TextFileAuthHandler extends FileAuthHandler {
|
||||
private static StringConfigEntry cc(String value) {
|
||||
StringConfigEntry entry = new StringConfigEntry(value, true, 4);
|
||||
entry.setComment(0, "\n\t"); // Pre-name
|
||||
entry.setComment(2, " "); // Pre-value
|
||||
return entry;
|
||||
}
|
||||
|
||||
public TextFileAuthHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readAuthFile() throws IOException {
|
||||
BlockConfigEntry authFile;
|
||||
try (BufferedReader reader = IOHelper.newReader(file)) {
|
||||
authFile = TextConfigReader.read(reader, false);
|
||||
}
|
||||
|
||||
// Read auths from config block
|
||||
Set<Map.Entry<String, ConfigEntry<?>>> entrySet = authFile.getValue().entrySet();
|
||||
for (Map.Entry<String, ConfigEntry<?>> entry : entrySet) {
|
||||
UUID uuid = UUID.fromString(entry.getKey());
|
||||
ConfigEntry<?> value = VerifyHelper.verify(entry.getValue(),
|
||||
v -> v.getType() == Type.BLOCK, "Illegal config entry type: " + uuid);
|
||||
|
||||
// Get auth entry data
|
||||
BlockConfigEntry authBlock = (BlockConfigEntry) value;
|
||||
String username = authBlock.getEntryValue("username", StringConfigEntry.class);
|
||||
String accessToken = authBlock.hasEntry("accessToken") ?
|
||||
authBlock.getEntryValue("accessToken", StringConfigEntry.class) : null;
|
||||
String serverID = authBlock.hasEntry("serverID") ?
|
||||
authBlock.getEntryValue("serverID", StringConfigEntry.class) : null;
|
||||
|
||||
// Add auth entry
|
||||
addAuth(uuid, new Entry(username, accessToken, serverID));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeAuthFileTmp() throws IOException {
|
||||
boolean next = false;
|
||||
|
||||
// Write auth blocks to map
|
||||
Set<Map.Entry<UUID, Entry>> entrySet = entrySet();
|
||||
Map<String, ConfigEntry<?>> map = new LinkedHashMap<>(entrySet.size());
|
||||
for (Map.Entry<UUID, Entry> entry : entrySet) {
|
||||
UUID uuid = entry.getKey();
|
||||
Entry auth = entry.getValue();
|
||||
|
||||
// Set auth entry data
|
||||
Map<String, ConfigEntry<?>> authMap = new LinkedHashMap<>(entrySet.size());
|
||||
authMap.put("username", cc(auth.getUsername()));
|
||||
String accessToken = auth.getAccessToken();
|
||||
if (accessToken != null)
|
||||
authMap.put("accessToken", cc(accessToken));
|
||||
String serverID = auth.getServerID();
|
||||
if (serverID != null)
|
||||
authMap.put("serverID", cc(serverID));
|
||||
|
||||
// Create and add auth block
|
||||
BlockConfigEntry authBlock = new BlockConfigEntry(authMap, true, 5);
|
||||
if (next)
|
||||
authBlock.setComment(0, "\n"); // Pre-name
|
||||
else
|
||||
next = true;
|
||||
authBlock.setComment(2, " "); // Pre-value
|
||||
authBlock.setComment(4, "\n"); // Post-comment
|
||||
map.put(uuid.toString(), authBlock);
|
||||
}
|
||||
|
||||
// Write auth handler file
|
||||
try (BufferedWriter writer = IOHelper.newWriter(fileTmp)) {
|
||||
BlockConfigEntry authFile = new BlockConfigEntry(map, true, 1);
|
||||
authFile.setComment(0, "\n");
|
||||
TextConfigWriter.write(authFile, writer, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +1,12 @@
|
|||
package ru.gravit.launchserver.auth.hwid;
|
||||
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AcceptHWIDHandler extends HWIDHandler {
|
||||
|
||||
public AcceptHWIDHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ban(List<HWID> hwid) {
|
||||
//SKIP
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package ru.gravit.launchserver.auth.hwid;
|
||||
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -10,19 +8,12 @@
|
|||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class HWIDHandler extends ConfigObject implements AutoCloseable {
|
||||
private static final Map<String, Adapter<HWIDHandler>> HW_HANDLERS = new ConcurrentHashMap<>(4);
|
||||
public abstract class HWIDHandler implements AutoCloseable {
|
||||
private static final Map<String, Class> HW_HANDLERS = new ConcurrentHashMap<>(4);
|
||||
private static boolean registredHandl = false;
|
||||
|
||||
|
||||
public static HWIDHandler newHandler(String name, BlockConfigEntry block) {
|
||||
Adapter<HWIDHandler> authHandlerAdapter = VerifyHelper.getMapValue(HW_HANDLERS, name,
|
||||
String.format("Unknown HWID handler: '%s'", name));
|
||||
return authHandlerAdapter.convert(block);
|
||||
}
|
||||
|
||||
|
||||
public static void registerHandler(String name, Adapter<HWIDHandler> adapter) {
|
||||
public static void registerHandler(String name, Class adapter) {
|
||||
VerifyHelper.verifyIDName(name);
|
||||
VerifyHelper.putIfAbsent(HW_HANDLERS, name, Objects.requireNonNull(adapter, "adapter"),
|
||||
String.format("HWID handler has been already registered: '%s'", name));
|
||||
|
@ -30,17 +21,13 @@ public static void registerHandler(String name, Adapter<HWIDHandler> adapter) {
|
|||
|
||||
public static void registerHandlers() {
|
||||
if (!registredHandl) {
|
||||
registerHandler("accept", AcceptHWIDHandler::new);
|
||||
registerHandler("mysql", MysqlHWIDHandler::new);
|
||||
registerHandler("json", JsonHWIDHandler::new);
|
||||
registerHandler("accept", AcceptHWIDHandler.class);
|
||||
registerHandler("mysql", MysqlHWIDHandler.class);
|
||||
registerHandler("json", JsonHWIDHandler.class);
|
||||
registredHandl = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected HWIDHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
public abstract void ban(List<HWID> hwid) throws HWIDException;
|
||||
|
||||
public void check(HWID hwid, String username) throws HWIDException {
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
import com.google.gson.JsonElement;
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.OshiHWID;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.utils.HTTPRequest;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
@ -19,11 +17,11 @@ public final class JsonHWIDHandler extends HWIDHandler {
|
|||
private static final Gson gson = new Gson();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final URL url;
|
||||
private final URL urlBan;
|
||||
private final URL urlUnBan;
|
||||
private URL url;
|
||||
private URL urlBan;
|
||||
private URL urlUnBan;
|
||||
@SuppressWarnings("unused")
|
||||
private final URL urlGet;
|
||||
private URL urlGet;
|
||||
|
||||
public class banRequest {
|
||||
public banRequest(String hwid) {
|
||||
|
@ -65,18 +63,6 @@ public HWIDRequest(String username) {
|
|||
String username;
|
||||
}
|
||||
|
||||
JsonHWIDHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
String configUrl = block.getEntryValue("url", StringConfigEntry.class);
|
||||
String configUrlBan = block.getEntryValue("urlBan", StringConfigEntry.class);
|
||||
String configUrlUnBan = block.getEntryValue("urlUnBan", StringConfigEntry.class);
|
||||
String configUrlGet = block.getEntryValue("urlGet", StringConfigEntry.class);
|
||||
url = IOHelper.convertToURL(configUrl);
|
||||
urlBan = IOHelper.convertToURL(configUrlBan);
|
||||
urlUnBan = IOHelper.convertToURL(configUrlUnBan);
|
||||
urlGet = IOHelper.convertToURL(configUrlGet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ban(List<HWID> l_hwid) throws HWIDException {
|
||||
for (HWID hwid : l_hwid) {
|
||||
|
|
|
@ -2,13 +2,9 @@
|
|||
|
||||
import ru.gravit.launcher.HWID;
|
||||
import ru.gravit.launcher.OshiHWID;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ListConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
@ -18,50 +14,19 @@
|
|||
import java.util.List;
|
||||
|
||||
public class MysqlHWIDHandler extends HWIDHandler {
|
||||
private final MySQLSourceConfig mySQLHolder;
|
||||
private final String query;
|
||||
private final String banMessage;
|
||||
private final String isBannedName;
|
||||
private final String loginName;
|
||||
private final String hwidName;
|
||||
private final String[] queryParams;
|
||||
private final String queryUpd;
|
||||
private final String[] queryParamsUpd;
|
||||
private final String queryBan;
|
||||
private final String[] queryParamsBan;
|
||||
private final String querySelect;
|
||||
private final String[] queryParamsSelect;
|
||||
|
||||
public MysqlHWIDHandler(BlockConfigEntry block) {
|
||||
super(block);
|
||||
mySQLHolder = new MySQLSourceConfig("hwidHandlerPool", block);
|
||||
|
||||
// Read query
|
||||
query = VerifyHelper.verify(block.getEntryValue("query", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "MySQL query can't be empty");
|
||||
queryParams = block.getEntry("queryParams", ListConfigEntry.class).
|
||||
stream(StringConfigEntry.class).toArray(String[]::new);
|
||||
isBannedName = VerifyHelper.verify(block.getEntryValue("isBannedName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "isBannedName can't be empty");
|
||||
loginName = VerifyHelper.verify(block.getEntryValue("loginName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "loginName can't be empty");
|
||||
banMessage = block.hasEntry("banMessage") ? block.getEntryValue("banMessage", StringConfigEntry.class) : "You HWID Banned";
|
||||
hwidName = VerifyHelper.verify(block.getEntryValue("hwidName", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "hwidName can't be empty");
|
||||
|
||||
queryUpd = VerifyHelper.verify(block.getEntryValue("queryUpd", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "MySQL queryUpd can't be empty");
|
||||
queryParamsUpd = block.getEntry("queryParamsUpd", ListConfigEntry.class).
|
||||
stream(StringConfigEntry.class).toArray(String[]::new);
|
||||
queryBan = VerifyHelper.verify(block.getEntryValue("queryBan", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "MySQL queryBan can't be empty");
|
||||
queryParamsBan = block.getEntry("queryParamsBan", ListConfigEntry.class).
|
||||
stream(StringConfigEntry.class).toArray(String[]::new);
|
||||
querySelect = VerifyHelper.verify(block.getEntryValue("querySelect", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "MySQL queryUpd can't be empty");
|
||||
queryParamsSelect = block.getEntry("queryParamsSelect", ListConfigEntry.class).
|
||||
stream(StringConfigEntry.class).toArray(String[]::new);
|
||||
}
|
||||
private MySQLSourceConfig mySQLHolder;
|
||||
private String query;
|
||||
private String banMessage;
|
||||
private String isBannedName;
|
||||
private String loginName;
|
||||
private String hwidName;
|
||||
private String[] queryParams;
|
||||
private String queryUpd;
|
||||
private String[] queryParamsUpd;
|
||||
private String queryBan;
|
||||
private String[] queryParamsBan;
|
||||
private String querySelect;
|
||||
private String[] queryParamsSelect;
|
||||
|
||||
@Override
|
||||
public void check0(HWID hwid, String username) throws HWIDException {
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
public final class AcceptAuthProvider extends AuthProvider {
|
||||
private final boolean isAdminAccess;
|
||||
|
||||
public AcceptAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
isAdminAccess = block.hasEntry("admin") ? block.getEntryValue("admin", BooleanConfigEntry.class) : false;
|
||||
}
|
||||
private boolean isAdminAccess;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||
|
@ -12,8 +10,8 @@
|
|||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class AuthProvider extends ConfigObject implements AutoCloseable {
|
||||
private static final Map<String, ServerAdapter<AuthProvider>> AUTH_PROVIDERS = new ConcurrentHashMap<>(8);
|
||||
public abstract class AuthProvider implements AutoCloseable {
|
||||
private static final Map<String, Class> AUTH_PROVIDERS = new ConcurrentHashMap<>(8);
|
||||
private static boolean registredProv = false;
|
||||
private LaunchServer server;
|
||||
|
||||
|
@ -23,31 +21,23 @@ public static AuthProviderResult authError(String message) throws AuthException
|
|||
}
|
||||
|
||||
|
||||
public static AuthProvider newProvider(String name, BlockConfigEntry block, LaunchServer server) {
|
||||
VerifyHelper.verifyIDName(name);
|
||||
ServerAdapter<AuthProvider> authHandlerAdapter = VerifyHelper.getMapValue(AUTH_PROVIDERS, name,
|
||||
String.format("Unknown auth provider: '%s'", name));
|
||||
return authHandlerAdapter.convert(block, server);
|
||||
}
|
||||
|
||||
|
||||
public static void registerProvider(String name, ServerAdapter<AuthProvider> adapter) {
|
||||
public static void registerProvider(String name, Class adapter) {
|
||||
VerifyHelper.putIfAbsent(AUTH_PROVIDERS, name, Objects.requireNonNull(adapter, "adapter"),
|
||||
String.format("Auth provider has been already registered: '%s'", name));
|
||||
}
|
||||
|
||||
public static void registerProviders() {
|
||||
if (!registredProv) {
|
||||
registerProvider("null", NullAuthProvider::new);
|
||||
registerProvider("accept", AcceptAuthProvider::new);
|
||||
registerProvider("reject", RejectAuthProvider::new);
|
||||
registerProvider("null", NullAuthProvider.class);
|
||||
registerProvider("accept", AcceptAuthProvider.class);
|
||||
registerProvider("reject", RejectAuthProvider.class);
|
||||
|
||||
// Auth providers that doesn't do nothing :D
|
||||
registerProvider("com.mojang", MojangAuthProvider::new);
|
||||
registerProvider("mysql", MySQLAuthProvider::new);
|
||||
registerProvider("file", FileAuthProvider::new);
|
||||
registerProvider("request", RequestAuthProvider::new);
|
||||
registerProvider("json", JsonAuthProvider::new);
|
||||
registerProvider("com.mojang", MojangAuthProvider.class);
|
||||
registerProvider("mysql", MySQLAuthProvider.class);
|
||||
registerProvider("file", FileAuthProvider.class);
|
||||
registerProvider("request", RequestAuthProvider.class);
|
||||
registerProvider("json", JsonAuthProvider.class);
|
||||
registredProv = true;
|
||||
}
|
||||
}
|
||||
|
@ -57,20 +47,8 @@ public AuthHandler getAccociateHandler(int this_position) {
|
|||
}
|
||||
|
||||
|
||||
protected AuthProvider(BlockConfigEntry block, LaunchServer launchServer) {
|
||||
super(block);
|
||||
server = launchServer;
|
||||
}
|
||||
|
||||
|
||||
public abstract AuthProviderResult auth(String login, String password, String ip) throws Exception;
|
||||
|
||||
@Override
|
||||
public abstract void close() throws IOException;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ServerAdapter<O extends ConfigObject> {
|
||||
|
||||
O convert(BlockConfigEntry entry, LaunchServer server);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,11 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper.DigestAlgorithm;
|
||||
|
||||
public abstract class DigestAuthProvider extends AuthProvider {
|
||||
private final DigestAlgorithm digest;
|
||||
|
||||
|
||||
protected DigestAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
digest = DigestAlgorithm.byName(block.getEntryValue("digest", StringConfigEntry.class));
|
||||
}
|
||||
private DigestAlgorithm digest;
|
||||
|
||||
|
||||
protected final void verifyDigest(String validDigest, String password) throws AuthException {
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.TextConfigReader;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ConfigEntry.Type;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class FileAuthProvider extends DigestAuthProvider {
|
||||
private static final class Entry extends ConfigObject {
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final String ip;
|
||||
|
||||
private Entry(BlockConfigEntry block) {
|
||||
super(block);
|
||||
username = VerifyHelper.verifyUsername(block.getEntryValue("username", StringConfigEntry.class));
|
||||
password = VerifyHelper.verify(block.getEntryValue("password", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, String.format("Password can't be empty: '%s'", username));
|
||||
ip = block.hasEntry("ip") ? VerifyHelper.verify(block.getEntryValue("ip", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, String.format("IP can't be empty: '%s'", username)) : null;
|
||||
}
|
||||
}
|
||||
|
||||
private final Path file;
|
||||
// Cache
|
||||
private final Map<String, Entry> entries = new HashMap<>(256);
|
||||
private final Object cacheLock = new Object();
|
||||
|
||||
private FileTime cacheLastModified;
|
||||
|
||||
public FileAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
file = IOHelper.toPath(block.getEntryValue("file", StringConfigEntry.class));
|
||||
|
||||
// Try to update cache
|
||||
try {
|
||||
updateCache();
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws IOException {
|
||||
Entry entry;
|
||||
synchronized (cacheLock) {
|
||||
updateCache();
|
||||
entry = entries.get(CommonHelper.low(login));
|
||||
}
|
||||
|
||||
// Verify digest and return true username
|
||||
verifyDigest(entry == null ? null : entry.password, password);
|
||||
if (entry == null || entry.ip != null && !entry.ip.equals(ip))
|
||||
authError("Authentication from this IP is not allowed");
|
||||
|
||||
// We're done
|
||||
return new AuthProviderResult(entry.username, SecurityHelper.randomStringToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private void updateCache() throws IOException {
|
||||
FileTime lastModified = IOHelper.readAttributes(file).lastModifiedTime();
|
||||
if (lastModified.equals(cacheLastModified))
|
||||
return; // Not modified, so cache is up-to-date
|
||||
|
||||
// Read file
|
||||
LogHelper.info("Recaching auth provider file: '%s'", file);
|
||||
BlockConfigEntry authFile;
|
||||
try (BufferedReader reader = IOHelper.newReader(file)) {
|
||||
authFile = TextConfigReader.read(reader, false);
|
||||
}
|
||||
|
||||
// Read entries from config block
|
||||
entries.clear();
|
||||
Set<Map.Entry<String, ConfigEntry<?>>> entrySet = authFile.getValue().entrySet();
|
||||
for (Map.Entry<String, ConfigEntry<?>> entry : entrySet) {
|
||||
String login = entry.getKey();
|
||||
ConfigEntry<?> value = VerifyHelper.verify(entry.getValue(), v -> v.getType() == Type.BLOCK,
|
||||
String.format("Illegal config entry type: '%s'", login));
|
||||
|
||||
// Add auth entry
|
||||
Entry auth = new Entry((BlockConfigEntry) value);
|
||||
VerifyHelper.putIfAbsent(entries, CommonHelper.low(login), auth,
|
||||
String.format("Duplicate login: '%s'", login));
|
||||
}
|
||||
|
||||
// Update last modified time
|
||||
cacheLastModified = lastModified;
|
||||
}
|
||||
}
|
|
@ -2,20 +2,16 @@
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.utils.HTTPRequest;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
public final class JsonAuthProvider extends AuthProvider {
|
||||
private final Gson gson = new Gson();
|
||||
private final URL url;
|
||||
private Gson gson = new Gson();
|
||||
private URL url;
|
||||
|
||||
public class authResult {
|
||||
String username;
|
||||
|
@ -35,12 +31,6 @@ public authRequest(String username, String password, String ip) {
|
|||
String ip;
|
||||
}
|
||||
|
||||
JsonAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
String configUrl = block.getEntryValue("url", StringConfigEntry.class);
|
||||
url = IOHelper.convertToURL(configUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws IOException {
|
||||
authRequest authRequest = new authRequest(login, password, ip);
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.HTTPRequest;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -25,10 +23,6 @@ public final class MojangAuthProvider extends AuthProvider {
|
|||
}
|
||||
}
|
||||
|
||||
public MojangAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
}
|
||||
|
||||
public class mojangAuth {
|
||||
public mojangAuth(String username, String password) {
|
||||
this.username = username;
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.ListConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
|
@ -18,24 +13,11 @@
|
|||
import java.sql.SQLException;
|
||||
|
||||
public final class MySQLAuthProvider extends AuthProvider {
|
||||
private final MySQLSourceConfig mySQLHolder;
|
||||
private final String query;
|
||||
private final String message;
|
||||
private final String[] queryParams;
|
||||
private final boolean usePermission;
|
||||
|
||||
public MySQLAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
mySQLHolder = new MySQLSourceConfig("authProviderPool", block);
|
||||
|
||||
// Read query
|
||||
query = VerifyHelper.verify(block.getEntryValue("query", StringConfigEntry.class),
|
||||
VerifyHelper.NOT_EMPTY, "MySQL query can't be empty");
|
||||
usePermission = block.hasEntry("usePermission") ? block.getEntryValue("usePermission", BooleanConfigEntry.class) : false;
|
||||
message = block.hasEntry("message") ? block.getEntryValue("message", StringConfigEntry.class) : "Incorrect username or password";
|
||||
queryParams = block.getEntry("queryParams", ListConfigEntry.class).
|
||||
stream(StringConfigEntry.class).toArray(String[]::new);
|
||||
}
|
||||
private MySQLSourceConfig mySQLHolder;
|
||||
private String query;
|
||||
private String message;
|
||||
private String[] queryParams;
|
||||
private boolean usePermission;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws SQLException, AuthException {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -10,10 +8,6 @@
|
|||
public final class NullAuthProvider extends AuthProvider {
|
||||
private volatile AuthProvider provider;
|
||||
|
||||
public NullAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws Exception {
|
||||
return getProvider().auth(login, password, ip);
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class RejectAuthProvider extends AuthProvider {
|
||||
private final String message;
|
||||
|
||||
public RejectAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
message = VerifyHelper.verify(block.getEntryValue("message", StringConfigEntry.class), VerifyHelper.NOT_EMPTY,
|
||||
"Auth error message can't be empty");
|
||||
}
|
||||
private String message;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws AuthException {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package ru.gravit.launchserver.auth.provider;
|
||||
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.ClientPermissions;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
@ -15,18 +11,9 @@
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
public final class RequestAuthProvider extends AuthProvider {
|
||||
private final String url;
|
||||
private final Pattern response;
|
||||
private final boolean usePermission;
|
||||
|
||||
public RequestAuthProvider(BlockConfigEntry block, LaunchServer server) {
|
||||
super(block, server);
|
||||
url = block.getEntryValue("url", StringConfigEntry.class);
|
||||
response = Pattern.compile(block.getEntryValue("response", StringConfigEntry.class));
|
||||
usePermission = block.hasEntry("usePermission") ? block.getEntryValue("usePermission", BooleanConfigEntry.class) : false;
|
||||
// Verify is valid URL
|
||||
IOHelper.verifyURL(getFormattedURL("urlAuthLogin", "urlAuthPassword", "127.0.0.1"));
|
||||
}
|
||||
private String url;
|
||||
private Pattern response;
|
||||
private boolean usePermission;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, String password, String ip) throws IOException {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ru.gravit.launcher.server;
|
||||
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
|
@ -20,9 +22,7 @@
|
|||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
@ -37,6 +37,8 @@ public class ServerWrapper {
|
|||
public static Config config;
|
||||
public static PublicURLClassLoader ucp;
|
||||
public static ClassLoader loader;
|
||||
private static Gson gson;
|
||||
private static GsonBuilder gsonBuiler;
|
||||
|
||||
public static Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules"));
|
||||
public static Path configFile = Paths.get(System.getProperty("serverwrapper.configFile", "ServerWrapper.cfg"));
|
||||
|
@ -91,9 +93,13 @@ public static void main(String[] args) throws Throwable {
|
|||
modulesManager.autoload(modulesDir);
|
||||
Launcher.modulesManager = modulesManager;
|
||||
modulesManager.preInitModules();
|
||||
LogHelper.debug("Read LaunchWrapper.cfg");
|
||||
gsonBuiler = new GsonBuilder();
|
||||
gson = gsonBuiler.create();
|
||||
generateConfigIfNotExists();
|
||||
try (BufferedReader reader = IOHelper.newReader(configFile)) {
|
||||
config = new Config(TextConfigReader.read(reader, true));
|
||||
try(Reader reader = IOHelper.newReader(configFile))
|
||||
{
|
||||
config = gson.fromJson(reader,Config.class);
|
||||
}
|
||||
LauncherConfig cfg = new LauncherConfig(config.address, config.port, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
|
||||
Launcher.setConfig(cfg);
|
||||
|
@ -148,20 +154,22 @@ private static void generateConfigIfNotExists() throws IOException {
|
|||
// Create new config
|
||||
LogHelper.info("Creating LaunchWrapper config");
|
||||
Config newConfig;
|
||||
try (BufferedReader reader = IOHelper.newReader(IOHelper.getResourceURL("ru/gravit/launcher/server/ServerWrapper.cfg"))) {
|
||||
newConfig = new Config(TextConfigReader.read(reader, false));
|
||||
try(Reader reader = IOHelper.newReader(IOHelper.getResourceURL("ru/gravit/launcher/server/ServerWrapper.cfg")))
|
||||
{
|
||||
newConfig = gson.fromJson(reader,Config.class);
|
||||
}
|
||||
|
||||
LogHelper.warning("Title is not set. Please show ServerWrapper.cfg");
|
||||
|
||||
// Write LaunchServer config
|
||||
LogHelper.info("Writing LaunchWrapper config file");
|
||||
try (BufferedWriter writer = IOHelper.newWriter(configFile)) {
|
||||
TextConfigWriter.write(newConfig.block, writer, true);
|
||||
try(Writer writer = IOHelper.newWriter(configFile))
|
||||
{
|
||||
gson.toJson(newConfig,writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Config extends ConfigObject {
|
||||
public static final class Config {
|
||||
public String title;
|
||||
public String projectname;
|
||||
public String address;
|
||||
|
@ -176,26 +184,6 @@ public static final class Config extends ConfigObject {
|
|||
public String mainclass;
|
||||
public String login;
|
||||
public String password;
|
||||
|
||||
protected Config(BlockConfigEntry block) {
|
||||
super(block);
|
||||
title = block.getEntryValue("title", StringConfigEntry.class);
|
||||
address = block.getEntryValue("address", StringConfigEntry.class);
|
||||
projectname = block.getEntryValue("projectName", StringConfigEntry.class);
|
||||
login = block.getEntryValue("login", StringConfigEntry.class);
|
||||
password = block.getEntryValue("password", StringConfigEntry.class);
|
||||
port = block.getEntryValue("port", IntegerConfigEntry.class);
|
||||
customClassPath = block.getEntryValue("customClassPath", BooleanConfigEntry.class);
|
||||
autoloadLibraries = block.getEntryValue("autoloadLibraries", BooleanConfigEntry.class);
|
||||
if (customClassPath)
|
||||
classpath = block.getEntryValue("classpath", StringConfigEntry.class);
|
||||
if (autoloadLibraries)
|
||||
librariesDir = block.getEntryValue("librariesDir", StringConfigEntry.class);
|
||||
mainclass = block.getEntryValue("MainClass", StringConfigEntry.class);
|
||||
reconnectCount = block.hasEntry("reconnectCount") ? block.getEntryValue("reconnectCount", IntegerConfigEntry.class) : 1;
|
||||
reconnectSleep = block.hasEntry("reconnectSleep") ? block.getEntryValue("reconnectSleep", IntegerConfigEntry.class) : 30000;
|
||||
syncAuth = block.hasEntry("syncAuth") ? block.getEntryValue("syncAuth", BooleanConfigEntry.class) : true;
|
||||
}
|
||||
}
|
||||
|
||||
public ClientProfile profile;
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.hasher.FileNameMatcher;
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.config.ConfigObject;
|
||||
import ru.gravit.launcher.serialize.config.entry.*;
|
||||
import ru.gravit.launcher.serialize.stream.StreamObject;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
|
@ -15,7 +11,7 @@
|
|||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("ComparableImplementedButEqualsNotOverridden")
|
||||
public final class ClientProfile extends ConfigObject implements Comparable<ClientProfile> {
|
||||
public final class ClientProfile implements Comparable<ClientProfile> {
|
||||
@LauncherAPI
|
||||
public enum Version {
|
||||
MC147("1.4.7", 51),
|
||||
|
@ -59,9 +55,6 @@ public String toString() {
|
|||
}
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static final StreamObject.Adapter<ClientProfile> RO_ADAPTER = input -> new ClientProfile(input, true);
|
||||
|
||||
public static final boolean profileCaseSensitive = Boolean.getBoolean("launcher.clientProfile.caseSensitive");
|
||||
|
||||
private static final FileNameMatcher ASSET_MATCHER = new FileNameMatcher(
|
||||
|
@ -69,13 +62,13 @@ public String toString() {
|
|||
// Version
|
||||
private String version;
|
||||
|
||||
private final String assetIndex;
|
||||
private String assetIndex;
|
||||
// Client
|
||||
private final int sortIndex;
|
||||
private int sortIndex;
|
||||
private String title;
|
||||
private final String serverAddress;
|
||||
private String serverAddress;
|
||||
|
||||
private final int serverPort;
|
||||
private int serverPort;
|
||||
|
||||
public static class MarkedString {
|
||||
@LauncherAPI
|
||||
|
@ -113,54 +106,17 @@ public int hashCode() {
|
|||
private final List<String> updateShared = new ArrayList<>();
|
||||
private final List<String> updateVerify = new ArrayList<>();
|
||||
private final Set<MarkedString> updateOptional = new HashSet<>();
|
||||
private final boolean updateFastCheck;
|
||||
private boolean updateFastCheck;
|
||||
|
||||
private final boolean useWhitelist;
|
||||
private boolean useWhitelist;
|
||||
// Client launcher
|
||||
private final String mainClass;
|
||||
private String mainClass;
|
||||
private final List<String> jvmArgs = new ArrayList<>();
|
||||
private final List<String> classPath = new ArrayList<>();
|
||||
private final List<String> clientArgs = new ArrayList<>();
|
||||
|
||||
private final List<String> whitelist = new ArrayList<>();
|
||||
|
||||
@LauncherAPI
|
||||
public ClientProfile(BlockConfigEntry block) {
|
||||
super(block);
|
||||
|
||||
// Version
|
||||
version = block.getEntryValue("version", StringConfigEntry.class);
|
||||
assetIndex = block.getEntryValue("assetIndex", StringConfigEntry.class);
|
||||
|
||||
// Client
|
||||
sortIndex = block.getEntryValue("sortIndex", IntegerConfigEntry.class);
|
||||
title = block.getEntryValue("title", StringConfigEntry.class);
|
||||
serverAddress = block.getEntryValue("serverAddress", StringConfigEntry.class);
|
||||
serverPort = block.getEntryValue("serverPort", IntegerConfigEntry.class);
|
||||
|
||||
// Updater and client watch service
|
||||
block.getEntry("update", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(update::add);
|
||||
block.getEntry("updateVerify", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(updateVerify::add);
|
||||
block.getEntry("updateShared", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(updateShared::add);
|
||||
block.getEntry("updateOptional", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(e -> updateOptional.add(new MarkedString(e)));
|
||||
block.getEntry("updateExclusions", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(updateExclusions::add);
|
||||
block.getEntry("enabledOptional", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(e -> updateOptional.stream().anyMatch(e1 -> e.equals(e1.string) && (e1.mark = true)));
|
||||
updateFastCheck = block.getEntryValue("updateFastCheck", BooleanConfigEntry.class);
|
||||
useWhitelist = block.getEntryValue("useWhitelist", BooleanConfigEntry.class);
|
||||
|
||||
// Client launcher
|
||||
mainClass = block.getEntryValue("mainClass", StringConfigEntry.class);
|
||||
block.getEntry("classPath", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(classPath::add);
|
||||
block.getEntry("jvmArgs", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(jvmArgs::add);
|
||||
block.getEntry("clientArgs", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(clientArgs::add);
|
||||
block.getEntry("whitelist", ListConfigEntry.class).stream(StringConfigEntry.class).forEach(whitelist::add);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public ClientProfile(HInput input, boolean ro) throws IOException {
|
||||
this(new BlockConfigEntry(input, ro));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ClientProfile o) {
|
||||
return Integer.compare(getSortIndex(), o.getSortIndex());
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry;
|
||||
import ru.gravit.launcher.serialize.stream.StreamObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class ConfigObject extends StreamObject {
|
||||
@FunctionalInterface
|
||||
public interface Adapter<O extends ConfigObject> {
|
||||
@LauncherAPI
|
||||
O convert(BlockConfigEntry entry);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public final BlockConfigEntry block;
|
||||
|
||||
@LauncherAPI
|
||||
protected ConfigObject(BlockConfigEntry block) {
|
||||
this.block = Objects.requireNonNull(block, "block");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void write(HOutput output) throws IOException {
|
||||
block.write(output);
|
||||
}
|
||||
}
|
|
@ -1,234 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.config.entry.*;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class TextConfigReader {
|
||||
@LauncherAPI
|
||||
public static BlockConfigEntry read(Reader reader, boolean ro) throws IOException {
|
||||
return new TextConfigReader(reader, ro).readBlock(0);
|
||||
}
|
||||
|
||||
private final LineNumberReader reader;
|
||||
private final boolean ro;
|
||||
private String skipped;
|
||||
|
||||
private int ch = -1;
|
||||
|
||||
private TextConfigReader(Reader reader, boolean ro) {
|
||||
this.reader = new LineNumberReader(reader);
|
||||
this.reader.setLineNumber(1);
|
||||
this.ro = ro;
|
||||
}
|
||||
|
||||
private IOException newIOException(String message) {
|
||||
return new IOException(message + " (line " + reader.getLineNumber() + ')');
|
||||
}
|
||||
|
||||
private int nextChar(boolean eof) throws IOException {
|
||||
ch = reader.read();
|
||||
if (eof && ch < 0)
|
||||
throw newIOException("Unexpected end of config");
|
||||
return ch;
|
||||
}
|
||||
|
||||
private int nextClean(boolean eof) throws IOException {
|
||||
nextChar(eof);
|
||||
return skipWhitespace(eof);
|
||||
}
|
||||
|
||||
private BlockConfigEntry readBlock(int cc) throws IOException {
|
||||
Map<String, ConfigEntry<?>> map = new LinkedHashMap<>(16);
|
||||
|
||||
// Read block entries
|
||||
boolean brackets = ch == '{';
|
||||
while (nextClean(brackets) >= 0 && (!brackets || ch != '}')) {
|
||||
String preNameComment = skipped;
|
||||
|
||||
// Read entry name
|
||||
String name = readToken();
|
||||
if (skipWhitespace(true) != ':')
|
||||
throw newIOException("Value start expected");
|
||||
String postNameComment = skipped;
|
||||
|
||||
// Read entry value
|
||||
nextClean(true);
|
||||
String preValueComment = skipped;
|
||||
ConfigEntry<?> entry = readEntry(4);
|
||||
if (skipWhitespace(true) != ';')
|
||||
throw newIOException("Value end expected");
|
||||
|
||||
// Set comments
|
||||
entry.setComment(0, preNameComment);
|
||||
entry.setComment(1, postNameComment);
|
||||
entry.setComment(2, preValueComment);
|
||||
entry.setComment(3, skipped);
|
||||
|
||||
// Try add entry to map
|
||||
if (map.put(name, entry) != null)
|
||||
throw newIOException(String.format("Duplicate config entry: '%s'", name));
|
||||
}
|
||||
|
||||
// Set comment after last entry and return block
|
||||
BlockConfigEntry block = new BlockConfigEntry(map, ro, cc + 1);
|
||||
block.setComment(cc, skipped);
|
||||
nextChar(false);
|
||||
return block;
|
||||
}
|
||||
|
||||
private ConfigEntry<?> readEntry(int cc) throws IOException {
|
||||
// Try detect type by first char
|
||||
switch (ch) {
|
||||
case '"': // String
|
||||
return readString(cc);
|
||||
case '[': // List
|
||||
return readList(cc);
|
||||
case '{': // Block
|
||||
return readBlock(cc);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Possibly integer value
|
||||
if (ch == '-' || ch >= '0' && ch <= '9')
|
||||
return readInteger(cc);
|
||||
|
||||
// Statement?
|
||||
String statement = readToken();
|
||||
switch (statement) {
|
||||
case "true":
|
||||
return new BooleanConfigEntry(Boolean.TRUE, ro, cc);
|
||||
case "false":
|
||||
return new BooleanConfigEntry(Boolean.FALSE, ro, cc);
|
||||
default:
|
||||
throw newIOException(String.format("Unknown statement: '%s'", statement));
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigEntry<Integer> readInteger(int cc) throws IOException {
|
||||
return new IntegerConfigEntry(Integer.parseInt(readToken()), ro, cc);
|
||||
}
|
||||
|
||||
private ConfigEntry<List<ConfigEntry<?>>> readList(int cc) throws IOException {
|
||||
List<ConfigEntry<?>> listValue = new ArrayList<>(16);
|
||||
|
||||
// Read list elements
|
||||
boolean hasNextElement = nextClean(true) != ']';
|
||||
String preValueComment = skipped;
|
||||
while (hasNextElement) {
|
||||
ConfigEntry<?> element = readEntry(2);
|
||||
hasNextElement = skipWhitespace(true) != ']';
|
||||
element.setComment(0, preValueComment);
|
||||
element.setComment(1, skipped);
|
||||
listValue.add(element);
|
||||
|
||||
// Prepare for next element read
|
||||
if (hasNextElement) {
|
||||
if (ch != ',')
|
||||
throw newIOException("Comma expected");
|
||||
nextClean(true);
|
||||
preValueComment = skipped;
|
||||
}
|
||||
}
|
||||
|
||||
// Set in-list comment (if no elements)
|
||||
boolean additional = listValue.isEmpty();
|
||||
ConfigEntry<List<ConfigEntry<?>>> list = new ListConfigEntry(listValue, ro, additional ? cc + 1 : cc);
|
||||
if (additional)
|
||||
list.setComment(cc, skipped);
|
||||
|
||||
// Return list
|
||||
nextChar(false);
|
||||
return list;
|
||||
}
|
||||
|
||||
private ConfigEntry<?> readString(int cc) throws IOException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// Read string chars
|
||||
while (nextChar(true) != '"')
|
||||
switch (ch) {
|
||||
case '\r':
|
||||
case '\n': // String termination
|
||||
throw newIOException("String termination");
|
||||
case '\\':
|
||||
int next = nextChar(true);
|
||||
switch (next) {
|
||||
case 't':
|
||||
builder.append('\t');
|
||||
break;
|
||||
case 'b':
|
||||
builder.append('\b');
|
||||
break;
|
||||
case 'n':
|
||||
builder.append('\n');
|
||||
break;
|
||||
case 'r':
|
||||
builder.append('\r');
|
||||
break;
|
||||
case 'f':
|
||||
builder.append('\f');
|
||||
break;
|
||||
case '"':
|
||||
case '\\':
|
||||
builder.append((char) next);
|
||||
break;
|
||||
default:
|
||||
throw newIOException("Illegal char escape: " + (char) next);
|
||||
}
|
||||
break;
|
||||
default: // Normal character
|
||||
builder.append((char) ch);
|
||||
break;
|
||||
}
|
||||
|
||||
// Return string
|
||||
nextChar(false);
|
||||
return new StringConfigEntry(builder.toString(), ro, cc);
|
||||
}
|
||||
|
||||
private String readToken() throws IOException {
|
||||
// Read token
|
||||
StringBuilder builder = new StringBuilder();
|
||||
while (VerifyHelper.isValidIDNameChar(ch)) {
|
||||
builder.append((char) ch);
|
||||
nextChar(false);
|
||||
}
|
||||
|
||||
// Return token as string
|
||||
String token = builder.toString();
|
||||
if (token.isEmpty())
|
||||
throw newIOException("Not a token");
|
||||
return token;
|
||||
}
|
||||
|
||||
private void skipComment(StringBuilder skippedBuilder, boolean eof) throws IOException {
|
||||
while (ch >= 0 && ch != '\r' && ch != '\n') {
|
||||
skippedBuilder.append((char) ch);
|
||||
nextChar(eof);
|
||||
}
|
||||
}
|
||||
|
||||
private int skipWhitespace(boolean eof) throws IOException {
|
||||
StringBuilder skippedBuilder = new StringBuilder();
|
||||
while (Character.isWhitespace(ch) || ch == '#') {
|
||||
if (ch == '#') {
|
||||
skipComment(skippedBuilder, eof);
|
||||
continue;
|
||||
}
|
||||
skippedBuilder.append((char) ch);
|
||||
nextChar(eof);
|
||||
}
|
||||
skipped = skippedBuilder.toString();
|
||||
return ch;
|
||||
}
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.config.entry.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public final class TextConfigWriter {
|
||||
@LauncherAPI
|
||||
public static void write(BlockConfigEntry block, Writer writer, boolean comments) throws IOException {
|
||||
new TextConfigWriter(writer, comments).writeBlock(block, false);
|
||||
}
|
||||
|
||||
private final Writer writer;
|
||||
|
||||
private final boolean comments;
|
||||
|
||||
private TextConfigWriter(Writer writer, boolean comments) {
|
||||
this.writer = writer;
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
private void writeBlock(BlockConfigEntry block, boolean brackets) throws IOException {
|
||||
// Write start bracket
|
||||
if (brackets)
|
||||
writer.write('{');
|
||||
|
||||
// Write block entries
|
||||
Map<String, ConfigEntry<?>> map = block.getValue();
|
||||
for (Entry<String, ConfigEntry<?>> mapEntry : map.entrySet()) {
|
||||
String name = mapEntry.getKey();
|
||||
ConfigEntry<?> entry = mapEntry.getValue();
|
||||
|
||||
// Write entry name
|
||||
writeComment(entry.getComment(0));
|
||||
writer.write(name);
|
||||
writeComment(entry.getComment(1));
|
||||
writer.write(':');
|
||||
|
||||
// Write entry value
|
||||
writeComment(entry.getComment(2));
|
||||
writeEntry(entry);
|
||||
writeComment(entry.getComment(3));
|
||||
writer.write(';');
|
||||
}
|
||||
writeComment(block.getComment(-1));
|
||||
|
||||
// Write end bracket
|
||||
if (brackets)
|
||||
writer.write('}');
|
||||
}
|
||||
|
||||
private void writeBoolean(BooleanConfigEntry entry) throws IOException {
|
||||
writer.write(entry.getValue().toString());
|
||||
}
|
||||
|
||||
private void writeComment(String comment) throws IOException {
|
||||
if (comments && comment != null)
|
||||
writer.write(comment);
|
||||
}
|
||||
|
||||
private void writeEntry(ConfigEntry<?> entry) throws IOException {
|
||||
ConfigEntry.Type type = entry.getType();
|
||||
switch (type) {
|
||||
case BLOCK:
|
||||
writeBlock((BlockConfigEntry) entry, true);
|
||||
break;
|
||||
case STRING:
|
||||
writeString((StringConfigEntry) entry);
|
||||
break;
|
||||
case INTEGER:
|
||||
writeInteger((IntegerConfigEntry) entry);
|
||||
break;
|
||||
case BOOLEAN:
|
||||
writeBoolean((BooleanConfigEntry) entry);
|
||||
break;
|
||||
case LIST:
|
||||
writeList((ListConfigEntry) entry);
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unsupported config entry type: " + type.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeInteger(IntegerConfigEntry entry) throws IOException {
|
||||
writer.write(Integer.toString(entry.getValue()));
|
||||
}
|
||||
|
||||
private void writeList(ListConfigEntry entry) throws IOException {
|
||||
writer.write('[');
|
||||
|
||||
// Write list elements
|
||||
List<ConfigEntry<?>> value = entry.getValue();
|
||||
for (int i = 0; i < value.size(); i++) {
|
||||
if (i > 0)
|
||||
writer.write(',');
|
||||
|
||||
// Write element
|
||||
ConfigEntry<?> element = value.get(i);
|
||||
writeComment(element.getComment(0));
|
||||
writeEntry(element);
|
||||
writeComment(element.getComment(1));
|
||||
}
|
||||
writeComment(entry.getComment(-1));
|
||||
|
||||
// Write end bracket
|
||||
writer.write(']');
|
||||
}
|
||||
|
||||
private void writeString(StringConfigEntry entry) throws IOException {
|
||||
writer.write('"');
|
||||
|
||||
// Quote string
|
||||
String s = entry.getValue();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
switch (ch) {
|
||||
case '\t':
|
||||
writer.write("\\t");
|
||||
break;
|
||||
case '\b':
|
||||
writer.write("\\b");
|
||||
break;
|
||||
case '\n':
|
||||
writer.write("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
writer.write("\\r");
|
||||
break;
|
||||
case '\f':
|
||||
writer.write("\\f");
|
||||
break;
|
||||
case '"':
|
||||
case '\\':
|
||||
writer.write('\\');
|
||||
writer.write(ch);
|
||||
break;
|
||||
default:
|
||||
writer.write(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Write end quote
|
||||
writer.write('"');
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config.entry;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public final class BlockConfigEntry extends ConfigEntry<Map<String, ConfigEntry<?>>> {
|
||||
private static Map<String, ConfigEntry<?>> readMap(HInput input, boolean ro) throws IOException {
|
||||
int entriesCount = input.readLength(0);
|
||||
Map<String, ConfigEntry<?>> map = new LinkedHashMap<>(entriesCount);
|
||||
for (int i = 0; i < entriesCount; i++) {
|
||||
String name = VerifyHelper.verifyIDName(input.readString(255));
|
||||
ConfigEntry<?> entry = readEntry(input, ro);
|
||||
|
||||
// Try add entry to map
|
||||
VerifyHelper.putIfAbsent(map, name, entry, String.format("Duplicate config entry: '%s'", name));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public BlockConfigEntry(HInput input, boolean ro) throws IOException {
|
||||
super(readMap(input, ro), ro, 0);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public BlockConfigEntry(int cc) {
|
||||
super(Collections.emptyMap(), false, cc);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public BlockConfigEntry(Map<String, ConfigEntry<?>> map, boolean ro, int cc) {
|
||||
super(map, ro, cc);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void clear() {
|
||||
super.getValue().clear();
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public <E extends ConfigEntry<?>> E getEntry(String name, Class<E> clazz) {
|
||||
Map<String, ConfigEntry<?>> map = super.getValue();
|
||||
ConfigEntry<?> value = map.get(name);
|
||||
if (!clazz.isInstance(value))
|
||||
throw new NoSuchElementException(name);
|
||||
return clazz.cast(value);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public <V, E extends ConfigEntry<V>> V getEntryValue(String name, Class<E> clazz) {
|
||||
return getEntry(name, clazz).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigEntry<?>> getValue() {
|
||||
Map<String, ConfigEntry<?>> value = super.getValue();
|
||||
return ro ? value : Collections.unmodifiableMap(value); // Already RO
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public boolean hasEntry(String name) {
|
||||
return getValue().containsKey(name);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void remove(String name) {
|
||||
super.getValue().remove(name);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void setEntry(String name, ConfigEntry<?> entry) {
|
||||
super.getValue().put(VerifyHelper.verifyIDName(name), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uncheckedSetValue(Map<String, ConfigEntry<?>> value) {
|
||||
Map<String, ConfigEntry<?>> newValue = new LinkedHashMap<>(value);
|
||||
newValue.keySet().stream().forEach(VerifyHelper::verifyIDName);
|
||||
|
||||
// Call super method to actually set new value
|
||||
super.uncheckedSetValue(ro ? Collections.unmodifiableMap(newValue) : newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(HOutput output) throws IOException {
|
||||
Set<Entry<String, ConfigEntry<?>>> entries = getValue().entrySet();
|
||||
output.writeLength(entries.size(), 0);
|
||||
for (Entry<String, ConfigEntry<?>> mapEntry : entries) {
|
||||
output.writeString(mapEntry.getKey(), 255);
|
||||
writeEntry(mapEntry.getValue(), output);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config.entry;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class BooleanConfigEntry extends ConfigEntry<Boolean> {
|
||||
@LauncherAPI
|
||||
public BooleanConfigEntry(boolean value, boolean ro, int cc) {
|
||||
super(value, ro, cc);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public BooleanConfigEntry(HInput input, boolean ro) throws IOException {
|
||||
this(input.readBoolean(), ro, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(HOutput output) throws IOException {
|
||||
output.writeBoolean(getValue());
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config.entry;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.stream.EnumSerializer;
|
||||
import ru.gravit.launcher.serialize.stream.EnumSerializer.Itf;
|
||||
import ru.gravit.launcher.serialize.stream.StreamObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class ConfigEntry<V> extends StreamObject {
|
||||
@LauncherAPI
|
||||
public enum Type implements Itf {
|
||||
BLOCK(1), BOOLEAN(2), INTEGER(3), STRING(4), LIST(5);
|
||||
private static final EnumSerializer<Type> SERIALIZER = new EnumSerializer<>(Type.class);
|
||||
|
||||
public static Type read(HInput input) throws IOException {
|
||||
return SERIALIZER.read(input);
|
||||
}
|
||||
|
||||
private final int n;
|
||||
|
||||
Type(int n) {
|
||||
this.n = n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumber() {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
protected static ConfigEntry<?> readEntry(HInput input, boolean ro) throws IOException {
|
||||
Type type = Type.read(input);
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
return new BooleanConfigEntry(input, ro);
|
||||
case INTEGER:
|
||||
return new IntegerConfigEntry(input, ro);
|
||||
case STRING:
|
||||
return new StringConfigEntry(input, ro);
|
||||
case LIST:
|
||||
return new ListConfigEntry(input, ro);
|
||||
case BLOCK:
|
||||
return new BlockConfigEntry(input, ro);
|
||||
default:
|
||||
throw new AssertionError("Unsupported config entry type: " + type.name());
|
||||
}
|
||||
}
|
||||
|
||||
protected static void writeEntry(ConfigEntry<?> entry, HOutput output) throws IOException {
|
||||
EnumSerializer.write(output, entry.getType());
|
||||
entry.write(output);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public final boolean ro;
|
||||
|
||||
private final String[] comments;
|
||||
|
||||
private V value;
|
||||
|
||||
protected ConfigEntry(V value, boolean ro, int cc) {
|
||||
this.ro = ro;
|
||||
comments = new String[cc];
|
||||
uncheckedSetValue(value);
|
||||
}
|
||||
|
||||
protected final void ensureWritable() {
|
||||
if (ro)
|
||||
throw new UnsupportedOperationException("Read-only");
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public final String getComment(int i) {
|
||||
if (i < 0)
|
||||
i += comments.length;
|
||||
return i >= comments.length ? null : comments[i];
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public abstract Type getType();
|
||||
|
||||
@LauncherAPI
|
||||
@SuppressWarnings("DesignForExtension")
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public final void setComment(int i, String comment) {
|
||||
comments[i] = comment;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public final void setValue(V value) {
|
||||
ensureWritable();
|
||||
uncheckedSetValue(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DesignForExtension")
|
||||
protected void uncheckedSetValue(V value) {
|
||||
this.value = Objects.requireNonNull(value, "value");
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config.entry;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class IntegerConfigEntry extends ConfigEntry<Integer> {
|
||||
@LauncherAPI
|
||||
public IntegerConfigEntry(HInput input, boolean ro) throws IOException {
|
||||
this(input.readVarInt(), ro, 0);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public IntegerConfigEntry(int value, boolean ro, int cc) {
|
||||
super(value, ro, cc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(HOutput output) throws IOException {
|
||||
output.writeVarInt(getValue());
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config.entry;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class ListConfigEntry extends ConfigEntry<List<ConfigEntry<?>>> {
|
||||
private static List<ConfigEntry<?>> readList(HInput input, boolean ro) throws IOException {
|
||||
int elementsCount = input.readLength(0);
|
||||
List<ConfigEntry<?>> list = new ArrayList<>(elementsCount);
|
||||
for (int i = 0; i < elementsCount; i++)
|
||||
list.add(readEntry(input, ro));
|
||||
return list;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public ListConfigEntry(HInput input, boolean ro) throws IOException {
|
||||
super(readList(input, ro), ro, 0);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public ListConfigEntry(List<ConfigEntry<?>> value, boolean ro, int cc) {
|
||||
super(value, ro, cc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.LIST;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public <V, E extends ConfigEntry<V>> Stream<V> stream(Class<E> clazz) {
|
||||
return getValue().stream().map(clazz::cast).map(ConfigEntry::getValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uncheckedSetValue(List<ConfigEntry<?>> value) {
|
||||
List<ConfigEntry<?>> list = new ArrayList<>(value);
|
||||
super.uncheckedSetValue(ro ? Collections.unmodifiableList(list) : list);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void verifyOfType(Type type) {
|
||||
if (getValue().stream().anyMatch(e -> e.getType() != type))
|
||||
throw new IllegalArgumentException("List type mismatch: " + type.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(HOutput output) throws IOException {
|
||||
List<ConfigEntry<?>> value = getValue();
|
||||
output.writeLength(value.size(), 0);
|
||||
for (ConfigEntry<?> element : value)
|
||||
writeEntry(element, output);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package ru.gravit.launcher.serialize.config.entry;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class StringConfigEntry extends ConfigEntry<String> {
|
||||
@LauncherAPI
|
||||
public StringConfigEntry(HInput input, boolean ro) throws IOException {
|
||||
this(input.readString(0), ro, 0);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public StringConfigEntry(String value, boolean ro, int cc) {
|
||||
super(value, ro, cc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.STRING;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uncheckedSetValue(String value) {
|
||||
super.uncheckedSetValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(HOutput output) throws IOException {
|
||||
output.writeString(getValue(), 0);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue