import com.fasterxml.jackson.databind.node.ContainerNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.asamk.signal.JsonReceiveMessageHandler;
-import org.asamk.signal.JsonWriter;
import org.asamk.signal.commands.Command;
import org.asamk.signal.commands.Commands;
import org.asamk.signal.commands.JsonRpcMultiCommand;
import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
import org.asamk.signal.commands.exceptions.UserErrorException;
+import org.asamk.signal.json.JsonReceiveMessageHandler;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.MultiAccountManager;
import org.asamk.signal.manager.RegistrationManager;
+import org.asamk.signal.output.JsonWriter;
import org.asamk.signal.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.nio.channels.OverlappingFileLockException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
if (!noReceiveOnStart) {
c.getAccountNumbers().stream().map(c::getManager).filter(Objects::nonNull).forEach(this::subscribeReceive);
+ c.addOnManagerAddedHandler(this::subscribeReceive);
+ c.addOnManagerRemovedHandler(this::unsubscribeReceive);
}
handleConnection();
subscribeReceive(m);
}
+ final var currentThread = Thread.currentThread();
+ m.addClosedListener(currentThread::interrupt);
+
handleConnection();
}
final ObjectMapper objectMapper, final String method, ContainerNode<?> params
) throws JsonRpcException {
var command = getCommand(method);
- // TODO implement link
if (c != null) {
if (command instanceof JsonRpcMultiCommand<?> jsonRpcCommand) {
return runCommand(objectMapper, params, new MultiCommandRunnerImpl<>(c, jsonRpcCommand));
final var registrationManager = c.getNewRegistrationManager(params.get("account").asText());
((ObjectNode) params).remove("account");
return registrationManager;
+ } catch (OverlappingFileLockException e) {
+ logger.warn("Account is already in use");
+ return null;
} catch (IOException | IllegalStateException e) {
logger.warn("Failed to load registration manager", e);
return null;
e.getMessage(),
null));
} catch (UserErrorException e) {
- throw new JsonRpcException(new JsonRpcResponse.Error(USER_ERROR, e.getMessage(), null));
+ throw new JsonRpcException(new JsonRpcResponse.Error(USER_ERROR,
+ e.getMessage(),
+ getErrorDataNode(objectMapper, result)));
} catch (IOErrorException e) {
- throw new JsonRpcException(new JsonRpcResponse.Error(IO_ERROR, e.getMessage(), null));
+ throw new JsonRpcException(new JsonRpcResponse.Error(IO_ERROR,
+ e.getMessage(),
+ getErrorDataNode(objectMapper, result)));
} catch (UntrustedKeyErrorException e) {
- throw new JsonRpcException(new JsonRpcResponse.Error(UNTRUSTED_KEY_ERROR, e.getMessage(), null));
+ throw new JsonRpcException(new JsonRpcResponse.Error(UNTRUSTED_KEY_ERROR,
+ e.getMessage(),
+ getErrorDataNode(objectMapper, result)));
} catch (Throwable e) {
logger.error("Command execution failed", e);
throw new JsonRpcException(new JsonRpcResponse.Error(JsonRpcResponse.Error.INTERNAL_ERROR,
e.getMessage(),
- null));
+ getErrorDataNode(objectMapper, result)));
}
Object output = result[0] == null ? Map.of() : result[0];
return objectMapper.valueToTree(output);
}
+ private JsonNode getErrorDataNode(final ObjectMapper objectMapper, final Object[] result) {
+ if (result[0] == null) {
+ return null;
+ }
+ return objectMapper.valueToTree(Map.of("response", result[0]));
+ }
+
private <T> void parseParamsAndRunCommand(
final ObjectMapper objectMapper,
final TreeNode params,