Merge remote-tracking branch 'remotes/upstream/avoidDuplicateFiles' into beta
[pub/Android/ownCloud.git] / src / com / owncloud / android / utils / FileStorageUtils.java
1 /**
2 * ownCloud Android client application
3 *
4 * @author David A. Velasco
5 * Copyright (C) 2015 ownCloud Inc.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2,
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 package com.owncloud.android.utils;
22
23 import java.io.File;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.Comparator;
28 import java.util.List;
29 import java.util.Vector;
30
31 import third_parties.daveKoeller.AlphanumComparator;
32
33 import com.owncloud.android.MainApp;
34 import com.owncloud.android.R;
35 import com.owncloud.android.datamodel.OCFile;
36 import com.owncloud.android.lib.resources.files.RemoteFile;
37
38 import android.annotation.SuppressLint;
39 import android.content.Context;
40 import android.content.SharedPreferences;
41 import android.preference.PreferenceManager;
42 import android.net.Uri;
43 import android.os.Environment;
44 import android.os.StatFs;
45 import android.webkit.MimeTypeMap;
46
47
48 /**
49 * Static methods to help in access to local file system.
50 */
51 public class FileStorageUtils {
52 public static final Integer SORT_NAME = 0;
53 public static final Integer SORT_DATE = 1;
54 public static final Integer SORT_SIZE = 2;
55 public static Integer mSortOrder = SORT_NAME;
56 public static Boolean mSortAscending = true;
57
58
59 //private static final String LOG_TAG = "FileStorageUtils";
60
61 public static final String getSavePath(String accountName) {
62 File sdCard = Environment.getExternalStorageDirectory();
63 return sdCard.getAbsolutePath() + "/" + MainApp.getDataFolder() + "/" + Uri.encode(accountName, "@");
64 // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
65 }
66
67 public static final String getDefaultSavePathFor(String accountName, OCFile file) {
68 return getSavePath(accountName) + file.getRemotePath();
69 }
70
71 public static final String getTemporalPath(String accountName) {
72 File sdCard = Environment.getExternalStorageDirectory();
73 return sdCard.getAbsolutePath() + "/" + MainApp.getDataFolder() + "/tmp/" + Uri.encode(accountName, "@");
74 // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
75 }
76
77 @SuppressLint("NewApi")
78 public static final long getUsableSpace(String accountName) {
79 File savePath = Environment.getExternalStorageDirectory();
80 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
81 return savePath.getUsableSpace();
82
83 } else {
84 StatFs stats = new StatFs(savePath.getAbsolutePath());
85 return stats.getAvailableBlocks() * stats.getBlockSize();
86 }
87
88 }
89
90 public static final String getLogPath() {
91 return Environment.getExternalStorageDirectory() + File.separator + MainApp.getDataFolder() + File.separator + "log";
92 }
93
94 public static String getInstantUploadFilePath(Context context, String fileName) {
95 SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
96 String uploadPathdef = context.getString(R.string.instant_upload_path);
97 String uploadPath = pref.getString("instant_upload_path", uploadPathdef);
98 String value = uploadPath + OCFile.PATH_SEPARATOR + (fileName == null ? "" : fileName);
99 return value;
100 }
101
102 /**
103 * Gets the composed path when video is or must be stored
104 * @param context
105 * @param fileName: video file name
106 * @return String: video file path composed
107 */
108 public static String getInstantVideoUploadFilePath(Context context, String fileName) {
109 SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
110 String uploadVideoPathdef = context.getString(R.string.instant_upload_path);
111 String uploadVideoPath = pref.getString("instant_video_upload_path", uploadVideoPathdef);
112 String value = uploadVideoPath + OCFile.PATH_SEPARATOR + (fileName == null ? "" : fileName);
113 return value;
114 }
115
116 public static String getParentPath(String remotePath) {
117 String parentPath = new File(remotePath).getParent();
118 parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
119 return parentPath;
120 }
121
122 /**
123 * Creates and populates a new {@link OCFile} object with the data read from the server.
124 *
125 * @param remote remote file read from the server (remote file or folder).
126 * @return New OCFile instance representing the remote resource described by we.
127 */
128 public static OCFile fillOCFile(RemoteFile remote) {
129 OCFile file = new OCFile(remote.getRemotePath());
130 file.setCreationTimestamp(remote.getCreationTimestamp());
131 file.setFileLength(remote.getLength());
132 file.setMimetype(remote.getMimeType());
133 file.setModificationTimestamp(remote.getModifiedTimestamp());
134 file.setEtag(remote.getEtag());
135 file.setPermissions(remote.getPermissions());
136 file.setRemoteId(remote.getRemoteId());
137 return file;
138 }
139
140 /**
141 * Creates and populates a new {@link RemoteFile} object with the data read from an {@link OCFile}.
142 *
143 * @param ocFile OCFile
144 * @return New RemoteFile instance representing the resource described by ocFile.
145 */
146 public static RemoteFile fillRemoteFile(OCFile ocFile){
147 RemoteFile file = new RemoteFile(ocFile.getRemotePath());
148 file.setCreationTimestamp(ocFile.getCreationTimestamp());
149 file.setLength(ocFile.getFileLength());
150 file.setMimeType(ocFile.getMimetype());
151 file.setModifiedTimestamp(ocFile.getModificationTimestamp());
152 file.setEtag(ocFile.getEtag());
153 file.setPermissions(ocFile.getPermissions());
154 file.setRemoteId(ocFile.getRemoteId());
155 return file;
156 }
157
158 /**
159 * Sorts all filenames, regarding last user decision
160 */
161 public static Vector<OCFile> sortOcFolder(Vector<OCFile> files){
162 switch (mSortOrder){
163 case 0:
164 files = FileStorageUtils.sortOCFilesByName(files);
165 break;
166 case 1:
167 files = FileStorageUtils.sortOCFilesByDate(files);
168 break;
169 case 2:
170 // mFiles = FileStorageUtils.sortBySize(mSortAscending);
171 break;
172 }
173
174 return files;
175 }
176
177 /**
178 * Sorts all filenames, regarding last user decision
179 */
180 public static File[] sortLocalFolder(File[] files){
181 switch (mSortOrder){
182 case 0:
183 files = FileStorageUtils.sortLocalFilesByName(files);
184 break;
185 case 1:
186 files = FileStorageUtils.sortLocalFilesByDate(files);
187 break;
188 case 2:
189 // mFiles = FileStorageUtils.sortBySize(mSortAscending);
190 break;
191 }
192
193 return files;
194 }
195
196 /**
197 * Sorts list by Date
198 * @param files
199 */
200 public static Vector<OCFile> sortOCFilesByDate(Vector<OCFile> files){
201 final Integer val;
202 if (mSortAscending){
203 val = 1;
204 } else {
205 val = -1;
206 }
207
208 Collections.sort(files, new Comparator<OCFile>() {
209 public int compare(OCFile o1, OCFile o2) {
210 if (o1.isFolder() && o2.isFolder()) {
211 Long obj1 = o1.getModificationTimestamp();
212 return val * obj1.compareTo(o2.getModificationTimestamp());
213 }
214 else if (o1.isFolder()) {
215 return -1;
216 } else if (o2.isFolder()) {
217 return 1;
218 } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){
219 return 0;
220 } else {
221 Long obj1 = o1.getModificationTimestamp();
222 return val * obj1.compareTo(o2.getModificationTimestamp());
223 }
224 }
225 });
226
227 return files;
228 }
229
230 /**
231 * Sorts list by Date
232 * @param filesArray
233 */
234 public static File[] sortLocalFilesByDate(File[] filesArray){
235 final Integer val;
236 if (mSortAscending){
237 val = 1;
238 } else {
239 val = -1;
240 }
241
242 List<File> files = new ArrayList<File>(Arrays.asList(filesArray));
243
244 Collections.sort(files, new Comparator<File>() {
245 public int compare(File o1, File o2) {
246 if (o1.isDirectory() && o2.isDirectory()) {
247 Long obj1 = o1.lastModified();
248 return val * obj1.compareTo(o2.lastModified());
249 }
250 else if (o1.isDirectory()) {
251 return -1;
252 } else if (o2.isDirectory()) {
253 return 1;
254 } else if (o1.lastModified() == 0 || o2.lastModified() == 0){
255 return 0;
256 } else {
257 Long obj1 = o1.lastModified();
258 return val * obj1.compareTo(o2.lastModified());
259 }
260 }
261 });
262
263 File[] returnArray = new File[1];
264 return files.toArray(returnArray);
265 }
266
267 // /**
268 // * Sorts list by Size
269 // * @param sortAscending true: ascending, false: descending
270 // */
271 // public static Vector<OCFile> sortBySize(Vector<OCFile> files){
272 // final Integer val;
273 // if (mSortAscending){
274 // val = 1;
275 // } else {
276 // val = -1;
277 // }
278 //
279 // Collections.sort(files, new Comparator<OCFile>() {
280 // public int compare(OCFile o1, OCFile o2) {
281 // if (o1.isFolder() && o2.isFolder()) {
282 // Long obj1 = getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1)));
283 // return val * obj1.compareTo(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));
284 // }
285 // else if (o1.isFolder()) {
286 // return -1;
287 // } else if (o2.isFolder()) {
288 // return 1;
289 // } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){
290 // return 0;
291 // } else {
292 // Long obj1 = o1.getFileLength();
293 // return val * obj1.compareTo(o2.getFileLength());
294 // }
295 // }
296 // });
297 //
298 // return files;
299 // }
300
301 /**
302 * Sorts list by Name
303 * @param files files to sort
304 */
305 public static Vector<OCFile> sortOCFilesByName(Vector<OCFile> files){
306 final Integer val;
307 if (mSortAscending){
308 val = 1;
309 } else {
310 val = -1;
311 }
312
313 Collections.sort(files, new Comparator<OCFile>() {
314 public int compare(OCFile o1, OCFile o2) {
315 if (o1.isFolder() && o2.isFolder()) {
316 return val * new AlphanumComparator().compare(o1, o2);
317 } else if (o1.isFolder()) {
318 return -1;
319 } else if (o2.isFolder()) {
320 return 1;
321 }
322 return val * new AlphanumComparator().compare(o1, o2);
323 }
324 });
325
326 return files;
327 }
328
329 /**
330 * Sorts list by Name
331 * @param filesArray files to sort
332 */
333 public static File[] sortLocalFilesByName(File[] filesArray){
334 final Integer val;
335 if (mSortAscending){
336 val = 1;
337 } else {
338 val = -1;
339 }
340
341 List<File> files = new ArrayList<File>(Arrays.asList(filesArray));
342
343 Collections.sort(files, new Comparator<File>() {
344 public int compare(File o1, File o2) {
345 if (o1.isDirectory() && o2.isDirectory()) {
346 return val * o1.getPath().toLowerCase().compareTo(o2.getPath().toLowerCase());
347 } else if (o1.isDirectory()) {
348 return -1;
349 } else if (o2.isDirectory()) {
350 return 1;
351 }
352 return val * new AlphanumComparator().compare(o1.getPath().toLowerCase(),
353 o2.getPath().toLowerCase());
354 }
355 });
356
357 File[] returnArray = new File[1];
358 return files.toArray(returnArray);
359 }
360
361 /**
362 * Local Folder size
363 * @param dir File
364 * @return Size in bytes
365 */
366 public static long getFolderSize(File dir) {
367 if (dir.exists()) {
368 long result = 0;
369 File[] fileList = dir.listFiles();
370 for(int i = 0; i < fileList.length; i++) {
371 if(fileList[i].isDirectory()) {
372 result += getFolderSize(fileList[i]);
373 } else {
374 result += fileList[i].length();
375 }
376 }
377 return result;
378 }
379 return 0;
380 }
381
382 /**
383 * Mimetype String of a file
384 * @param path
385 * @return
386 */
387 public static String getMimeTypeFromName(String path) {
388 String extension = "";
389 int pos = path.lastIndexOf('.');
390 if (pos >= 0) {
391 extension = path.substring(pos + 1);
392 }
393 String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
394 return (result != null) ? result : "";
395 }
396
397 }