Persisitence and loading for ServiceDiscoveryResult

This commit is contained in:
Stephen Paul Weber 2016-01-12 21:53:38 -05:00
parent 56f8fff935
commit ad36a4ba89
2 changed files with 98 additions and 11 deletions

View file

@ -1,6 +1,7 @@
package eu.siacs.conversations.entities; package eu.siacs.conversations.entities;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor;
import android.util.Base64; import android.util.Base64;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.Comparable; import java.lang.Comparable;
@ -17,6 +18,10 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class ServiceDiscoveryResult { public class ServiceDiscoveryResult {
public static final String TABLENAME = "discovery_results";
public static final String HASH = "hash";
public static final String VER = "ver";
public static final String RESULT = "result";
protected static String blankNull(String s) { protected static String blankNull(String s) {
return s == null ? "" : s; return s == null ? "" : s;
@ -36,10 +41,21 @@ public class ServiceDiscoveryResult {
} }
public Identity(final Element el) { public Identity(final Element el) {
this.category = el.getAttribute("category"); this(
this.type = el.getAttribute("type"); el.getAttribute("category"),
this.lang = el.getAttribute("xml:lang"); el.getAttribute("type"),
this.name = el.getAttribute("name"); el.getAttribute("xml:lang"),
el.getAttribute("name")
);
}
public Identity(final JSONObject o) {
this(
o.optString("category", null),
o.optString("type", null),
o.optString("lang", null),
o.optString("name", null)
);
} }
public String getCategory() { public String getCategory() {
@ -88,17 +104,15 @@ public class ServiceDiscoveryResult {
} }
} }
protected final String hash;
protected final byte[] ver;
protected final List<Identity> identities; protected final List<Identity> identities;
protected final List<String> features; protected final List<String> features;
public ServiceDiscoveryResult(final List<Identity> identities, final List<String> features) {
this.identities = identities;
this.features = features;
}
public ServiceDiscoveryResult(final IqPacket packet) { public ServiceDiscoveryResult(final IqPacket packet) {
this.identities = new ArrayList<>(); this.identities = new ArrayList<>();
this.features = new ArrayList<>(); this.features = new ArrayList<>();
this.hash = "sha-1"; // We only support sha-1 for now
final List<Element> elements = packet.query().getChildren(); final List<Element> elements = packet.query().getChildren();
@ -114,6 +128,33 @@ public class ServiceDiscoveryResult {
} }
} }
} }
this.ver = this.mkCapHash();
}
public ServiceDiscoveryResult(String hash, byte[] ver, JSONObject o) throws JSONException {
this.identities = new ArrayList<>();
this.features = new ArrayList<>();
this.hash = hash;
this.ver = ver;
JSONArray identities = o.optJSONArray("identities");
for(int i = 0; i < identities.length(); i++) {
this.identities.add(new Identity(identities.getJSONObject(i)));
}
JSONArray features = o.optJSONArray("features");
for(int i = 0; i < features.length(); i++) {
this.features.add(features.getString(i));
}
}
public ServiceDiscoveryResult(Cursor cursor) throws JSONException {
this(
cursor.getString(cursor.getColumnIndex(HASH)),
Base64.decode(cursor.getString(cursor.getColumnIndex(VER)), Base64.DEFAULT),
new JSONObject(cursor.getString(cursor.getColumnIndex(RESULT)))
);
} }
public List<Identity> getIdentities() { public List<Identity> getIdentities() {
@ -135,7 +176,7 @@ public class ServiceDiscoveryResult {
return false; return false;
} }
public byte[] getCapHash() { protected byte[] mkCapHash() {
StringBuilder s = new StringBuilder(); StringBuilder s = new StringBuilder();
List<Identity> identities = this.getIdentities(); List<Identity> identities = this.getIdentities();
@ -191,4 +232,11 @@ public class ServiceDiscoveryResult {
} }
} }
public ContentValues getContentValues() {
final ContentValues values = new ContentValues();
values.put(HASH, this.hash);
values.put(VER, new String(Base64.encode(this.ver, Base64.DEFAULT)).trim());
values.put(RESULT, this.toJSON().toString());
return values;
}
} }

View file

