]> nmode's Git Repositories - signal-cli/commitdiff
Use Java 17
authorAsamK <asamk@gmx.de>
Sun, 24 Oct 2021 19:06:13 +0000 (21:06 +0200)
committerAsamK <asamk@gmx.de>
Wed, 27 Oct 2021 12:39:40 +0000 (14:39 +0200)
51 files changed:
.github/workflows/ci.yml
.github/workflows/codeql-analysis.yml
CHANGELOG.md
README.md
build.gradle.kts
lib/build.gradle.kts
lib/src/main/java/org/asamk/signal/manager/LibSignalLogger.java
lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/SignalWebSocketHealthMonitor.java
lib/src/main/java/org/asamk/signal/manager/TrustLevel.java
lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java
lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java
lib/src/main/java/org/asamk/signal/manager/api/TypingAction.java
lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java
lib/src/main/java/org/asamk/signal/manager/groups/GroupId.java
lib/src/main/java/org/asamk/signal/manager/groups/GroupIdV1.java
lib/src/main/java/org/asamk/signal/manager/groups/GroupIdV2.java
lib/src/main/java/org/asamk/signal/manager/groups/GroupInviteLinkUrl.java
lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java
lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java
lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java
lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfo.java
lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV1.java
lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV2.java
lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java
lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java
lib/src/main/java/org/asamk/signal/manager/util/ProfileUtils.java
run_tests.sh
src/main/java/org/asamk/SignalControl.java
src/main/java/org/asamk/signal/ReceiveMessageHandler.java
src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java
src/main/java/org/asamk/signal/commands/JoinGroupCommand.java
src/main/java/org/asamk/signal/commands/ListContactsCommand.java
src/main/java/org/asamk/signal/commands/ListDevicesCommand.java
src/main/java/org/asamk/signal/commands/ListGroupsCommand.java
src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java
src/main/java/org/asamk/signal/commands/QuitGroupCommand.java
src/main/java/org/asamk/signal/commands/ReceiveCommand.java
src/main/java/org/asamk/signal/commands/RegisterCommand.java
src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java
src/main/java/org/asamk/signal/commands/SendCommand.java
src/main/java/org/asamk/signal/commands/SendReactionCommand.java
src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java
src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java
src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java
src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java
src/main/java/org/asamk/signal/jsonrpc/JsonRpcBulkMessage.java
src/main/java/org/asamk/signal/jsonrpc/JsonRpcMessage.java
src/main/java/org/asamk/signal/jsonrpc/JsonRpcRequest.java
src/main/java/org/asamk/signal/jsonrpc/JsonRpcResponse.java
src/main/java/org/asamk/signal/util/ErrorUtils.java

index 1fb5f7f4def3b999f1937e86d1a26ed2c5d768fe..ff73584b53833c2e48239f02aa55abf116ccfe07 100644 (file)
@@ -8,7 +8,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        java: [ '11', '17' ]
+        java: [ '17' ]
 
     steps:
       - uses: actions/checkout@v1
index c55e656db3035e5fc6bd335a87507abae500c625..0ef62f7e5b7790deffe9fb408c3a46ec2816aff3 100644 (file)
@@ -19,7 +19,7 @@ jobs:
       - name: Setup Java JDK
         uses: actions/setup-java@v1
         with:
-          java-version: 11
+          java-version: 17
 
       - name: Checkout repository
         uses: actions/checkout@v2
index a4f3bdbec1d344fe1b383540711cefcfe4c8429a..3e60c8a4f13667ee2f3a95392dbf0128846463c9 100644 (file)
@@ -1,6 +1,7 @@
 # Changelog
 
 ## [Unreleased]
+**Attention**: Now requires Java 17
 
 ## [0.9.2] - 2021-10-24
 ### Fixed
