1 package org
.asamk
.signal
.manager
;
3 import org
.slf4j
.Logger
;
4 import org
.slf4j
.LoggerFactory
;
6 import java
.io
.IOException
;
8 import java
.util
.ArrayList
;
9 import java
.util
.Collection
;
10 import java
.util
.HashMap
;
11 import java
.util
.HashSet
;
12 import java
.util
.List
;
15 import java
.util
.concurrent
.TimeoutException
;
16 import java
.util
.function
.Consumer
;
18 class MultiAccountManagerImpl
implements MultiAccountManager
{
20 private final static Logger logger
= LoggerFactory
.getLogger(MultiAccountManagerImpl
.class);
22 private final Set
<Consumer
<Manager
>> onManagerAddedHandlers
= new HashSet
<>();
23 private final Set
<Consumer
<Manager
>> onManagerRemovedHandlers
= new HashSet
<>();
24 private final Set
<Manager
> managers
= new HashSet
<>();
25 private final Map
<URI
, ProvisioningManager
> provisioningManagers
= new HashMap
<>();
26 private final SignalAccountFiles signalAccountFiles
;
28 public MultiAccountManagerImpl(final Collection
<Manager
> managers
, final SignalAccountFiles signalAccountFiles
) {
29 this.signalAccountFiles
= signalAccountFiles
;
30 this.managers
.addAll(managers
);
31 managers
.forEach(m
-> m
.addClosedListener(() -> this.removeManager(m
)));
35 public List
<String
> getAccountNumbers() {
36 synchronized (managers
) {
37 return managers
.stream().map(Manager
::getSelfNumber
).toList();
42 public List
<Manager
> getManagers() {
43 synchronized (managers
) {
44 return new ArrayList
<>(managers
);
48 void addManager(final Manager m
) {
49 synchronized (managers
) {
50 if (managers
.contains(m
)) {
54 m
.addClosedListener(() -> this.removeManager(m
));
56 synchronized (onManagerAddedHandlers
) {
57 for (final var handler
: onManagerAddedHandlers
) {
64 public void addOnManagerAddedHandler(final Consumer
<Manager
> handler
) {
65 synchronized (onManagerAddedHandlers
) {
66 onManagerAddedHandlers
.add(handler
);
70 void removeManager(final Manager m
) {
71 synchronized (managers
) {
72 if (!managers
.remove(m
)) {
76 synchronized (onManagerRemovedHandlers
) {
77 for (final var handler
: onManagerRemovedHandlers
) {
84 public void addOnManagerRemovedHandler(final Consumer
<Manager
> handler
) {
85 synchronized (onManagerRemovedHandlers
) {
86 onManagerRemovedHandlers
.add(handler
);
91 public Manager
getManager(final String number
) {
92 synchronized (managers
) {
93 return managers
.stream().filter(m
-> m
.getSelfNumber().equals(number
)).findFirst().orElse(null);
98 public URI
getNewProvisioningDeviceLinkUri() throws TimeoutException
, IOException
{
99 final var provisioningManager
= getNewProvisioningManager();
100 final var deviceLinkUri
= provisioningManager
.getDeviceLinkUri();
101 provisioningManagers
.put(deviceLinkUri
, provisioningManager
);
102 return deviceLinkUri
;
106 public ProvisioningManager
getProvisioningManagerFor(final URI deviceLinkUri
) {
107 return provisioningManagers
.remove(deviceLinkUri
);
110 private ProvisioningManager
getNewProvisioningManager() {
111 return signalAccountFiles
.initProvisioningManager(this::addManager
);
115 public RegistrationManager
getNewRegistrationManager(String number
) throws IOException
{
116 return signalAccountFiles
.initRegistrationManager(number
, this::addManager
);
120 public void close() {
121 synchronized (managers
) {
122 for (var m
: new ArrayList
<>(managers
)) {
125 } catch (IOException e
) {
126 logger
.warn("Cleanup failed", e
);