@ -31,6 +31,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.json.JSONException;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.AxolotlService;
@ -41,6 +42,7 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Roster; import eu.siacs.conversations.entities.Roster;
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jid.Jid;
@ -49,7 +51,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null; private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history"; private static final String DATABASE_NAME = "history";
private static final int DATABASE_VERSION = 22; private static final int DATABASE_VERSION = 23;
private static String CREATE_CONTATCS_STATEMENT = "create table " private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, " + Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@ -63,6 +65,14 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ ") ON DELETE CASCADE, UNIQUE(" + Contact.ACCOUNT + ", " + ") ON DELETE CASCADE, UNIQUE(" + Contact.ACCOUNT + ", "
+ Contact.JID + ") ON CONFLICT REPLACE);"; + Contact.JID + ") ON CONFLICT REPLACE);";
private static String CREATE_DISCOVERY_RESULTS_STATEMENT = "create table "
+ ServiceDiscoveryResult.TABLENAME + "("
+ ServiceDiscoveryResult.HASH + " TEXT, "
+ ServiceDiscoveryResult.VER + " TEXT, "
+ ServiceDiscoveryResult.RESULT + " TEXT, "
+ "UNIQUE(" + ServiceDiscoveryResult.HASH + ", "
+ ServiceDiscoveryResult.VER + ") ON CONFLICT REPLACE);";
private static String CREATE_PREKEYS_STATEMENT = "CREATE TABLE " private static String CREATE_PREKEYS_STATEMENT = "CREATE TABLE "
+ SQLiteAxolotlStore.PREKEY_TABLENAME + "(" + SQLiteAxolotlStore.PREKEY_TABLENAME + "("
+ SQLiteAxolotlStore.ACCOUNT + " TEXT, " + SQLiteAxolotlStore.ACCOUNT + " TEXT, "
@ -158,6 +168,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ ") ON DELETE CASCADE);"); + ") ON DELETE CASCADE);");
db.execSQL(CREATE_CONTATCS_STATEMENT); db.execSQL(CREATE_CONTATCS_STATEMENT);
db.execSQL(CREATE_DISCOVERY_RESULTS_STATEMENT);
db.execSQL(CREATE_SESSIONS_STATEMENT); db.execSQL(CREATE_SESSIONS_STATEMENT);
db.execSQL(CREATE_PREKEYS_STATEMENT); db.execSQL(CREATE_PREKEYS_STATEMENT);
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT); db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
@ -355,6 +366,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
if (oldVersion < 22 && newVersion >= 22) { if (oldVersion < 22 && newVersion >= 22) {
db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE); db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE);
} }
if (oldVersion < 23 && newVersion >= 23) {
db.execSQL(CREATE_DISCOVERY_RESULTS_STATEMENT);
}
} }
public static synchronized DatabaseBackend getInstance(Context context) { public static synchronized DatabaseBackend getInstance(Context context) {
@ -379,6 +394,30 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.insert(Account.TABLENAME, null, account.getContentValues()); db.insert(Account.TABLENAME, null, account.getContentValues());
} }
public void insertDiscoveryResult(ServiceDiscoveryResult result) {
SQLiteDatabase db = this.getWritableDatabase();
db.insert(ServiceDiscoveryResult.TABLENAME, null, result.getContentValues());
}
public ServiceDiscoveryResult findDiscoveryResult(final String hash, final String ver) {
SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = {hash, ver};
Cursor cursor = db.query(ServiceDiscoveryResult.TABLENAME, null,
ServiceDiscoveryResult.HASH + "=? AND " + ServiceDiscoveryResult.VER + "=?",
selectionArgs, null, null, null);
if (cursor.getCount() == 0)
return null;
cursor.moveToFirst();
ServiceDiscoveryResult result = null;
try {
result = new ServiceDiscoveryResult(cursor);
} catch (JSONException e) { /* result is still null */ }
cursor.close();
return result;
}
public CopyOnWriteArrayList<Conversation> getConversations(int status) { public CopyOnWriteArrayList<Conversation> getConversations(int status) {
CopyOnWriteArrayList<Conversation> list = new CopyOnWriteArrayList<>(); CopyOnWriteArrayList<Conversation> list = new CopyOnWriteArrayList<>();
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();