index fe4358493af629a87dd8d445a3f1c9f6dbe3ac19..b041b4a087d26331c5f482384dfe86243ffa8350 100644 (file)
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ It also has a JSON-RPC based interface, see the [documentation](https://github.c
 You can [build signal-cli](#building) yourself, or use the [provided binary files](https://github.com/AsamK/signal-cli/releases/latest), which should work on Linux, macOS and Windows. For Arch Linux there is also a [package in AUR](https://aur.archlinux.org/packages/signal-cli/) and there is a [FreeBSD port](https://www.freshports.org/net-im/signal-cli) available as well.
 
 System requirements:
-- at least Java Runtime Environment (JRE) 11
+- at least Java Runtime Environment (JRE) 17
 - native libraries: libzkgroup, libsignal-client
 
   Those are bundled for x86_64 Linux (with recent enough glibc, see #643), for other systems/architectures see: [Provide native lib for libsignal](https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal)
index f59bc2d06ff09502c9fb1075332127ba15b4e9c4..481f2668ba1f576d846cbdc3a5104eeb11d84bbc 100644 (file)
@@ -9,8 +9,8 @@ plugins {
 version = "0.9.2"
 
 java {
-    sourceCompatibility = JavaVersion.VERSION_11
-    targetCompatibility = JavaVersion.VERSION_11
+    sourceCompatibility = JavaVersion.VERSION_17
+    targetCompatibility = JavaVersion.VERSION_17
 }
 
 application {
@@ -22,6 +22,7 @@ graalvmNative {
         this["main"].run {
             configurationFileDirectories.from(file("graalvm-config-dir"))
             buildArgs.add("--allow-incomplete-classpath")
+            buildArgs.add("--report-unsupported-elements-at-runtime")
         }
     }
 }
index d720f3b95215fa5edaaa401f7bb8862b23f93058..31de50e0785ddaef6d0e1ac05c86b25839e51b7d 100644 (file)
@@ -4,8 +4,8 @@ plugins {
 }
 
 java {
-    sourceCompatibility = JavaVersion.VERSION_11
-    targetCompatibility = JavaVersion.VERSION_11
+    sourceCompatibility = JavaVersion.VERSION_17
+    targetCompatibility = JavaVersion.VERSION_17
 }
 
 repositories {
index 3be4d7e9617ad853e19d35c63b17aa12b12c284d..c14b0f13be92cb889d5c6941a22046bed20d2d66 100644 (file)
@@ -20,22 +20,11 @@ public class LibSignalLogger implements SignalProtocolLogger {
     public void log(final int priority, final String tag, final String message) {
         final var logMessage = String.format("[%s]: %s", tag, message);
         switch (priority) {
-            case SignalProtocolLogger.VERBOSE:
-                logger.trace(logMessage);
-                break;
-            case SignalProtocolLogger.DEBUG:
-                logger.debug(logMessage);
-                break;
-            case SignalProtocolLogger.INFO:
-                logger.info(logMessage);
-                break;
-            case SignalProtocolLogger.WARN:
-                logger.warn(logMessage);
-                break;
-            case SignalProtocolLogger.ERROR:
-            case SignalProtocolLogger.ASSERT:
-                logger.error(logMessage);
-                break;
+            case SignalProtocolLogger.VERBOSE -> logger.trace(logMessage);
+            case SignalProtocolLogger.DEBUG -> logger.debug(logMessage);
+            case SignalProtocolLogger.INFO -> logger.info(logMessage);
+            case SignalProtocolLogger.WARN -> logger.warn(logMessage);
+            case SignalProtocolLogger.ERROR, SignalProtocolLogger.ASSERT -> logger.error(logMessage);
         }
     }
 }
index 2ea965919d18d4777af9b654d0d333ec00d3457e..1a1e735e15a6a7d16b266e5de29c7d7ea29ebb3f 100644 (file)
@@ -569,16 +569,15 @@ public class ManagerImpl implements Manager {
         long timestamp = System.currentTimeMillis();
         messageBuilder.withTimestamp(timestamp);
         for (final var recipient : recipients) {
-            if (recipient instanceof RecipientIdentifier.Single) {
-                final var recipientId = resolveRecipient((RecipientIdentifier.Single) recipient);
+            if (recipient instanceof RecipientIdentifier.Single single) {
+                final var recipientId = resolveRecipient(single);
                 final var result = sendHelper.sendMessage(messageBuilder, recipientId);
                 results.put(recipient, List.of(result));
             } else if (recipient instanceof RecipientIdentifier.NoteToSelf) {
                 final var result = sendHelper.sendSelfMessage(messageBuilder);
                 results.put(recipient, List.of(result));
-            } else if (recipient instanceof RecipientIdentifier.Group) {
-                final var groupId = ((RecipientIdentifier.Group) recipient).groupId;
-                final var result = sendHelper.sendAsGroupMessage(messageBuilder, groupId);
+            } else if (recipient instanceof RecipientIdentifier.Group group) {
+                final var result = sendHelper.sendAsGroupMessage(messageBuilder, group.groupId);
                 results.put(recipient, result);
             }
         }
index 556e227d422341caba88b4011dc2a7f6af27611c..b905f9b70d378bfb9a8f561e6ec5d6cee7673803 100644 (file)
@@ -63,15 +63,9 @@ public final class SignalWebSocketHealthMonitor implements HealthMonitor {
 
     private synchronized void onStateChange(WebSocketConnectionState connectionState, HealthState healthState) {
         switch (connectionState) {
-            case CONNECTED:
-                logger.debug("WebSocket is now connected");
-                break;
-            case AUTHENTICATION_FAILED:
-                logger.debug("WebSocket authentication failed");
-                break;
-            case FAILED:
-                logger.debug("WebSocket connection failed");
-                break;
+            case CONNECTED -> logger.debug("WebSocket is now connected");
+            case AUTHENTICATION_FAILED -> logger.debug("WebSocket authentication failed");
+            case FAILED -> logger.debug("WebSocket connection failed");
         }
 
         healthState.needsKeepAlive = connectionState == WebSocketConnectionState.CONNECTED;
index 5c712866228db229dc0503e6f0d2881775e10e4d..fead442cd2f537f1cda9cd244120301d5f41045a 100644 (file)
@@ -18,40 +18,27 @@ public enum TrustLevel {
     }
 
     public static TrustLevel fromIdentityState(ContactRecord.IdentityState identityState) {
-        switch (identityState) {
-            case DEFAULT:
-                return TRUSTED_UNVERIFIED;
-            case UNVERIFIED:
-                return UNTRUSTED;
-            case VERIFIED:
-                return TRUSTED_VERIFIED;
-            case UNRECOGNIZED:
-                return null;
-        }
-        throw new RuntimeException("Unknown identity state: " + identityState);
+        return switch (identityState) {
+            case DEFAULT -> TRUSTED_UNVERIFIED;
+            case UNVERIFIED -> UNTRUSTED;
+            case VERIFIED -> TRUSTED_VERIFIED;
+            case UNRECOGNIZED -> null;
+        };
     }
 
     public static TrustLevel fromVerifiedState(VerifiedMessage.VerifiedState verifiedState) {
-        switch (verifiedState) {
-            case DEFAULT:
-                return TRUSTED_UNVERIFIED;
-            case UNVERIFIED:
-                return UNTRUSTED;
-            case VERIFIED:
-                return TRUSTED_VERIFIED;
-        }
-        throw new RuntimeException("Unknown verified state: " + verifiedState);
+        return switch (verifiedState) {
+            case DEFAULT -> TRUSTED_UNVERIFIED;
+            case UNVERIFIED -> UNTRUSTED;
+            case VERIFIED -> TRUSTED_VERIFIED;
+        };
     }
 
     public VerifiedMessage.VerifiedState toVerifiedState() {
-        switch (this) {
-            case TRUSTED_UNVERIFIED:
-                return VerifiedMessage.VerifiedState.DEFAULT;
-            case UNTRUSTED:
-                return VerifiedMessage.VerifiedState.UNVERIFIED;
-            case TRUSTED_VERIFIED:
-                return VerifiedMessage.VerifiedState.VERIFIED;
-        }
-        throw new RuntimeException("Unknown verified state: " + this);
+        return switch (this) {
+            case TRUSTED_UNVERIFIED -> VerifiedMessage.VerifiedState.DEFAULT;
+            case UNTRUSTED -> VerifiedMessage.VerifiedState.UNVERIFIED;
+            case TRUSTED_VERIFIED -> VerifiedMessage.VerifiedState.VERIFIED;
+        };
     }
 }
index ecd5597d57519d9427f501f93331ad237a1bbabb..3ecd9a1e1d04d5ead4c5c3697d49a07e3f540dce 100644 (file)
@@ -54,17 +54,12 @@ public class SendRetryMessageRequestAction implements HandleAction {
     }
 
     private static int envelopeTypeToCiphertextMessageType(int envelopeType) {
-        switch (envelopeType) {
-            case SignalServiceProtos.Envelope.Type.PREKEY_BUNDLE_VALUE:
-                return CiphertextMessage.PREKEY_TYPE;
-            case SignalServiceProtos.Envelope.Type.UNIDENTIFIED_SENDER_VALUE:
-                return CiphertextMessage.SENDERKEY_TYPE;
-            case SignalServiceProtos.Envelope.Type.PLAINTEXT_CONTENT_VALUE:
-                return CiphertextMessage.PLAINTEXT_CONTENT_TYPE;
-            case SignalServiceProtos.Envelope.Type.CIPHERTEXT_VALUE:
-            default:
-                return CiphertextMessage.WHISPER_TYPE;
-        }
+        return switch (envelopeType) {
+            case SignalServiceProtos.Envelope.Type.PREKEY_BUNDLE_VALUE -> CiphertextMessage.PREKEY_TYPE;
+            case SignalServiceProtos.Envelope.Type.UNIDENTIFIED_SENDER_VALUE -> CiphertextMessage.SENDERKEY_TYPE;
+            case SignalServiceProtos.Envelope.Type.PLAINTEXT_CONTENT_VALUE -> CiphertextMessage.PLAINTEXT_CONTENT_TYPE;
+            default -> CiphertextMessage.WHISPER_TYPE;
+        };
     }
 
     @Override
index be1029e69be4baedc4048103dc82a2f3150e40e9..ec2d00f555e11a8aee146e7d9041728fee750113 100644 (file)
@@ -9,9 +9,9 @@ import org.whispersystems.signalservice.api.util.UuidUtil;
 
 import java.util.UUID;
 
-public abstract class RecipientIdentifier {
+public sealed abstract class RecipientIdentifier {
 
-    public static class NoteToSelf extends RecipientIdentifier {
+    public static final class NoteToSelf extends RecipientIdentifier {
 
         public static NoteToSelf INSTANCE = new NoteToSelf();
 
@@ -19,7 +19,7 @@ public abstract class RecipientIdentifier {
         }
     }
 
-    public abstract static class Single extends RecipientIdentifier {
+    public sealed static abstract class Single extends RecipientIdentifier {
 
         public static Single fromString(String identifier, String localNumber) throws InvalidNumberException {
             return UuidUtil.isUuid(identifier)
@@ -43,7 +43,7 @@ public abstract class RecipientIdentifier {
         public abstract String getIdentifier();
     }
 
-    public static class Uuid extends Single {
+    public static final class Uuid extends Single {
 
         public final UUID uuid;
 
@@ -72,7 +72,7 @@ public abstract class RecipientIdentifier {
         }
     }
 
-    public static class Number extends Single {
+    public static final class Number extends Single {
 
         public final String number;
 
@@ -101,7 +101,7 @@ public abstract class RecipientIdentifier {
         }
     }
 
-    public static class Group extends RecipientIdentifier {
+    public static final class Group extends RecipientIdentifier {
 
         public final GroupId groupId;
 
index 228990c19cd3466daa6855ffe5322a7436284fcd..86a858f01cd8d96252a13aae6f4ecf7f81a8274e 100644 (file)
@@ -7,13 +7,9 @@ public enum TypingAction {
     STOP;
 
     public SignalServiceTypingMessage.Action toSignalService() {
-        switch (this) {
-            case START:
-                return SignalServiceTypingMessage.Action.STARTED;
-            case STOP:
-                return SignalServiceTypingMessage.Action.STOPPED;
-            default:
-                throw new IllegalStateException("Invalid typing action " + this);
-        }
+        return switch (this) {
+            case START -> SignalServiceTypingMessage.Action.STARTED;
+            case STOP -> SignalServiceTypingMessage.Action.STOPPED;
+        };
     }
 }
index a9a08d93e8d91d353c89844a9f863d441d29866e..2634a59342e9976d46d2e78d1e5c25339dafaf81 100644 (file)
@@ -88,19 +88,15 @@ public class ServiceConfig {
 
         final var interceptors = List.of(userAgentInterceptor);
 
-        switch (serviceEnvironment) {
-            case LIVE:
-                return new ServiceEnvironmentConfig(LiveConfig.createDefaultServiceConfiguration(interceptors),
-                        LiveConfig.getUnidentifiedSenderTrustRoot(),
-                        LiveConfig.createKeyBackupConfig(),
-                        LiveConfig.getCdsMrenclave());
-            case SANDBOX:
-                return new ServiceEnvironmentConfig(SandboxConfig.createDefaultServiceConfiguration(interceptors),
-                        SandboxConfig.getUnidentifiedSenderTrustRoot(),
-                        SandboxConfig.createKeyBackupConfig(),
-                        SandboxConfig.getCdsMrenclave());
-            default:
-                throw new IllegalArgumentException("Unsupported environment");
-        }
+        return switch (serviceEnvironment) {
+            case LIVE -> new ServiceEnvironmentConfig(LiveConfig.createDefaultServiceConfiguration(interceptors),
+                    LiveConfig.getUnidentifiedSenderTrustRoot(),
+                    LiveConfig.createKeyBackupConfig(),
+                    LiveConfig.getCdsMrenclave());
+            case SANDBOX -> new ServiceEnvironmentConfig(SandboxConfig.createDefaultServiceConfiguration(interceptors),
+                    SandboxConfig.getUnidentifiedSenderTrustRoot(),
+                    SandboxConfig.createKeyBackupConfig(),
+                    SandboxConfig.getCdsMrenclave());
+        };
     }
 }
index 9ecb963092dba37fc4c05aab9ec892ab2f05bdb5..38ddd4b62cca85766dd96aecff679efd0b198443 100644 (file)
@@ -3,7 +3,7 @@ package org.asamk.signal.manager.groups;
 import java.util.Arrays;
 import java.util.Base64;
 
-public abstract class GroupId {
+public abstract sealed class GroupId permits GroupIdV1, GroupIdV2 {
 
     private final byte[] id;
 
index d2012fa0fec525b4e58454a6838c0d9908edb21c..acec587b99c1e42d7208e08e73c20e28cf718a68 100644 (file)
@@ -4,7 +4,7 @@ import java.util.Base64;
 
 import static org.asamk.signal.manager.util.KeyUtils.getSecretBytes;
 
-public class GroupIdV1 extends GroupId {
+public final class GroupIdV1 extends GroupId {
 
     public static GroupIdV1 createRandom() {
         return new GroupIdV1(getSecretBytes(16));
index 913a9e936a69973a6882405e83feca979cbd3a48..35aac3304545e9569f1ba3b3a5b3fdf01d0deffa 100644 (file)
@@ -2,7 +2,7 @@ package org.asamk.signal.manager.groups;
 
 import java.util.Base64;
 
-public class GroupIdV2 extends GroupId {
+public final class GroupIdV2 extends GroupId {
 
     public static GroupIdV2 fromBase64(String groupId) {
         return new GroupIdV2(Base64.getDecoder().decode(groupId));
index dd9dd2d265434ff639ed53b55196f1ee0c2de2ae..0498fba18454b7da18d1e892b8d80d0569df1bbf 100644 (file)
@@ -56,7 +56,7 @@ public final class GroupInviteLinkUrl {
             var groupInviteLink = GroupInviteLink.parseFrom(bytes);
 
             switch (groupInviteLink.getContentsCase()) {
-                case V1CONTENTS: {
+                case V1CONTENTS -> {
                     var groupInviteLinkContentsV1 = groupInviteLink.getV1Contents();
                     var groupMasterKey = new GroupMasterKey(groupInviteLinkContentsV1.getGroupMasterKey()
                             .toByteArray());
@@ -65,8 +65,7 @@ public final class GroupInviteLinkUrl {
 
                     return new GroupInviteLinkUrl(groupMasterKey, password);
                 }
-                default:
-                    throw new UnknownGroupLinkVersionException("Url contains no known group link content");
+                default -> throw new UnknownGroupLinkVersionException("Url contains no known group link content");
             }
         } catch (InvalidInputException | IOException e) {
             throw new InvalidGroupLinkException(e);
index ee2e94166ccbb55b23c7cb33402038d7f22924cd..dbee3e842e09fc32018e39795b418a6fa19fa8d8 100644 (file)
@@ -351,8 +351,7 @@ public class GroupHelper {
 
     private GroupInfo getGroup(GroupId groupId, boolean forceUpdate) {
         final var group = account.getGroupStore().getGroup(groupId);
-        if (group instanceof GroupInfoV2) {
-            final var groupInfoV2 = (GroupInfoV2) group;
+        if (group instanceof GroupInfoV2 groupInfoV2) {
             if (forceUpdate || (!groupInfoV2.isPermissionDenied() && groupInfoV2.getGroup() == null)) {
                 final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
                 DecryptedGroup decryptedGroup;
index 746af2f91ecc9f5bd3d93b9aa77e2dd09261e779..f526a596f8d9bc44ba64ef0be9e3c30bfb3ad66a 100644 (file)
@@ -391,27 +391,18 @@ public class GroupV2Helper {
     }
 
     private AccessControl.AccessRequired toAccessControl(final GroupLinkState state) {
-        switch (state) {
-            case DISABLED:
-                return AccessControl.AccessRequired.UNSATISFIABLE;
-            case ENABLED:
-                return AccessControl.AccessRequired.ANY;
-            case ENABLED_WITH_APPROVAL:
-                return AccessControl.AccessRequired.ADMINISTRATOR;
-            default:
-                throw new AssertionError();
-        }
+        return switch (state) {
+            case DISABLED -> AccessControl.AccessRequired.UNSATISFIABLE;
+            case ENABLED -> AccessControl.AccessRequired.ANY;
+            case ENABLED_WITH_APPROVAL -> AccessControl.AccessRequired.ADMINISTRATOR;
+        };
     }
 
     private AccessControl.AccessRequired toAccessControl(final GroupPermission permission) {
-        switch (permission) {
-            case EVERY_MEMBER:
-                return AccessControl.AccessRequired.MEMBER;
-            case ONLY_ADMINS:
-                return AccessControl.AccessRequired.ADMINISTRATOR;
-            default:
-                throw new AssertionError();
-        }
+        return switch (permission) {
+            case EVERY_MEMBER -> AccessControl.AccessRequired.MEMBER;
+            case ONLY_ADMINS -> AccessControl.AccessRequired.ADMINISTRATOR;
+        };
     }
 
     private GroupsV2Operations.GroupOperations getGroupOperations(final GroupInfoV2 groupInfoV2) {
index e3fc7fc26676e7f7e284ef5d80b1d75f4c8cc12f..6fe04dce12483bd92f7210747659589ab6220a2c 100644 (file)
@@ -83,8 +83,7 @@ public class SyncHelper {
             try (OutputStream fos = new FileOutputStream(groupsFile)) {
                 var out = new DeviceGroupsOutputStream(fos);
                 for (var record : account.getGroupStore().getGroups()) {
-                    if (record instanceof GroupInfoV1) {
-                        var groupInfo = (GroupInfoV1) record;
+                    if (record instanceof GroupInfoV1 groupInfo) {
                         out.write(new DeviceGroup(groupInfo.getGroupId().serialize(),
                                 Optional.fromNullable(groupInfo.name),
                                 groupInfo.getMembers()
index b4f4e63a6cba5fd9a3522667bae29c655f281131..2c2102595fb23c8b56f0e929c3c0ee49dfc2cca6 100644 (file)
@@ -9,7 +9,7 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-public abstract class GroupInfo {
+public sealed abstract class GroupInfo permits GroupInfoV1, GroupInfoV2 {
 
     public abstract GroupId getGroupId();
 
index dbd2dcbba873422296a4ed8f78e803cba297947f..4e759e5fc32d5dce4c1c5c4ad250de0400af0b1c 100644 (file)
@@ -11,7 +11,7 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
 
-public class GroupInfoV1 extends GroupInfo {
+public final class GroupInfoV1 extends GroupInfo {
 
     private final GroupIdV1 groupId;
 
index 34db2a2879ecb66590bb95715c51238935688daf..793cde5d9c81b5c35464d1937ffd8cb14b17f100 100644 (file)
@@ -15,7 +15,7 @@ import org.whispersystems.signalservice.api.util.UuidUtil;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-public class GroupInfoV2 extends GroupInfo {
+public final class GroupInfoV2 extends GroupInfo {
 
     private final GroupIdV2 groupId;
     private final GroupMasterKey masterKey;
@@ -197,12 +197,9 @@ public class GroupInfoV2 extends GroupInfo {
     }
 
     private static GroupPermission toGroupPermission(final AccessControl.AccessRequired permission) {
-        switch (permission) {
-            case ADMINISTRATOR:
-                return GroupPermission.ONLY_ADMINS;
-            case MEMBER:
-            default:
-                return GroupPermission.EVERY_MEMBER;
-        }
+        return switch (permission) {
+            case ADMINISTRATOR -> GroupPermission.ONLY_ADMINS;
+            default -> GroupPermission.EVERY_MEMBER;
+        };
     }
 }
index b38d3902ceb8439415d5e2c05e29bce8cd9a119f..5cef1b338a58bd4f392e416b56508014fcb282ba 100644 (file)
@@ -75,8 +75,7 @@ public class GroupStore {
             final Saver saver
     ) {
         final var groups = storage.groups.stream().map(g -> {
-            if (g instanceof Storage.GroupV1) {
-                final var g1 = (Storage.GroupV1) g;
+            if (g instanceof Storage.GroupV1 g1) {
                 final var members = g1.members.stream().map(m -> {
                     if (m.recipientId == null) {
                         return recipientResolver.resolveRecipient(new RecipientAddress(UuidUtil.parseOrNull(m.uuid),
@@ -186,8 +185,7 @@ public class GroupStore {
         synchronized (groups) {
             var modified = false;
             for (var group : this.groups.values()) {
-                if (group instanceof GroupInfoV1) {
-                    var groupV1 = (GroupInfoV1) group;
+                if (group instanceof GroupInfoV1 groupV1) {
                     if (groupV1.isMember(toBeMergedRecipientId)) {
                         groupV1.removeMember(toBeMergedRecipientId);
                         groupV1.addMembers(List.of(recipientId));
@@ -220,8 +218,7 @@ public class GroupStore {
 
     private GroupInfoV1 getGroupV1ByV2IdLocked(GroupIdV2 groupIdV2) {
         for (var g : groups.values()) {
-            if (g instanceof GroupInfoV1) {
-                final var gv1 = (GroupInfoV1) g;
+            if (g instanceof GroupInfoV1 gv1) {
                 if (groupIdV2.equals(gv1.getExpectedV2Id())) {
                     return gv1;
                 }
@@ -256,8 +253,7 @@ public class GroupStore {
 
     private Storage toStorageLocked() {
         return new Storage(groups.values().stream().map(g -> {
-            if (g instanceof GroupInfoV1) {
-                final var g1 = (GroupInfoV1) g;
+            if (g instanceof GroupInfoV1 g1) {
                 return new Storage.GroupV1(g1.getGroupId().toBase64(),
                         g1.getExpectedV2Id().toBase64(),
                         g1.name,
index c0f5b0b8d1cb90dd35102e6859060e5152fcde1f..bd8710dd1dad0e44465fae7c6f331890d7fc5e68 100644 (file)
@@ -19,7 +19,7 @@ public class RecipientAddress {
      */
     public RecipientAddress(Optional<UUID> uuid, Optional<String> e164) {
         uuid = uuid.isPresent() && uuid.get().equals(UuidUtil.UNKNOWN_UUID) ? Optional.empty() : uuid;
-        if (!uuid.isPresent() && !e164.isPresent()) {
+        if (uuid.isEmpty() && e164.isEmpty()) {
             throw new AssertionError("Must have either a UUID or E164 number!");
         }
 
index c1b1183c31bc3454ce96b5f5b3f864717d632fb9..0f5b7407ca94fca7a8deed3918327bcc7a861c8e 100644 (file)
@@ -91,14 +91,11 @@ public class ProfileUtils {
         }
         String[] parts = name.split("\0");
 
-        switch (parts.length) {
-            case 0:
-                return new Pair<>(null, null);
-            case 1:
-                return new Pair<>(parts[0], null);
-            default:
-                return new Pair<>(parts[0], parts[1]);
-        }
+        return switch (parts.length) {
+            case 0 -> new Pair<>(null, null);
+            case 1 -> new Pair<>(parts[0], null);
+            default -> new Pair<>(parts[0], parts[1]);
+        };
     }
 
     static String trimZeros(String str) {
index b3b51835845200b69f60edbfd3993979c6a5d240..b41a460deaef48a1aa5f3196cd12c2d5276934a7 100755 (executable)
@@ -6,7 +6,7 @@ fi
 
 set -e
 # To update graalvm config, set GRAALVM_HOME, e.g:
-# export GRAALVM_HOME=/usr/lib/jvm/java-11-graalvm
+# export GRAALVM_HOME=/usr/lib/jvm/java-17-graalvm
 if [ ! -z "$GRAALVM_HOME" ]; then
   export JAVA_HOME=$GRAALVM_HOME
   export SIGNAL_CLI_OPTS='-agentlib:native-image-agent=config-merge-dir=graalvm-config-dir/'
index 911ccb615d541fe0c8200ac6c0cfb1e481ae0d4c..610ca103827b1eb5df5071a259859dff297efe39 100644 (file)
@@ -26,7 +26,7 @@ public interface SignalControl extends DBusInterface {
 
     String link(String newDeviceName) throws Error.Failure;
 
-    public String version();
+    String version();
 
     List<DBusPath> listAccounts();
 
index b1580b349b0088d99fdea712caf2a35aff447299..d86ab26c0f8368861b8ffbde530661698898773a 100644 (file)
@@ -53,8 +53,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
             writer.println("Got receipt.");
         } else if (envelope.isSignalMessage() || envelope.isPreKeySignalMessage() || envelope.isUnidentifiedSender()) {
             if (exception != null) {
-                if (exception instanceof UntrustedIdentityException) {
-                    var e = (UntrustedIdentityException) exception;
+                if (exception instanceof UntrustedIdentityException e) {
                     writer.println(
                             "The user’s key is untrusted, either the user has reinstalled Signal or a third party sent this message.");
                     final var recipientName = getLegacyIdentifier(m.resolveSignalServiceAddress(e.getSender()));
index be94fb361263fb6203d6fa1d20aac369eae0004b..e5685f1a7be8fa6f96ce2c11e286770d9a2aebde 100644 (file)
@@ -47,8 +47,7 @@ public class GetUserStatusCommand implements JsonRpcLocalCommand {
         }
 
         // Output
-        if (outputWriter instanceof JsonWriter) {
-            final var jsonWriter = (JsonWriter) outputWriter;
+        if (outputWriter instanceof JsonWriter jsonWriter) {
 
             var jsonUserStatuses = registered.entrySet().stream().map(entry -> {
                 final var number = entry.getValue().first();
index 1e06ea9ce9d3ca349cb76f4e0136b1e74f455876..892879f6c01f4757f9f52a07b16b6ea2fbfee10c 100644 (file)
@@ -55,8 +55,7 @@ public class JoinGroupCommand implements JsonRpcLocalCommand {
         try {
             final var results = m.joinGroup(linkUrl);
             var newGroupId = results.first();
-            if (outputWriter instanceof JsonWriter) {
-                final var writer = (JsonWriter) outputWriter;
+            if (outputWriter instanceof JsonWriter writer) {
                 if (!m.getGroup(newGroupId).isMember()) {
                     writer.write(Map.of("groupId", newGroupId.toBase64(), "onlyRequested", true));
                 } else {
index b6dfc3ce229c92d2320ae579754dbb0035e6b42d..2d0f63224b1075fa0ffc8fe8089c7788f27de4a9 100644 (file)
@@ -27,8 +27,7 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
     public void handleCommand(final Namespace ns, final Manager m, final OutputWriter outputWriter) {
         var contacts = m.getContacts();
 
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             for (var c : contacts) {
                 final var contact = c.second();
                 writer.println("Number: {} Name: {} Blocked: {} Message expiration: {}",
index 1de5b84222fa610e730b905f21e5b73da4f2af94..d9a5ea3314337dfbb2176d636c9aa179ae05d145 100644 (file)
@@ -43,8 +43,7 @@ public class ListDevicesCommand implements JsonRpcLocalCommand {
             throw new IOErrorException("Failed to get linked devices: " + e.getMessage(), e);
         }
 
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             for (var d : devices) {
                 writer.println("- Device {}{}:", d.getId(), (d.isThisDevice() ? " (this device)" : ""));
                 writer.indent(w -> {
index b2182429d30648de5de762149d5ef50bcc2e80e9..3321c34bf1ae7737e0d8c64a758d1bbc7f7b75c3 100644 (file)
@@ -80,8 +80,7 @@ public class ListGroupsCommand implements JsonRpcLocalCommand {
     ) throws CommandException {
         final var groups = m.getGroups();
 
-        if (outputWriter instanceof JsonWriter) {
-            final var jsonWriter = (JsonWriter) outputWriter;
+        if (outputWriter instanceof JsonWriter jsonWriter) {
 
             var jsonGroups = groups.stream().map(group -> {
                 final var groupInviteLink = group.getGroupInviteLinkUrl();
index ed2942a5f7d836656db3995e7906631f6dd886a7..d7646ebbfa3bea4789255171e4e7625c7899dea8 100644 (file)
@@ -59,8 +59,7 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand {
             identities = m.getIdentities(CommandUtil.getSingleRecipientIdentifier(number, m.getSelfNumber()));
         }
 
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             for (var id : identities) {
                 printIdentityFingerprint(writer, m, id);
             }
index 1d6611b58b814214be22b8828d6a0cdf2ba1eda5..8c3ac3bd206f70514a77364788aaa8d6dd27262e 100644 (file)
@@ -79,8 +79,7 @@ public class QuitGroupCommand implements JsonRpcLocalCommand {
     }
 
     private void outputResult(final OutputWriter outputWriter, final long timestamp) {
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             writer.println("{}", timestamp);
         } else {
             final var writer = (JsonWriter) outputWriter;
index 6b2e497e10b3fd8953bf1960275de1fc497f2c7a..e1a9a2f311bdbd594a42b1cbf0c6b5166636c7c9 100644 (file)
@@ -58,8 +58,7 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
             final Namespace ns, final Signal signal, DBusConnection dbusconnection, final OutputWriter outputWriter
     ) throws CommandException {
         try {
-            if (outputWriter instanceof JsonWriter) {
-                final var jsonWriter = (JsonWriter) outputWriter;
+            if (outputWriter instanceof JsonWriter jsonWriter) {
 
                 dbusconnection.addSigHandler(Signal.MessageReceived.class, signal, messageReceived -> {
                     var envelope = new JsonMessageEnvelope(messageReceived);
index af6c06ad3916ce6e756f6ebdbc131e66a5d1dc8c..7e4fe505978ef78017070b7ca866687c5e32e662 100644 (file)
@@ -40,10 +40,11 @@ public class RegisterCommand implements RegistrationCommand {
         } catch (CaptchaRequiredException e) {
             String message;
             if (captcha == null) {
-                message = "Captcha required for verification, use --captcha CAPTCHA\n"
-                        + "To get the token, go to https://signalcaptchas.org/registration/generate.html\n"
-                        + "Check the developer tools (F12) console for a failed redirect to signalcaptcha://\n"
-                        + "Everything after signalcaptcha:// is the captcha token.";
+                message = """
+                        Captcha required for verification, use --captcha CAPTCHA
+                        To get the token, go to https://signalcaptchas.org/registration/generate.html
+                        Check the developer tools (F12) console for a failed redirect to signalcaptcha://
+                        Everything after signalcaptcha:// is the captcha token.""";
             } else {
                 message = "Invalid captcha given.";
             }
index c9eab95ca57d5ab06f01b9e5fd7c7aace92135f2..1204963c4a65d0638bb67e902c18cf1923a5fb74 100644 (file)
@@ -67,8 +67,7 @@ public class RemoteDeleteCommand implements JsonRpcLocalCommand {
     }
 
     private void outputResult(final OutputWriter outputWriter, final long timestamp) {
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             writer.println("{}", timestamp);
         } else {
             final var writer = (JsonWriter) outputWriter;
index dba7689f2fbad2a2e8b5600db8399d41d35bc025..ab8bce16cbfded8ba33c17d508c233a9b9b41e90 100644 (file)
@@ -113,8 +113,7 @@ public class SendCommand implements JsonRpcLocalCommand {
     }
 
     private void outputResult(final OutputWriter outputWriter, final long timestamp) {
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             writer.println("{}", timestamp);
         } else {
             final var writer = (JsonWriter) outputWriter;
index 857f603dc2f3f7bea794ca3e409a820550201adb..62d040a332b64d5bab4d33da2c2e5b9610a74e03 100644 (file)
@@ -83,8 +83,7 @@ public class SendReactionCommand implements JsonRpcLocalCommand {
     }
 
     private void outputResult(final OutputWriter outputWriter, final long timestamp) {
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             writer.println("{}", timestamp);
         } else {
             final var writer = (JsonWriter) outputWriter;
index b63a7160c509f80bfaedfb2a18e824bea5eba410..c51df8e0c9b845142fc683d262a0b98bd6054fe8 100644 (file)
@@ -77,33 +77,23 @@ public class UpdateGroupCommand implements JsonRpcLocalCommand {
         if (value == null) {
             return null;
         }
-        switch (value) {
-            case "enabled":
-                return GroupLinkState.ENABLED;
-            case "enabled-with-approval":
-            case "enabledWithApproval":
-                return GroupLinkState.ENABLED_WITH_APPROVAL;
-            case "disabled":
-                return GroupLinkState.DISABLED;
-            default:
-                throw new UserErrorException("Invalid group link state: " + value);
-        }
+        return switch (value) {
+            case "enabled" -> GroupLinkState.ENABLED;
+            case "enabled-with-approval", "enabledWithApproval" -> GroupLinkState.ENABLED_WITH_APPROVAL;
+            case "disabled" -> GroupLinkState.DISABLED;
+            default -> throw new UserErrorException("Invalid group link state: " + value);
+        };
     }
 
     GroupPermission getGroupPermission(String value) throws UserErrorException {
         if (value == null) {
             return null;
         }
-        switch (value) {
-            case "every-member":
-            case "everyMember":
-                return GroupPermission.EVERY_MEMBER;
-            case "only-admins":
-            case "onlyAdmins":
-                return GroupPermission.ONLY_ADMINS;
-            default:
-                throw new UserErrorException("Invalid group permission: " + value);
-        }
+        return switch (value) {
+            case "every-member", "everyMember" -> GroupPermission.EVERY_MEMBER;
+            case "only-admins", "onlyAdmins" -> GroupPermission.ONLY_ADMINS;
+            default -> throw new UserErrorException("Invalid group permission: " + value);
+        };
     }
 
     @Override
@@ -179,8 +169,7 @@ public class UpdateGroupCommand implements JsonRpcLocalCommand {
     }
 
     private void outputResult(final OutputWriter outputWriter, final Long timestamp, final GroupId groupId) {
-        if (outputWriter instanceof PlainTextWriter) {
-            final var writer = (PlainTextWriter) outputWriter;
+        if (outputWriter instanceof PlainTextWriter writer) {
             if (groupId != null) {
                 writer.println("Created new group: \"{}\"", groupId.toBase64());
             }
index 53b64b8c64dfd477da46e752ff315fd568edecde..23d293655e7eb37515d6c773b728ca8e71c106b3 100644 (file)
@@ -42,8 +42,7 @@ public class UploadStickerPackCommand implements JsonRpcLocalCommand {
 
         try {
             var url = m.uploadStickerPack(path);
-            if (outputWriter instanceof PlainTextWriter) {
-                final var writer = (PlainTextWriter) outputWriter;
+            if (outputWriter instanceof PlainTextWriter writer) {
                 writer.println("{}", url);
             } else {
                 final var writer = (JsonWriter) outputWriter;
index fcbadd38de3cd43fb1317a6c6fc94e6fa704b645..ea5912244f7db381898e3440969331cf0576ab32 100644 (file)
@@ -274,15 +274,9 @@ public class DbusManagerImpl implements Manager {
         }
         if (updateGroup.getGroupLinkState() != null) {
             switch (updateGroup.getGroupLinkState()) {
-                case DISABLED:
-                    group.disableLink();
-                    break;
-                case ENABLED:
-                    group.enableLink(false);
-                    break;
-                case ENABLED_WITH_APPROVAL:
-                    group.enableLink(true);
-                    break;
+                case DISABLED -> group.disableLink();
+                case ENABLED -> group.enableLink(false);
+                case ENABLED_WITH_APPROVAL -> group.enableLink(true);
             }
         }
         return new SendGroupMessageResults(0, List.of());
index e49e6125b77dee0c4a58ab4e88b8e9be328d34f7..0d44de5d91fd3540ebc4135bafae138ffaf640ea 100644 (file)
@@ -71,8 +71,7 @@ public class JsonMessageEnvelope {
             this.sourceNumber = source.getNumber().orNull();
             this.sourceUuid = source.getUuid().toString();
             this.sourceDevice = content.getSenderDevice();
-        } else if (exception instanceof UntrustedIdentityException) {
-            var e = (UntrustedIdentityException) exception;
+        } else if (exception instanceof UntrustedIdentityException e) {
             final var source = m.resolveSignalServiceAddress(e.getSender());
             this.source = getLegacyIdentifier(source);
             this.sourceNumber = source.getNumber().orNull();
index d1b632127646d7387d7723cd1d81c6557880940f..1ffdb01623b50c2f6c6b416cd13fa36a1e0f13e8 100644 (file)
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 
 import java.util.List;
 
-public class JsonRpcBulkMessage extends JsonRpcMessage {
+public final class JsonRpcBulkMessage extends JsonRpcMessage {
 
     List<JsonNode> messages;
 
index 7f8b0a1a99553e1da8a60ce926dd8620c9eec69a..9cc7c87d2daea8c51897374a08986fd32a969071 100644 (file)
@@ -4,6 +4,6 @@ package org.asamk.signal.jsonrpc;
  * Represents a JSON-RPC (bulk) request or (bulk) response.
  * https://www.jsonrpc.org/specification
  */
-public abstract class JsonRpcMessage {
+public sealed abstract class JsonRpcMessage permits JsonRpcBulkMessage, JsonRpcRequest, JsonRpcResponse {
 
 }
index 1ae8552a8cb4af03f3382aa2d0d0f16c4c239608..ac54c7b7e774d3d2dbba2c491768b46fc232aaff 100644 (file)
@@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.node.ValueNode;
  * Represents a JSON-RPC request.
  * https://www.jsonrpc.org/specification#request_object
  */
-public class JsonRpcRequest extends JsonRpcMessage {
+public final class JsonRpcRequest extends JsonRpcMessage {
 
     /**
      * A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
index b5279b7d75501a9345d182282e3c407edf7d479e..406212d825ab6482df97c20c09571e2cd7b291b1 100644 (file)
@@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.node.ValueNode;
  * Represents a JSON-RPC response.
  * https://www.jsonrpc.org/specification#response_object
  */
-public class JsonRpcResponse extends JsonRpcMessage {
+public final class JsonRpcResponse extends JsonRpcMessage {
 
     /**
      * A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
index e40ed2183fc54f39ef71c585aa2bda600b9a7048..1c8a8f38fb2942286428dbc31675b4e12e1b3223 100644 (file)
@@ -64,12 +64,12 @@ public class ErrorUtils {
                     "CAPTCHA proof required for sending to \"%s\", available options \"%s\" with challenge token \"%s\", or wait \"%d\" seconds.\n"
                             + (
                             failure.getOptions().contains(ProofRequiredException.Option.RECAPTCHA)
-                                    ?
-                                    "To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html\n"
-                                            + "Check the developer tools (F12) console for a failed redirect to signalcaptcha://\n"
-                                            + "Everything after signalcaptcha:// is the captcha token.\n"
-                                            + "Use the following command to submit the captcha token:\n"
-                                            + "signal-cli submitRateLimitChallenge --challenge CHALLENGE_TOKEN --captcha CAPTCHA_TOKEN"
+                                    ? """
+                                    To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html
+                                    Check the developer tools (F12) console for a failed redirect to signalcaptcha://
+                                    Everything after signalcaptcha:// is the captcha token.
+                                    Use the following command to submit the captcha token:
+                                    signal-cli submitRateLimitChallenge --challenge CHALLENGE_TOKEN --captcha CAPTCHA_TOKEN"""
                                     : ""
                     ),
                     identifier,