mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Store schema version in database. Dev task #50.
If the schema of the database is incompatible with the schema expected by the code, the database throws a DbSchemaException. LifecycleManager indicates the error to BriarService, which uses HomeScreenActivity to show a notification and quit the app.
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
<string name="passwords_do_not_match">Passwords do not match</string>
|
||||
<string name="enter_password">Enter your password:</string>
|
||||
<string name="try_again">Wrong password, try again:</string>
|
||||
<string name="startup_failed_notification_title">Briar could not start up</string>
|
||||
<string name="startup_failed_notification_text">You may need to reinstall Briar.</string>
|
||||
<string name="expiry_warning">This software has expired.\nPlease install a newer version.</string>
|
||||
<string name="contact_list_button">Contacts</string>
|
||||
<string name="forums_button">Forums</string>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.android;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
|
||||
import static java.util.logging.Level.INFO;
|
||||
|
||||
@@ -13,6 +14,7 @@ import org.briarproject.R;
|
||||
import org.briarproject.api.android.AndroidExecutor;
|
||||
import org.briarproject.api.db.DatabaseConfig;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
|
||||
import roboguice.service.RoboService;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
@@ -30,11 +32,11 @@ public class BriarService extends RoboService {
|
||||
private final Binder binder = new BriarBinder();
|
||||
|
||||
@Inject private DatabaseConfig databaseConfig;
|
||||
private boolean started = false;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject private volatile LifecycleManager lifecycleManager;
|
||||
@Inject private volatile AndroidExecutor androidExecutor;
|
||||
private volatile boolean started = false;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@@ -51,21 +53,31 @@ public class BriarService extends RoboService {
|
||||
b.setContentTitle(getText(R.string.notification_title));
|
||||
b.setContentText(getText(R.string.notification_text));
|
||||
b.setWhen(0); // Don't show the time
|
||||
b.setOngoing(true);
|
||||
// Touch the notification to show the home screen
|
||||
Intent i = new Intent(this, HomeScreenActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
|
||||
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
|
||||
b.setContentIntent(pi);
|
||||
b.setOngoing(true);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
|
||||
FLAG_ACTIVITY_SINGLE_TOP);
|
||||
b.setContentIntent(PendingIntent.getActivity(this, 0, i, 0));
|
||||
startForeground(1, b.build());
|
||||
// Start the services in a background thread
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
lifecycleManager.startServices();
|
||||
if(lifecycleManager.startServices()) {
|
||||
started = true;
|
||||
} else {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Startup failed");
|
||||
Intent i = new Intent(BriarService.this,
|
||||
HomeScreenActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK |
|
||||
FLAG_ACTIVITY_CLEAR_TOP);
|
||||
i.putExtra("briar.STARTUP_FAILED", true);
|
||||
startActivity(i);
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
started = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,11 +96,11 @@ public class BriarService extends RoboService {
|
||||
super.onDestroy();
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Destroyed");
|
||||
// Stop the services in a background thread
|
||||
if(started) new Thread() {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
androidExecutor.shutdown();
|
||||
lifecycleManager.stopServices();
|
||||
if(started) lifecycleManager.stopServices();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.android;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.text.InputType.TYPE_CLASS_TEXT;
|
||||
import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
|
||||
import static android.view.Gravity.CENTER;
|
||||
@@ -41,10 +42,15 @@ import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import roboguice.activity.RoboActivity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.text.Editable;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
@@ -90,9 +96,17 @@ public class HomeScreenActivity extends RoboActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(state);
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Created");
|
||||
Intent i = getIntent();
|
||||
long handle = i.getLongExtra("org.briarproject.LOCAL_AUTHOR_HANDLE", -1);
|
||||
if(handle != -1) {
|
||||
boolean failed = i.getBooleanExtra("briar.STARTUP_FAILED", false);
|
||||
long handle = i.getLongExtra("briar.LOCAL_AUTHOR_HANDLE", -1);
|
||||
if(failed) {
|
||||
// LifecycleManager failed to start all necessary services
|
||||
showStartupFailureNotification();
|
||||
finish();
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Exiting");
|
||||
System.exit(0);
|
||||
} else if(handle != -1) {
|
||||
// The activity was launched from the setup wizard
|
||||
if(System.currentTimeMillis() < EXPIRY_DATE) {
|
||||
showSpinner();
|
||||
@@ -118,13 +132,30 @@ public class HomeScreenActivity extends RoboActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void showStartupFailureNotification() {
|
||||
NotificationCompat.Builder b = new NotificationCompat.Builder(this);
|
||||
b.setSmallIcon(android.R.drawable.stat_notify_error);
|
||||
b.setContentTitle(getText(R.string.startup_failed_notification_title));
|
||||
b.setContentText(getText(R.string.startup_failed_notification_text));
|
||||
// Touch the notification to relaunch the app
|
||||
Intent i = new Intent(this, HomeScreenActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
b.setContentIntent(PendingIntent.getActivity(this, 0, i, 0));
|
||||
Notification n = b.build();
|
||||
Object o = getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationManager nm = (NotificationManager) o;
|
||||
nm.notify(0, n);
|
||||
}
|
||||
|
||||
private void showSpinner() {
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(MATCH_MATCH);
|
||||
layout.setGravity(CENTER);
|
||||
|
||||
ProgressBar progress = new ProgressBar(this);
|
||||
progress.setIndeterminate(true);
|
||||
layout.addView(progress);
|
||||
|
||||
setContentView(layout);
|
||||
}
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ public class SetupActivity extends RoboActivity implements OnClickListener {
|
||||
public void run() {
|
||||
Intent i = new Intent(SetupActivity.this,
|
||||
HomeScreenActivity.class);
|
||||
i.putExtra("org.briarproject.LOCAL_AUTHOR_HANDLE", handle);
|
||||
i.putExtra("briar.LOCAL_AUTHOR_HANDLE", handle);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(i);
|
||||
finish();
|
||||
|
||||
@@ -212,10 +212,10 @@ ConnectionListener {
|
||||
GroupId inbox = item.getInboxGroupId();
|
||||
AuthorId localAuthorId = item.getContact().getLocalAuthorId();
|
||||
Intent i = new Intent(this, ConversationActivity.class);
|
||||
i.putExtra("org.briarproject.CONTACT_ID", contactId.getInt());
|
||||
i.putExtra("org.briarproject.CONTACT_NAME", contactName);
|
||||
i.putExtra("org.briarproject.GROUP_ID", inbox.getBytes());
|
||||
i.putExtra("org.briarproject.LOCAL_AUTHOR_ID", localAuthorId.getBytes());
|
||||
i.putExtra("briar.CONTACT_ID", contactId.getInt());
|
||||
i.putExtra("briar.CONTACT_NAME", contactName);
|
||||
i.putExtra("briar.GROUP_ID", inbox.getBytes());
|
||||
i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,16 +68,16 @@ implements EventListener, OnClickListener, OnItemClickListener {
|
||||
super.onCreate(state);
|
||||
|
||||
Intent i = getIntent();
|
||||
int id = i.getIntExtra("org.briarproject.CONTACT_ID", -1);
|
||||
int id = i.getIntExtra("briar.CONTACT_ID", -1);
|
||||
if(id == -1) throw new IllegalStateException();
|
||||
contactId = new ContactId(id);
|
||||
contactName = i.getStringExtra("org.briarproject.CONTACT_NAME");
|
||||
contactName = i.getStringExtra("briar.CONTACT_NAME");
|
||||
if(contactName == null) throw new IllegalStateException();
|
||||
setTitle(contactName);
|
||||
byte[] b = i.getByteArrayExtra("org.briarproject.GROUP_ID");
|
||||
byte[] b = i.getByteArrayExtra("briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
b = i.getByteArrayExtra("org.briarproject.LOCAL_AUTHOR_ID");
|
||||
b = i.getByteArrayExtra("briar.LOCAL_AUTHOR_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
localAuthorId = new AuthorId(b);
|
||||
|
||||
@@ -221,9 +221,9 @@ implements EventListener, OnClickListener, OnItemClickListener {
|
||||
|
||||
public void onClick(View view) {
|
||||
Intent i = new Intent(this, WritePrivateMessageActivity.class);
|
||||
i.putExtra("org.briarproject.CONTACT_NAME", contactName);
|
||||
i.putExtra("org.briarproject.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("org.briarproject.LOCAL_AUTHOR_ID", localAuthorId.getBytes());
|
||||
i.putExtra("briar.CONTACT_NAME", contactName);
|
||||
i.putExtra("briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
@@ -235,14 +235,14 @@ implements EventListener, OnClickListener, OnItemClickListener {
|
||||
private void displayMessage(int position) {
|
||||
MessageHeader header = adapter.getItem(position).getHeader();
|
||||
Intent i = new Intent(this, ReadPrivateMessageActivity.class);
|
||||
i.putExtra("org.briarproject.CONTACT_ID", contactId.getInt());
|
||||
i.putExtra("org.briarproject.CONTACT_NAME", contactName);
|
||||
i.putExtra("org.briarproject.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("org.briarproject.LOCAL_AUTHOR_ID", localAuthorId.getBytes());
|
||||
i.putExtra("org.briarproject.AUTHOR_NAME", header.getAuthor().getName());
|
||||
i.putExtra("org.briarproject.MESSAGE_ID", header.getId().getBytes());
|
||||
i.putExtra("org.briarproject.CONTENT_TYPE", header.getContentType());
|
||||
i.putExtra("org.briarproject.TIMESTAMP", header.getTimestamp());
|
||||
i.putExtra("briar.CONTACT_ID", contactId.getInt());
|
||||
i.putExtra("briar.CONTACT_NAME", contactName);
|
||||
i.putExtra("briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes());
|
||||
i.putExtra("briar.AUTHOR_NAME", header.getAuthor().getName());
|
||||
i.putExtra("briar.MESSAGE_ID", header.getId().getBytes());
|
||||
i.putExtra("briar.CONTENT_TYPE", header.getContentType());
|
||||
i.putExtra("briar.TIMESTAMP", header.getTimestamp());
|
||||
startActivityForResult(i, position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,30 +72,30 @@ implements OnClickListener {
|
||||
super.onCreate(state);
|
||||
|
||||
Intent i = getIntent();
|
||||
contactName = i.getStringExtra("org.briarproject.CONTACT_NAME");
|
||||
contactName = i.getStringExtra("briar.CONTACT_NAME");
|
||||
if(contactName == null) throw new IllegalStateException();
|
||||
setTitle(contactName);
|
||||
byte[] b = i.getByteArrayExtra("org.briarproject.LOCAL_AUTHOR_ID");
|
||||
byte[] b = i.getByteArrayExtra("briar.LOCAL_AUTHOR_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
localAuthorId = new AuthorId(b);
|
||||
String authorName = i.getStringExtra("org.briarproject.AUTHOR_NAME");
|
||||
String authorName = i.getStringExtra("briar.AUTHOR_NAME");
|
||||
if(authorName == null) throw new IllegalStateException();
|
||||
b = i.getByteArrayExtra("org.briarproject.MESSAGE_ID");
|
||||
b = i.getByteArrayExtra("briar.MESSAGE_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
messageId = new MessageId(b);
|
||||
b = i.getByteArrayExtra("org.briarproject.GROUP_ID");
|
||||
b = i.getByteArrayExtra("briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
String contentType = i.getStringExtra("org.briarproject.CONTENT_TYPE");
|
||||
String contentType = i.getStringExtra("briar.CONTENT_TYPE");
|
||||
if(contentType == null) throw new IllegalStateException();
|
||||
timestamp = i.getLongExtra("org.briarproject.TIMESTAMP", -1);
|
||||
timestamp = i.getLongExtra("briar.TIMESTAMP", -1);
|
||||
if(timestamp == -1) throw new IllegalStateException();
|
||||
|
||||
if(state == null) {
|
||||
read = false;
|
||||
setReadInDatabase(true);
|
||||
} else {
|
||||
read = state.getBoolean("org.briarproject.READ");
|
||||
read = state.getBoolean("briar.READ");
|
||||
}
|
||||
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
@@ -257,7 +257,7 @@ implements OnClickListener {
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle state) {
|
||||
super.onSaveInstanceState(state);
|
||||
state.putBoolean("org.briarproject.READ", read);
|
||||
state.putBoolean("briar.READ", read);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
@@ -271,12 +271,12 @@ implements OnClickListener {
|
||||
finish();
|
||||
} else if(view == replyButton) {
|
||||
Intent i = new Intent(this, WritePrivateMessageActivity.class);
|
||||
i.putExtra("org.briarproject.CONTACT_NAME", contactName);
|
||||
i.putExtra("org.briarproject.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("org.briarproject.LOCAL_AUTHOR_ID",
|
||||
i.putExtra("briar.CONTACT_NAME", contactName);
|
||||
i.putExtra("briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("briar.LOCAL_AUTHOR_ID",
|
||||
localAuthorId.getBytes());
|
||||
i.putExtra("org.briarproject.PARENT_ID", messageId.getBytes());
|
||||
i.putExtra("org.briarproject.TIMESTAMP", timestamp);
|
||||
i.putExtra("briar.PARENT_ID", messageId.getBytes());
|
||||
i.putExtra("briar.TIMESTAMP", timestamp);
|
||||
startActivity(i);
|
||||
setResult(RESULT_REPLY);
|
||||
finish();
|
||||
|
||||
@@ -78,17 +78,17 @@ implements OnClickListener {
|
||||
super.onCreate(state);
|
||||
|
||||
Intent i = getIntent();
|
||||
contactName = i.getStringExtra("org.briarproject.CONTACT_NAME");
|
||||
contactName = i.getStringExtra("briar.CONTACT_NAME");
|
||||
if(contactName == null) throw new IllegalStateException();
|
||||
byte[] b = i.getByteArrayExtra("org.briarproject.GROUP_ID");
|
||||
byte[] b = i.getByteArrayExtra("briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
b = i.getByteArrayExtra("org.briarproject.LOCAL_AUTHOR_ID");
|
||||
b = i.getByteArrayExtra("briar.LOCAL_AUTHOR_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
localAuthorId = new AuthorId(b);
|
||||
b = i.getByteArrayExtra("org.briarproject.PARENT_ID");
|
||||
b = i.getByteArrayExtra("briar.PARENT_ID");
|
||||
if(b != null) parentId = new MessageId(b);
|
||||
timestamp = i.getLongExtra("org.briarproject.TIMESTAMP", -1);
|
||||
timestamp = i.getLongExtra("briar.TIMESTAMP", -1);
|
||||
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(MATCH_WRAP);
|
||||
|
||||
@@ -69,17 +69,17 @@ SelectContactsDialog.Listener {
|
||||
super.onCreate(state);
|
||||
|
||||
Intent i = getIntent();
|
||||
byte[] b = i.getByteArrayExtra("org.briarproject.GROUP_ID");
|
||||
byte[] b = i.getByteArrayExtra("briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
GroupId id = new GroupId(b);
|
||||
String name = i.getStringExtra("org.briarproject.GROUP_NAME");
|
||||
String name = i.getStringExtra("briar.GROUP_NAME");
|
||||
if(name == null) throw new IllegalStateException();
|
||||
setTitle(name);
|
||||
b = i.getByteArrayExtra("org.briarproject.GROUP_SALT");
|
||||
b = i.getByteArrayExtra("briar.GROUP_SALT");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
group = new Group(id, name, b);
|
||||
subscribed = i.getBooleanExtra("org.briarproject.SUBSCRIBED", false);
|
||||
boolean all = i.getBooleanExtra("org.briarproject.VISIBLE_TO_ALL", false);
|
||||
subscribed = i.getBooleanExtra("briar.SUBSCRIBED", false);
|
||||
boolean all = i.getBooleanExtra("briar.VISIBLE_TO_ALL", false);
|
||||
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(MATCH_MATCH);
|
||||
|
||||
@@ -67,10 +67,10 @@ OnClickListener, OnItemClickListener {
|
||||
super.onCreate(state);
|
||||
|
||||
Intent i = getIntent();
|
||||
byte[] b = i.getByteArrayExtra("org.briarproject.GROUP_ID");
|
||||
byte[] b = i.getByteArrayExtra("briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
groupName = i.getStringExtra("org.briarproject.GROUP_NAME");
|
||||
groupName = i.getStringExtra("briar.GROUP_NAME");
|
||||
if(groupName == null) throw new IllegalStateException();
|
||||
setTitle(groupName);
|
||||
|
||||
@@ -210,7 +210,7 @@ OnClickListener, OnItemClickListener {
|
||||
|
||||
public void onClick(View view) {
|
||||
Intent i = new Intent(this, WriteGroupPostActivity.class);
|
||||
i.putExtra("org.briarproject.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("briar.GROUP_ID", groupId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
@@ -222,16 +222,16 @@ OnClickListener, OnItemClickListener {
|
||||
private void displayMessage(int position) {
|
||||
MessageHeader item = adapter.getItem(position);
|
||||
Intent i = new Intent(this, ReadGroupPostActivity.class);
|
||||
i.putExtra("org.briarproject.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("org.briarproject.GROUP_NAME", groupName);
|
||||
i.putExtra("org.briarproject.MESSAGE_ID", item.getId().getBytes());
|
||||
i.putExtra("briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("briar.GROUP_NAME", groupName);
|
||||
i.putExtra("briar.MESSAGE_ID", item.getId().getBytes());
|
||||
Author author = item.getAuthor();
|
||||
if(author != null) {
|
||||
i.putExtra("org.briarproject.AUTHOR_ID", author.getId().getBytes());
|
||||
i.putExtra("org.briarproject.AUTHOR_NAME", author.getName());
|
||||
i.putExtra("briar.AUTHOR_ID", author.getId().getBytes());
|
||||
i.putExtra("briar.AUTHOR_NAME", author.getName());
|
||||
}
|
||||
i.putExtra("org.briarproject.CONTENT_TYPE", item.getContentType());
|
||||
i.putExtra("org.briarproject.TIMESTAMP", item.getTimestamp());
|
||||
i.putExtra("briar.CONTENT_TYPE", item.getContentType());
|
||||
i.putExtra("briar.TIMESTAMP", item.getTimestamp());
|
||||
startActivityForResult(i, position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,8 +347,8 @@ implements EventListener, OnClickListener, OnItemClickListener {
|
||||
} else {
|
||||
Intent i = new Intent(this, GroupActivity.class);
|
||||
Group g = item.getGroup();
|
||||
i.putExtra("org.briarproject.GROUP_ID", g.getId().getBytes());
|
||||
i.putExtra("org.briarproject.GROUP_NAME", g.getName());
|
||||
i.putExtra("briar.GROUP_ID", g.getId().getBytes());
|
||||
i.putExtra("briar.GROUP_NAME", g.getName());
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,11 +132,11 @@ implements EventListener, OnItemClickListener {
|
||||
GroupStatus s = item.getGroupStatus();
|
||||
Group g = s.getGroup();
|
||||
Intent i = new Intent(this, ConfigureGroupActivity.class);
|
||||
i.putExtra("org.briarproject.GROUP_ID", g.getId().getBytes());
|
||||
i.putExtra("org.briarproject.GROUP_NAME", g.getName());
|
||||
i.putExtra("org.briarproject.GROUP_SALT", g.getSalt());
|
||||
i.putExtra("org.briarproject.SUBSCRIBED", s.isSubscribed());
|
||||
i.putExtra("org.briarproject.VISIBLE_TO_ALL", s.isVisibleToAll());
|
||||
i.putExtra("briar.GROUP_ID", g.getId().getBytes());
|
||||
i.putExtra("briar.GROUP_NAME", g.getName());
|
||||
i.putExtra("briar.GROUP_SALT", g.getSalt());
|
||||
i.putExtra("briar.SUBSCRIBED", s.isSubscribed());
|
||||
i.putExtra("briar.VISIBLE_TO_ALL", s.isVisibleToAll());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,26 +69,26 @@ implements OnClickListener {
|
||||
super.onCreate(state);
|
||||
|
||||
Intent i = getIntent();
|
||||
byte[] b = i.getByteArrayExtra("org.briarproject.GROUP_ID");
|
||||
byte[] b = i.getByteArrayExtra("briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
String groupName = i.getStringExtra("org.briarproject.GROUP_NAME");
|
||||
String groupName = i.getStringExtra("briar.GROUP_NAME");
|
||||
if(groupName == null) throw new IllegalStateException();
|
||||
setTitle(groupName);
|
||||
b = i.getByteArrayExtra("org.briarproject.MESSAGE_ID");
|
||||
b = i.getByteArrayExtra("briar.MESSAGE_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
messageId = new MessageId(b);
|
||||
String contentType = i.getStringExtra("org.briarproject.CONTENT_TYPE");
|
||||
String contentType = i.getStringExtra("briar.CONTENT_TYPE");
|
||||
if(contentType == null) throw new IllegalStateException();
|
||||
timestamp = i.getLongExtra("org.briarproject.TIMESTAMP", -1);
|
||||
timestamp = i.getLongExtra("briar.TIMESTAMP", -1);
|
||||
if(timestamp == -1) throw new IllegalStateException();
|
||||
String authorName = i.getStringExtra("org.briarproject.AUTHOR_NAME");
|
||||
String authorName = i.getStringExtra("briar.AUTHOR_NAME");
|
||||
|
||||
if(state == null) {
|
||||
read = false;
|
||||
setReadInDatabase(true);
|
||||
} else {
|
||||
read = state.getBoolean("org.briarproject.READ");
|
||||
read = state.getBoolean("briar.READ");
|
||||
}
|
||||
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
@@ -255,7 +255,7 @@ implements OnClickListener {
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle state) {
|
||||
super.onSaveInstanceState(state);
|
||||
state.putBoolean("org.briarproject.READ", read);
|
||||
state.putBoolean("briar.READ", read);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
@@ -269,9 +269,9 @@ implements OnClickListener {
|
||||
finish();
|
||||
} else if(view == replyButton) {
|
||||
Intent i = new Intent(this, WriteGroupPostActivity.class);
|
||||
i.putExtra("org.briarproject.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("org.briarproject.PARENT_ID", messageId.getBytes());
|
||||
i.putExtra("org.briarproject.TIMESTAMP", timestamp);
|
||||
i.putExtra("briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("briar.PARENT_ID", messageId.getBytes());
|
||||
i.putExtra("briar.TIMESTAMP", timestamp);
|
||||
startActivity(i);
|
||||
setResult(RESULT_REPLY);
|
||||
finish();
|
||||
|
||||
@@ -89,16 +89,16 @@ implements OnItemSelectedListener, OnClickListener {
|
||||
super.onCreate(state);
|
||||
|
||||
Intent i = getIntent();
|
||||
byte[] b = i.getByteArrayExtra("org.briarproject.GROUP_ID");
|
||||
byte[] b = i.getByteArrayExtra("briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
|
||||
b = i.getByteArrayExtra("org.briarproject.PARENT_ID");
|
||||
b = i.getByteArrayExtra("briar.PARENT_ID");
|
||||
if(b != null) parentId = new MessageId(b);
|
||||
timestamp = i.getLongExtra("org.briarproject.TIMESTAMP", -1);
|
||||
timestamp = i.getLongExtra("briar.TIMESTAMP", -1);
|
||||
|
||||
if(state != null) {
|
||||
b = state.getByteArray("org.briarproject.LOCAL_AUTHOR_ID");
|
||||
b = state.getByteArray("briar.LOCAL_AUTHOR_ID");
|
||||
if(b != null) localAuthorId = new AuthorId(b);
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ implements OnItemSelectedListener, OnClickListener {
|
||||
super.onSaveInstanceState(state);
|
||||
if(localAuthorId != null) {
|
||||
byte[] b = localAuthorId.getBytes();
|
||||
state.putByteArray("org.briarproject.LOCAL_AUTHOR_ID", b);
|
||||
state.putByteArray("briar.LOCAL_AUTHOR_ID", b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,17 +78,17 @@ implements InvitationListener {
|
||||
setView(new NetworkSetupView(this));
|
||||
} else {
|
||||
// Restore the activity's state
|
||||
byte[] b = state.getByteArray("org.briarproject.LOCAL_AUTHOR_ID");
|
||||
byte[] b = state.getByteArray("briar.LOCAL_AUTHOR_ID");
|
||||
if(b != null) localAuthorId = new AuthorId(b);
|
||||
taskHandle = state.getLong("org.briarproject.TASK_HANDLE", -1);
|
||||
taskHandle = state.getLong("briar.TASK_HANDLE", -1);
|
||||
task = referenceManager.getReference(taskHandle,
|
||||
InvitationTask.class);
|
||||
if(task == null) {
|
||||
// No background task - we must be in an initial or final state
|
||||
localInvitationCode = state.getInt("org.briarproject.LOCAL_CODE");
|
||||
remoteInvitationCode = state.getInt("org.briarproject.REMOTE_CODE");
|
||||
connectionFailed = state.getBoolean("org.briarproject.FAILED");
|
||||
contactName = state.getString("org.briarproject.CONTACT_NAME");
|
||||
localInvitationCode = state.getInt("briar.LOCAL_CODE");
|
||||
remoteInvitationCode = state.getInt("briar.REMOTE_CODE");
|
||||
connectionFailed = state.getBoolean("briar.FAILED");
|
||||
contactName = state.getString("briar.CONTACT_NAME");
|
||||
if(contactName != null) {
|
||||
localCompared = remoteCompared = true;
|
||||
localMatched = remoteMatched = true;
|
||||
@@ -184,13 +184,13 @@ implements InvitationListener {
|
||||
super.onSaveInstanceState(state);
|
||||
if(localAuthorId != null) {
|
||||
byte[] b = localAuthorId.getBytes();
|
||||
state.putByteArray("org.briarproject.LOCAL_AUTHOR_ID", b);
|
||||
state.putByteArray("briar.LOCAL_AUTHOR_ID", b);
|
||||
}
|
||||
state.putInt("org.briarproject.LOCAL_CODE", localInvitationCode);
|
||||
state.putInt("org.briarproject.REMOTE_CODE", remoteInvitationCode);
|
||||
state.putBoolean("org.briarproject.FAILED", connectionFailed);
|
||||
state.putString("org.briarproject.CONTACT_NAME", contactName);
|
||||
if(task != null) state.putLong("org.briarproject.TASK_HANDLE", taskHandle);
|
||||
state.putInt("briar.LOCAL_CODE", localInvitationCode);
|
||||
state.putInt("briar.REMOTE_CODE", remoteInvitationCode);
|
||||
state.putBoolean("briar.FAILED", connectionFailed);
|
||||
state.putString("briar.CONTACT_NAME", contactName);
|
||||
if(task != null) state.putLong("briar.TASK_HANDLE", taskHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
10
briar-api/src/org/briarproject/api/db/DbSchemaException.java
Normal file
10
briar-api/src/org/briarproject/api/db/DbSchemaException.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package org.briarproject.api.db;
|
||||
|
||||
/**
|
||||
* Thrown when the schema of the database differs from the schema expected by
|
||||
* the code.
|
||||
*/
|
||||
public class DbSchemaException extends DbException {
|
||||
|
||||
private static final long serialVersionUID = -4444069279533651710L;
|
||||
}
|
||||
@@ -13,8 +13,11 @@ public interface LifecycleManager {
|
||||
*/
|
||||
public void registerForShutdown(ExecutorService e);
|
||||
|
||||
/** Starts any registered {@link Service}s. */
|
||||
public void startServices();
|
||||
/**
|
||||
* Starts any registered {@link Service}s and returns true if all services
|
||||
* started successfully.
|
||||
*/
|
||||
public boolean startServices();
|
||||
|
||||
/**
|
||||
* Stops any registered {@link Service}s and shuts down any registered
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.db.DbClosedException;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.DbSchemaException;
|
||||
import org.briarproject.api.db.MessageHeader;
|
||||
import org.briarproject.api.messaging.Group;
|
||||
import org.briarproject.api.messaging.GroupId;
|
||||
@@ -56,6 +57,14 @@ import org.briarproject.api.transport.TemporarySecret;
|
||||
*/
|
||||
abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
private static final int SCHEMA_VERSION = 1;
|
||||
|
||||
private static final String CREATE_SETTINGS =
|
||||
"CREATE TABLE settings"
|
||||
+ " (key VARCHAR NOT NULL,"
|
||||
+ " value VARCHAR NOT NULL,"
|
||||
+ " PRIMARY KEY (key))";
|
||||
|
||||
// Locking: identity
|
||||
// Dependents: contact, message, retention, subscription, transport, window
|
||||
private static final String CREATE_LOCAL_AUTHORS =
|
||||
@@ -356,7 +365,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
// Open the database and create the tables if necessary
|
||||
Connection txn = startTransaction();
|
||||
try {
|
||||
if(!reopen) createTables(txn);
|
||||
if(reopen) {
|
||||
if(!checkSchemaVersion(txn))
|
||||
throw new DbSchemaException();
|
||||
} else {
|
||||
createTables(txn);
|
||||
setSchemaVersion(txn);
|
||||
}
|
||||
commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
abortTransaction(txn);
|
||||
@@ -364,10 +379,53 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkSchemaVersion(Connection txn) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
String value;
|
||||
try {
|
||||
String sql = "SELECT value FROM settings WHERE key = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setString(1, "schemaVersion");
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) throw new DbStateException();
|
||||
value = rs.getString(1);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
try {
|
||||
return Integer.valueOf(value) == SCHEMA_VERSION;
|
||||
} catch(NumberFormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToClose(ResultSet rs) {
|
||||
if(rs != null) try {
|
||||
rs.close();
|
||||
} catch(SQLException e) {
|
||||
if(LOG.isLoggable(WARNING))LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToClose(Statement s) {
|
||||
if(s != null) try {
|
||||
s.close();
|
||||
} catch(SQLException e) {
|
||||
if(LOG.isLoggable(WARNING))LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void createTables(Connection txn) throws DbException {
|
||||
Statement s = null;
|
||||
try {
|
||||
s = txn.createStatement();
|
||||
s.executeUpdate(insertTypeNames(CREATE_SETTINGS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_LOCAL_AUTHORS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUPS));
|
||||
@@ -405,19 +463,19 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
return s;
|
||||
}
|
||||
|
||||
private void tryToClose(Statement s) {
|
||||
if(s != null) try {
|
||||
s.close();
|
||||
private void setSchemaVersion(Connection txn) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "INSERT INTO settings (key, value) VALUES (?, ?)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setString(1, "schemaVersion");
|
||||
ps.setString(2, String.valueOf(SCHEMA_VERSION));
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch(SQLException e) {
|
||||
if(LOG.isLoggable(WARNING))LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToClose(ResultSet rs) {
|
||||
if(rs != null) try {
|
||||
rs.close();
|
||||
} catch(SQLException e) {
|
||||
if(LOG.isLoggable(WARNING))LOG.log(WARNING, e.toString(), e);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class LifecycleManagerImpl implements LifecycleManager {
|
||||
executors.add(e);
|
||||
}
|
||||
|
||||
public void startServices() {
|
||||
public boolean startServices() {
|
||||
try {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Starting");
|
||||
boolean reopened = db.open();
|
||||
@@ -64,12 +64,16 @@ class LifecycleManagerImpl implements LifecycleManager {
|
||||
if(started) LOG.info("Service started: " + name);
|
||||
else LOG.info("Service failed to start: " + name);
|
||||
}
|
||||
if(!started) return false;
|
||||
}
|
||||
startupLatch.countDown();
|
||||
return true;
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return false;
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public class TestLifecycleModule extends AbstractModule {
|
||||
|
||||
public void registerForShutdown(ExecutorService e) {}
|
||||
|
||||
public void startServices() {}
|
||||
public boolean startServices() { return true; }
|
||||
|
||||
public void stopServices() {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user