mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-07-29 18:27:36 +02:00
Migrate to Java 8 (sponsored contribution)
Java >8 includes many helpful features and API additions. Current phoronix benchmarks indicated a very similar performance. Furthermore, the fact that Java 18 even works with 1.8.8 contributed to the decision to move to Java 17 like vanilla Java in 1.19. This also helps us to learn about the newer features added for our personal interests. As this is a free project, this motivated us to make this step. Nevertheless, many server owners were frustrated about this decision. Thanks to financial contribution, we revised this decision until Java 8 is end of life or no longer used actively used according to bstats.org
This commit is contained in:
@ -50,7 +50,7 @@ import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Base64.Encoder;
|
||||
import java.util.random.RandomGenerator;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
@ -59,6 +59,8 @@ import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import lombok.val;
|
||||
|
||||
/**
|
||||
* Encryption and decryption minecraft util for connection between servers
|
||||
* and paid Minecraft account clients.
|
||||
@ -85,7 +87,7 @@ final class EncryptionUtil {
|
||||
}
|
||||
|
||||
private EncryptionUtil() {
|
||||
// utility
|
||||
throw new RuntimeException("No instantiation of utility classes allowed");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +114,7 @@ final class EncryptionUtil {
|
||||
* @param random random generator
|
||||
* @return a token with 4 bytes long
|
||||
*/
|
||||
public static byte[] generateVerifyToken(RandomGenerator random) {
|
||||
public static byte[] generateVerifyToken(Random random) {
|
||||
byte[] token = new byte[VERIFY_TOKEN_LENGTH];
|
||||
random.nextBytes(token);
|
||||
return token;
|
||||
@ -177,9 +179,9 @@ final class EncryptionUtil {
|
||||
|
||||
private static PublicKey loadMojangSessionKey()
|
||||
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
var keyUrl = FastLoginBukkit.class.getClassLoader().getResource("yggdrasil_session_pubkey.der");
|
||||
var keyData = Resources.toByteArray(keyUrl);
|
||||
var keySpec = new X509EncodedKeySpec(keyData);
|
||||
val keyUrl = FastLoginBukkit.class.getClassLoader().getResource("yggdrasil_session_pubkey.der");
|
||||
val keyData = Resources.toByteArray(keyUrl);
|
||||
val keySpec = new X509EncodedKeySpec(keyData);
|
||||
|
||||
return KeyFactory.getInstance("RSA").generatePublic(keySpec);
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
import lombok.var;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.ENCRYPTION_BEGIN;
|
||||
@ -171,7 +172,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
Either<byte[], ?> either = packet.getSpecificModifier(Either.class).read(0);
|
||||
if (clientPublicKey == null) {
|
||||
Optional<byte[]> left = either.left();
|
||||
if (left.isEmpty()) {
|
||||
if (!left.isPresent()) {
|
||||
plugin.getLog().error("No verify token sent if requested without player signed key {}", sender);
|
||||
return false;
|
||||
}
|
||||
@ -179,7 +180,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
return EncryptionUtil.verifyNonce(expectedToken, keyPair.getPrivate(), left.get());
|
||||
} else {
|
||||
Optional<?> optSignatureData = either.right();
|
||||
if (optSignatureData.isEmpty()) {
|
||||
if (!optSignatureData.isPresent()) {
|
||||
plugin.getLog().error("No signature given to sent player signing key {}", sender);
|
||||
return false;
|
||||
}
|
||||
@ -219,7 +220,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
.optionRead(0);
|
||||
|
||||
var clientKey = profileKey.flatMap(opt -> opt).flatMap(this::verifyPublicKey);
|
||||
if (verifyClientKeys && clientKey.isEmpty()) {
|
||||
if (verifyClientKeys && !clientKey.isPresent()) {
|
||||
// missing or incorrect
|
||||
// expired always not allowed
|
||||
player.kickPlayer(plugin.getCore().getMessage("invalid-public-key"));
|
||||
@ -240,7 +241,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
||||
Instant expires = profileKey.getExpireTime();
|
||||
PublicKey key = profileKey.getKey();
|
||||
byte[] signature = profileKey.getSignature();
|
||||
ClientPublicKey clientKey = new ClientPublicKey(expires, key, signature);
|
||||
ClientPublicKey clientKey = ClientPublicKey.of(expires, key, signature);
|
||||
try {
|
||||
if (EncryptionUtil.verifyClientKey(clientKey, Instant.now())) {
|
||||
return Optional.of(clientKey);
|
||||
|
@ -60,6 +60,7 @@ import java.util.UUID;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import lombok.val;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||
@ -268,7 +269,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
startPacket.getStrings().write(0, username);
|
||||
|
||||
EquivalentConverter<WrappedProfileKeyData> converter = BukkitConverters.getWrappedPublicKeyDataConverter();
|
||||
var wrappedKey = Optional.ofNullable(clientKey).map(key ->
|
||||
val wrappedKey = Optional.ofNullable(clientKey).map(key ->
|
||||
new WrappedProfileKeyData(clientKey.expiry(), clientKey.key(), clientKey.signature())
|
||||
);
|
||||
|
||||
|
@ -28,7 +28,15 @@ package com.github.games647.fastlogin.bukkit.listener.protocollib.packet;
|
||||
import java.security.PublicKey;
|
||||
import java.time.Instant;
|
||||
|
||||
public record ClientPublicKey(Instant expiry, PublicKey key, byte[] signature) {
|
||||
import lombok.Value;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(fluent = true)
|
||||
@Value(staticConstructor = "of")
|
||||
public class ClientPublicKey {
|
||||
Instant expiry;
|
||||
PublicKey key;
|
||||
byte[] signature;
|
||||
|
||||
public boolean isExpired(Instant verifyTimestamp) {
|
||||
return !verifyTimestamp.isBefore(expiry);
|
||||
|
@ -30,6 +30,7 @@ import com.github.games647.fastlogin.core.CommonUtil;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
|
||||
import lombok.val;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -38,13 +39,12 @@ class FastLoginBukkitTest {
|
||||
|
||||
@Test
|
||||
void testRGB() {
|
||||
var message = "&x00002a00002b&lText";
|
||||
var msg = CommonUtil.translateColorCodes(message);
|
||||
val message = "&x00002a00002b&lText";
|
||||
val msg = CommonUtil.translateColorCodes(message);
|
||||
assertEquals(msg, "§x00002a00002b§lText");
|
||||
|
||||
var components = TextComponent.fromLegacyText(msg);
|
||||
var expected = """
|
||||
{"bold":true,"color":"#00a00b","text":"Text"}""";
|
||||
val components = TextComponent.fromLegacyText(msg);
|
||||
val expected = "{\"bold\":true,\"color\":\"#00a00b\",\"text\":\"Text\"}";
|
||||
assertEquals(ComponentSerializer.toString(components), expected);
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,13 @@ import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
|
||||
import lombok.val;
|
||||
|
||||
public class Base64Adapter extends TypeAdapter<byte[]> {
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, byte[] value) throws IOException {
|
||||
var encoded = Base64.getEncoder().encodeToString(value);
|
||||
val encoded = Base64.getEncoder().encodeToString(value);
|
||||
out.value(encoded);
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import lombok.val;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
@ -60,7 +61,7 @@ class EncryptionUtilTest {
|
||||
|
||||
@Test
|
||||
void testVerifyToken() {
|
||||
var random = ThreadLocalRandom.current();
|
||||
val random = ThreadLocalRandom.current();
|
||||
byte[] token = EncryptionUtil.generateVerifyToken(random);
|
||||
|
||||
assertAll(
|
||||
@ -88,10 +89,10 @@ class EncryptionUtilTest {
|
||||
|
||||
@Test
|
||||
void testExpiredClientKey() throws Exception {
|
||||
var clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||
|
||||
// Client expires at the exact second mentioned, so use it for verification
|
||||
var expiredTimestamp = clientKey.expiry();
|
||||
val expiredTimestamp = clientKey.expiry();
|
||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expiredTimestamp));
|
||||
}
|
||||
|
||||
@ -105,7 +106,7 @@ class EncryptionUtilTest {
|
||||
"client_keys/invalid_wrong_signature.json"
|
||||
})
|
||||
void testInvalidClientKey(String clientKeySource) throws Exception {
|
||||
var clientKey = ResourceLoader.loadClientKey(clientKeySource);
|
||||
val clientKey = ResourceLoader.loadClientKey(clientKeySource);
|
||||
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||
|
||||
assertFalse(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp));
|
||||
@ -113,8 +114,8 @@ class EncryptionUtilTest {
|
||||
|
||||
@Test
|
||||
void testValidClientKey() throws Exception {
|
||||
var clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||
var verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||
val clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
|
||||
val verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
|
||||
|
||||
assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp));
|
||||
}
|
||||
@ -122,7 +123,7 @@ class EncryptionUtilTest {
|
||||
@Test
|
||||
void testDecryptSharedSecret() throws Exception {
|
||||
KeyPair serverPair = EncryptionUtil.generateKeyPair();
|
||||
var serverPK = serverPair.getPublic();
|
||||
val serverPK = serverPair.getPublic();
|
||||
|
||||
SecretKey secretKey = generateSharedKey();
|
||||
byte[] encryptedSecret = encrypt(serverPK, secretKey.getEncoded());
|
||||
@ -134,7 +135,7 @@ class EncryptionUtilTest {
|
||||
private static byte[] encrypt(PublicKey receiverKey, byte... message)
|
||||
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
|
||||
IllegalBlockSizeException, BadPaddingException {
|
||||
var encryptCipher = Cipher.getInstance(receiverKey.getAlgorithm());
|
||||
val encryptCipher = Cipher.getInstance(receiverKey.getAlgorithm());
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, receiverKey);
|
||||
return encryptCipher.doFinal(message);
|
||||
}
|
||||
@ -150,9 +151,9 @@ class EncryptionUtilTest {
|
||||
|
||||
@Test
|
||||
void testServerIdHash() throws Exception {
|
||||
var serverId = "";
|
||||
var sharedSecret = generateSharedKey();
|
||||
var serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
||||
val serverId = "";
|
||||
val sharedSecret = generateSharedKey();
|
||||
val serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
||||
|
||||
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
||||
assertEquals(EncryptionUtil.getServerIdHashString(serverId, sharedSecret, serverPK), sessionHash);
|
||||
@ -166,7 +167,7 @@ class EncryptionUtilTest {
|
||||
// sha1.update(server's encoded public key from Encryption Request)
|
||||
// hash := sha1.hexdigest() # String of hex characters
|
||||
@SuppressWarnings("deprecation")
|
||||
var hasher = Hashing.sha1().newHasher();
|
||||
val hasher = Hashing.sha1().newHasher();
|
||||
hasher.putString(serverId, StandardCharsets.US_ASCII);
|
||||
hasher.putBytes(sharedSecret.getEncoded());
|
||||
hasher.putBytes(serverPK.getEncoded());
|
||||
@ -179,9 +180,9 @@ class EncryptionUtilTest {
|
||||
|
||||
@Test
|
||||
void testServerIdHashWrongSecret() throws Exception {
|
||||
var serverId = "";
|
||||
var sharedSecret = generateSharedKey();
|
||||
var serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
||||
val serverId = "";
|
||||
val sharedSecret = generateSharedKey();
|
||||
val serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
|
||||
|
||||
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
||||
assertNotEquals(EncryptionUtil.getServerIdHashString("", generateSharedKey(), serverPK), sessionHash);
|
||||
@ -189,12 +190,12 @@ class EncryptionUtilTest {
|
||||
|
||||
@Test
|
||||
void testServerIdHashWrongServerKey() {
|
||||
var serverId = "";
|
||||
var sharedSecret = generateSharedKey();
|
||||
var serverPK = EncryptionUtil.generateKeyPair().getPublic();
|
||||
val serverId = "";
|
||||
val sharedSecret = generateSharedKey();
|
||||
val serverPK = EncryptionUtil.generateKeyPair().getPublic();
|
||||
|
||||
String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
|
||||
var wrongPK = EncryptionUtil.generateKeyPair().getPublic();
|
||||
val wrongPK = EncryptionUtil.generateKeyPair().getPublic();
|
||||
assertNotEquals(EncryptionUtil.getServerIdHashString("", sharedSecret, wrongPK), sessionHash);
|
||||
}
|
||||
|
||||
@ -238,8 +239,8 @@ class EncryptionUtilTest {
|
||||
@Test
|
||||
void testNonce() throws Exception {
|
||||
byte[] expected = {1, 2, 3, 4};
|
||||
var serverKey = EncryptionUtil.generateKeyPair();
|
||||
var encryptedNonce = encrypt(serverKey.getPublic(), expected);
|
||||
val serverKey = EncryptionUtil.generateKeyPair();
|
||||
val encryptedNonce = encrypt(serverKey.getPublic(), expected);
|
||||
|
||||
assertTrue(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
|
||||
}
|
||||
@ -247,19 +248,19 @@ class EncryptionUtilTest {
|
||||
@Test
|
||||
void testNonceIncorrect() throws Exception {
|
||||
byte[] expected = {1, 2, 3, 4};
|
||||
var serverKey = EncryptionUtil.generateKeyPair();
|
||||
val serverKey = EncryptionUtil.generateKeyPair();
|
||||
|
||||
// flipped first character
|
||||
var encryptedNonce = encrypt(serverKey.getPublic(), new byte[]{0, 2, 3, 4});
|
||||
val encryptedNonce = encrypt(serverKey.getPublic(), new byte[]{0, 2, 3, 4});
|
||||
assertFalse(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNonceFailedDecryption() throws Exception {
|
||||
byte[] expected = {1, 2, 3, 4};
|
||||
var serverKey = EncryptionUtil.generateKeyPair();
|
||||
val serverKey = EncryptionUtil.generateKeyPair();
|
||||
// generate a new keypair that is different
|
||||
var encryptedNonce = encrypt(EncryptionUtil.generateKeyPair().getPublic(), expected);
|
||||
val encryptedNonce = encrypt(EncryptionUtil.generateKeyPair().getPublic(), expected);
|
||||
|
||||
assertThrows(GeneralSecurityException.class,
|
||||
() -> EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce)
|
||||
@ -269,7 +270,7 @@ class EncryptionUtilTest {
|
||||
@Test
|
||||
void testNonceIncorrectEmpty() {
|
||||
byte[] expected = {1, 2, 3, 4};
|
||||
var serverKey = EncryptionUtil.generateKeyPair();
|
||||
val serverKey = EncryptionUtil.generateKeyPair();
|
||||
byte[] encryptedNonce = {};
|
||||
|
||||
assertThrows(GeneralSecurityException.class,
|
||||
|
@ -33,6 +33,7 @@ import com.google.gson.JsonObject;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@ -57,26 +58,26 @@ public class ResourceLoader {
|
||||
) {
|
||||
PemObject pemObject = pemReader.readPemObject();
|
||||
byte[] content = pemObject.getContent();
|
||||
var privateKeySpec = new PKCS8EncodedKeySpec(content);
|
||||
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(content);
|
||||
|
||||
var factory = KeyFactory.getInstance("RSA");
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
return (RSAPrivateKey) factory.generatePrivate(privateKeySpec);
|
||||
}
|
||||
}
|
||||
|
||||
protected static ClientPublicKey loadClientKey(String path)
|
||||
throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
|
||||
var keyUrl = Resources.getResource(path);
|
||||
URL keyUrl = Resources.getResource(path);
|
||||
|
||||
var lines = Resources.toString(keyUrl, StandardCharsets.US_ASCII);
|
||||
var object = new Gson().fromJson(lines, JsonObject.class);
|
||||
String lines = Resources.toString(keyUrl, StandardCharsets.US_ASCII);
|
||||
JsonObject object = new Gson().fromJson(lines, JsonObject.class);
|
||||
|
||||
Instant expires = Instant.parse(object.getAsJsonPrimitive("expires_at").getAsString());
|
||||
String key = object.getAsJsonPrimitive("key").getAsString();
|
||||
RSAPublicKey publicKey = parsePublicKey(key);
|
||||
|
||||
byte[] signature = Base64.getDecoder().decode(object.getAsJsonPrimitive("signature").getAsString());
|
||||
return new ClientPublicKey(expires, publicKey, signature);
|
||||
return ClientPublicKey.of(expires, publicKey, signature);
|
||||
}
|
||||
|
||||
private static RSAPublicKey parsePublicKey(String keySpec)
|
||||
@ -87,9 +88,9 @@ public class ResourceLoader {
|
||||
) {
|
||||
PemObject pemObject = pemReader.readPemObject();
|
||||
byte[] content = pemObject.getContent();
|
||||
var pubKeySpec = new X509EncodedKeySpec(content);
|
||||
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
|
||||
|
||||
var factory = KeyFactory.getInstance("RSA");
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
return (RSAPublicKey) factory.generatePublic(pubKeySpec);
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,13 @@ import com.google.gson.annotations.JsonAdapter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import lombok.val;
|
||||
|
||||
public class SignatureTestData {
|
||||
|
||||
public static SignatureTestData fromResource(String resourceName) throws IOException {
|
||||
var keyUrl = Resources.getResource(resourceName);
|
||||
var encodedSignature = Resources.toString(keyUrl, StandardCharsets.US_ASCII);
|
||||
val keyUrl = Resources.getResource(resourceName);
|
||||
val encodedSignature = Resources.toString(keyUrl, StandardCharsets.US_ASCII);
|
||||
|
||||
return new Gson().fromJson(encodedSignature, SignatureTestData.class);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.connection.Server;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
|
||||
@ -100,7 +101,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
||||
//events
|
||||
PluginManager pluginManager = getProxy().getPluginManager();
|
||||
|
||||
ConnectListener connectListener = new ConnectListener(this, core.getAntiBot());
|
||||
Listener connectListener = new ConnectListener(this, core.getAntiBot());
|
||||
pluginManager.registerListener(this, connectListener);
|
||||
pluginManager.registerListener(this, new PluginMessageListener(this));
|
||||
|
||||
|
@ -25,10 +25,10 @@
|
||||
*/
|
||||
package com.github.games647.fastlogin.core;
|
||||
|
||||
import com.github.games647.craftapi.cache.SafeCacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
@ -43,7 +43,7 @@ public final class CommonUtil {
|
||||
private static final char TRANSLATED_CHAR = '§';
|
||||
|
||||
public static <K, V> ConcurrentMap<K, V> buildCache(int expireAfterWrite, int maxSize) {
|
||||
SafeCacheBuilder<Object, Object> builder = SafeCacheBuilder.newBuilder();
|
||||
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
|
||||
|
||||
if (expireAfterWrite > 0) {
|
||||
builder.expireAfterWrite(expireAfterWrite, TimeUnit.MINUTES);
|
||||
@ -53,9 +53,7 @@ public final class CommonUtil {
|
||||
builder.maximumSize(maxSize);
|
||||
}
|
||||
|
||||
return builder.build(CacheLoader.from(() -> {
|
||||
throw new UnsupportedOperationException();
|
||||
}));
|
||||
return builder.<K, V>build().asMap();
|
||||
}
|
||||
|
||||
public static String translateColorCodes(String rawMessage) {
|
||||
@ -74,7 +72,7 @@ public final class CommonUtil {
|
||||
* This creates a SLF4J logger. In the process it initializes the SLF4J service provider. This method looks
|
||||
* for the provider in the plugin jar instead of in the server jar when creating a Logger. The provider is only
|
||||
* initialized once, so this method should be called early.
|
||||
*
|
||||
* <p>
|
||||
* The provider is bound to the service class `SLF4JServiceProvider`. Relocating this class makes it available
|
||||
* for exclusive own usage. Other dependencies will use the relocated service too, and therefore will find the
|
||||
* initialized provider.
|
||||
@ -98,7 +96,8 @@ public final class CommonUtil {
|
||||
Constructor<JDK14LoggerAdapter> cons = adapterClass.getDeclaredConstructor(java.util.logging.Logger.class);
|
||||
cons.setAccessible(true);
|
||||
return cons.newInstance(parent);
|
||||
} catch (ReflectiveOperationException reflectEx) {
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
|
||||
| NoSuchMethodException reflectEx) {
|
||||
parent.log(Level.WARNING, "Cannot create slf4j logging adapter", reflectEx);
|
||||
parent.log(Level.WARNING, "Creating logger instance manually...");
|
||||
return LoggerFactory.getLogger(parent.getName());
|
||||
@ -109,6 +108,6 @@ public final class CommonUtil {
|
||||
}
|
||||
|
||||
private CommonUtil() {
|
||||
//Utility class
|
||||
throw new RuntimeException("No instantiation of utility classes allowed");
|
||||
}
|
||||
}
|
||||
|
@ -118,10 +118,11 @@ public class StoredProfile extends Profile {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof StoredProfile that)) {
|
||||
if (!(o instanceof StoredProfile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StoredProfile that = (StoredProfile) o;
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
|
9
pom.xml
9
pom.xml
@ -48,7 +48,7 @@
|
||||
<!-- Set default for non-git clones -->
|
||||
<git.commit.id>Unknown</git.commit.id>
|
||||
|
||||
<java.version>17</java.version>
|
||||
<java.version>8</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
|
||||
@ -189,5 +189,12 @@
|
||||
<version>5.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.24</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
Reference in New Issue
Block a user