]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java
83f0bb269e9da4a9e5512a33053e9fdc7b7e55b7
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / MultiAccountManagerImpl.java
1 package org.asamk.signal.manager;
2
3 import org.asamk.signal.manager.config.ServiceEnvironment;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 import java.io.File;
8 import java.io.IOException;
9 import java.net.URI;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.concurrent.TimeoutException;
18 import java.util.function.Consumer;
19
20 public class MultiAccountManagerImpl implements MultiAccountManager {
21
22 private final static Logger logger = LoggerFactory.getLogger(MultiAccountManagerImpl.class);
23
24 private final Set<Consumer<Manager>> onManagerAddedHandlers = new HashSet<>();
25 private final Set<Consumer<Manager>> onManagerRemovedHandlers = new HashSet<>();
26 private final Set<Manager> managers = new HashSet<>();
27 private final Map<URI, ProvisioningManager> provisioningManagers = new HashMap<>();
28 private final File dataPath;
29 private final ServiceEnvironment serviceEnvironment;
30 private final String userAgent;
31
32 public MultiAccountManagerImpl(
33 final Collection<Manager> managers,
34 final File dataPath,
35 final ServiceEnvironment serviceEnvironment,
36 final String userAgent
37 ) {
38 this.managers.addAll(managers);
39 managers.forEach(m -> m.addClosedListener(() -> this.removeManager(m)));
40 this.dataPath = dataPath;
41 this.serviceEnvironment = serviceEnvironment;
42 this.userAgent = userAgent;
43 }
44
45 @Override
46 public List<String> getAccountNumbers() {
47 synchronized (managers) {
48 return managers.stream().map(Manager::getSelfNumber).toList();
49 }
50 }
51
52 @Override
53 public List<Manager> getManagers() {
54 synchronized (managers) {
55 return new ArrayList<>(managers);
56 }
57 }
58
59 void addManager(final Manager m) {
60 synchronized (managers) {
61 if (managers.contains(m)) {
62 return;
63 }
64 managers.add(m);
65 m.addClosedListener(() -> this.removeManager(m));
66 }
67 synchronized (onManagerAddedHandlers) {
68 for (final var handler : onManagerAddedHandlers) {
69 handler.accept(m);
70 }
71 }
72 }
73
74 @Override
75 public void addOnManagerAddedHandler(final Consumer<Manager> handler) {
76 synchronized (onManagerAddedHandlers) {
77 onManagerAddedHandlers.add(handler);
78 }
79 }
80
81 void removeManager(final Manager m) {
82 synchronized (managers) {
83 if (!managers.remove(m)) {
84 return;
85 }
86 }
87 synchronized (onManagerRemovedHandlers) {
88 for (final var handler : onManagerRemovedHandlers) {
89 handler.accept(m);
90 }
91 }
92 }
93
94 @Override
95 public void addOnManagerRemovedHandler(final Consumer<Manager> handler) {
96 synchronized (onManagerRemovedHandlers) {
97 onManagerRemovedHandlers.add(handler);
98 }
99 }
100
101 @Override
102 public Manager getManager(final String account) {
103 synchronized (managers) {
104 return managers.stream().filter(m -> m.getSelfNumber().equals(account)).findFirst().orElse(null);
105 }
106 }
107
108 @Override
109 public URI getNewProvisioningDeviceLinkUri() throws TimeoutException, IOException {
110 final var provisioningManager = getNewProvisioningManager();
111 final var deviceLinkUri = provisioningManager.getDeviceLinkUri();
112 provisioningManagers.put(deviceLinkUri, provisioningManager);
113 return deviceLinkUri;
114 }
115
116 @Override
117 public ProvisioningManager getProvisioningManagerFor(final URI deviceLinkUri) {
118 return provisioningManagers.remove(deviceLinkUri);
119 }
120
121 private ProvisioningManager getNewProvisioningManager() {
122 return ProvisioningManager.init(dataPath, serviceEnvironment, userAgent, this::addManager);
123 }
124
125 @Override
126 public RegistrationManager getNewRegistrationManager(String account) throws IOException {
127 return RegistrationManager.init(account, dataPath, serviceEnvironment, userAgent, this::addManager);
128 }
129
130 @Override
131 public void close() {
132 synchronized (managers) {
133 for (var m : new ArrayList<>(managers)) {
134 try {
135 m.close();
136 } catch (IOException e) {
137 logger.warn("Cleanup failed", e);
138 }
139 }
140 managers.clear();
141 }
142 }
143 }