1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 package org.mozilla.gecko.sync.repositories.android; 6 7 import java.util.ArrayList; 8 import java.util.Collection; 9 import java.util.Collections; 10 import java.util.HashMap; 11 import java.util.List; 12 import java.util.Map; 13 14 import org.json.simple.JSONArray; 15 16 import org.mozilla.gecko.sync.CommandProcessor.Command; 17 import org.mozilla.gecko.sync.repositories.NullCursorException; 18 import org.mozilla.gecko.sync.repositories.domain.ClientRecord; 19 import org.mozilla.gecko.sync.setup.Constants; 20 21 import android.content.Context; 22 import android.database.Cursor; 23 24 public class ClientsDatabaseAccessor { 25 26 public static final String LOG_TAG = "ClientsDatabaseAccessor"; 27 28 private ClientsDatabase db; 29 30 // Need this so we can properly stub out the class for testing. ClientsDatabaseAccessor()31 public ClientsDatabaseAccessor() {} 32 ClientsDatabaseAccessor(Context context)33 public ClientsDatabaseAccessor(Context context) { 34 db = new ClientsDatabase(context); 35 } 36 store(ClientRecord record)37 public void store(ClientRecord record) { 38 db.store(getProfileId(), record); 39 } 40 store(Collection<ClientRecord> records)41 public void store(Collection<ClientRecord> records) { 42 for (ClientRecord record : records) { 43 this.store(record); 44 } 45 } 46 store(String accountGUID, Command command)47 public void store(String accountGUID, Command command) throws NullCursorException { 48 db.store(accountGUID, command.commandType, command.args.toJSONString()); 49 } 50 fetchClient(String accountGUID)51 public ClientRecord fetchClient(String accountGUID) throws NullCursorException { 52 final Cursor cur = db.fetchClientsCursor(accountGUID, getProfileId()); 53 try { 54 if (!cur.moveToFirst()) { 55 return null; 56 } 57 return recordFromCursor(cur); 58 } finally { 59 cur.close(); 60 } 61 } 62 fetchAllClients()63 public Map<String, ClientRecord> fetchAllClients() throws NullCursorException { 64 final HashMap<String, ClientRecord> map = new HashMap<String, ClientRecord>(); 65 final Cursor cur = db.fetchAllClients(); 66 try { 67 if (!cur.moveToFirst()) { 68 return Collections.unmodifiableMap(map); 69 } 70 71 while (!cur.isAfterLast()) { 72 ClientRecord clientRecord = recordFromCursor(cur); 73 map.put(clientRecord.guid, clientRecord); 74 cur.moveToNext(); 75 } 76 return Collections.unmodifiableMap(map); 77 } finally { 78 cur.close(); 79 } 80 } 81 fetchAllCommands()82 public List<Command> fetchAllCommands() throws NullCursorException { 83 final List<Command> commands = new ArrayList<Command>(); 84 final Cursor cur = db.fetchAllCommands(); 85 try { 86 if (!cur.moveToFirst()) { 87 return Collections.unmodifiableList(commands); 88 } 89 90 while (!cur.isAfterLast()) { 91 Command command = commandFromCursor(cur); 92 commands.add(command); 93 cur.moveToNext(); 94 } 95 return Collections.unmodifiableList(commands); 96 } finally { 97 cur.close(); 98 } 99 } 100 fetchCommandsForClient(String accountGUID)101 public List<Command> fetchCommandsForClient(String accountGUID) throws NullCursorException { 102 final List<Command> commands = new ArrayList<Command>(); 103 final Cursor cur = db.fetchCommandsForClient(accountGUID); 104 try { 105 if (!cur.moveToFirst()) { 106 return Collections.unmodifiableList(commands); 107 } 108 109 while(!cur.isAfterLast()) { 110 Command command = commandFromCursor(cur); 111 commands.add(command); 112 cur.moveToNext(); 113 } 114 return Collections.unmodifiableList(commands); 115 } finally { 116 cur.close(); 117 } 118 } 119 recordFromCursor(Cursor cur)120 protected static ClientRecord recordFromCursor(Cursor cur) { 121 final String accountGUID = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_ACCOUNT_GUID); 122 final String clientName = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_NAME); 123 final String clientType = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_TYPE); 124 125 final ClientRecord record = new ClientRecord(accountGUID); 126 record.name = clientName; 127 record.type = clientType; 128 129 // Optional fields. These will either be null or strings. 130 record.formfactor = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_FORMFACTOR); 131 record.os = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_OS); 132 record.device = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_DEVICE); 133 record.appPackage = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_APP_PACKAGE); 134 record.application = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_APPLICATION); 135 136 return record; 137 } 138 commandFromCursor(Cursor cur)139 protected static Command commandFromCursor(Cursor cur) { 140 String commandType = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_COMMAND); 141 JSONArray commandArgs = RepoUtils.getJSONArrayFromCursor(cur, ClientsDatabase.COL_ARGS); 142 return new Command(commandType, commandArgs); 143 } 144 clientsCount()145 public int clientsCount() { 146 try { 147 final Cursor cur = db.fetchAllClients(); 148 try { 149 return cur.getCount(); 150 } finally { 151 cur.close(); 152 } 153 } catch (NullCursorException e) { 154 return 0; 155 } 156 157 } 158 getProfileId()159 private String getProfileId() { 160 return Constants.DEFAULT_PROFILE; 161 } 162 wipeDB()163 public void wipeDB() { 164 db.wipeDB(); 165 } 166 wipeClientsTable()167 public void wipeClientsTable() { 168 db.wipeClientsTable(); 169 } 170 wipeCommandsTable()171 public void wipeCommandsTable() { 172 db.wipeCommandsTable(); 173 } 174 close()175 public void close() { 176 db.close(); 177 } 178 } 179