• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DbDowngradeHelper(int version)51     private DbDowngradeHelper(int version) {
52         this.version = version;
53     }
54 
onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)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 
parse(File file)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 
updateSchemaFile(File schemaFile, int expectedVersion, Context context, int schemaResId)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