OSDN Git Service

auto import from //depot/cupcake/@136594
authorThe Android Open Source Project <initial-contribution@android.com>
Thu, 5 Mar 2009 22:34:38 +0000 (14:34 -0800)
committerThe Android Open Source Project <initial-contribution@android.com>
Thu, 5 Mar 2009 22:34:38 +0000 (14:34 -0800)
src/com/android/im/app/DatabaseUtils.java
src/com/android/im/app/FrontDoorPlugin.java
src/com/android/im/service/RemoteImService.java

index 90d0433..503f9be 100644 (file)
@@ -17,6 +17,8 @@
 
 package com.android.im.app;
 
+import com.android.im.plugin.ImConfigNames;
+
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -27,8 +29,14 @@ import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.provider.Im;
+import android.util.Log;
+
+import java.util.Map;
 
 public class DatabaseUtils {
+
+    private static final String TAG = ImApp.LOG_TAG;
+
     private DatabaseUtils() {
     }
 
@@ -125,4 +133,121 @@ public class DatabaseUtils {
         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 = Im.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(Im.BrandingResourceMapCache.PROVIDER_ID);
+        where.append('=');
+        where.append(providerId);
+        return cr.delete(Im.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(Im.ProviderSettings.PROVIDER, providerId);
+            settingValue.put(Im.ProviderSettings.NAME, entry.getKey());
+            settingValue.put(Im.ProviderSettings.VALUE, entry.getValue());
+            settingValues[index++] = settingValue;
+        }
+        return cr.bulkInsert(Im.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(Im.Provider.NAME, providerName);
+        values.put(Im.Provider.FULLNAME, providerFullName);
+        values.put(Im.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
+        values.put(Im.Provider.SIGNUP_URL, signUpUrl);
+        Uri result = cr.insert(Im.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(Im.Provider.FULLNAME, providerFullName);
+        values.put(Im.Provider.SIGNUP_URL, signUpUrl);
+        values.put(Im.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
+        Uri uri = ContentUris.withAppendedId(Im.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 = Im.ProviderSettings.getStringValue(cr, providerId,
+                ImConfigNames.PLUGIN_VERSION);
+        if (oldVersion == null) {
+            return true;
+        }
+        return !oldVersion.equals(newVersion);
+    }
 }
index ea8047d..1bbcac1 100644 (file)
@@ -16,6 +16,7 @@
  */
 package com.android.im.app;
 
+import com.android.im.plugin.ImConfigNames;
 import com.android.im.plugin.ImPluginConstants;
 
 import android.app.Service;
@@ -62,28 +63,26 @@ public class FrontDoorPlugin extends Service {
 
     private ArrayList<String> mProviderNames;
     private HashMap<String, String> mPackageNames;
-    private HashMap<String, String> mClassNames;
-    private HashMap<String, String> mSrcPaths;
     private HashMap<String, Map<Integer, Integer>> mBrandingResources;
 
     @Override
     public IBinder onBind(Intent intent) {
-        // temporary provider ID<->Name mappings
+        // temporary mappings
         HashMap<String, Long> providerNameToId = new HashMap<String, Long>();
         HashMap<Long, String> providerIdToName = new HashMap<Long, String>();
+        HashMap<String, Class> classes = new HashMap<String, Class>();
 
-        loadThirdPartyPlugins(providerNameToId, providerIdToName);
-        loadBrandingResources(providerNameToId, providerIdToName);
+        loadThirdPartyPlugins(providerNameToId, providerIdToName, classes);
+        loadBrandingResources(providerNameToId, providerIdToName, classes);
 
         return mBinder;
     }
 
-    private void loadThirdPartyPlugins(HashMap<String, Long> providerNameToId,
-            HashMap<Long, String> providerIdToName) {
+    private void loadThirdPartyPlugins(
+            HashMap<String, Long> providerNameToId, HashMap<Long, String> providerIdToName,
+            HashMap<String, Class> classes) {
         mProviderNames = new ArrayList<String>();
         mPackageNames = new HashMap<String, String>();
-        mClassNames = new HashMap<String, String>();
-        mSrcPaths = new HashMap<String, String>();
 
         PackageManager pm = getPackageManager();
         List<ResolveInfo> plugins = pm.queryIntentServices(
@@ -103,7 +102,8 @@ public class FrontDoorPlugin extends Service {
             Bundle metaData = serviceInfo.metaData;
             if (metaData != null) {
                 providerName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_NAME);
-                providerFullName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_FULL_NAME);
+                providerFullName =
+                    metaData.getString(ImPluginConstants.METADATA_PROVIDER_FULL_NAME);
                 signUpUrl = metaData.getString(ImPluginConstants.METADATA_SIGN_UP_URL);
             }
             if (TextUtils.isEmpty(providerName) || TextUtils.isEmpty(providerFullName)) {
@@ -113,65 +113,34 @@ public class FrontDoorPlugin extends Service {
 
             mProviderNames.add(providerName);
             mPackageNames.put(providerName, serviceInfo.packageName);
-            mClassNames.put(providerName, serviceInfo.name);
-            mSrcPaths.put(providerName, serviceInfo.applicationInfo.sourceDir);
 
-            long providerId = updateProviderDb(providerName, providerFullName, signUpUrl);
-            providerNameToId.put(providerName, providerId);
-            providerIdToName.put(providerId, providerName);
-        }
-    }
-
-    private long updateProviderDb(
-            String providerName, String providerFullName, String signUpUrl) {
-        long providerId;
-        ContentResolver cr = getContentResolver();
-        String where = Im.Provider.NAME + "=?";
-        String[] selectionArgs = new String[]{providerName};
-        Cursor c = cr.query(Im.Provider.CONTENT_URI, null, where, selectionArgs, null);
+            String className = serviceInfo.name;
+            String srcPath = serviceInfo.applicationInfo.sourceDir;
+            Class pluginClass = loadClass(className, srcPath);
+            if (pluginClass == null) {
+                Log.e(TAG, "Can not load package for plugin " + providerName);
+                continue;
+            }
+            classes.put(providerName, pluginClass);
 
-        try {
-            if (c.moveToFirst()) {
-                providerId = c.getLong(c.getColumnIndexOrThrow(Im.Provider._ID));
-                String origFullName = c.getString(
-                        c.getColumnIndexOrThrow(Im.Provider.FULLNAME));
-                String origCategory = c.getString(
-                        c.getColumnIndexOrThrow(Im.Provider.CATEGORY));
-                String origSignupUrl = c.getString(
-                        c.getColumnIndexOrThrow(Im.Provider.SIGNUP_URL));
-                ContentValues values = new ContentValues();
-                if (origFullName == null || !origFullName.equals(providerFullName)) {
-                    values.put(Im.Provider.FULLNAME, providerFullName);
-                }
-                if (origCategory == null) {
-                    values.put(Im.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
-                }
-                if (origSignupUrl == null || !origSignupUrl.equals(signUpUrl)) {
-                    values.put(Im.Provider.SIGNUP_URL, signUpUrl);
-                }
-                if (values.size() > 0) {
-                    Uri uri = ContentUris.withAppendedId(Im.Provider.CONTENT_URI, providerId);
-                    cr.update(uri, values, null, null);
-                }
-            } else {
-                ContentValues values = new ContentValues(3);
-                values.put(Im.Provider.NAME, providerName);
-                values.put(Im.Provider.FULLNAME, providerFullName);
-                values.put(Im.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
-                values.put(Im.Provider.SIGNUP_URL, signUpUrl);
-
-                Uri result = cr.insert(Im.Provider.CONTENT_URI, values);
-                providerId = ContentUris.parseId(result);
+            Map<String, String> config = loadProviderConfigFromPlugin(pluginClass);
+            if (config == null) {
+                Log.e(TAG, "Can not load config for plugin " + providerName);
+                continue;
             }
-        } finally {
-            c.close();
-        }
+            config.put(ImConfigNames.PLUGIN_PATH, srcPath);
+            config.put(ImConfigNames.PLUGIN_CLASS, className);
 
-        return providerId;
+            long providerId = DatabaseUtils.updateProviderDb(getContentResolver(),
+                    providerName, providerFullName, signUpUrl, config);
+            providerNameToId.put(providerName, providerId);
+            providerIdToName.put(providerId, providerName);
+        }
     }
 
-    private void loadBrandingResources(HashMap<String, Long> providerNameToId,
-            HashMap<Long, String> providerIdToName) {
+    private void loadBrandingResources(
+            HashMap<String, Long> providerNameToId, HashMap<Long, String> providerIdToName,
+            HashMap<String, Class> classes) {
         mBrandingResources = new HashMap<String, Map<Integer, Integer>>();
 
         // first try load from cache
@@ -182,8 +151,7 @@ public class FrontDoorPlugin extends Service {
         for (String provider : mProviderNames) {
             long providerId = providerNameToId.get(provider);
             if (!mBrandingResources.containsKey(provider)) {
-                Map<Integer, Integer> resMap = loadBrandingResource(mClassNames.get(provider),
-                        mSrcPaths.get(provider));
+                Map<Integer, Integer> resMap = loadBrandingResource(classes.get(provider));
                 if (resMap != null) {
                     mBrandingResources.put(provider, resMap);
                     for (int appResId : resMap.keySet()) {
@@ -254,27 +222,15 @@ public class FrontDoorPlugin extends Service {
     /**
      * Load branding resources from one plugin.
      */
-    private Map<Integer, Integer> loadBrandingResource(String className, String srcPath) {
-        Map retVal = null;
-
-        if (LOCAL_DEBUG) log("loadBrandingResource: className=" + className +
-                ", srcPath=" + srcPath);
-
-        PathClassLoader classLoader = new PathClassLoader(srcPath,
-                getCustomClassLoader());
-
+    private Map<Integer, Integer> loadBrandingResource(Class cls) {
         try {
-            Class cls = classLoader.loadClass(className);
             Method m = cls.getMethod("getResourceMap");
-
             // TODO: this would still cause a VM verifier exception to be thrown if.
             // the landing page Android.mk and AndroidManifest.xml don't include use-library for
             // "com.android.im.plugin". This is even with getCustomClassLoader() as the parent
             // class loader.
-            retVal = (Map)m.invoke(cls.newInstance(), new Object[]{});
+            return (Map)m.invoke(cls.newInstance(), new Object[]{});
 
-        } catch (ClassNotFoundException e) {
-            Log.e(TAG, "Failed load the plugin resource map", e);
         } catch (IllegalAccessException e) {
             Log.e(TAG, "Failed load the plugin resource map", e);
         } catch (InstantiationException e) {
@@ -288,19 +244,44 @@ public class FrontDoorPlugin extends Service {
         } catch (InvocationTargetException e) {
             Log.e(TAG, "Failed load the plugin resource map", e);
         }
+        return null;
+    }
 
-        return retVal;
+    /**
+     * Load plugin config.
+     */
+    private Map<String, String> loadProviderConfigFromPlugin(Class cls) {
+        try {
+            Method m = cls.getMethod("onBind", Intent.class);
+            com.android.im.plugin.IImPlugin plugin =
+                (com.android.im.plugin.IImPlugin)m.invoke(cls.newInstance(), new Object[]{null});
+            return plugin.getProviderConfig();
+        } catch (IllegalAccessException e) {
+            Log.e(TAG, "Could not create plugin instance", e);
+        } catch (InstantiationException e) {
+            Log.e(TAG, "Could not create plugin instance", e);
+        } catch (SecurityException e) {
+            Log.e(TAG, "Could not load config from the plugin", e);
+        } catch (NoSuchMethodException e) {
+            Log.e(TAG, "Could not load config from the plugin", e);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Could not load config from the plugin", e);
+        } catch (InvocationTargetException e) {
+            Log.e(TAG, "Could not load config from the plugin", e);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not load config from the plugin", e);
+        }
+        return null;
     }
 
-    private ClassLoader getCustomClassLoader() {
-        /*
-        // TODO: should not hard code the path!
-        ClassLoader retVal = new PathClassLoader("/System/framework/com.android.im.plugin.jar",
-                getClassLoader());
-        if (LOCAL_DEBUG) log("getCustomClassLoader: " + retVal);
-        return retVal;
-        */
-        return getClassLoader();
+    private Class loadClass(String className, String srcPath) {
+        PathClassLoader loader = new PathClassLoader(srcPath, getClassLoader());
+        try {
+            return loader.loadClass(className);
+        } catch (ClassNotFoundException e) {
+            Log.e(TAG, "Could not find plugin class", e);
+        }
+        return null;
     }
 
     private void log(String msg) {
index c7ed6f7..1745e70 100644 (file)
@@ -55,6 +55,7 @@ import android.text.TextUtils;
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.im.app.DatabaseUtils;
 import com.android.im.IConnectionCreationListener;
 import com.android.im.IImConnection;
 import com.android.im.IRemoteImService;
@@ -168,8 +169,8 @@ public class RemoteImService extends Service {
 
             config.put(ImConfigNames.PLUGIN_PATH, pluginInfo.mSrcPath);
             config.put(ImConfigNames.PLUGIN_CLASS, pluginInfo.mClassName);
-            long providerId = updateProviderDb(providerName, providerFullName, signUpUrl,
-                    config);
+            long providerId = DatabaseUtils.updateProviderDb(getContentResolver(),
+                    providerName, providerFullName, signUpUrl, config);
             mPlugins.put(providerId, pluginInfo);
         }
     }
@@ -210,78 +211,6 @@ public class RemoteImService extends Service {
         return null;
     }
 
-    private long updateProviderDb(String providerName, String providerFullName,
-            String signUpUrl, Map<String, String> config) {
-        long providerId = -1;
-        ContentResolver cr = getContentResolver();
-        String where = Im.Provider.NAME + "=?";
-        String[] selectionArgs = new String[]{providerName};
-        Cursor c = cr.query(Im.Provider.CONTENT_URI,
-                null /* projection */,
-                where,
-                selectionArgs,
-                null /* sort order */);
-        String pluginVersion = config.get(ImConfigNames.PLUGIN_VERSION);
-        boolean versionChanged;
-        try {
-            if (c.moveToFirst()) {
-                providerId = c.getLong(c.getColumnIndexOrThrow(Im.Provider._ID));
-                versionChanged = isPluginVersionChanged(cr, providerId, pluginVersion);
-                if (versionChanged) {
-                    // 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(Im.Provider.FULLNAME, providerFullName);
-                    values.put(Im.Provider.SIGNUP_URL, signUpUrl);
-                    values.put(Im.Provider.CATEGORY, "com.android.im.IMPS_CATEGORY");
-                    Uri uri = ContentUris.withAppendedId(Im.Provider.CONTENT_URI, providerId);
-                    cr.update(uri, values, null, null);
-                }
-            } else {
-                ContentValues values = new ContentValues(3);
-                values.put(Im.Provider.NAME, providerName);
-                values.put(Im.Provider.FULLNAME, providerFullName);
-                values.put(Im.Provider.CATEGORY, "com.android.im.IMPS_CATEGORY");
-                values.put(Im.Provider.SIGNUP_URL, signUpUrl);
-
-                Uri result = cr.insert(Im.Provider.CONTENT_URI, values);
-                providerId = ContentUris.parseId(result);
-                versionChanged = true;
-            }
-        } finally {
-            c.close();
-        }
-
-        if (versionChanged) {
-            ContentValues[] settingValues = new ContentValues[config.size()];
-
-            int index = 0;
-            for (Map.Entry<String, String> entry : config.entrySet()) {
-                ContentValues settingValue = new ContentValues();
-                settingValue.put(Im.ProviderSettings.PROVIDER, providerId);
-                settingValue.put(Im.ProviderSettings.NAME, entry.getKey());
-                settingValue.put(Im.ProviderSettings.VALUE, entry.getValue());
-                settingValues[index++] = settingValue;
-            }
-            cr.bulkInsert(Im.ProviderSettings.CONTENT_URI, settingValues);
-        }
-
-        return providerId;
-    }
-
-    private boolean isPluginVersionChanged(ContentResolver cr, long providerId,
-            String newVersion) {
-        String oldVersion = Im.ProviderSettings.getStringValue(cr, providerId,
-                ImConfigNames.PLUGIN_VERSION);
-        if (oldVersion == null) {
-            return true;
-        }
-        return !oldVersion.equals(newVersion);
-    }
-
     @Override
     public void onStart(Intent intent, int startId) {
         super.onStart(intent, startId);