/* * Copyright 2016 requery.io * * 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 io.requery.android.sqlcipher; import android.content.Context; import android.database.Cursor; import io.requery.android.DefaultMapping; import io.requery.android.LoggingListener; import io.requery.android.sqlite.DatabaseProvider; import io.requery.android.sqlite.SchemaUpdater; import io.requery.meta.EntityModel; import io.requery.sql.Configuration; import io.requery.sql.ConfigurationBuilder; import io.requery.sql.Mapping; import io.requery.sql.Platform; import io.requery.sql.SchemaModifier; import io.requery.sql.TableCreationMode; import io.requery.sql.platform.SQLite; import io.requery.util.function.Function; import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteOpenHelper; import java.sql.Connection; import java.sql.SQLException; public class SqlCipherDatabaseSource extends SQLiteOpenHelper implements DatabaseProvider<SQLiteDatabase> { private final Platform platform; private final EntityModel model; private final Mapping mapping; private final String password; private SQLiteDatabase db; private Configuration configuration; private boolean loggingEnabled; private TableCreationMode mode; public SqlCipherDatabaseSource(Context context, EntityModel model, String name, String password, int version) { super(context, name, null, version); if (model == null) { throw new IllegalArgumentException("null model"); } this.platform = new SQLite(); this.mapping = onCreateMapping(platform); this.model = model; this.password = password; this.mode = TableCreationMode.CREATE_NOT_EXISTS; SQLiteDatabase.loadLibs(context); } @Override public void setLoggingEnabled(boolean enable) { this.loggingEnabled = enable; } @Override public void setTableCreationMode(TableCreationMode mode) { this.mode = mode; } protected Mapping onCreateMapping(Platform platform) { return new DefaultMapping(platform); } protected void onConfigure(ConfigurationBuilder builder) { if (loggingEnabled) { LoggingListener loggingListener = new LoggingListener(); builder.addStatementListener(loggingListener); } } private Connection getConnection(SQLiteDatabase db) throws SQLException { synchronized (this) { return new SqlCipherConnection(db); } } @Override public Configuration getConfiguration() { if (configuration == null) { ConfigurationBuilder builder = new ConfigurationBuilder(this, model) .setMapping(mapping) .setPlatform(platform) .setBatchUpdateSize(1000); onConfigure(builder); configuration = builder.build(); } return configuration; } @Override public void onCreate(SQLiteDatabase db) { this.db = db; new SchemaModifier(getConfiguration()).createTables(TableCreationMode.CREATE); } @Override public void onConfigure(SQLiteDatabase db) { if (!db.isReadOnly()) { db.execSQL("PRAGMA foreign_keys = ON"); } } @Override public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) { this.db = db; SchemaUpdater updater = new SchemaUpdater(getConfiguration(), new Function<String, Cursor>() { @Override public Cursor apply(String s) { return db.rawQuery(s, null); } }, mode); updater.update(); } @Override public Connection getConnection() throws SQLException { synchronized (this) { if (db == null) { db = getWritableDatabase(password); } return getConnection(db); } } @Override public SQLiteDatabase getReadableDatabase() { return getReadableDatabase(password); } @Override public SQLiteDatabase getWritableDatabase() { return getWritableDatabase(password); } }