aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java')
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java122
1 files changed, 60 insertions, 62 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 41b577cf3..3da670e2e 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -20,16 +20,18 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
+import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
+import android.util.Log;
-import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
@@ -38,89 +40,83 @@ import java.util.Locale;
* file from the dictionary provider
*/
public class BinaryDictionaryFileDumper {
+ private static final String TAG = BinaryDictionaryFileDumper.class.getSimpleName();
+
/**
* The size of the temporary buffer to copy files.
*/
static final int FILE_READ_BUFFER_SIZE = 1024;
+ private static final String DICTIONARY_PROJECTION[] = { "id" };
+
// Prevents this class to be accidentally instantiated.
private BinaryDictionaryFileDumper() {
}
/**
- * Generates a file name that matches the locale passed as an argument.
- * The file name is basically the result of the .toString() method, except we replace
- * any @File.separator with an underscore to avoid generating a file name that may not
- * be created.
- * @param locale the locale for which to get the file name
- * @param context the context to use for getting the directory
- * @return the name of the file to be created
+ * Return for a given locale or dictionary id the provider URI to get the dictionary.
*/
- private static String getCacheFileNameForLocale(Locale locale, Context context) {
- // The following assumes two things :
- // 1. That File.separator is not the same character as "_"
- // I don't think any android system will ever use "_" as a path separator
- // 2. That no two locales differ by only a File.separator versus a "_"
- // Since "_" can't be part of locale components this should be safe.
- // Examples:
- // en -> en
- // en_US_POSIX -> en_US_POSIX
- // en__foo/bar -> en__foo_bar
- final String[] separator = { File.separator };
- final String[] empty = { "_" };
- final CharSequence basename = TextUtils.replace(locale.toString(), separator, empty);
- return context.getFilesDir() + File.separator + basename;
+ private static Uri getProviderUri(String path) {
+ return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
+ path).build();
}
/**
- * Return for a given locale the provider URI to query to get the dictionary.
+ * Queries a content provider for the list of dictionaries for a specific locale
+ * available to copy into Latin IME.
*/
- public static Uri getProviderUri(Locale locale) {
- return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
- .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
- locale.toString()).build();
+ private static List<String> getDictIdList(final Locale locale, final Context context) {
+ final ContentResolver resolver = context.getContentResolver();
+ final Uri dictionaryPackUri = getProviderUri(locale.toString());
+
+ final Cursor c = resolver.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null, null);
+ if (null == c) return Collections.<String>emptyList();
+ if (c.getCount() <= 0 || !c.moveToFirst()) {
+ c.close();
+ return Collections.<String>emptyList();
+ }
+
+ final List<String> list = new ArrayList<String>();
+ do {
+ final String id = c.getString(0);
+ if (TextUtils.isEmpty(id)) continue;
+ list.add(id);
+ } while (c.moveToNext());
+ c.close();
+ return list;
}
/**
- * Queries a content provider for dictionary data for some locale and returns the file addresses
+ * Queries a content provider for dictionary data for some locale and cache the returned files
*
- * This will query a content provider for dictionary data for a given locale, and return
- * the addresses of a file set the members of which are suitable to be mmap'ed. It will copy
- * them to local storage if needed.
- * It should also check the dictionary versions to avoid unnecessary copies but this is
- * still in TODO state.
- * This will make the data from the content provider the cached dictionary for this locale,
- * overwriting any previous cached data.
+ * This will query a content provider for dictionary data for a given locale, and copy the
+ * files locally so that they can be mmap'ed. This may overwrite previously cached dictionaries
+ * with newer versions if a newer version is made available by the content provider.
* @returns the addresses of the files, or null if no data could be obtained.
* @throw FileNotFoundException if the provider returns non-existent data.
* @throw IOException if the provider-returned data could not be read.
*/
- public static List<AssetFileAddress> getDictSetFromContentProvider(Locale locale,
- Context context) throws FileNotFoundException, IOException {
- // TODO: check whether the dictionary is the same or not and if it is, return the cached
- // file.
- // TODO: This should be able to read a number of files from the dictionary pack, copy
- // them all and return them.
+ public static List<AssetFileAddress> cacheDictionariesFromContentProvider(final Locale locale,
+ final Context context) throws FileNotFoundException, IOException {
final ContentResolver resolver = context.getContentResolver();
- final Uri dictionaryPackUri = getProviderUri(locale);
- final AssetFileDescriptor afd = resolver.openAssetFileDescriptor(dictionaryPackUri, "r");
- if (null == afd) return null;
- final String fileName =
- copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context));
- afd.close();
- return Arrays.asList(AssetFileAddress.makeFromFileName(fileName));
- }
-
- /**
- * Accepts a file as dictionary data for some locale and returns the name of a file.
- *
- * This will make the data in the input file the cached dictionary for this locale, overwriting
- * any previous cached data.
- */
- public static String getDictionaryFileFromFile(String fileName, Locale locale,
- Context context) throws FileNotFoundException, IOException {
- return copyFileTo(new FileInputStream(fileName), getCacheFileNameForLocale(locale,
- context));
+ final List<String> idList = getDictIdList(locale, context);
+ final List<AssetFileAddress> fileAddressList = new ArrayList<AssetFileAddress>();
+ for (String id : idList) {
+ final Uri wordListUri = getProviderUri(id);
+ final AssetFileDescriptor afd =
+ resolver.openAssetFileDescriptor(wordListUri, "r");
+ if (null == afd) continue;
+ final String fileName = copyFileTo(afd.createInputStream(),
+ BinaryDictionaryGetter.getCacheFileName(id, locale, context));
+ afd.close();
+ if (0 >= resolver.delete(wordListUri, null, null)) {
+ // I'd rather not print the word list ID to the log here out of security concerns
+ Log.e(TAG, "Could not have the dictionary pack delete a word list");
+ }
+ fileAddressList.add(AssetFileAddress.makeFromFileName(fileName));
+ }
+ return fileAddressList;
}
/**
@@ -135,7 +131,9 @@ public class BinaryDictionaryFileDumper {
final Locale savedLocale = Utils.setSystemLocale(res, locale);
final InputStream stream = res.openRawResource(resource);
Utils.setSystemLocale(res, savedLocale);
- return copyFileTo(stream, getCacheFileNameForLocale(locale, context));
+ return copyFileTo(stream,
+ BinaryDictionaryGetter.getCacheFileName(Integer.toString(resource),
+ locale, context));
}
/**