summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorBen Kwa <kenobi@google.com>2015-04-22 15:43:17 -0700
committerBen Kwa <kenobi@google.com>2015-04-23 16:14:20 -0700
commit62539a220c6810f66b63060326bd1668f7d6b029 (patch)
tree427d3640ead7472d3f404632c35e0476d13211ed /core
parent00c7949426fe56c4d10aeaeb59b0b103bf03fcb7 (diff)
downloadframeworks_base-62539a220c6810f66b63060326bd1668f7d6b029.zip
frameworks_base-62539a220c6810f66b63060326bd1668f7d6b029.tar.gz
frameworks_base-62539a220c6810f66b63060326bd1668f7d6b029.tar.bz2
Move extension checking code into FileUtils.
Move code for checking file extensions and MIME types from ExternalStorageProvider into android.os.FileUtils, so it can be used by other clients (e.g. DownloadsProvider). BUG=20157955 Change-Id: Ib16a16af723c21fb8d2912c8917dfd68653ea6fa
Diffstat (limited to 'core')
-rw-r--r--core/java/android/os/FileUtils.java75
-rw-r--r--core/tests/coretests/src/android/os/FileUtilsTest.java64
2 files changed, 139 insertions, 0 deletions
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index b302f95..931cd3e 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -16,11 +16,13 @@
package android.os;
+import android.provider.DocumentsContract.Document;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
+import android.webkit.MimeTypeMap;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
@@ -34,6 +36,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.Objects;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
@@ -533,4 +536,76 @@ public class FileUtils {
}
return null;
}
+
+ /**
+ * Generates a unique file name under the given parent directory. If the display name doesn't
+ * have an extension that matches the requested MIME type, the default extension for that MIME
+ * type is appended. If a file already exists, the name is appended with a numerical value to
+ * make it unique.
+ *
+ * For example, the display name 'example' with 'text/plain' MIME might produce
+ * 'example.txt' or 'example (1).txt', etc.
+ *
+ * @throws FileNotFoundException
+ */
+ public static File buildUniqueFile(File parent, String mimeType, String displayName)
+ throws FileNotFoundException {
+ String name;
+ String ext;
+
+ if (Document.MIME_TYPE_DIR.equals(mimeType)) {
+ name = displayName;
+ ext = null;
+ } else {
+ String mimeTypeFromExt;
+
+ // Extract requested extension from display name
+ final int lastDot = displayName.lastIndexOf('.');
+ if (lastDot >= 0) {
+ name = displayName.substring(0, lastDot);
+ ext = displayName.substring(lastDot + 1);
+ mimeTypeFromExt = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
+ ext.toLowerCase());
+ } else {
+ name = displayName;
+ ext = null;
+ mimeTypeFromExt = null;
+ }
+
+ if (mimeTypeFromExt == null) {
+ mimeTypeFromExt = "application/octet-stream";
+ }
+
+ final String extFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType(
+ mimeType);
+ if (Objects.equals(mimeType, mimeTypeFromExt) || Objects.equals(ext, extFromMimeType)) {
+ // Extension maps back to requested MIME type; allow it
+ } else {
+ // No match; insist that create file matches requested MIME
+ name = displayName;
+ ext = extFromMimeType;
+ }
+ }
+
+ File file = buildFile(parent, name, ext);
+
+ // If conflicting file, try adding counter suffix
+ int n = 0;
+ while (file.exists()) {
+ if (n++ >= 32) {
+ throw new FileNotFoundException("Failed to create unique file");
+ }
+ file = buildFile(parent, name + " (" + n + ")", ext);
+ }
+
+ return file;
+ }
+
+ private static File buildFile(File parent, String name, String ext) {
+ if (TextUtils.isEmpty(ext)) {
+ return new File(parent, name);
+ } else {
+ return new File(parent, name + "." + ext);
+ }
+ }
}
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 5c9e813..ee9e2e4 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -21,6 +21,7 @@ import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import android.content.Context;
+import android.provider.DocumentsContract.Document;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
@@ -43,6 +44,8 @@ public class FileUtilsTest extends AndroidTestCase {
private File mDir;
private File mTestFile;
private File mCopyFile;
+ private File mTarget;
+
@Override
protected void setUp() throws Exception {
@@ -50,11 +53,15 @@ public class FileUtilsTest extends AndroidTestCase {
mDir = getContext().getDir("testing", Context.MODE_PRIVATE);
mTestFile = new File(mDir, "test.file");
mCopyFile = new File(mDir, "copy.file");
+
+ mTarget = getContext().getFilesDir();
+ FileUtils.deleteContents(mTarget);
}
@Override
protected void tearDown() throws Exception {
IoUtils.deleteContents(mDir);
+ FileUtils.deleteContents(mTarget);
}
// TODO: test setPermissions(), getPermissions()
@@ -225,6 +232,63 @@ public class FileUtilsTest extends AndroidTestCase {
assertEquals("foo_bar__baz", FileUtils.buildValidFatFilename("foo?bar**baz"));
}
+ public void testBuildUniqueFile_normal() throws Exception {
+ assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test"));
+ assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
+ assertNameEquals("test.jpeg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpeg"));
+ assertNameEquals("TEst.JPeg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "TEst.JPeg"));
+ assertNameEquals("test.png.jpg",
+ FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.png.jpg"));
+ assertNameEquals("test.png.jpg",
+ FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.png"));
+
+ assertNameEquals("test.flac", FileUtils.buildUniqueFile(mTarget, "audio/flac", "test"));
+ assertNameEquals("test.flac", FileUtils.buildUniqueFile(mTarget, "audio/flac", "test.flac"));
+ assertNameEquals("test.flac",
+ FileUtils.buildUniqueFile(mTarget, "application/x-flac", "test"));
+ assertNameEquals("test.flac",
+ FileUtils.buildUniqueFile(mTarget, "application/x-flac", "test.flac"));
+ }
+
+ public void testBuildUniqueFile_unknown() throws Exception {
+ assertNameEquals("test",
+ FileUtils.buildUniqueFile(mTarget, "application/octet-stream", "test"));
+ assertNameEquals("test.jpg",
+ FileUtils.buildUniqueFile(mTarget, "application/octet-stream", "test.jpg"));
+ assertNameEquals(".test",
+ FileUtils.buildUniqueFile(mTarget, "application/octet-stream", ".test"));
+
+ assertNameEquals("test", FileUtils.buildUniqueFile(mTarget, "lolz/lolz", "test"));
+ assertNameEquals("test.lolz", FileUtils.buildUniqueFile(mTarget, "lolz/lolz", "test.lolz"));
+ }
+
+ public void testBuildUniqueFile_dir() throws Exception {
+ assertNameEquals("test", FileUtils.buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test"));
+ new File(mTarget, "test").mkdir();
+ assertNameEquals("test (1)",
+ FileUtils.buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test"));
+
+ assertNameEquals("test.jpg",
+ FileUtils.buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test.jpg"));
+ new File(mTarget, "test.jpg").mkdir();
+ assertNameEquals("test.jpg (1)",
+ FileUtils.buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test.jpg"));
+ }
+
+ public void testBuildUniqueFile_increment() throws Exception {
+ assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
+ new File(mTarget, "test.jpg").createNewFile();
+ assertNameEquals("test (1).jpg",
+ FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
+ new File(mTarget, "test (1).jpg").createNewFile();
+ assertNameEquals("test (2).jpg",
+ FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
+ }
+
+ private static void assertNameEquals(String expected, File actual) {
+ assertEquals(expected, actual.getName());
+ }
+
private void touch(String name, long age) throws Exception {
final File file = new File(mDir, name);
file.createNewFile();