1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.messaging.util; 18 19 import android.content.Context; 20 import android.webkit.MimeTypeMap; 21 22 import com.android.messaging.Factory; 23 import com.android.messaging.R; 24 import com.google.common.io.Files; 25 26 import java.io.File; 27 import java.io.IOException; 28 import java.text.SimpleDateFormat; 29 import java.util.Date; 30 import java.util.Locale; 31 32 public class FileUtil { 33 /** Returns a new file name, ensuring that such a file does not already exist. */ getNewFile(File directory, String extension, String fileNameFormat)34 private static synchronized File getNewFile(File directory, String extension, 35 String fileNameFormat) throws IOException { 36 final Date date = new Date(System.currentTimeMillis()); 37 final SimpleDateFormat dateFormat = new SimpleDateFormat(fileNameFormat); 38 final String numberedFileNameFormat = dateFormat.format(date) + "_%02d" + "." + extension; 39 for (int i = 1; i <= 99; i++) { // Only save 99 of the same file name. 40 final String newName = String.format(Locale.US, numberedFileNameFormat, i); 41 File testFile = new File(directory, newName); 42 if (!testFile.exists()) { 43 testFile.createNewFile(); 44 return testFile; 45 } 46 } 47 LogUtil.e(LogUtil.BUGLE_TAG, "Too many duplicate file names: " + numberedFileNameFormat); 48 return null; 49 } 50 51 /** 52 * Creates an unused name to use for creating a new file. The format happens to be similar 53 * to that used by the Android camera application. 54 * 55 * @param directory directory that the file should be saved to 56 * @param contentType of the media being saved 57 * @return file name to be used for creating the new file. The caller is responsible for 58 * actually creating the file. 59 */ getNewFile(File directory, String contentType)60 public static File getNewFile(File directory, String contentType) throws IOException { 61 MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); 62 String fileExtension = mimeTypeMap.getExtensionFromMimeType(contentType); 63 64 final Context context = Factory.get().getApplicationContext(); 65 String fileNameFormat = context.getString(ContentType.isImageType(contentType) 66 ? R.string.new_image_file_name_format : R.string.new_file_name_format); 67 return getNewFile(directory, fileExtension, fileNameFormat); 68 } 69 70 /** Delete everything below and including root */ removeFileOrDirectory(File root)71 public static void removeFileOrDirectory(File root) { 72 removeFileOrDirectoryExcept(root, null); 73 } 74 75 /** Delete everything below and including root except for the given file */ removeFileOrDirectoryExcept(File root, File exclude)76 public static void removeFileOrDirectoryExcept(File root, File exclude) { 77 if (root.exists()) { 78 if (root.isDirectory()) { 79 for (File file : root.listFiles()) { 80 if (exclude == null || !file.equals(exclude)) { 81 removeFileOrDirectoryExcept(file, exclude); 82 } 83 } 84 root.delete(); 85 } else if (root.isFile()) { 86 root.delete(); 87 } 88 } 89 } 90 91 /** 92 * Move all files and folders under a directory into the target. 93 */ moveAllContentUnderDirectory(File sourceDir, File targetDir)94 public static void moveAllContentUnderDirectory(File sourceDir, File targetDir) { 95 if (sourceDir.isDirectory() && targetDir.isDirectory()) { 96 if (isSameOrSubDirectory(sourceDir, targetDir)) { 97 LogUtil.e(LogUtil.BUGLE_TAG, "Can't move directory content since the source " + 98 "directory is a parent of the target"); 99 return; 100 } 101 for (File file : sourceDir.listFiles()) { 102 if (file.isDirectory()) { 103 final File dirTarget = new File(targetDir, file.getName()); 104 dirTarget.mkdirs(); 105 moveAllContentUnderDirectory(file, dirTarget); 106 } else { 107 try { 108 final File fileTarget = new File(targetDir, file.getName()); 109 Files.move(file, fileTarget); 110 } catch (IOException e) { 111 LogUtil.e(LogUtil.BUGLE_TAG, "Failed to move files", e); 112 // Try proceed with the next file. 113 } 114 } 115 } 116 } 117 } 118 119 /** 120 * Checks, whether the child directory is the same as, or a sub-directory of the base 121 * directory. 122 */ isSameOrSubDirectory(File base, File child)123 private static boolean isSameOrSubDirectory(File base, File child) { 124 try { 125 base = base.getCanonicalFile(); 126 child = child.getCanonicalFile(); 127 File parentFile = child; 128 while (parentFile != null) { 129 if (base.equals(parentFile)) { 130 return true; 131 } 132 parentFile = parentFile.getParentFile(); 133 } 134 return false; 135 } catch (IOException ex) { 136 LogUtil.e(LogUtil.BUGLE_TAG, "Error while accessing file", ex); 137 return false; 138 } 139 } 140 } 141