blob: cab41f2db1705e3214745a48cfb8e40f405d6c54 [file] [log] [blame]
/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 The Android Open Source Project
*
* 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 com.android.im.app;
import com.android.im.plugin.ImConfigNames;
import com.android.im.provider.Imps;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.Log;
import android.util.Base64;
import java.util.Map;
public class DatabaseUtils {
private static final String TAG = ImApp.LOG_TAG;
private DatabaseUtils() {
}
public static Cursor queryAccountsForProvider(ContentResolver cr,
String[] projection, long providerId) {
StringBuilder where = new StringBuilder(Imps.Account.ACTIVE);
where.append("=1 AND ").append(Imps.Account.PROVIDER).append('=').append(providerId);
Cursor c = cr.query(Imps.Account.CONTENT_URI, projection, where.toString(), null, null);
if (c != null && !c.moveToFirst()) {
c.close();
return null;
}
return c;
}
public static Drawable getAvatarFromCursor(Cursor cursor, int dataColumn) {
byte[] rawData = cursor.getBlob(dataColumn);
if (rawData == null) {
return null;
}
return decodeAvatar(rawData);
}
public static Uri getAvatarUri(Uri baseUri, long providerId, long accountId) {
Uri.Builder builder = baseUri.buildUpon();
ContentUris.appendId(builder, providerId);
ContentUris.appendId(builder, accountId);
return builder.build();
}
public static Drawable getAvatarFromCursor(Cursor cursor, int dataColumn,
int encodedDataColumn, String username, boolean updateBlobUseCursor,
ContentResolver resolver, Uri updateBlobUri) {
/**
* Optimization: the avatar table in IM content provider have two
* columns, one for the raw blob data, another for the base64 encoded
* data. The reason for this is when the avatars are initially
* downloaded, they are in the base64 encoded form, and instead of
* base64 decode the avatars for all the buddies up front, we can just
* simply store the encoded data in the table, and decode them on demand
* when displaying them. Once we decode the avatar, we store the decoded
* data as a blob, and null out the encoded column in the avatars table.
* query the raw blob data first, if present, great; if not, query the
* encoded data, decode it and store as the blob, and null out the
* encoded column.
*/
byte[] rawData = cursor.getBlob(dataColumn);
if (rawData == null) {
String encodedData = cursor.getString(encodedDataColumn);
if (encodedData == null) {
// Log.e(LogTag.LOG_TAG, "getAvatarFromCursor for " + username +
// ", no raw or encoded data!");
return null;
}
rawData = Base64.decode(encodedData, Base64.DEFAULT);
// if (DBG) {
// log("getAvatarFromCursor for " + username + ": found encoded
// data,"
// + " update blob with data, len=" + rawData.length);
// }
if (updateBlobUseCursor) {
cursor.updateBlob(dataColumn, rawData);
cursor.updateString(encodedDataColumn, null);
cursor.commitUpdates();
} else {
updateAvatarBlob(resolver, updateBlobUri, rawData, username);
}
}
return decodeAvatar(rawData);
}
private static void updateAvatarBlob(ContentResolver resolver, Uri updateUri, byte[] data,
String username) {
ContentValues values = new ContentValues(3);
values.put(Imps.Avatars.DATA, data);
StringBuilder buf = new StringBuilder(Imps.Avatars.CONTACT);
buf.append("=?");
String[] selectionArgs = new String[] {
username
};
resolver.update(updateUri, values, buf.toString(), selectionArgs);
}
private static Drawable decodeAvatar(byte[] data) {
Bitmap b = BitmapFactory.decodeByteArray(data, 0, data.length);
Drawable avatar = new BitmapDrawable(b);
return avatar;
}
/**
* Update IM provider database for a plugin using newly loaded information.
* @param cr the resolver
* @param providerName the plugin provider name
* @param providerFullName the full name
* @param signUpUrl the plugin's service signup URL
* @param config the plugin's settings
* @return the provider ID of the plugin
*/
public static long updateProviderDb(ContentResolver cr,
String providerName, String providerFullName, String signUpUrl,
Map<String, String> config) {
boolean versionChanged;
// query provider data
long providerId = Imps.Provider.getProviderIdForName(cr, providerName);
if (providerId > 0) {
// already loaded, check if version changed
String pluginVersion = config.get(ImConfigNames.PLUGIN_VERSION);
if (!isPluginVersionChanged(cr, providerId, pluginVersion)) {
// no change, just return
return providerId;
}
// changed, update provider meta data
updateProviderRow(cr, providerId, providerFullName, signUpUrl);
// clear branding resource map cache
clearBrandingResourceMapCache(cr, providerId);
Log.d(TAG, "Plugin " + providerName + "(" + providerId +
") has a version change. Database updated.");
} else {
// new plugin, not loaded before, insert the provider data
providerId = insertProviderRow(cr, providerName, providerFullName, signUpUrl);
Log.d(TAG, "Plugin " + providerName + "(" + providerId +
") is new. Provider added to IM db.");
}
// plugin provider has been inserted/updated, we need to update settings
saveProviderSettings(cr, providerId, config);
return providerId;
}
/**
* Clear the branding resource map cache.
*/
private static int clearBrandingResourceMapCache(ContentResolver cr, long providerId) {
StringBuilder where = new StringBuilder();
where.append(Imps.BrandingResourceMapCache.PROVIDER_ID);
where.append('=');
where.append(providerId);
return cr.delete(Imps.BrandingResourceMapCache.CONTENT_URI, where.toString(), null);
}
/**
* Insert the plugin settings into the database.
*/
private static int saveProviderSettings(ContentResolver cr, long providerId,
Map<String, String> config) {
ContentValues[] settingValues = new ContentValues[config.size()];
int index = 0;
for (Map.Entry<String, String> entry : config.entrySet()) {
ContentValues settingValue = new ContentValues();
settingValue.put(Imps.ProviderSettings.PROVIDER, providerId);
settingValue.put(Imps.ProviderSettings.NAME, entry.getKey());
settingValue.put(Imps.ProviderSettings.VALUE, entry.getValue());
settingValues[index++] = settingValue;
}
return cr.bulkInsert(Imps.ProviderSettings.CONTENT_URI, settingValues);
}
/**
* Insert a new plugin provider to the provider table.
*/
private static long insertProviderRow(ContentResolver cr, String providerName,
String providerFullName, String signUpUrl) {
ContentValues values = new ContentValues(3);
values.put(Imps.Provider.NAME, providerName);
values.put(Imps.Provider.FULLNAME, providerFullName);
values.put(Imps.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
values.put(Imps.Provider.SIGNUP_URL, signUpUrl);
Uri result = cr.insert(Imps.Provider.CONTENT_URI, values);
return ContentUris.parseId(result);
}
/**
* Update the data of a plugin provider.
*/
private static int updateProviderRow(ContentResolver cr, long providerId,
String providerFullName, String signUpUrl) {
// Update the full name, signup url and category each time when the plugin change
// instead of specific version change because this is called only once.
// It's ok to update them even the values are not changed.
// Note that we don't update the provider name because it's used as
// identifier at some place and the plugin should never change it.
ContentValues values = new ContentValues(3);
values.put(Imps.Provider.FULLNAME, providerFullName);
values.put(Imps.Provider.SIGNUP_URL, signUpUrl);
values.put(Imps.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
Uri uri = ContentUris.withAppendedId(Imps.Provider.CONTENT_URI, providerId);
return cr.update(uri, values, null, null);
}
/**
* Compare the saved version of a plugin provider with the newly loaded version.
*/
private static boolean isPluginVersionChanged(ContentResolver cr, long providerId,
String newVersion) {
String oldVersion = Imps.ProviderSettings.getStringValue(cr, providerId,
ImConfigNames.PLUGIN_VERSION);
if (oldVersion == null) {
return true;
}
return !oldVersion.equals(newVersion);
}
}