diff options
author | Kenny Root <kenny@the-b.org> | 2015-09-11 22:05:35 -0700 |
---|---|---|
committer | Kenny Root <kenny@the-b.org> | 2015-09-11 22:05:35 -0700 |
commit | 0bed9c91a9088da9eaf3284351aec86e4fc6bde9 (patch) | |
tree | 3b370a05e2f30511089d787256471219605c0aad /app | |
parent | 7bcd9f1b733b0587c7c09af9097a112809a6fa4d (diff) | |
parent | 705b3461cfa26f074464a32a2642741691340c1f (diff) | |
download | connectbot-0bed9c91a9088da9eaf3284351aec86e4fc6bde9.tar.gz connectbot-0bed9c91a9088da9eaf3284351aec86e4fc6bde9.tar.bz2 connectbot-0bed9c91a9088da9eaf3284351aec86e4fc6bde9.zip |
Merge pull request #195 from kruton/database-refactor
Database refactor, part 1
Diffstat (limited to 'app')
18 files changed, 479 insertions, 438 deletions
diff --git a/app/src/androidTest/java/org/connectbot/StartupTest.java b/app/src/androidTest/java/org/connectbot/StartupTest.java index a60d00e..14eabff 100644 --- a/app/src/androidTest/java/org/connectbot/StartupTest.java +++ b/app/src/androidTest/java/org/connectbot/StartupTest.java @@ -1,40 +1,34 @@ package org.connectbot; -import org.connectbot.bean.HostBean; import org.connectbot.util.HostDatabase; -import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import android.content.Context; import android.content.Intent; import android.content.res.Resources; -import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; -import android.support.annotation.NonNull; import android.support.annotation.StringRes; import android.support.test.InstrumentationRegistry; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.espresso.action.CloseKeyboardAction; import android.support.test.espresso.intent.Intents; -import android.support.test.espresso.matcher.BoundedMatcher; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; import static android.support.test.espresso.Espresso.onData; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; import static android.support.test.espresso.action.ViewActions.longClick; import static android.support.test.espresso.action.ViewActions.pressBack; import static android.support.test.espresso.action.ViewActions.pressImeActionButton; import static android.support.test.espresso.action.ViewActions.pressMenuKey; import static android.support.test.espresso.action.ViewActions.typeText; -import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.intent.Intents.intended; import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent; @@ -58,8 +52,8 @@ public class StartupTest { @Before public void makeDatabasePristine() { - HostDatabase db = new HostDatabase(InstrumentationRegistry.getTargetContext()); - db.resetDatabase(); + Context testContext = InstrumentationRegistry.getTargetContext(); + HostDatabase.resetInMemoryInstance(testContext); mActivityRule.launchActivity(new Intent()); } @@ -107,9 +101,9 @@ public class StartupTest { } @Test - public void localConnectionCanChangeToRed() throws Exception { - startNewLocalConnectionAndGoBack("Local1"); - changeColor("Local1", R.color.red, R.string.color_red); + public void localConnectionCanChangeToRed() { + startNewLocalConnectionAndGoBack("RedLocal"); + changeColor("RedLocal", R.color.red, R.string.color_red); } /** @@ -163,4 +157,40 @@ public class StartupTest { onView(withId(R.id.console_flip)).check(matches( hasDescendant(allOf(isDisplayed(), withId(R.id.terminal_view))))); } + + /* + * This is to work around a race condition where the software keyboard does not dismiss in time + * and you get a Security Exception. + * + * From: https://code.google.com/p/android-test-kit/issues/detail?id=79#c7 + */ + public static ViewAction closeSoftKeyboard() { + return new ViewAction() { + /** + * The delay time to allow the soft keyboard to dismiss. + */ + private static final long KEYBOARD_DISMISSAL_DELAY_MILLIS = 1000L; + + /** + * The real {@link CloseKeyboardAction} instance. + */ + private final ViewAction mCloseSoftKeyboard = new CloseKeyboardAction(); + + @Override + public Matcher<View> getConstraints() { + return mCloseSoftKeyboard.getConstraints(); + } + + @Override + public String getDescription() { + return mCloseSoftKeyboard.getDescription(); + } + + @Override + public void perform(final UiController uiController, final View view) { + mCloseSoftKeyboard.perform(uiController, view); + uiController.loopMainThreadForAtLeast(KEYBOARD_DISMISSAL_DELAY_MILLIS); + } + }; + } } diff --git a/app/src/main/java/org/connectbot/ColorsActivity.java b/app/src/main/java/org/connectbot/ColorsActivity.java index f149e79..1ec1fb0 100644 --- a/app/src/main/java/org/connectbot/ColorsActivity.java +++ b/app/src/main/java/org/connectbot/ColorsActivity.java @@ -18,9 +18,8 @@ package org.connectbot; import java.text.NumberFormat; -import java.util.Arrays; -import java.util.List; +import org.connectbot.data.ColorStorage; import org.connectbot.util.Colors; import org.connectbot.util.HostDatabase; import org.connectbot.util.UberColorPickerDialog; @@ -55,8 +54,8 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC private int mColorScheme; - private List<Integer> mColorList; - private HostDatabase mHostDb; + private int[] mColorList; + private ColorStorage mHostDb; private int mCurrentColor = 0; @@ -70,9 +69,9 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC mColorScheme = HostDatabase.DEFAULT_COLOR_SCHEME; - mHostDb = new HostDatabase(this); + mHostDb = HostDatabase.get(this); - mColorList = Arrays.asList(mHostDb.getColorsForScheme(mColorScheme)); + mColorList = mHostDb.getColorsForScheme(mColorScheme); mDefaultColors = mHostDb.getDefaultColorsForScheme(mColorScheme); mColorGrid = (GridView) findViewById(R.id.color_grid); @@ -96,7 +95,6 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC super.onDestroy(); if (mHostDb != null) { - mHostDb.close(); mHostDb = null; } } @@ -105,8 +103,9 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC protected void onResume() { super.onResume(); - if (mHostDb == null) - mHostDb = new HostDatabase(this); + if (mHostDb == null) { + mHostDb = HostDatabase.get(this); + } } private class ColorsAdapter extends BaseAdapter { @@ -131,18 +130,18 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC c = (ColorView) convertView; } - c.setColor(mColorList.get(position)); + c.setColor(mColorList[position]); c.setNumber(position + 1); return c; } public int getCount() { - return mColorList.size(); + return mColorList.length; } public Object getItem(int position) { - return mColorList.get(position); + return mColorList[position]; } public long getItemId(int position) { @@ -290,7 +289,7 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC private void editColor(int colorNumber) { mCurrentColor = colorNumber; - new UberColorPickerDialog(this, this, mColorList.get(colorNumber)).show(); + new UberColorPickerDialog(this, this, mColorList[colorNumber]).show(); } public void onItemClick(AdapterView<?> parent, View view, int position, long id) { @@ -301,7 +300,7 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC public void colorChanged(int value) { mHostDb.setGlobalColor(mCurrentColor, value); - mColorList.set(mCurrentColor, value); + mColorList[mCurrentColor] = value; mColorGrid.invalidateViews(); } @@ -320,8 +319,9 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC } } - if (needUpdate) + if (needUpdate) { mHostDb.setDefaultColorsForScheme(mColorScheme, mDefaultColors[0], mDefaultColors[1]); + } } @Override @@ -336,9 +336,9 @@ public class ColorsActivity extends Activity implements OnItemClickListener, OnC public boolean onMenuItemClick(MenuItem arg0) { // Reset each individual color to defaults. for (int i = 0; i < Colors.defaults.length; i++) { - if (!mColorList.get(i).equals(Colors.defaults[i])) { + if (mColorList[i] != Colors.defaults[i]) { mHostDb.setGlobalColor(i, Colors.defaults[i]); - mColorList.set(i, Colors.defaults[i]); + mColorList[i] = Colors.defaults[i]; } } mColorGrid.invalidateViews(); diff --git a/app/src/main/java/org/connectbot/ConsoleActivity.java b/app/src/main/java/org/connectbot/ConsoleActivity.java index 7ed9076..5258bef 100644 --- a/app/src/main/java/org/connectbot/ConsoleActivity.java +++ b/app/src/main/java/org/connectbot/ConsoleActivity.java @@ -167,8 +167,6 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne bound.setResizeAllowed(true); final String requestedNickname = (requested != null) ? requested.getFragment() : null; - int requestedIndex = 0; - TerminalBridge requestedBridge = bound.getConnectedBridge(requestedNickname); // If we didn't find the requested connection, try opening it @@ -183,9 +181,11 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne // create views for all bridges on this service adapter.notifyDataSetChanged(); - requestedIndex = bound.getBridges().indexOf(requestedBridge); + int requestedIndex = bound.getBridges().indexOf(requestedBridge); - setDisplayedTerminal(requestedIndex == -1 ? 0 : requestedIndex); + if (requestedIndex != -1) { + setDisplayedTerminal(requestedIndex); + } } public void onServiceDisconnected(ComponentName className) { diff --git a/app/src/main/java/org/connectbot/GeneratePubkeyActivity.java b/app/src/main/java/org/connectbot/GeneratePubkeyActivity.java index 7510394..17db685 100644 --- a/app/src/main/java/org/connectbot/GeneratePubkeyActivity.java +++ b/app/src/main/java/org/connectbot/GeneratePubkeyActivity.java @@ -298,9 +298,8 @@ public class GeneratePubkeyActivity extends Activity implements OnEntropyGathere pubkey.setStartup(unlockAtStartup.isChecked()); pubkey.setConfirmUse(confirmUse.isChecked()); - PubkeyDatabase pubkeydb = new PubkeyDatabase(GeneratePubkeyActivity.this); + PubkeyDatabase pubkeydb = PubkeyDatabase.get(GeneratePubkeyActivity.this); pubkeydb.savePubkey(pubkey); - pubkeydb.close(); } catch (Exception e) { Log.e(TAG, "Could not generate key pair"); diff --git a/app/src/main/java/org/connectbot/HostEditorActivity.java b/app/src/main/java/org/connectbot/HostEditorActivity.java index 3976858..f9dee45 100644 --- a/app/src/main/java/org/connectbot/HostEditorActivity.java +++ b/app/src/main/java/org/connectbot/HostEditorActivity.java @@ -66,9 +66,9 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr protected final void cacheValues() { // fill a cursor and cache the values locally - // this makes sure we dont have any floating cursor to dispose later + // this makes sure we don't have any floating cursor to dispose later - SQLiteDatabase db = hostdb.getReadableDatabase(); + SQLiteDatabase db = hostdb.getWritableDatabase(); Cursor cursor = db.query(table, null, "_id = ?", new String[] { String.valueOf(id) }, null, null, null); @@ -81,23 +81,6 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr } } cursor.close(); - db.close(); - -// db = pubkeydb.getReadableDatabase(); -// cursor = db.query(PubkeyDatabase.TABLE_PUBKEYS, -// new String[] { "_id", PubkeyDatabase.FIELD_PUBKEY_NICKNAME }, -// null, null, null, null, null); -// -// if (cursor.moveToFirst()) { -// do { -// String pubkeyid = String.valueOf(cursor.getLong(0)); -// String value = cursor.getString(1); -// pubkeys.put(pubkeyid, value); -// } while (cursor.moveToNext()); -// } -// -// cursor.close(); -// db.close(); } public boolean contains(String key) { @@ -115,10 +98,14 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr } public boolean commit() { - //Log.d(this.getClass().toString(), "commit() changes back to database"); SQLiteDatabase db = hostdb.getWritableDatabase(); - db.update(table, update, "_id = ?", new String[] { String.valueOf(id) }); - db.close(); + db.beginTransaction(); + try { + db.update(table, update, "_id = ?", new String[] {String.valueOf(id)}); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } // make sure we refresh the parent cached values cacheValues(); @@ -244,8 +231,8 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr // TODO: we could pass through a specific ContentProvider uri here //this.getPreferenceManager().setSharedPreferencesName(uri); - this.hostdb = new HostDatabase(this); - this.pubkeydb = new PubkeyDatabase(this); + this.hostdb = HostDatabase.get(this); + this.pubkeydb = PubkeyDatabase.get(this); host = hostdb.findHostById(hostId); @@ -306,11 +293,8 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - if (this.hostdb == null) - this.hostdb = new HostDatabase(this); - - if (this.pubkeydb == null) - this.pubkeydb = new PubkeyDatabase(this); + hostdb = HostDatabase.get(this); + pubkeydb = PubkeyDatabase.get(this); } @Override @@ -319,15 +303,8 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr unbindService(connection); - if (this.hostdb != null) { - this.hostdb.close(); - this.hostdb = null; - } - - if (this.pubkeydb != null) { - this.pubkeydb.close(); - this.pubkeydb = null; - } + hostdb = null; + pubkeydb = null; } private void updateSummaries() { diff --git a/app/src/main/java/org/connectbot/HostListActivity.java b/app/src/main/java/org/connectbot/HostListActivity.java index e6f185e..927e483 100644 --- a/app/src/main/java/org/connectbot/HostListActivity.java +++ b/app/src/main/java/org/connectbot/HostListActivity.java @@ -20,6 +20,7 @@ package org.connectbot; import java.util.List; import org.connectbot.bean.HostBean; +import org.connectbot.data.HostStorage; import org.connectbot.service.OnHostStatusChangedListener; import org.connectbot.service.TerminalBridge; import org.connectbot.service.TerminalManager; @@ -71,7 +72,7 @@ public class HostListActivity extends ListActivity implements OnHostStatusChange protected TerminalManager bound = null; - protected HostDatabase hostdb; + private HostStorage hostdb; private List<HostBean> hosts; protected LayoutInflater inflater = null; @@ -125,8 +126,7 @@ public class HostListActivity extends ListActivity implements OnHostStatusChange // start the terminal manager service this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - if (this.hostdb == null) - this.hostdb = new HostDatabase(this); + hostdb = HostDatabase.get(this); } @Override @@ -134,10 +134,7 @@ public class HostListActivity extends ListActivity implements OnHostStatusChange super.onStop(); this.unbindService(connection); - if (this.hostdb != null) { - this.hostdb.close(); - this.hostdb = null; - } + hostdb = null; closeOnDisconnectAll = true; } @@ -205,7 +202,7 @@ public class HostListActivity extends ListActivity implements OnHostStatusChange || Intent.ACTION_PICK.equals(getIntent().getAction()); // connect with hosts database and populate list - this.hostdb = new HostDatabase(this); + this.hostdb = HostDatabase.get(this); ListView list = this.getListView(); this.sortedByColor = prefs.getBoolean(PreferenceConstants.SORT_BY_COLOR, false); @@ -485,7 +482,7 @@ public class HostListActivity extends ListActivity implements OnHostStatusChange } if (hostdb == null) - hostdb = new HostDatabase(this); + hostdb = HostDatabase.get(this); hosts = hostdb.getHosts(sortedByColor); diff --git a/app/src/main/java/org/connectbot/PortForwardListActivity.java b/app/src/main/java/org/connectbot/PortForwardListActivity.java index 8ffe6eb..868c611 100644 --- a/app/src/main/java/org/connectbot/PortForwardListActivity.java +++ b/app/src/main/java/org/connectbot/PortForwardListActivity.java @@ -84,8 +84,7 @@ public class PortForwardListActivity extends ListActivity { this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - if (this.hostdb == null) - this.hostdb = new HostDatabase(this); + hostdb = HostDatabase.get(this); } @Override @@ -94,10 +93,7 @@ public class PortForwardListActivity extends ListActivity { this.unbindService(connection); - if (this.hostdb != null) { - this.hostdb.close(); - this.hostdb = null; - } + hostdb = null; } @Override @@ -109,7 +105,7 @@ public class PortForwardListActivity extends ListActivity { setContentView(R.layout.act_portforwardlist); // connect with hosts database and populate list - this.hostdb = new HostDatabase(this); + this.hostdb = HostDatabase.get(this); host = hostdb.findHostById(hostId); { @@ -215,8 +211,9 @@ public class PortForwardListActivity extends ListActivity { hostBridge.enablePortForward(pfb); } - if (host != null && !hostdb.savePortForward(pfb)) + if (host != null && !hostdb.savePortForward(pfb)) { throw new SQLException("Could not save port forward"); + } updateHandler.sendEmptyMessage(-1); } catch (Exception e) { @@ -312,8 +309,9 @@ public class PortForwardListActivity extends ListActivity { }, LISTENER_CYCLE_TIME); - if (!hostdb.savePortForward(pfb)) + if (!hostdb.savePortForward(pfb)) { throw new SQLException("Could not save port forward"); + } updateHandler.sendEmptyMessage(-1); } catch (Exception e) { diff --git a/app/src/main/java/org/connectbot/PubkeyListActivity.java b/app/src/main/java/org/connectbot/PubkeyListActivity.java index 084a30b..d8a8e70 100644 --- a/app/src/main/java/org/connectbot/PubkeyListActivity.java +++ b/app/src/main/java/org/connectbot/PubkeyListActivity.java @@ -88,7 +88,6 @@ public class PubkeyListActivity extends ListActivity implements EventListener { private static final String ANDEXPLORER_TITLE = "explorer_title"; private static final String MIME_TYPE_ANDEXPLORER_FILE = "vnd.android.cursor.dir/lysesoft.andexplorer.file"; - protected PubkeyDatabase pubkeydb; private List<PubkeyBean> pubkeys; protected ClipboardManager clipboard; @@ -120,8 +119,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener { bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - if (pubkeydb == null) - pubkeydb = new PubkeyDatabase(this); + updateList(); } @Override @@ -129,11 +127,6 @@ public class PubkeyListActivity extends ListActivity implements EventListener { super.onStop(); unbindService(connection); - - if (pubkeydb != null) { - pubkeydb.close(); - pubkeydb = null; - } } @Override @@ -141,11 +134,6 @@ public class PubkeyListActivity extends ListActivity implements EventListener { super.onCreate(icicle); setContentView(R.layout.act_pubkeylist); - // connect with hosts database and populate list - pubkeydb = new PubkeyDatabase(this); - - updateList(); - registerForContextMenu(getListView()); getListView().setOnItemClickListener(new OnItemClickListener() { @@ -327,7 +315,8 @@ public class PubkeyListActivity extends ListActivity implements EventListener { public boolean onMenuItemClick(MenuItem item) { // toggle onstart status pubkey.setStartup(!pubkey.isStartup()); - pubkeydb.savePubkey(pubkey); + PubkeyDatabase pubkeyDb = PubkeyDatabase.get(PubkeyListActivity.this); + pubkeyDb.savePubkey(pubkey); updateList(); return true; } @@ -401,7 +390,8 @@ public class PubkeyListActivity extends ListActivity implements EventListener { .setPositiveButton(android.R.string.ok, null) .create().show(); else { - pubkeydb.savePubkey(pubkey); + PubkeyDatabase pubkeyDb = PubkeyDatabase.get(PubkeyListActivity.this); + pubkeyDb.savePubkey(pubkey); updateList(); } } catch (Exception e) { @@ -426,7 +416,8 @@ public class PubkeyListActivity extends ListActivity implements EventListener { public boolean onMenuItemClick(MenuItem item) { // toggle confirm use pubkey.setConfirmUse(!pubkey.isConfirmUse()); - pubkeydb.savePubkey(pubkey); + PubkeyDatabase pubkeyDb = PubkeyDatabase.get(PubkeyListActivity.this); + pubkeyDb.savePubkey(pubkey); updateList(); return true; } @@ -442,11 +433,13 @@ public class PubkeyListActivity extends ListActivity implements EventListener { public void onClick(DialogInterface dialog, int which) { // dont forget to remove from in-memory - if (loaded) + if (loaded) { bound.removeKey(pubkey.getNickname()); + } // delete from backend database and update gui - pubkeydb.deletePubkey(pubkey); + PubkeyDatabase pubkeyDb = PubkeyDatabase.get(PubkeyListActivity.this); + pubkeyDb.deletePubkey(pubkey); updateList(); } }) @@ -459,9 +452,8 @@ public class PubkeyListActivity extends ListActivity implements EventListener { } protected void updateList() { - if (pubkeydb == null) return; - - pubkeys = pubkeydb.allPubkeys(); + PubkeyDatabase pubkeyDb = PubkeyDatabase.get(PubkeyListActivity.this); + pubkeys = pubkeyDb.allPubkeys(); PubkeyAdapter adapter = new PubkeyAdapter(this, pubkeys); this.setListAdapter(adapter); @@ -492,7 +484,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener { } /** - * @param name + * @param file */ private void readKeyFromFile(File file) { PubkeyBean pubkey = new PubkeyBean(); @@ -541,9 +533,8 @@ public class PubkeyListActivity extends ListActivity implements EventListener { } // write new value into database - if (pubkeydb == null) - pubkeydb = new PubkeyDatabase(this); - pubkeydb.savePubkey(pubkey); + PubkeyDatabase pubkeyDb = PubkeyDatabase.get(this); + pubkeyDb.savePubkey(pubkey); updateList(); } catch (Exception e) { diff --git a/app/src/main/java/org/connectbot/data/ColorStorage.java b/app/src/main/java/org/connectbot/data/ColorStorage.java new file mode 100644 index 0000000..eb3d2d2 --- /dev/null +++ b/app/src/main/java/org/connectbot/data/ColorStorage.java @@ -0,0 +1,31 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2015 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot.data; + +/** + * Created by kroot on 9/11/15. + */ +public interface ColorStorage { + public int[] getColorsForScheme(int colorScheme); + + public void setGlobalColor(int mCurrentColor, int value); + + public int[] getDefaultColorsForScheme(int colorScheme); + + public void setDefaultColorsForScheme(int mColorScheme, int mDefaultColor, int mDefaultColor1); +} diff --git a/app/src/main/java/org/connectbot/data/HostStorage.java b/app/src/main/java/org/connectbot/data/HostStorage.java new file mode 100644 index 0000000..dc3e5d7 --- /dev/null +++ b/app/src/main/java/org/connectbot/data/HostStorage.java @@ -0,0 +1,89 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2015 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot.data; + +import java.util.List; +import java.util.Map; + +import org.connectbot.bean.HostBean; +import org.connectbot.bean.PortForwardBean; + +import com.trilead.ssh2.KnownHosts; + +import android.support.annotation.VisibleForTesting; + +/** + * Interface that defines the operation used to interact with the storage layer. + */ +public interface HostStorage { + /** + * Resets the database during testing. + */ + @VisibleForTesting + void resetDatabase(); + + /** + * Finds the host that is represented by the given selection. + * @param selection all fields to be considered + * @return the matching host + */ + HostBean findHost(Map<String, String> selection); + + /** + * Deletes the given {@code host} from the storage layer. + */ + void deleteHost(HostBean host); + + /** + * Saves the given {@code host} to the storage layer. + */ + HostBean saveHost(HostBean host); + + /** + * Returns a list of all the hosts as a list of {@link HostBean}. + * @param sortedByColor if hosts should be grouped by color. + */ + List<HostBean> getHosts(boolean sortedByColor); + + /** + * Updates the last connected time for {@code host}. + */ + void touchHost(HostBean host); + + /** + * Finds a {@link HostBean} based on the given {@code hostId}. + */ + HostBean findHostById(long hostId); + + /** + * Returns the list of known hosts. + * + * @see #saveKnownHost(String, int, String, byte[]) + */ + KnownHosts getKnownHosts(); + + /** + * Adds a known host to the database for later retrieval using {@link #getKnownHosts()}. + */ + void saveKnownHost(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey); + + /** + * Return all port forwards for the given {@code host}. + */ + List<PortForwardBean> getPortForwardsForHost(HostBean host); +} diff --git a/app/src/main/java/org/connectbot/service/BackupAgent.java b/app/src/main/java/org/connectbot/service/BackupAgent.java index 312ae3b..6e57f27 100644 --- a/app/src/main/java/org/connectbot/service/BackupAgent.java +++ b/app/src/main/java/org/connectbot/service/BackupAgent.java @@ -17,19 +17,14 @@ package org.connectbot.service; -import java.io.IOException; - import org.connectbot.util.HostDatabase; import org.connectbot.util.PreferenceConstants; import org.connectbot.util.PubkeyDatabase; import android.annotation.TargetApi; import android.app.backup.BackupAgentHelper; -import android.app.backup.BackupDataInput; -import android.app.backup.BackupDataOutput; import android.app.backup.FileBackupHelper; import android.app.backup.SharedPreferencesBackupHelper; -import android.os.ParcelFileDescriptor; import android.util.Log; /** @@ -53,24 +48,4 @@ public class BackupAgent extends BackupAgentHelper { addHelper(PubkeyDatabase.DB_NAME, pubkeys); } - - @Override - public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException { - synchronized (HostDatabase.dbLock) { - super.onBackup(oldState, data, newState); - } - } - - @Override - public void onRestore(BackupDataInput data, int appVersionCode, - ParcelFileDescriptor newState) throws IOException { - Log.d("ConnectBot.BackupAgent", "onRestore called"); - - synchronized (HostDatabase.dbLock) { - Log.d("ConnectBot.BackupAgent", "onRestore in-lock"); - - super.onRestore(data, appVersionCode, newState); - } - } } diff --git a/app/src/main/java/org/connectbot/service/TerminalBridge.java b/app/src/main/java/org/connectbot/service/TerminalBridge.java index 6d47f96..b9e29e8 100644 --- a/app/src/main/java/org/connectbot/service/TerminalBridge.java +++ b/app/src/main/java/org/connectbot/service/TerminalBridge.java @@ -65,7 +65,7 @@ public class TerminalBridge implements VDUDisplay { private final static int FONT_SIZE_STEP = 2; private final float displayDensity; - public Integer[] color; + public int[] color; public int defaultFg = HostDatabase.DEFAULT_FG_COLOR; public int defaultBg = HostDatabase.DEFAULT_BG_COLOR; @@ -533,7 +533,7 @@ public class TerminalBridge implements VDUDisplay { } host.setFontSize((int) sizeDp); - manager.hostdb.updateFontSize(host); + manager.hostdb.saveHost(host); forcedSize = false; } @@ -950,11 +950,11 @@ public class TerminalBridge implements VDUDisplay { } public final void resetColors() { - int[] defaults = manager.hostdb.getDefaultColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); + int[] defaults = manager.colordb.getDefaultColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); defaultFg = defaults[0]; defaultBg = defaults[1]; - color = manager.hostdb.getColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); + color = manager.colordb.getColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); } private static Pattern urlPattern = null; diff --git a/app/src/main/java/org/connectbot/service/TerminalManager.java b/app/src/main/java/org/connectbot/service/TerminalManager.java index 5416ddb..88c0811 100644 --- a/app/src/main/java/org/connectbot/service/TerminalManager.java +++ b/app/src/main/java/org/connectbot/service/TerminalManager.java @@ -35,6 +35,8 @@ import java.util.TimerTask; import org.connectbot.R; import org.connectbot.bean.HostBean; import org.connectbot.bean.PubkeyBean; +import org.connectbot.data.ColorStorage; +import org.connectbot.data.HostStorage; import org.connectbot.transport.TransportFactory; import org.connectbot.util.HostDatabase; import org.connectbot.util.PreferenceConstants; @@ -87,7 +89,8 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen public Resources res; - public HostDatabase hostdb; + public HostStorage hostdb; + public ColorStorage colordb; public PubkeyDatabase pubkeydb; protected SharedPreferences prefs; @@ -129,8 +132,9 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen pubkeyTimer = new Timer("pubkeyTimer", true); - hostdb = new HostDatabase(this); - pubkeydb = new PubkeyDatabase(this); + hostdb = HostDatabase.get(this); + colordb = HostDatabase.get(this); + pubkeydb = PubkeyDatabase.get(this); // load all marked pubkeys into memory updateSavingKeys(); @@ -173,15 +177,8 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen disconnectAll(true, false); - if (hostdb != null) { - hostdb.close(); - hostdb = null; - } - - if (pubkeydb != null) { - pubkeydb.close(); - pubkeydb = null; - } + hostdb = null; + pubkeydb = null; synchronized (this) { if (idleTimer != null) diff --git a/app/src/main/java/org/connectbot/transport/SSH.java b/app/src/main/java/org/connectbot/transport/SSH.java index 4bad2f1..0867256 100644 --- a/app/src/main/java/org/connectbot/transport/SSH.java +++ b/app/src/main/java/org/connectbot/transport/SSH.java @@ -292,9 +292,8 @@ public class SSH extends AbsTransport implements ConnectionMonitor, InteractiveC } /** - * Attempt connection with database row pointed to by cursor. - * @param cursor - * @return true for successful authentication + * Attempt connection with given {@code pubkey}. + * @return {@code true} for successful authentication * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException * @throws IOException diff --git a/app/src/main/java/org/connectbot/transport/TransportFactory.java b/app/src/main/java/org/connectbot/transport/TransportFactory.java index 3f387c6..680cb33 100644 --- a/app/src/main/java/org/connectbot/transport/TransportFactory.java +++ b/app/src/main/java/org/connectbot/transport/TransportFactory.java @@ -21,7 +21,7 @@ import java.util.HashMap; import java.util.Map; import org.connectbot.bean.HostBean; -import org.connectbot.util.HostDatabase; +import org.connectbot.data.HostStorage; import android.content.Context; import android.net.Uri; @@ -112,10 +112,9 @@ public class TransportFactory { /** * @param hostdb Handle to HostDatabase * @param uri URI to target server - * @param host HostBean in which to put the results * @return true when host was found */ - public static HostBean findHost(HostDatabase hostdb, Uri uri) { + public static HostBean findHost(HostStorage hostdb, Uri uri) { AbsTransport transport = getTransport(uri.getScheme()); Map<String, String> selection = new HashMap<String, String>(); diff --git a/app/src/main/java/org/connectbot/util/Colors.java b/app/src/main/java/org/connectbot/util/Colors.java index ff88d68..e0637fb 100644 --- a/app/src/main/java/org/connectbot/util/Colors.java +++ b/app/src/main/java/org/connectbot/util/Colors.java @@ -22,7 +22,7 @@ package org.connectbot.util; * */ public class Colors { - public final static Integer[] defaults = new Integer[] { + public final static int[] defaults = new int[] { 0xff000000, // black 0xffcc0000, // red 0xff00cc00, // green diff --git a/app/src/main/java/org/connectbot/util/HostDatabase.java b/app/src/main/java/org/connectbot/util/HostDatabase.java index f721aeb..7c59807 100644 --- a/app/src/main/java/org/connectbot/util/HostDatabase.java +++ b/app/src/main/java/org/connectbot/util/HostDatabase.java @@ -26,6 +26,8 @@ import java.util.Map.Entry; import org.connectbot.bean.HostBean; import org.connectbot.bean.PortForwardBean; +import org.connectbot.data.ColorStorage; +import org.connectbot.data.HostStorage; import android.content.ContentValues; import android.content.Context; @@ -43,7 +45,7 @@ import com.trilead.ssh2.KnownHosts; * * @author jsharkey */ -public class HostDatabase extends RobustSQLiteOpenHelper { +public class HostDatabase extends RobustSQLiteOpenHelper implements HostStorage, ColorStorage { public final static String TAG = "CB.HostDatabase"; @@ -139,17 +141,35 @@ public class HostDatabase extends RobustSQLiteOpenHelper { addIndexName(TABLE_COLOR_DEFAULTS + FIELD_COLOR_SCHEME + "index"); } - public static final Object[] dbLock = new Object[0]; - /** Used during upgrades from DB version 23 to 24. */ private final float displayDensity; - public HostDatabase(Context context) { - super(context, DB_NAME, null, DB_VERSION); + private static final Object sInstanceLock = new Object(); - this.displayDensity = context.getResources().getDisplayMetrics().density; + private static HostDatabase sInstance; + + private final SQLiteDatabase mDb; + + public static HostDatabase get(Context context) { + synchronized (sInstanceLock) { + if (sInstance != null) { + return sInstance; + } + + sInstance = new HostDatabase(context.getApplicationContext()); + return sInstance; + } + } + + private HostDatabase(Context context) { + this(context, DB_NAME); + } + + private HostDatabase(Context context, String dbName) { + super(context, dbName, null, DB_VERSION); - getWritableDatabase().close(); + this.displayDensity = context.getResources().getDisplayMetrics().density; + mDb = getWritableDatabase(); } @Override @@ -210,13 +230,25 @@ public class HostDatabase extends RobustSQLiteOpenHelper { @VisibleForTesting public void resetDatabase() { - SQLiteDatabase db = getWritableDatabase(); - db.execSQL("DROP TABLE IF EXISTS " + TABLE_HOSTS); - db.execSQL("DROP TABLE IF EXISTS " + TABLE_PORTFORWARDS); - db.execSQL("DROP TABLE IF EXISTS " + TABLE_COLORS); - db.execSQL("DROP TABLE IF EXISTS " + TABLE_COLOR_DEFAULTS); - createTables(db); - db.close(); + try { + mDb.beginTransaction(); + + mDb.execSQL("DROP TABLE IF EXISTS " + TABLE_HOSTS); + mDb.execSQL("DROP TABLE IF EXISTS " + TABLE_PORTFORWARDS); + mDb.execSQL("DROP TABLE IF EXISTS " + TABLE_COLORS); + mDb.execSQL("DROP TABLE IF EXISTS " + TABLE_COLOR_DEFAULTS); + + createTables(mDb); + + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); + } + } + + @VisibleForTesting + public static void resetInMemoryInstance(Context context) { + get(context).resetDatabase(); } @Override @@ -301,23 +333,31 @@ public class HostDatabase extends RobustSQLiteOpenHelper { ContentValues values = new ContentValues(); values.put(FIELD_HOST_LASTCONNECT, now); - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - - db.update(TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) }); + mDb.beginTransaction(); + try { + mDb.update(TABLE_HOSTS, values, "_id = ?", new String[] {String.valueOf(host.getId())}); + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } } /** - * Create a new host using the given parameters. + * Create a new or update an existing {@code host}. */ public HostBean saveHost(HostBean host) { - long id; - - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); + long id = host.getId(); - id = db.insert(TABLE_HOSTS, null, host.getValues()); + mDb.beginTransaction(); + try { + if (id == -1) { + id = mDb.insert(TABLE_HOSTS, null, host.getValues()); + } else { + mDb.update(TABLE_HOSTS, host.getValues(), "_id = ?", new String[] {String.valueOf(id)}); + } + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } host.setId(id); @@ -326,37 +366,19 @@ public class HostDatabase extends RobustSQLiteOpenHelper { } /** - * Update a field in a host record. - */ - public boolean updateFontSize(HostBean host) { - long id = host.getId(); - if (id < 0) - return false; - - ContentValues updates = new ContentValues(); - updates.put(FIELD_HOST_FONTSIZE, host.getFontSize()); - - synchronized (dbLock) { - SQLiteDatabase db = getWritableDatabase(); - - db.update(TABLE_HOSTS, updates, "_id = ?", - new String[] { String.valueOf(id) }); - - } - - return true; - } - - /** * Delete a specific host by its <code>_id</code> value. */ public void deleteHost(HostBean host) { - if (host.getId() < 0) + if (host.getId() < 0) { return; + } - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - db.delete(TABLE_HOSTS, "_id = ?", new String[] { String.valueOf(host.getId()) }); + mDb.beginTransaction(); + try { + mDb.delete(TABLE_HOSTS, "_id = ?", new String[] {String.valueOf(host.getId())}); + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } } @@ -368,15 +390,11 @@ public class HostDatabase extends RobustSQLiteOpenHelper { String sortField = sortColors ? FIELD_HOST_COLOR : FIELD_HOST_NICKNAME; List<HostBean> hosts; - synchronized (dbLock) { - SQLiteDatabase db = this.getReadableDatabase(); - - Cursor c = db.query(TABLE_HOSTS, null, null, null, null, null, sortField + " ASC"); + Cursor c = mDb.query(TABLE_HOSTS, null, null, null, null, null, sortField + " ASC"); - hosts = createHostBeans(c); + hosts = createHostBeans(c); - c.close(); - } + c.close(); return hosts; } @@ -480,20 +498,13 @@ public class HostDatabase extends RobustSQLiteOpenHelper { String selectionValues[] = new String[selectionValuesList.size()]; selectionValuesList.toArray(selectionValues); - selectionValuesList = null; - - HostBean host; - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); + Cursor c = mDb.query(TABLE_HOSTS, null, + selectionBuilder.toString(), + selectionValues, + null, null, null); - Cursor c = db.query(TABLE_HOSTS, null, - selectionBuilder.toString(), - selectionValues, - null, null, null); - - host = getFirstHostBean(c); - } + HostBean host = getFirstHostBean(c); return host; } @@ -503,19 +514,11 @@ public class HostDatabase extends RobustSQLiteOpenHelper { * @return host matching the hostId or {@code null} if none match */ public HostBean findHostById(long hostId) { - HostBean host; + Cursor c = mDb.query(TABLE_HOSTS, null, + "_id = ?", new String[] {String.valueOf(hostId)}, + null, null, null); - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - - Cursor c = db.query(TABLE_HOSTS, null, - "_id = ?", new String[] { String.valueOf(hostId) }, - null, null, null); - - host = getFirstHostBean(c); - } - - return host; + return getFirstHostBean(c); } /** @@ -530,14 +533,10 @@ public class HostDatabase extends RobustSQLiteOpenHelper { values.put(FIELD_HOST_HOSTKEYALGO, hostkeyalgo); values.put(FIELD_HOST_HOSTKEY, hostkey); - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - - db.update(TABLE_HOSTS, values, - FIELD_HOST_HOSTNAME + " = ? AND " + FIELD_HOST_PORT + " = ?", - new String[] { hostname, String.valueOf(port) }); - Log.d(TAG, String.format("Finished saving hostkey information for '%s'", hostname)); - } + mDb.update(TABLE_HOSTS, values, + FIELD_HOST_HOSTNAME + " = ? AND " + FIELD_HOST_PORT + " = ?", + new String[] {hostname, String.valueOf(port)}); + Log.d(TAG, String.format("Finished saving hostkey information for '%s'", hostname)); } /** @@ -547,36 +546,33 @@ public class HostDatabase extends RobustSQLiteOpenHelper { public KnownHosts getKnownHosts() { KnownHosts known = new KnownHosts(); - synchronized (dbLock) { - SQLiteDatabase db = this.getReadableDatabase(); - Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_HOSTNAME, - FIELD_HOST_PORT, FIELD_HOST_HOSTKEYALGO, FIELD_HOST_HOSTKEY }, - null, null, null, null, null); + Cursor c = mDb.query(TABLE_HOSTS, new String[] {FIELD_HOST_HOSTNAME, + FIELD_HOST_PORT, FIELD_HOST_HOSTKEYALGO, FIELD_HOST_HOSTKEY}, + null, null, null, null, null); - if (c != null) { - int COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME), + if (c != null) { + int COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME), COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT), COL_HOSTKEYALGO = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEYALGO), COL_HOSTKEY = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEY); - while (c.moveToNext()) { - String hostname = c.getString(COL_HOSTNAME), + while (c.moveToNext()) { + String hostname = c.getString(COL_HOSTNAME), hostkeyalgo = c.getString(COL_HOSTKEYALGO); - int port = c.getInt(COL_PORT); - byte[] hostkey = c.getBlob(COL_HOSTKEY); + int port = c.getInt(COL_PORT); + byte[] hostkey = c.getBlob(COL_HOSTKEY); - if (hostkeyalgo == null || hostkeyalgo.length() == 0) continue; - if (hostkey == null || hostkey.length == 0) continue; + if (hostkeyalgo == null || hostkeyalgo.length() == 0) continue; + if (hostkey == null || hostkey.length == 0) continue; - try { - known.addHostkey(new String[] { String.format("%s:%d", hostname, port) }, hostkeyalgo, hostkey); - } catch (Exception e) { - Log.e(TAG, "Problem while adding a known host from database", e); - } + try { + known.addHostkey(new String[] {String.format("%s:%d", hostname, port)}, hostkeyalgo, hostkey); + } catch (Exception e) { + Log.e(TAG, "Problem while adding a known host from database", e); } - - c.close(); } + + c.close(); } return known; @@ -592,10 +588,12 @@ public class HostDatabase extends RobustSQLiteOpenHelper { ContentValues values = new ContentValues(); values.put(FIELD_HOST_PUBKEYID, PUBKEYID_ANY); - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - - db.update(TABLE_HOSTS, values, FIELD_HOST_PUBKEYID + " = ?", new String[] { String.valueOf(pubkeyId) }); + mDb.beginTransaction(); + try { + mDb.update(TABLE_HOSTS, values, FIELD_HOST_PUBKEYID + " = ?", new String[] {String.valueOf(pubkeyId)}); + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } Log.d(TAG, String.format("Set all hosts using pubkey id %d to -1", pubkeyId)); @@ -616,17 +614,14 @@ public class HostDatabase extends RobustSQLiteOpenHelper { return portForwards; } - synchronized (dbLock) { - SQLiteDatabase db = this.getReadableDatabase(); - - Cursor c = db.query(TABLE_PORTFORWARDS, new String[] { - "_id", FIELD_PORTFORWARD_NICKNAME, FIELD_PORTFORWARD_TYPE, FIELD_PORTFORWARD_SOURCEPORT, - FIELD_PORTFORWARD_DESTADDR, FIELD_PORTFORWARD_DESTPORT }, - FIELD_PORTFORWARD_HOSTID + " = ?", new String[] { String.valueOf(host.getId()) }, - null, null, null); + Cursor c = mDb.query(TABLE_PORTFORWARDS, new String[] { + "_id", FIELD_PORTFORWARD_NICKNAME, FIELD_PORTFORWARD_TYPE, FIELD_PORTFORWARD_SOURCEPORT, + FIELD_PORTFORWARD_DESTADDR, FIELD_PORTFORWARD_DESTPORT}, + FIELD_PORTFORWARD_HOSTID + " = ?", new String[] {String.valueOf(host.getId())}, + null, null, null); - while (c.moveToNext()) { - PortForwardBean pfb = new PortForwardBean( + while (c.moveToNext()) { + PortForwardBean pfb = new PortForwardBean( c.getInt(0), host.getId(), c.getString(1), @@ -634,12 +629,11 @@ public class HostDatabase extends RobustSQLiteOpenHelper { c.getInt(3), c.getString(4), c.getInt(5)); - portForwards.add(pfb); - } - - c.close(); + portForwards.add(pfb); } + c.close(); + return portForwards; } @@ -649,22 +643,25 @@ public class HostDatabase extends RobustSQLiteOpenHelper { * @return true on success */ public boolean savePortForward(PortForwardBean pfb) { - boolean success = false; - - synchronized (dbLock) { - SQLiteDatabase db = getWritableDatabase(); - + mDb.beginTransaction(); + try { if (pfb.getId() < 0) { - long id = db.insert(TABLE_PORTFORWARDS, null, pfb.getValues()); - pfb.setId(id); - success = true; + long addedId = mDb.insert(TABLE_PORTFORWARDS, null, pfb.getValues()); + if (addedId == -1) { + return false; + } + pfb.setId(addedId); } else { - if (db.update(TABLE_PORTFORWARDS, pfb.getValues(), "_id = ?", new String[] { String.valueOf(pfb.getId()) }) > 0) - success = true; + if (mDb.update(TABLE_PORTFORWARDS, pfb.getValues(), "_id = ?", new String[] {String.valueOf(pfb.getId())}) <= 0) { + return false; + } } - } - return success; + mDb.setTransactionSuccessful(); + return true; + } finally { + mDb.endTransaction(); + } } /** @@ -672,34 +669,34 @@ public class HostDatabase extends RobustSQLiteOpenHelper { * @param pfb {@link PortForwardBean} to delete */ public void deletePortForward(PortForwardBean pfb) { - if (pfb.getId() < 0) + if (pfb.getId() < 0) { return; + } - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - db.delete(TABLE_PORTFORWARDS, "_id = ?", new String[] { String.valueOf(pfb.getId()) }); + mDb.beginTransaction(); + try { + mDb.delete(TABLE_PORTFORWARDS, "_id = ?", new String[] {String.valueOf(pfb.getId())}); + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } } - public Integer[] getColorsForScheme(int scheme) { - Integer[] colors = Colors.defaults.clone(); - - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); + public int[] getColorsForScheme(int scheme) { + int[] colors = Colors.defaults.clone(); - Cursor c = db.query(TABLE_COLORS, new String[] { - FIELD_COLOR_NUMBER, FIELD_COLOR_VALUE }, - FIELD_COLOR_SCHEME + " = ?", - new String[] { String.valueOf(scheme) }, - null, null, null); + Cursor c = mDb.query(TABLE_COLORS, new String[] { + FIELD_COLOR_NUMBER, FIELD_COLOR_VALUE}, + FIELD_COLOR_SCHEME + " = ?", + new String[] {String.valueOf(scheme)}, + null, null, null); - while (c.moveToNext()) { - colors[c.getInt(0)] = Integer.valueOf(c.getInt(1)); - } - - c.close(); + while (c.moveToNext()) { + colors[c.getInt(0)] = Integer.valueOf(c.getInt(1)); } + c.close(); + return colors; } @@ -709,27 +706,31 @@ public class HostDatabase extends RobustSQLiteOpenHelper { final String[] whereArgs = new String[] { String.valueOf(scheme), String.valueOf(number) }; if (value == Colors.defaults[number]) { - synchronized (dbLock) { - db = getWritableDatabase(); - - db.delete(TABLE_COLORS, + mDb.beginTransaction(); + try { + mDb.delete(TABLE_COLORS, WHERE_SCHEME_AND_COLOR, whereArgs); + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } } else { final ContentValues values = new ContentValues(); values.put(FIELD_COLOR_VALUE, value); - synchronized (dbLock) { - db = getWritableDatabase(); - - final int rowsAffected = db.update(TABLE_COLORS, values, + mDb.beginTransaction(); + try { + final int rowsAffected = mDb.update(TABLE_COLORS, values, WHERE_SCHEME_AND_COLOR, whereArgs); if (rowsAffected == 0) { values.put(FIELD_COLOR_SCHEME, scheme); values.put(FIELD_COLOR_NUMBER, number); - db.insert(TABLE_COLORS, null, values); + mDb.insert(TABLE_COLORS, null, values); } + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } } } @@ -741,23 +742,19 @@ public class HostDatabase extends RobustSQLiteOpenHelper { public int[] getDefaultColorsForScheme(int scheme) { int[] colors = new int[] { DEFAULT_FG_COLOR, DEFAULT_BG_COLOR }; - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - - Cursor c = db.query(TABLE_COLOR_DEFAULTS, - new String[] { FIELD_COLOR_FG, FIELD_COLOR_BG }, - FIELD_COLOR_SCHEME + " = ?", - new String[] { String.valueOf(scheme) }, - null, null, null); + Cursor c = mDb.query(TABLE_COLOR_DEFAULTS, + new String[] {FIELD_COLOR_FG, FIELD_COLOR_BG}, + FIELD_COLOR_SCHEME + " = ?", + new String[] {String.valueOf(scheme)}, + null, null, null); - if (c.moveToFirst()) { - colors[0] = c.getInt(0); - colors[1] = c.getInt(1); - } - - c.close(); + if (c.moveToFirst()) { + colors[0] = c.getInt(0); + colors[1] = c.getInt(1); } + c.close(); + return colors; } @@ -778,16 +775,18 @@ public class HostDatabase extends RobustSQLiteOpenHelper { values.put(FIELD_COLOR_FG, fg); values.put(FIELD_COLOR_BG, bg); - synchronized (dbLock) { - db = getWritableDatabase(); - - int rowsAffected = db.update(TABLE_COLOR_DEFAULTS, values, + mDb.beginTransaction(); + try { + int rowsAffected = mDb.update(TABLE_COLOR_DEFAULTS, values, schemeWhere, whereArgs); if (rowsAffected == 0) { values.put(FIELD_COLOR_SCHEME, scheme); - db.insert(TABLE_COLOR_DEFAULTS, null, values); + mDb.insert(TABLE_COLOR_DEFAULTS, null, values); } + mDb.setTransactionSuccessful(); + } finally { + mDb.endTransaction(); } } } diff --git a/app/src/main/java/org/connectbot/util/PubkeyDatabase.java b/app/src/main/java/org/connectbot/util/PubkeyDatabase.java index 02bf5b9..c66c8bf 100644 --- a/app/src/main/java/org/connectbot/util/PubkeyDatabase.java +++ b/app/src/main/java/org/connectbot/util/PubkeyDatabase.java @@ -61,7 +61,23 @@ public class PubkeyDatabase extends RobustSQLiteOpenHelper { addTableName(TABLE_PUBKEYS); } - public PubkeyDatabase(Context context) { + private static final Object sInstanceLock = new Object(); + + private static PubkeyDatabase sInstance; + + public static PubkeyDatabase get(Context context) { + synchronized (sInstanceLock) { + if (sInstance != null) { + return sInstance; + } + + Context appContext = context.getApplicationContext(); + sInstance = new PubkeyDatabase(appContext); + return sInstance; + } + } + + private PubkeyDatabase(Context context) { super(context, DB_NAME, null, DB_VERSION); this.context = context; @@ -98,27 +114,19 @@ public class PubkeyDatabase extends RobustSQLiteOpenHelper { * Delete a specific host by its <code>_id</code> value. */ public void deletePubkey(PubkeyBean pubkey) { - HostDatabase hostdb = new HostDatabase(context); + HostDatabase hostdb = HostDatabase.get(context); hostdb.stopUsingPubkey(pubkey.getId()); - hostdb.close(); SQLiteDatabase db = getWritableDatabase(); - db.delete(TABLE_PUBKEYS, "_id = ?", new String[] { Long.toString(pubkey.getId()) }); - db.close(); + db.beginTransaction(); + try { + db.delete(TABLE_PUBKEYS, "_id = ?", new String[] {Long.toString(pubkey.getId())}); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } } - /** - * Return a cursor that contains information about all known hosts. - */ - /* - public Cursor allPubkeys() { - SQLiteDatabase db = this.getReadableDatabase(); - return db.query(TABLE_PUBKEYS, new String[] { "_id", - FIELD_PUBKEY_NICKNAME, FIELD_PUBKEY_TYPE, FIELD_PUBKEY_PRIVATE, - FIELD_PUBKEY_PUBLIC, FIELD_PUBKEY_ENCRYPTED, FIELD_PUBKEY_STARTUP }, - null, null, null, null, null); - }*/ - public List<PubkeyBean> allPubkeys() { return getPubkeys(null, null); } @@ -164,14 +172,12 @@ public class PubkeyDatabase extends RobustSQLiteOpenHelper { c.close(); } - db.close(); - return pubkeys; } /** - * @param hostId - * @return + * @param pubkeyId database ID for a desired pubkey + * @return object representing the pubkey */ public PubkeyBean findPubkeyById(long pubkeyId) { SQLiteDatabase db = getReadableDatabase(); @@ -189,8 +195,6 @@ public class PubkeyDatabase extends RobustSQLiteOpenHelper { c.close(); } - db.close(); - return pubkey; } @@ -230,8 +234,6 @@ public class PubkeyDatabase extends RobustSQLiteOpenHelper { c.close(); } - db.close(); - return list; } @@ -250,58 +252,9 @@ public class PubkeyDatabase extends RobustSQLiteOpenHelper { c.close(); } - db.close(); - return nickname; } -/* - public void setOnStart(long id, boolean onStart) { - - SQLiteDatabase db = this.getWritableDatabase(); - - ContentValues values = new ContentValues(); - values.put(FIELD_PUBKEY_STARTUP, onStart ? 1 : 0); - - db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { Long.toString(id) }); - - } - - public boolean changePassword(long id, String oldPassword, String newPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException { - SQLiteDatabase db = this.getWritableDatabase(); - - Cursor c = db.query(TABLE_PUBKEYS, new String[] { FIELD_PUBKEY_TYPE, - FIELD_PUBKEY_PRIVATE, FIELD_PUBKEY_ENCRYPTED }, - "_id = ?", new String[] { String.valueOf(id) }, - null, null, null); - - if (!c.moveToFirst()) - return false; - - String keyType = c.getString(0); - byte[] encPriv = c.getBlob(1); - c.close(); - - PrivateKey priv; - try { - priv = PubkeyUtils.decodePrivate(encPriv, keyType, oldPassword); - } catch (InvalidKeyException e) { - return false; - } catch (BadPaddingException e) { - return false; - } catch (InvalidKeySpecException e) { - return false; - } - - ContentValues values = new ContentValues(); - values.put(FIELD_PUBKEY_PRIVATE, PubkeyUtils.getEncodedPrivate(priv, newPassword)); - values.put(FIELD_PUBKEY_ENCRYPTED, newPassword.length() > 0 ? 1 : 0); - db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(id) }); - - return true; - } - */ - /** * @param pubkey */ @@ -311,19 +264,26 @@ public class PubkeyDatabase extends RobustSQLiteOpenHelper { ContentValues values = pubkey.getValues(); - if (pubkey.getId() > 0) { - values.remove("_id"); - if (db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(pubkey.getId()) }) > 0) - success = true; - } - - if (!success) { - long id = db.insert(TABLE_PUBKEYS, null, pubkey.getValues()); - pubkey.setId(id); - } + db.beginTransaction(); + try { + if (pubkey.getId() > 0) { + values.remove("_id"); + if (db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] {String.valueOf(pubkey.getId())}) > 0) + success = true; + } - db.close(); + if (!success) { + long id = db.insert(TABLE_PUBKEYS, null, pubkey.getValues()); + if (id != -1) { + // TODO add some error handling here? + pubkey.setId(id); + } + } + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } return pubkey; } } |