/*
* The contents of this file are subject to the OpenMRS Public License
* Version 1.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://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.mobile.databases;
import android.content.Context;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteDatabaseHook;
import net.sqlcipher.database.SQLiteException;
import net.sqlcipher.database.SQLiteOpenHelper;
import net.sqlcipher.database.SQLiteStatement;
import org.openmrs.mobile.R;
import org.openmrs.mobile.application.OpenMRS;
import org.openmrs.mobile.application.OpenMRSLogger;
import org.openmrs.mobile.utilities.StringUtils;
public abstract class OpenMRSSQLiteOpenHelper extends SQLiteOpenHelper {
protected OpenMRSLogger mLogger = OpenMRS.getInstance().getOpenMRSLogger();
public static final String DATABASE_NAME = OpenMRS.getInstance().
getResources().getString(R.string.dbname);
private String mSecretKey;
public OpenMRSSQLiteOpenHelper(Context context, SQLiteDatabase.CursorFactory factory, int version, SQLiteDatabaseHook hook) {
super(context, DATABASE_NAME, factory, version, hook);
}
public OpenMRSSQLiteOpenHelper(Context context, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, factory, version, new OpenMRSDefaultDBHook());
}
public OpenMRSSQLiteOpenHelper(Context context, SQLiteDatabase.CursorFactory factory, int version, String secretKey) {
this(context, factory, version);
mSecretKey = secretKey;
}
public String getSecretKey() {
return mSecretKey != null ? mSecretKey : OpenMRS.getInstance().getSecretKey();
}
public synchronized SQLiteDatabase getWritableDatabase() {
SQLiteDatabase db;
try {
db = getWritableDatabase(getSecretKey());
} catch (SQLiteException e) {
db = openDatabaseWithoutSecretKey(true);
}
return db;
}
public synchronized SQLiteDatabase getReadableDatabase() {
SQLiteDatabase db;
try {
db = getReadableDatabase(getSecretKey());
} catch (SQLiteException e) {
db = openDatabaseWithoutSecretKey(false);
}
return db;
}
private SQLiteDatabase openDatabaseWithoutSecretKey(boolean writable) {
SQLiteDatabase db;
mLogger.w("Can't open database with secret key. Trying to open without key (may be not encrypted).");
if (writable) {
db = getWritableDatabase("");
} else {
db = getReadableDatabase("");
}
mLogger.w("Database opened but is not encrypted!");
return db;
}
public static class OpenMRSDefaultDBHook implements SQLiteDatabaseHook {
@Override
public void preKey(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("PRAGMA cipher_default_kdf_iter = '4000'");
}
@Override
public void postKey(SQLiteDatabase sqLiteDatabase) {
// This method is intentionally empty
}
}
/**
* Null safe wrapper method for
* @see net.sqlcipher.database.SQLiteStatement#bindString(int, String)
*
* @param columnIndex
* @param columnValue
* @param statement
*/
public void bindString(int columnIndex, String columnValue, SQLiteStatement statement) {
if (StringUtils.notNull(columnValue)) {
statement.bindString(columnIndex, columnValue);
}
}
/**
* Null safe wrapper method for
* @see net.sqlcipher.database.SQLiteStatement#bindLong(int, long)
*
* @param columnIndex
* @param columnValue
* @param statement
*/
public void bindLong(int columnIndex, Long columnValue, SQLiteStatement statement) {
if (null != columnValue) {
statement.bindLong(columnIndex, columnValue);
}
}
/**
* Null safe wrapper method for
* @see net.sqlcipher.database.SQLiteStatement#bindDouble(int, double)
*
* @param columnIndex
* @param columnValue
* @param statement
*/
public void bindDouble(int columnIndex, Double columnValue, SQLiteStatement statement) {
if (null != columnValue) {
statement.bindDouble(columnIndex, columnValue);
}
}
/**
* Null safe wrapper method for
* @see net.sqlcipher.database.SQLiteStatement#bindBlob(int, byte[])
*
* @param columnIndex
* @param columnValue
* @param statement
*/
public void bindBlob(int columnIndex, byte[] columnValue, SQLiteStatement statement) {
if (null != columnValue) {
statement.bindBlob(columnIndex, columnValue);
}
}
}