1 package com.xtremelabs.robolectric.shadows; 2 3 import android.app.Application; 4 import android.content.Context; 5 import android.content.res.Resources; 6 import android.content.res.TypedArray; 7 import android.util.AttributeSet; 8 import com.xtremelabs.robolectric.internal.Implementation; 9 import com.xtremelabs.robolectric.internal.Implements; 10 import com.xtremelabs.robolectric.internal.RealObject; 11 import com.xtremelabs.robolectric.res.ResourceLoader; 12 13 import java.io.File; 14 import java.io.FileInputStream; 15 import java.io.FileNotFoundException; 16 import java.io.FileOutputStream; 17 import java.io.IOException; 18 19 import static com.xtremelabs.robolectric.Robolectric.shadowOf; 20 21 /** 22 * Calls through to the {@code resourceLoader} to actually load resources. 23 */ 24 @SuppressWarnings({"UnusedDeclaration"}) 25 @Implements(Context.class) 26 abstract public class ShadowContext { 27 public static final File CACHE_DIR = createTempDir("android-cache"); 28 public static final File EXTERNAL_CACHE_DIR = createTempDir("android-external-cache"); 29 public static final File FILES_DIR = createTempDir("android-tmp"); 30 public static final File EXTERNAL_FILES_DIR = createTempDir("android-external-files"); 31 32 @RealObject private Context realContext; 33 34 @Implementation getDir(String name, int mode)35 public File getDir(String name, int mode) { 36 // TODO: honor operating mode. 37 File file = new File(FILES_DIR, name); 38 if (!file.exists()) { 39 file.mkdir(); 40 } 41 return file; 42 } 43 44 @Implementation getString(int resId)45 public String getString(int resId) { 46 return realContext.getResources().getString(resId); 47 } 48 49 @Implementation getText(int resId)50 public CharSequence getText(int resId) { 51 return realContext.getResources().getText(resId); 52 } 53 54 @Implementation getString(int resId, Object... formatArgs)55 public String getString(int resId, Object... formatArgs) { 56 return realContext.getResources().getString(resId, formatArgs); 57 } 58 59 @Implementation getTheme()60 abstract public Resources.Theme getTheme(); 61 62 @Implementation obtainStyledAttributes( int[] attrs)63 public final TypedArray obtainStyledAttributes( 64 int[] attrs) { 65 return getTheme().obtainStyledAttributes(attrs); 66 } 67 68 @Implementation obtainStyledAttributes( int resid, int[] attrs)69 public final TypedArray obtainStyledAttributes( 70 int resid, int[] attrs) throws Resources.NotFoundException { 71 return getTheme().obtainStyledAttributes(resid, attrs); 72 } 73 74 @Implementation obtainStyledAttributes( AttributeSet set, int[] attrs)75 public final TypedArray obtainStyledAttributes( 76 AttributeSet set, int[] attrs) { 77 return getTheme().obtainStyledAttributes(set, attrs, 0, 0); 78 } 79 80 @Implementation obtainStyledAttributes( AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)81 public final TypedArray obtainStyledAttributes( 82 AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { 83 return getTheme().obtainStyledAttributes( 84 set, attrs, defStyleAttr, defStyleRes); 85 } 86 87 @Implementation getCacheDir()88 public File getCacheDir() { 89 CACHE_DIR.mkdirs(); 90 return CACHE_DIR; 91 } 92 93 @Implementation getFilesDir()94 public File getFilesDir() { 95 FILES_DIR.mkdirs(); 96 return FILES_DIR; 97 } 98 99 @Implementation getExternalCacheDir()100 public File getExternalCacheDir() { 101 EXTERNAL_CACHE_DIR.mkdir(); 102 return EXTERNAL_CACHE_DIR; 103 } 104 105 @Implementation getExternalFilesDir(String type)106 public File getExternalFilesDir(String type) { 107 File f = (type == null) ? EXTERNAL_FILES_DIR : new File( EXTERNAL_FILES_DIR, type ); 108 f.mkdirs(); 109 return f; 110 } 111 112 @Implementation openFileInput(String path)113 public FileInputStream openFileInput(String path) throws FileNotFoundException { 114 return new FileInputStream(getFileStreamPath(path)); 115 } 116 117 @Implementation openFileOutput(String path, int mode)118 public FileOutputStream openFileOutput(String path, int mode) throws FileNotFoundException { 119 return new FileOutputStream(getFileStreamPath(path)); 120 } 121 122 @Implementation getFileStreamPath(String name)123 public File getFileStreamPath(String name) { 124 if (name.contains(File.separator)) { 125 throw new IllegalArgumentException("File " + name + " contains a path separator"); 126 } 127 return new File(getFilesDir(), name); 128 } 129 130 @Implementation deleteFile(String name)131 public boolean deleteFile(String name) { 132 return getFileStreamPath(name).delete(); 133 } 134 135 /** 136 * Non-Android accessor. 137 * 138 * @return the {@code ResourceLoader} associated with this {@code Context} 139 */ getResourceLoader()140 public ResourceLoader getResourceLoader() { 141 return shadowOf((Application) realContext.getApplicationContext()).getResourceLoader(); 142 } 143 clearFilesAndCache()144 public static void clearFilesAndCache() { 145 clearFiles(FILES_DIR); 146 clearFiles(CACHE_DIR); 147 clearFiles(EXTERNAL_CACHE_DIR); 148 clearFiles(EXTERNAL_FILES_DIR); 149 } 150 clearFiles(File dir)151 public static void clearFiles(File dir) { 152 if (dir != null && dir.isDirectory()) { 153 File[] files = dir.listFiles(); 154 if (files != null) { 155 for (File f : files) { 156 if (f.isDirectory()) { 157 clearFiles(f); 158 } 159 f.delete(); 160 } 161 } 162 } 163 } 164 createTempDir(String name)165 private static File createTempDir(String name) { 166 try { 167 File tmp = File.createTempFile(name, "robolectric"); 168 if (!tmp.delete()) throw new IOException("could not delete "+tmp); 169 if (!tmp.mkdirs()) throw new IOException("could not create "+tmp); 170 tmp.deleteOnExit(); 171 172 return tmp; 173 } catch (IOException e) { 174 throw new RuntimeException(e); 175 } 176 } 177 } 178