Home | History | Annotate | Download | only in model
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.launcher3.model;
     17 
     18 import android.content.Context;
     19 import android.database.sqlite.SQLiteDatabase;
     20 import android.database.sqlite.SQLiteException;
     21 import android.util.Log;
     22 import android.util.SparseArray;
     23 
     24 import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
     25 import com.android.launcher3.util.IOUtils;
     26 
     27 import org.json.JSONArray;
     28 import org.json.JSONException;
     29 import org.json.JSONObject;
     30 
     31 import java.io.File;
     32 import java.io.FileOutputStream;
     33 import java.io.IOException;
     34 import java.io.InputStream;
     35 import java.util.ArrayList;
     36 import java.util.Collections;
     37 
     38 /**
     39  * Utility class to handle DB downgrade
     40  */
     41 public class DbDowngradeHelper {
     42 
     43     private static final String TAG = "DbDowngradeHelper";
     44 
     45     private static final String KEY_VERSION = "version";
     46     private static final String KEY_DOWNGRADE_TO = "downgrade_to_";
     47 
     48     private final SparseArray<String[]> mStatements = new SparseArray<>();
     49     public final int version;
     50 
     51     private DbDowngradeHelper(int version) {
     52         this.version = version;
     53     }
     54 
     55     public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
     56         ArrayList<String> allCommands = new ArrayList<>();
     57 
     58         for (int i = oldVersion - 1; i >= newVersion; i--) {
     59             String[] commands = mStatements.get(i);
     60             if (commands == null) {
     61                 throw new SQLiteException("Downgrade path not supported to version " + i);
     62             }
     63             Collections.addAll(allCommands, commands);
     64         }
     65 
     66         try (SQLiteTransaction t = new SQLiteTransaction(db)) {
     67             for (String sql : allCommands) {
     68                 db.execSQL(sql);
     69             }
     70             t.commit();
     71         }
     72     }
     73 
     74     public static DbDowngradeHelper parse(File file) throws JSONException, IOException {
     75         JSONObject obj = new JSONObject(new String(IOUtils.toByteArray(file)));
     76         DbDowngradeHelper helper = new DbDowngradeHelper(obj.getInt(KEY_VERSION));
     77         for (int version = helper.version - 1; version > 0; version--) {
     78             if (obj.has(KEY_DOWNGRADE_TO + version)) {
     79                 JSONArray statements = obj.getJSONArray(KEY_DOWNGRADE_TO + version);
     80                 String[] parsed = new String[statements.length()];
     81                 for (int i = 0; i < parsed.length; i++) {
     82                     parsed[i] = statements.getString(i);
     83                 }
     84                 helper.mStatements.put(version, parsed);
     85             }
     86         }
     87         return helper;
     88     }
     89 
     90     public static void updateSchemaFile(File schemaFile, int expectedVersion,
     91             Context context, int schemaResId) {
     92         try {
     93             if (DbDowngradeHelper.parse(schemaFile).version >= expectedVersion) {
     94                 return;
     95             }
     96         } catch (Exception e) {
     97             // Schema error
     98         }
     99 
    100         // Write the updated schema
    101         try (FileOutputStream fos = new FileOutputStream(schemaFile);
    102             InputStream in = context.getResources().openRawResource(schemaResId)) {
    103             IOUtils.copy(in, fos);
    104         } catch (IOException e) {
    105             Log.e(TAG, "Error writing schema file", e);
    106         }
    107     }
    108 }
    109