blob: 38ad569044a006bd1414243217ce08e73afcd627 [file] [log] [blame]
package org.robolectric.shadows;
import android.app.Application;
import android.content.Context;
import android.content.res.Resources;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.view.View;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.res.Attribute;
import org.robolectric.res.ResName;
import org.robolectric.res.ResourceLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import static org.fest.reflect.core.Reflection.method;
import static org.robolectric.Robolectric.shadowOf;
/**
* Calls through to the {@code resourceLoader} to actually load resources.
*/
@SuppressWarnings({"UnusedDeclaration"})
@Implements(value = Context.class, resetStaticState = true)
abstract public class ShadowContext {
public static final File CACHE_DIR = createTempDir("android-cache");
public static final File EXTERNAL_CACHE_DIR = createTempDir("android-external-cache");
public static final File FILES_DIR = createTempDir("android-tmp");
public static final File EXTERNAL_FILES_DIR = createTempDir("android-external-files");
public static final File DATABASE_DIR = createTempDir("android-database");
@RealObject private Context realContext;
private ShadowApplication shadowApplication;
@Implementation
public String getString(int resId) {
return realContext.getResources().getString(resId);
}
@Implementation
public CharSequence getText(int resId) {
return realContext.getResources().getText(resId);
}
@Implementation
public String getString(int resId, Object... formatArgs) {
return realContext.getResources().getString(resId, formatArgs);
}
public RoboAttributeSet createAttributeSet(List<Attribute> attributes, Class<? extends View> viewClass) {
RoboAttributeSet attributeSet = new RoboAttributeSet(attributes, getResources(), viewClass);
if (isStrictI18n()) {
attributeSet.validateStrictI18n();
}
return attributeSet;
}
@Implementation
public Resources getResources() {
throw new RuntimeException("you should override me in a subclass!");
}
@Implementation
public File getCacheDir() {
CACHE_DIR.mkdirs();
return CACHE_DIR;
}
@Implementation
public File getFilesDir() {
FILES_DIR.mkdirs();
return FILES_DIR;
}
@Implementation
public String[] fileList() {
return getFilesDir().list();
}
@Implementation
public File getDatabasePath(String name) {
File file = new File(name);
if (file.isAbsolute()) {
return file;
} else {
DATABASE_DIR.mkdirs();
return new File(DATABASE_DIR, name);
}
}
@Implementation
public File getExternalCacheDir() {
EXTERNAL_CACHE_DIR.mkdir();
return EXTERNAL_CACHE_DIR;
}
@Implementation
public File getExternalFilesDir(String type) {
File f = (type == null) ? EXTERNAL_FILES_DIR : new File( EXTERNAL_FILES_DIR, type );
f.mkdirs();
return f;
}
@Implementation
public FileInputStream openFileInput(String path) throws FileNotFoundException {
return new FileInputStream(getFileStreamPath(path));
}
@Implementation
public FileOutputStream openFileOutput(String path, int mode) throws FileNotFoundException {
if ((mode & Context.MODE_APPEND) == Context.MODE_APPEND) {
return new FileOutputStream(getFileStreamPath(path), true);
}
return new FileOutputStream(getFileStreamPath(path));
}
@Implementation
public File getFileStreamPath(String name) {
if (name.contains(File.separator)) {
throw new IllegalArgumentException("File " + name + " contains a path separator");
}
return new File(getFilesDir(), name);
}
@Implementation
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
return openOrCreateDatabase(name, mode, factory, null);
}
@Implementation
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler databaseErrorHandler) {
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(), factory, databaseErrorHandler);
}
@Implementation
public boolean deleteFile(String name) {
return getFileStreamPath(name).delete();
}
/**
* Non-Android accessor.
*
* @return the {@code ResourceLoader} associated with this {@code Context}
*/
public ResourceLoader getResourceLoader() {
return shadowOf((Application) realContext.getApplicationContext()).getResourceLoader();
}
public boolean isStrictI18n() {
return getShadowApplication().isStrictI18n();
}
public static void reset() {
clearFiles(FILES_DIR);
clearFiles(CACHE_DIR);
clearFiles(EXTERNAL_CACHE_DIR);
clearFiles(EXTERNAL_FILES_DIR);
clearFiles(DATABASE_DIR);
}
public static void clearFiles(File dir) {
if (dir != null && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
clearFiles(f);
}
f.delete();
}
}
}
}
public static File createTempDir(String name) {
// todo: need to clear these out between tests, delete recursively, etc...
try {
File tmp = File.createTempFile(name, "robolectric");
if (!tmp.delete()) throw new IOException("could not delete "+tmp);
tmp = new File(tmp, UUID.randomUUID().toString());
if (!tmp.mkdirs()) throw new IOException("could not create "+tmp);
tmp.deleteOnExit();
return tmp;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public ResName getResName(int resourceId) {
return getResourceLoader().getResourceIndex().getResName(resourceId);
}
public ShadowApplication getShadowApplication() {
return shadowApplication;
}
public void callAttachBaseContext(Context context) {
method("attachBaseContext")
.withParameterTypes(Context.class)
.in(realContext)
.invoke(context);
}
}