RenamingDelegatingContext.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.test;
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.google.android.collect.Sets;
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContextWrapper;
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentProvider;
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream;
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is a class which delegates to the given context, but performs database
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and file operations with a renamed database/file name (prefixes default
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * names with a given prefix).
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class RenamingDelegatingContext extends ContextWrapper {
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mFileContext;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mFilePrefix = null;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Set<String> mDatabaseNames = Sets.newHashSet();
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Set<String> mFileNames = Sets.newHashSet();
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static <T extends ContentProvider> T providerWithRenamedContext(
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Class<T> contentProvider, Context c, String filePrefix)
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws IllegalAccessException, InstantiationException {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return providerWithRenamedContext(contentProvider, c, filePrefix, false);
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static <T extends ContentProvider> T providerWithRenamedContext(
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Class<T> contentProvider, Context c, String filePrefix,
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean allowAccessToExistingFilesAndDbs)
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws IllegalAccessException, InstantiationException {
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Class<T> mProviderClass = contentProvider;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        T mProvider = mProviderClass.newInstance();
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RenamingDelegatingContext mContext = new RenamingDelegatingContext(c, filePrefix);
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (allowAccessToExistingFilesAndDbs) {
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.makeExistingFilesAndDbsAccessible();
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProvider.attachInfo(mContext, null);
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mProvider;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Makes accessible all files and databases whose names match the filePrefix that was passed to
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the constructor. Normally only files and databases that were created through this context are
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessible.
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void makeExistingFilesAndDbsAccessible() {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String[] databaseList = mFileContext.databaseList();
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (String diskName : databaseList) {
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (shouldDiskNameBeVisible(diskName)) {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDatabaseNames.add(publicNameFromDiskName(diskName));
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String[] fileList = mFileContext.fileList();
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (String diskName : fileList) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (shouldDiskNameBeVisible(diskName)) {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFileNames.add(publicNameFromDiskName(diskName));
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns if the given diskName starts with the given prefix or not.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param diskName name of the database/file.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean shouldDiskNameBeVisible(String diskName) {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return diskName.startsWith(mFilePrefix);
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the public name (everything following the prefix) of the given diskName.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param diskName name of the database/file.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String publicNameFromDiskName(String diskName) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!shouldDiskNameBeVisible(diskName)) {
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("disk file should not be visible: " + diskName);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return diskName.substring(mFilePrefix.length(), diskName.length());
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context : the context that will be delagated.
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filePrefix : a prefix with which database and file names will be
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * prefixed.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public RenamingDelegatingContext(Context context, String filePrefix) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileContext = context;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilePrefix = filePrefix;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context : the context that will be delagated.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param fileContext : the context that file and db methods will be delgated to
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filePrefix : a prefix with which database and file names will be
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * prefixed.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public RenamingDelegatingContext(Context context, Context fileContext, String filePrefix) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileContext = fileContext;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFilePrefix = filePrefix;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getDatabasePrefix() {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFilePrefix;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String renamedFileName(String name) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFilePrefix + name;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SQLiteDatabase openOrCreateDatabase(String name,
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mode, SQLiteDatabase.CursorFactory factory) {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String internalName = renamedFileName(name);
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mDatabaseNames.contains(name)) {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabaseNames.add(name);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFileContext.deleteDatabase(internalName);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFileContext.openOrCreateDatabase(internalName, mode, factory);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean deleteDatabase(String name) {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabaseNames.contains(name)) {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabaseNames.remove(name);
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mFileContext.deleteDatabase(renamedFileName(name));
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] databaseList() {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDatabaseNames.toArray(new String[]{});
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileInputStream openFileInput(String name)
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String internalName = renamedFileName(name);
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFileNames.contains(name)) {
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mFileContext.openFileInput(internalName);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new FileNotFoundException(internalName);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileOutputStream openFileOutput(String name, int mode)
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileNames.add(name);
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFileContext.openFileOutput(renamedFileName(name), mode);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public File getFileStreamPath(String name) {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFileContext.getFileStreamPath(renamedFileName(name));
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean deleteFile(String name) {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFileNames.contains(name)) {
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFileNames.remove(name);
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mFileContext.deleteFile(renamedFileName(name));
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] fileList() {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFileNames.toArray(new String[]{});
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//    /**
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//     * Given an array of files returns only those whose names indicate that they belong to this
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//     * context.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//     * @param allFiles the original list of files
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//     * @return the pruned list of files
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//     */
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//    private String[] prunedFileList(String[] allFiles) {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//        List<String> files = Lists.newArrayList();
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//        for (String file : allFiles) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//            if (file.startsWith(mFilePrefix)) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//                files.add(file);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//            }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//        }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//        return files.toArray(new String[]{});
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//    }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}