add AccountRepository

This commit is contained in:
Daniel Gultsch 2023-01-20 18:35:13 +01:00
parent 359ef330df
commit d25cc059c5
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
5 changed files with 108 additions and 17 deletions

View file

@ -29,27 +29,36 @@
package eu.siacs.conversations.ui.util; package eu.siacs.conversations.ui.util;
import java.util.function.Supplier;
public class PendingItem<T> { public class PendingItem<T> {
private T item = null; private T item = null;
public synchronized void push(T item) { public synchronized void push(T item) {
this.item = item; this.item = item;
} }
public synchronized T pop() { public synchronized T pop() {
final T item = this.item; final T item = this.item;
this.item = null; this.item = null;
return item; return item;
} }
public synchronized T peek() { public synchronized T peek() {
return item; return item;
} }
public synchronized boolean clear() { public synchronized T peekOrCreate(final Supplier<T> supplier) {
boolean notNull = this.item != null; if (this.item == null) {
this.item = null; this.item = supplier.get();
return notNull; }
} return this.item;
}
public synchronized boolean clear() {
boolean notNull = this.item != null;
this.item = null;
return notNull;
}
} }

View file

@ -0,0 +1,15 @@
package im.conversations.android.repository;
import android.content.Context;
import im.conversations.android.database.ConversationsDatabase;
public abstract class AbstractRepository {
protected final Context context;
protected final ConversationsDatabase database;
protected AbstractRepository(final Context context) {
this.context = context;
this.database = ConversationsDatabase.getInstance(context);
}
}

View file

@ -0,0 +1,36 @@
package im.conversations.android.repository;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.common.base.Preconditions;
import eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.IDs;
import im.conversations.android.database.CredentialStore;
import im.conversations.android.database.entity.AccountEntity;
import im.conversations.android.database.model.Account;
public class AccountRepository extends AbstractRepository {
public AccountRepository(final Context context) {
super(context);
}
public Account createAccount(@NonNull final Jid address, final String password) {
Preconditions.checkArgument(
address.isBareJid(), "Account should be specified without resource");
Preconditions.checkArgument(password != null, "Missing password");
final byte[] randomSeed = IDs.seed();
final var entity = new AccountEntity();
entity.address = address;
entity.enabled = true;
entity.randomSeed = randomSeed;
final long id = database.accountDao().insert(entity);
final var account = new Account(id, address, entity.randomSeed);
try {
CredentialStore.getInstance(context).setPassword(account, password);
} catch (final Exception e) {
throw new IllegalStateException("Could not store password", e);
}
return account;
}
}

View file

@ -0,0 +1,10 @@
package im.conversations.android.xmpp;
public class ConnectionException extends Exception {
private final ConnectionState connectionState;
public ConnectionException(ConnectionState state) {
this.connectionState = state;
}
}

View file

@ -30,6 +30,7 @@ import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.MemorizingTrustManager; import eu.siacs.conversations.services.MemorizingTrustManager;
import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.MessageArchiveService;
import eu.siacs.conversations.services.NotificationService; import eu.siacs.conversations.services.NotificationService;
import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.utils.Patterns; import eu.siacs.conversations.utils.Patterns;
import eu.siacs.conversations.utils.PhoneHelper; import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.utils.Resolver; import eu.siacs.conversations.utils.Resolver;
@ -160,6 +161,7 @@ public class XmppConnection implements Runnable {
private final Consumer<Jid> bindConsumer; private final Consumer<Jid> bindConsumer;
private final ClassToInstanceMap<AbstractManager> managers; private final ClassToInstanceMap<AbstractManager> managers;
private Consumer<XmppConnection> statusListener = null; private Consumer<XmppConnection> statusListener = null;
private PendingItem<SettableFuture<XmppConnection>> connectedFuture = new PendingItem<>();
private SaslMechanism saslMechanism; private SaslMechanism saslMechanism;
private HashedToken.Mechanism hashTokenRequest; private HashedToken.Mechanism hashTokenRequest;
private HttpUrl redirectionUrl = null; private HttpUrl redirectionUrl = null;
@ -244,6 +246,16 @@ public class XmppConnection implements Runnable {
if (nextStatus.isError() || nextStatus == ConnectionState.ONLINE) { if (nextStatus.isError() || nextStatus == ConnectionState.ONLINE) {
this.recentErrorConnectionState = nextStatus; this.recentErrorConnectionState = nextStatus;
} }
if (nextStatus != ConnectionState.CONNECTING && nextStatus != ConnectionState.OFFLINE) {
final var future = this.connectedFuture.pop();
if (future != null) {
if (nextStatus == ConnectionState.ONLINE) {
future.set(this);
} else {
future.setException(new ConnectionException(nextStatus));
}
}
}
} }
if (statusListener != null) { if (statusListener != null) {
statusListener.accept(this); statusListener.accept(this);
@ -2225,6 +2237,15 @@ public class XmppConnection implements Runnable {
this.statusListener = listener; this.statusListener = listener;
} }
public ListenableFuture<XmppConnection> asConnectedFuture() {
synchronized (this) {
if (this.connectionState == ConnectionState.ONLINE) {
return Futures.immediateFuture(this);
}
return this.connectedFuture.peekOrCreate(SettableFuture::create);
}
}
private void forceCloseSocket() { private void forceCloseSocket() {
FileBackend.close(this.socket); FileBackend.close(this.socket);
FileBackend.close(this.tagReader); FileBackend.close(this.tagReader);