Перевод конфигов на Json часть 1

Не комплируется
This commit is contained in:
Gravit 2018-12-23 22:50:31 +07:00
parent d2916d180d
commit 49b085278c
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
34 changed files with 134 additions and 1514 deletions

View file

@ -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) {

View file

@ -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;

View file

@ -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 {

View file

@ -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)

View file

@ -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 {

View file

@ -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

View file

@ -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() {

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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

View file

@ -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 {

View file

@ -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) {

View file

@ -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 {

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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 {

View file

@ -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);

View file

@ -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 {

View file

@ -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 {

View file

@ -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;

View file

@ -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());

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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('"');
}
}

View file

@ -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);
}
}
}

View file

@ -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());
}
}

View file

@ -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");
}
}

View file

@ -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());
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}