OSDN Git Service

Fixed MediaScan Issue w/ Directories
[android-x86/packages-apps-CMFileManager.git] / src / com / cyanogenmod / filemanager / util / CommandHelper.java
1 /*
2  * Copyright (C) 2012 The CyanogenMod 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.cyanogenmod.filemanager.util;
18
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.media.MediaScannerConnection;
24 import android.net.Uri;
25
26 import com.cyanogenmod.filemanager.commands.AsyncResultListener;
27 import com.cyanogenmod.filemanager.commands.ChangeOwnerExecutable;
28 import com.cyanogenmod.filemanager.commands.ChangePermissionsExecutable;
29 import com.cyanogenmod.filemanager.commands.ChecksumExecutable;
30 import com.cyanogenmod.filemanager.commands.CompressExecutable;
31 import com.cyanogenmod.filemanager.commands.ConcurrentAsyncResultListener;
32 import com.cyanogenmod.filemanager.commands.CopyExecutable;
33 import com.cyanogenmod.filemanager.commands.CreateDirExecutable;
34 import com.cyanogenmod.filemanager.commands.CreateFileExecutable;
35 import com.cyanogenmod.filemanager.commands.DeleteDirExecutable;
36 import com.cyanogenmod.filemanager.commands.DeleteFileExecutable;
37 import com.cyanogenmod.filemanager.commands.DiskUsageExecutable;
38 import com.cyanogenmod.filemanager.commands.EchoExecutable;
39 import com.cyanogenmod.filemanager.commands.ExecExecutable;
40 import com.cyanogenmod.filemanager.commands.Executable;
41 import com.cyanogenmod.filemanager.commands.FindExecutable;
42 import com.cyanogenmod.filemanager.commands.FolderUsageExecutable;
43 import com.cyanogenmod.filemanager.commands.GroupsExecutable;
44 import com.cyanogenmod.filemanager.commands.IdentityExecutable;
45 import com.cyanogenmod.filemanager.commands.LinkExecutable;
46 import com.cyanogenmod.filemanager.commands.ListExecutable;
47 import com.cyanogenmod.filemanager.commands.MountExecutable;
48 import com.cyanogenmod.filemanager.commands.MountPointInfoExecutable;
49 import com.cyanogenmod.filemanager.commands.MoveExecutable;
50 import com.cyanogenmod.filemanager.commands.ParentDirExecutable;
51 import com.cyanogenmod.filemanager.commands.ProcessIdExecutable;
52 import com.cyanogenmod.filemanager.commands.QuickFolderSearchExecutable;
53 import com.cyanogenmod.filemanager.commands.ReadExecutable;
54 import com.cyanogenmod.filemanager.commands.ResolveLinkExecutable;
55 import com.cyanogenmod.filemanager.commands.SIGNAL;
56 import com.cyanogenmod.filemanager.commands.SendSignalExecutable;
57 import com.cyanogenmod.filemanager.commands.SyncResultExecutable;
58 import com.cyanogenmod.filemanager.commands.UncompressExecutable;
59 import com.cyanogenmod.filemanager.commands.WritableExecutable;
60 import com.cyanogenmod.filemanager.commands.WriteExecutable;
61 import com.cyanogenmod.filemanager.commands.shell.InvalidCommandDefinitionException;
62 import com.cyanogenmod.filemanager.console.AuthenticationFailedException;
63 import com.cyanogenmod.filemanager.console.CancelledOperationException;
64 import com.cyanogenmod.filemanager.console.CommandNotFoundException;
65 import com.cyanogenmod.filemanager.console.Console;
66 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
67 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
68 import com.cyanogenmod.filemanager.console.ExecutionException;
69 import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
70 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
71 import com.cyanogenmod.filemanager.console.OperationTimeoutException;
72 import com.cyanogenmod.filemanager.console.ReadOnlyFilesystemException;
73 import com.cyanogenmod.filemanager.console.VirtualMountPointConsole;
74 import com.cyanogenmod.filemanager.console.secure.SecureConsole;
75 import com.cyanogenmod.filemanager.model.Directory;
76 import com.cyanogenmod.filemanager.model.DiskUsage;
77 import com.cyanogenmod.filemanager.model.FileSystemObject;
78 import com.cyanogenmod.filemanager.model.FolderUsage;
79 import com.cyanogenmod.filemanager.model.Group;
80 import com.cyanogenmod.filemanager.model.Identity;
81 import com.cyanogenmod.filemanager.model.MountPoint;
82 import com.cyanogenmod.filemanager.model.ParentDirectory;
83 import com.cyanogenmod.filemanager.model.Permissions;
84 import com.cyanogenmod.filemanager.model.Query;
85 import com.cyanogenmod.filemanager.model.SearchResult;
86 import com.cyanogenmod.filemanager.model.User;
87 import com.cyanogenmod.filemanager.preferences.CompressionMode;
88 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
89
90 import java.io.File;
91 import java.io.FileNotFoundException;
92 import java.io.IOException;
93 import java.util.ArrayList;
94 import java.util.List;
95 import java.util.Stack;
96
97
98 /**
99  * A helper class with useful methods for deal with commands.
100  */
101 public final class CommandHelper {
102
103     /**
104      * A wrapper class for asynchronous operations that need restore the filesystem
105      * after the operation.
106      */
107     private static class UnmountAsyncResultListener implements AsyncResultListener {
108
109         Context mCtx;
110         AsyncResultListener mRef;
111         boolean mUnmount = false;
112         Console mConsole;
113         MountPoint mMountPoint;
114
115         /**
116          * Constructor of <code>UnmountAsyncResultListener</code>
117          */
118         public UnmountAsyncResultListener() {
119             super();
120         }
121
122         /**
123          * {@inheritDoc}
124          */
125         @Override
126         public void onAsyncStart() {
127             if (this.mRef != null) {
128                 this.mRef.onAsyncStart();
129             }
130         }
131
132         /**
133          * {@inheritDoc}
134          */
135         @Override
136         public void onAsyncEnd(boolean cancelled) {
137             if (this.mRef != null) {
138                 this.mRef.onAsyncEnd(cancelled);
139             }
140         }
141
142         /**
143          * {@inheritDoc}
144          */
145         @Override
146         public void onAsyncExitCode(int exitCode) {
147             if (this.mRef != null) {
148                 this.mRef.onAsyncExitCode(exitCode);
149             }
150
151             // Now if that the process has finished check if the operation
152             // requires to unmount the filesystem
153             if (this.mUnmount && this.mConsole != null &&
154                 this.mMountPoint != null && this.mCtx != null) {
155                 // Run in background because the console is still executing
156                 // the command
157                 Thread t = new Thread() {
158                     @Override
159                     public void run() {
160                         try {
161                             MountExecutable unmountExecutable =
162                                     UnmountAsyncResultListener.this.mConsole.
163                                         getExecutableFactory().newCreator().
164                                             createMountExecutable(
165                                                     UnmountAsyncResultListener.this.mMountPoint,
166                                                     false);
167                             UnmountAsyncResultListener.this.mConsole.execute(
168                                     unmountExecutable, mCtx);
169                         } catch (Exception e) {
170                             // Capture the exception but not show to the user
171                             ExceptionUtil.translateException(
172                                     UnmountAsyncResultListener.this.mCtx, e, true, false);
173                         }
174                     }
175                 };
176                 t.start();
177             }
178         }
179
180         /**
181          * {@inheritDoc}
182          */
183         @Override
184         public void onPartialResult(Object result) {
185             if (this.mRef != null) {
186                 this.mRef.onPartialResult(result);
187             }
188         }
189
190         /**
191          * {@inheritDoc}
192          */
193         @Override
194         public void onException(Exception cause) {
195             if (this.mRef != null) {
196                 this.mRef.onException(cause);
197             }
198         }
199     }
200
201     /**
202      * Constructor of <code>CommandHelper</code>.
203      */
204     private CommandHelper() {
205         super();
206     }
207
208     /**
209      * Method that changes the owner of a file system object.
210      *
211      * @param context The current context (needed if console == null)
212      * @param src The file system object to change its permissions
213      * @param user The new user owner of the file system object
214      * @param group The new group owner of the file system object
215      * @param console The console in which execute the program. <code>null</code>
216      * to attach to the default console
217      * @return boolean The operation result
218      * @throws FileNotFoundException If the initial directory not exists
219      * @throws IOException If initial directory couldn't be checked
220      * @throws InvalidCommandDefinitionException If the command has an invalid definition
221      * @throws NoSuchFileOrDirectory If the file or directory was not found
222      * @throws ConsoleAllocException If the console can't be allocated
223      * @throws InsufficientPermissionsException If an operation requires elevated permissions
224      * @throws CommandNotFoundException If the command was not found
225      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
226      * @throws ExecutionException If the operation returns a invalid exit code
227      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
228      * @throws CancelledOperationException If the operation was cancelled
229      * @see ChangeOwnerExecutable
230      */
231     public static boolean changeOwner(
232             Context context, String src, User user, Group group, Console console)
233             throws FileNotFoundException, IOException, ConsoleAllocException,
234             NoSuchFileOrDirectory, InsufficientPermissionsException,
235             CommandNotFoundException, OperationTimeoutException, ExecutionException,
236             InvalidCommandDefinitionException, ReadOnlyFilesystemException,
237             CancelledOperationException {
238         Console c = ensureConsole(context, console);
239         ChangeOwnerExecutable executable =
240                 c.getExecutableFactory().
241                     newCreator().createChangeOwnerExecutable(src, user, group);
242         writableExecute(context, executable, c);
243         return executable.getResult().booleanValue();
244     }
245
246     /**
247      * Method that changes the permissions of a file system object.
248      *
249      * @param context The current context (needed if console == null)
250      * @param src The file system object to change its permissions
251      * @param permissions The new permissions of the file system object
252      * @param console The console in which execute the program. <code>null</code>
253      * to attach to the default console
254      * @return boolean The operation result
255      * @throws FileNotFoundException If the initial directory not exists
256      * @throws IOException If initial directory couldn't be checked
257      * @throws InvalidCommandDefinitionException If the command has an invalid definition
258      * @throws NoSuchFileOrDirectory If the file or directory was not found
259      * @throws ConsoleAllocException If the console can't be allocated
260      * @throws InsufficientPermissionsException If an operation requires elevated permissions
261      * @throws CommandNotFoundException If the command was not found
262      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
263      * @throws ExecutionException If the operation returns a invalid exit code
264      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
265      * @throws CancelledOperationException If the operation was cancelled
266      * @see ChangePermissionsExecutable
267      */
268     public static boolean changePermissions(
269             Context context, String src, Permissions permissions, Console console)
270             throws FileNotFoundException, IOException, ConsoleAllocException,
271             NoSuchFileOrDirectory, InsufficientPermissionsException,
272             CommandNotFoundException, OperationTimeoutException,
273             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
274             CancelledOperationException {
275         Console c = ensureConsole(context, console);
276         ChangePermissionsExecutable executable =
277                 c.getExecutableFactory().newCreator().
278                     createChangePermissionsExecutable(src, permissions);
279         writableExecute(context, executable, c);
280         return executable.getResult().booleanValue();
281     }
282
283     /**
284      * Method that creates a directory.
285      *
286      * @param context The current context (needed if console == null)
287      * @param directory The directory to create
288      * @param console The console in which execute the program. <code>null</code>
289      * to attach to the default console
290      * @return boolean The operation result
291      * @throws FileNotFoundException If the initial directory not exists
292      * @throws IOException If initial directory couldn't be checked
293      * @throws InvalidCommandDefinitionException If the command has an invalid definition
294      * @throws NoSuchFileOrDirectory If the file or directory was not found
295      * @throws ConsoleAllocException If the console can't be allocated
296      * @throws InsufficientPermissionsException If an operation requires elevated permissions
297      * @throws CommandNotFoundException If the command was not found
298      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
299      * @throws ExecutionException If the operation returns a invalid exit code
300      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
301      * @throws CancelledOperationException If the operation was cancelled
302      * @see CreateDirExecutable
303      */
304     public static boolean createDirectory(Context context, String directory, Console console)
305             throws FileNotFoundException, IOException, ConsoleAllocException,
306             NoSuchFileOrDirectory, InsufficientPermissionsException,
307             CommandNotFoundException, OperationTimeoutException,
308             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
309             CancelledOperationException {
310         Console c = ensureConsoleForFile(context, console, directory);
311         CreateDirExecutable executable =
312                 c.getExecutableFactory().newCreator().createCreateDirectoryExecutable(directory);
313         writableExecute(context, executable, c);
314
315         // Do media scan
316         MediaScannerConnection.scanFile(context, new String[]{
317                 MediaHelper.normalizeMediaPath(directory)}, null, null);
318
319         return executable.getResult().booleanValue();
320     }
321
322     /**
323      * Method that creates a file.
324      *
325      * @param context The current context (needed if console == null)
326      * @param file The file to create
327      * @param console The console in which execute the program. <code>null</code>
328      * to attach to the default console
329      * @return boolean The operation result
330      * @throws FileNotFoundException If the initial directory not exists
331      * @throws IOException If initial directory couldn't be checked
332      * @throws InvalidCommandDefinitionException If the command has an invalid definition
333      * @throws NoSuchFileOrDirectory If the file or directory was not found
334      * @throws ConsoleAllocException If the console can't be allocated
335      * @throws InsufficientPermissionsException If an operation requires elevated permissions
336      * @throws CommandNotFoundException If the command was not found
337      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
338      * @throws ExecutionException If the operation returns a invalid exit code
339      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
340      * @throws CancelledOperationException If the operation was cancelled
341      * @see CreateFileExecutable
342      */
343     public static boolean createFile(Context context, String file, Console console)
344             throws FileNotFoundException, IOException, ConsoleAllocException,
345             NoSuchFileOrDirectory, InsufficientPermissionsException,
346             CommandNotFoundException, OperationTimeoutException,
347             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
348             CancelledOperationException {
349         Console c = ensureConsoleForFile(context, console, file);
350         CreateFileExecutable executable =
351                 c.getExecutableFactory().newCreator().createCreateFileExecutable(file);
352         writableExecute(context, executable, c);
353
354         // Do media scan
355         MediaScannerConnection.scanFile(context, new String[]{
356                 MediaHelper.normalizeMediaPath(file)}, null, null);
357
358         return executable.getResult().booleanValue();
359     }
360
361     /**
362      * Method that deletes a directory.
363      *
364      * @param context The current context (needed if console == null)
365      * @param directory The directory to delete
366      * @param console The console in which execute the program. <code>null</code>
367      * to attach to the default console
368      * @return boolean The operation result
369      * @throws FileNotFoundException If the initial directory not exists
370      * @throws IOException If initial directory couldn't be checked
371      * @throws InvalidCommandDefinitionException If the command has an invalid definition
372      * @throws NoSuchFileOrDirectory If the file or directory was not found
373      * @throws ConsoleAllocException If the console can't be allocated
374      * @throws InsufficientPermissionsException If an operation requires elevated permissions
375      * @throws CommandNotFoundException If the command was not found
376      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
377      * @throws ExecutionException If the operation returns a invalid exit code
378      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
379      * @throws CancelledOperationException If the operation was cancelled
380      * @see DeleteDirExecutable
381      */
382     public static boolean deleteDirectory(Context context, String directory, Console console)
383             throws FileNotFoundException, IOException, ConsoleAllocException,
384             NoSuchFileOrDirectory, InsufficientPermissionsException,
385             CommandNotFoundException, OperationTimeoutException,
386             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
387             CancelledOperationException {
388         Console c = ensureConsoleForFile(context, console, directory);
389         DeleteDirExecutable executable =
390                 c.getExecutableFactory().newCreator().createDeleteDirExecutable(directory);
391         writableExecute(context, executable, c);
392
393         // update media scan
394         MediaScannerConnection.scanFile(context, new String[]{
395                 MediaHelper.normalizeMediaPath(directory)}, null, null);
396
397         return executable.getResult().booleanValue();
398     }
399
400     /**
401      * Method that deletes a file.
402      *
403      * @param context The current context (needed if console == null)
404      * @param file The file to delete
405      * @param console The console in which execute the program. <code>null</code>
406      * to attach to the default console
407      * @return boolean The operation result
408      * @throws FileNotFoundException If the initial directory not exists
409      * @throws IOException If initial directory couldn't be checked
410      * @throws InvalidCommandDefinitionException If the command has an invalid definition
411      * @throws NoSuchFileOrDirectory If the file or directory was not found
412      * @throws ConsoleAllocException If the console can't be allocated
413      * @throws InsufficientPermissionsException If an operation requires elevated permissions
414      * @throws CommandNotFoundException If the command was not found
415      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
416      * @throws ExecutionException If the operation returns a invalid exit code
417      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
418      * @throws CancelledOperationException If the operation was cancelled
419      * @see DeleteFileExecutable
420      */
421     public static boolean deleteFile(Context context, String file, Console console)
422             throws FileNotFoundException, IOException, ConsoleAllocException,
423             NoSuchFileOrDirectory, InsufficientPermissionsException,
424             CommandNotFoundException, OperationTimeoutException,
425             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
426             CancelledOperationException {
427         Console c = ensureConsoleForFile(context, console, file);
428         DeleteFileExecutable executable =
429                 c.getExecutableFactory().newCreator().createDeleteFileExecutable(file);
430         writableExecute(context, executable, c);
431
432         // Remove from mediascanner
433         MediaScannerConnection.scanFile(context, new String[]{
434                 MediaHelper.normalizeMediaPath(file)
435         }, null, null);
436
437         return executable.getResult().booleanValue();
438     }
439
440     /**
441      * Method that resolves a symlink to its real file system object.
442      *
443      * @param context The current context (needed if console == null)
444      * @param symlink The link to be resolved
445      * @param console The console in which execute the program. <code>null</code>
446      * to attach to the default console
447      * @return String The resolved link
448      * @throws FileNotFoundException If the initial directory not exists
449      * @throws IOException If initial directory couldn't be checked
450      * @throws InvalidCommandDefinitionException If the command has an invalid definition
451      * @throws NoSuchFileOrDirectory If the file or directory was not found
452      * @throws ConsoleAllocException If the console can't be allocated
453      * @throws InsufficientPermissionsException If an operation requires elevated permissions
454      * @throws CommandNotFoundException If the command was not found
455      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
456      * @throws ExecutionException If the operation returns a invalid exit code
457      * @throws CancelledOperationException If the operation was cancelled
458      * @see ResolveLinkExecutable
459      */
460     public static FileSystemObject resolveSymlink(Context context, String symlink, Console console)
461             throws FileNotFoundException, IOException, ConsoleAllocException,
462             NoSuchFileOrDirectory, InsufficientPermissionsException,
463             CommandNotFoundException, OperationTimeoutException,
464             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
465         Console c = ensureConsole(context, console);
466         ResolveLinkExecutable executable =
467                 c.getExecutableFactory().newCreator().createResolveLinkExecutable(symlink);
468         execute(context, executable, c);
469         return executable.getResult();
470     }
471
472     /**
473      * Method that retrieves the information of a file system object.
474      *
475      * @param context The current context (needed if console == null)
476      * @param src The file system object
477      * @param console The console in which execute the program. <code>null</code>
478      * to attach to the default console
479      * @return FileSystemObject The file system object reference
480      * @throws FileNotFoundException If the initial directory not exists
481      * @throws IOException If initial directory couldn't be checked
482      * @throws InvalidCommandDefinitionException If the command has an invalid definition
483      * @throws NoSuchFileOrDirectory If the file or directory was not found
484      * @throws ConsoleAllocException If the console can't be allocated
485      * @throws InsufficientPermissionsException If an operation requires elevated permissions
486      * @throws CommandNotFoundException If the command was not found
487      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
488      * @throws ExecutionException If the operation returns a invalid exit code
489      * @throws CancelledOperationException If the operation was cancelled
490      * @see ListExecutable
491      */
492     public static FileSystemObject getFileInfo(Context context, String src, Console console)
493             throws FileNotFoundException, IOException, ConsoleAllocException,
494             NoSuchFileOrDirectory, InsufficientPermissionsException,
495             CommandNotFoundException, OperationTimeoutException,
496             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
497         return getFileInfo(context, src, true, console);
498     }
499
500     /**
501      * Method that retrieves the information of a file system object.
502      *
503      * @param context The current context (needed if console == null)
504      * @param src The file system object
505      * @param followSymlinks It should be follow the symlinks
506      * @param console The console in which execute the program. <code>null</code>
507      * to attach to the default console
508      * @return FileSystemObject The file system object reference
509      * @throws FileNotFoundException If the initial directory not exists
510      * @throws IOException If initial directory couldn't be checked
511      * @throws InvalidCommandDefinitionException If the command has an invalid definition
512      * @throws NoSuchFileOrDirectory If the file or directory was not found
513      * @throws ConsoleAllocException If the console can't be allocated
514      * @throws InsufficientPermissionsException If an operation requires elevated permissions
515      * @throws CommandNotFoundException If the command was not found
516      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
517      * @throws ExecutionException If the operation returns a invalid exit code
518      * @throws CancelledOperationException If the operation was cancelled
519      * @see ListExecutable
520      */
521     public static FileSystemObject getFileInfo(
522             Context context, String src, boolean followSymlinks, Console console)
523             throws FileNotFoundException, IOException, ConsoleAllocException,
524             NoSuchFileOrDirectory, InsufficientPermissionsException,
525             CommandNotFoundException, OperationTimeoutException,
526             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
527         Console c = ensureConsoleForFile(context, console, src);
528         ListExecutable executable =
529                 c.getExecutableFactory().
530                     newCreator().createFileInfoExecutable(src, followSymlinks);
531         execute(context, executable, c);
532         List<FileSystemObject> files = executable.getResult();
533         if (files != null && files.size() > 0) {
534             // Resolve symlinks prior to return the object
535             if (followSymlinks) {
536                 FileHelper.resolveSymlinks(context, files);
537             }
538             return files.get(0);
539         }
540         return null;
541     }
542
543     /**
544      * Method that retrieves the information of the groups of the current user.
545      *
546      * @param context The current context (needed if console == null)
547      * @param console The console in which execute the program. <code>null</code>
548      * to attach to the default console
549      * @return List<Group> The groups of the current user
550      * @throws FileNotFoundException If the initial directory not exists
551      * @throws IOException If initial directory couldn't be checked
552      * @throws InvalidCommandDefinitionException If the command has an invalid definition
553      * @throws NoSuchFileOrDirectory If the file or directory was not found
554      * @throws ConsoleAllocException If the console can't be allocated
555      * @throws InsufficientPermissionsException If an operation requires elevated permissions
556      * @throws CommandNotFoundException If the command was not found
557      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
558      * @throws ExecutionException If the operation returns a invalid exit code
559      * @throws CancelledOperationException If the operation was cancelled
560      * @see GroupsExecutable
561      */
562     public static List<Group> getGroups(Context context, Console console)
563             throws FileNotFoundException, IOException, ConsoleAllocException,
564             NoSuchFileOrDirectory, InsufficientPermissionsException,
565             CommandNotFoundException, OperationTimeoutException,
566             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
567         Console c = ensureConsole(context, console);
568         GroupsExecutable executable =
569                 c.getExecutableFactory().newCreator().createGroupsExecutable();
570         execute(context, executable, c);
571         return executable.getResult();
572     }
573
574     /**
575      * Method that retrieves the identity of the current user.
576      *
577      * @param context The current context (needed if console == null)
578      * @param console The console in which execute the program. <code>null</code>
579      * to attach to the default console
580      * @return Identity The identity of the current user
581      * @throws FileNotFoundException If the initial directory not exists
582      * @throws IOException If initial directory couldn't be checked
583      * @throws InvalidCommandDefinitionException If the command has an invalid definition
584      * @throws NoSuchFileOrDirectory If the file or directory was not found
585      * @throws ConsoleAllocException If the console can't be allocated
586      * @throws InsufficientPermissionsException If an operation requires elevated permissions
587      * @throws CommandNotFoundException If the command was not found
588      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
589      * @throws ExecutionException If the operation returns a invalid exit code
590      * @throws CancelledOperationException If the operation was cancelled
591      * @see IdentityExecutable
592      */
593    public static Identity getIdentity(Context context, Console console)
594            throws FileNotFoundException, IOException, ConsoleAllocException,
595            NoSuchFileOrDirectory, InsufficientPermissionsException,
596            CommandNotFoundException, OperationTimeoutException,
597            ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
598        Console c = ensureConsole(context, console);
599        IdentityExecutable executable =
600                c.getExecutableFactory().newCreator().createIdentityExecutable();
601        execute(context, executable, c);
602        return executable.getResult();
603    }
604
605    /**
606     * Method that creates a symlink of an other file system object.
607     *
608     * @param context The current context (needed if console == null)
609     * @param src The absolute path to the source fso
610     * @param link The absolute path to the link fso
611     * @param console The console in which execute the program. <code>null</code>
612     * to attach to the default console
613     * @return boolean The operation result
614     * @throws FileNotFoundException If the initial directory not exists
615     * @throws IOException If initial directory couldn't be checked
616     * @throws InvalidCommandDefinitionException If the command has an invalid definition
617     * @throws NoSuchFileOrDirectory If the file or directory was not found
618     * @throws ConsoleAllocException If the console can't be allocated
619     * @throws InsufficientPermissionsException If an operation requires elevated permissions
620     * @throws CommandNotFoundException If the command was not found
621     * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
622     * @throws ExecutionException If the operation returns a invalid exit code
623     * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
624     * @throws CancelledOperationException If the operation was cancelled
625     * @see LinkExecutable
626     */
627    public static boolean createLink(Context context, String src, String link, Console console)
628            throws FileNotFoundException, IOException, ConsoleAllocException,
629            NoSuchFileOrDirectory, InsufficientPermissionsException,
630            CommandNotFoundException, OperationTimeoutException,
631            ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
632            CancelledOperationException {
633        Console c = ensureConsole(context, console);
634        LinkExecutable executable =
635                c.getExecutableFactory().newCreator().createLinkExecutable(src, link);
636        writableExecute(context, executable, c);
637        return executable.getResult().booleanValue();
638    }
639
640     /**
641      * Method that retrieves the parent directory of a file system object.
642      *
643      * @param context The current context (needed if console == null)
644      * @param src The file system object
645      * @param console The console in which execute the program. <code>null</code>
646      * to attach to the default console
647      * @return String The current directory
648      * @throws FileNotFoundException If the initial directory not exists
649      * @throws IOException If initial directory couldn't be checked
650      * @throws InvalidCommandDefinitionException If the command has an invalid definition
651      * @throws NoSuchFileOrDirectory If the file or directory was not found
652      * @throws ConsoleAllocException If the console can't be allocated
653      * @throws InsufficientPermissionsException If an operation requires elevated permissions
654      * @throws CommandNotFoundException If the command was not found
655      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
656      * @throws ExecutionException If the operation returns a invalid exit code
657      * @throws CancelledOperationException If the operation was cancelled
658      * @see ParentDirExecutable
659      */
660     public static String getParentDir(Context context, String src, Console console)
661             throws FileNotFoundException, IOException, ConsoleAllocException,
662             NoSuchFileOrDirectory, InsufficientPermissionsException,
663             CommandNotFoundException, OperationTimeoutException,
664             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
665         Console c = ensureConsoleForFile(context, console, src);
666         ParentDirExecutable executable =
667                 c.getExecutableFactory().newCreator().createParentDirExecutable(src);
668         execute(context, executable, c);
669         return executable.getResult();
670     }
671
672     /**
673      * Method that retrieves the value of a variable.
674      *
675      * @param context The current context (needed if console == null)
676      * @param msg The message to echo. This message can have one or multiple variables
677      * and text. xe: "This is $VAR_1 the value of $VAR2" or simple "$PATH"
678      * @param console The console in which execute the program. <code>null</code>
679      * to attach to the default console
680      * @return String The value  of the variable
681      * @throws FileNotFoundException If the initial directory not exists
682      * @throws IOException If initial directory couldn't be checked
683      * @throws InvalidCommandDefinitionException If the command has an invalid definition
684      * @throws NoSuchFileOrDirectory If the file or directory was not found
685      * @throws ConsoleAllocException If the console can't be allocated
686      * @throws InsufficientPermissionsException If an operation requires elevated permissions
687      * @throws CommandNotFoundException If the command was not found
688      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
689      * @throws ExecutionException If the operation returns a invalid exit code
690      * @throws CancelledOperationException If the operation was cancelled
691      * @see EchoExecutable
692      */
693     public static String getVariable(Context context, String msg, Console console)
694             throws FileNotFoundException, IOException, ConsoleAllocException,
695             NoSuchFileOrDirectory, InsufficientPermissionsException,
696             CommandNotFoundException, OperationTimeoutException,
697             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
698         Console c = ensureConsole(context, console);
699         EchoExecutable executable =
700                 c.getExecutableFactory().newCreator().createEchoExecutable(msg);
701         execute(context, executable, c);
702         return executable.getResult();
703     }
704
705     /**
706      * Method that lists a directory.
707      *
708      * @param context The current context (needed if console == null)
709      * @param directory The path of the directory to list
710      * @param console The console in which execute the program. <code>null</code>
711      * to attach to the default console
712      * @return List<FileSystemObject> The list of files of the directory
713      * @throws FileNotFoundException If the initial directory not exists
714      * @throws IOException If initial directory couldn't be checked
715      * @throws InvalidCommandDefinitionException If the command has an invalid definition
716      * @throws NoSuchFileOrDirectory If the file or directory was not found
717      * @throws ConsoleAllocException If the console can't be allocated
718      * @throws InsufficientPermissionsException If an operation requires elevated permissions
719      * @throws CommandNotFoundException If the command was not found
720      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
721      * @throws ExecutionException If the operation returns a invalid exit code
722      * @throws CancelledOperationException If the operation was cancelled
723      * @see ListExecutable
724      */
725     public static List<FileSystemObject> listFiles(
726             Context context, String directory, Console console)
727             throws FileNotFoundException, IOException, ConsoleAllocException,
728             NoSuchFileOrDirectory, InsufficientPermissionsException,
729             CommandNotFoundException, OperationTimeoutException,
730             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException,
731             CancelledOperationException {
732         Console c = ensureConsoleForFile(context, console, directory);
733         ListExecutable executable =
734                 c.getExecutableFactory().newCreator().
735                     createListExecutable(directory);
736         execute(context, executable, c);
737         List<FileSystemObject> result = executable.getResult();
738         FileHelper.resolveSymlinks(context, result);
739
740         // And now we need to verify if the directory is the
741         if (VirtualMountPointConsole.isVirtualStorageDir(directory)) {
742             result.addAll(VirtualMountPointConsole.getVirtualMountableDirectories());
743         }
744
745         return result;
746     }
747
748     /**
749      *
750      * @param context
751      * @param srcPath null or the source in which the file is being moved from
752      * @param destPath the root of the path being created
753      */
754     private static void recursiveScan(@NonNull final Context context,
755                                       @Nullable String srcPath,
756                                       @NonNull String destPath) {
757         ArrayList<String> paths = new ArrayList<>();
758         Stack<FileSystemObject> pathsToScan = new Stack<>();
759         try {
760             FileSystemObject fso = getFileInfo(context, destPath, null);
761             if (fso == null) {
762                 return;
763             }
764             pathsToScan.push(fso);
765             while (!pathsToScan.isEmpty()) {
766                 fso = pathsToScan.pop();
767                 if (srcPath != null) {
768                     String src = fso.getFullPath().replace(destPath, srcPath);
769                     // Add the path to be deleted
770                     paths.add(MediaHelper.normalizeMediaPath(src));
771                 }
772                 // Add the path to be added
773                 paths.add(MediaHelper.normalizeMediaPath(fso.getFullPath()));
774                 if (fso instanceof Directory) {
775                     try {
776                         List<FileSystemObject> files =
777                                 CommandHelper.listFiles(context, fso.getFullPath(), null);
778
779                         if (files == null) {
780                             continue;
781                         }
782                         for (FileSystemObject file : files) {
783                             if (file instanceof ParentDirectory) {
784                                 continue;
785                             }
786                             pathsToScan.push(file);
787                         }
788                     } catch (IOException
789                             | ConsoleAllocException
790                             | NoSuchFileOrDirectory
791                             | InsufficientPermissionsException
792                             | CommandNotFoundException
793                             | OperationTimeoutException
794                             | ExecutionException
795                             | InvalidCommandDefinitionException e) {
796                         // Just skip this directory
797                     }
798                 }
799
800                 if (paths.size() > 100) {
801                     MediaScannerConnection.scanFile(context, paths.toArray(new String[paths.size()]), null, null);
802                     paths.clear();
803                 }
804             }
805             MediaScannerConnection.scanFile(context, paths.toArray(new String[paths.size()]), null, null);
806         } catch (IOException
807                 | ConsoleAllocException
808                 | NoSuchFileOrDirectory
809                 | InsufficientPermissionsException
810                 | CommandNotFoundException
811                 | OperationTimeoutException
812                 | ExecutionException
813                 | InvalidCommandDefinitionException e) {
814             // Just stop scanning
815         }
816     }
817
818     /**
819      * Method that moves a file system object.
820      *
821      * @param context The current context (needed if console == null)
822      * @param src The file system object to move
823      * @param dst The destination file system object
824      * @param console The console in which execute the program. <code>null</code>
825      * to attach to the default console
826      * @return boolean The operation result
827      * @throws FileNotFoundException If the initial directory not exists
828      * @throws IOException If initial directory couldn't be checked
829      * @throws InvalidCommandDefinitionException If the command has an invalid definition
830      * @throws NoSuchFileOrDirectory If the file or directory was not found
831      * @throws ConsoleAllocException If the console can't be allocated
832      * @throws InsufficientPermissionsException If an operation requires elevated permissions
833      * @throws CommandNotFoundException If the command was not found
834      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
835      * @throws ExecutionException If the operation returns a invalid exit code
836      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
837      * @throws CancelledOperationException If the operation was cancelled
838      * @see MoveExecutable
839      */
840     public static boolean move(Context context, String src, String dst, Console console)
841             throws FileNotFoundException, IOException, ConsoleAllocException,
842             NoSuchFileOrDirectory, InsufficientPermissionsException,
843             CommandNotFoundException, OperationTimeoutException,
844             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
845             CancelledOperationException {
846
847         Console cSrc = ensureConsoleForFile(context, console, src);
848         Console cDst = ensureConsoleForFile(context, console, dst);
849         boolean ret = true;
850
851         if (cSrc.equals(cDst) && !FileHelper.isSamePath(src, dst)) {
852             // Is safe to use the same console
853             MoveExecutable executable =
854                     cSrc.getExecutableFactory().newCreator().createMoveExecutable(src, dst);
855             writableExecute(context, executable, cSrc);
856             ret = executable.getResult().booleanValue();
857         } else {
858             // We need to create a temporary file in the external filesystem to make it
859             // available to virtual consoles
860
861             // 1.- Move to a temporary file with the source console (destination
862             // is a safe location)
863             File tmp = FileHelper.createTempFilename(context, true);
864             try {
865                 MoveExecutable moveExecutable =
866                         cSrc.getExecutableFactory().newCreator().createMoveExecutable(
867                                 src, tmp.getAbsolutePath());
868                 writableExecute(context, moveExecutable, cSrc);
869                 if (!moveExecutable.getResult().booleanValue()) {
870                     ret = false;
871                 }
872
873
874                 // 2.- Move the temporary file to the final filesystem with the destination console
875                 if (ret) {
876                     moveExecutable =
877                             cDst.getExecutableFactory().newCreator().createMoveExecutable(
878                                     tmp.getAbsolutePath(), dst);
879                     writableExecute(context, moveExecutable, cDst);
880                     if (!moveExecutable.getResult().booleanValue()) {
881                         ret = false;
882                     }
883                 }
884
885             } finally {
886                 FileHelper.deleteFileOrFolder(tmp);
887             }
888         }
889
890         // Do media scan (don't scan the file if is virtual file)
891         if (ret) {
892             File parent = new File(dst).getParentFile();
893             if ((parent != null && !VirtualMountPointConsole.isVirtualStorageResource(parent
894                     .getAbsolutePath()))) {
895                 recursiveScan(context, src, dst);
896             }
897         }
898
899         return ret;
900     }
901
902     /**
903      * Method that copies a file system object.
904      *
905      * @param context The current context (needed if console == null)
906      * @param src The file system object to copy
907      * @param dst The destination file system object
908      * @param console The console in which execute the program. <code>null</code>
909      * to attach to the default console
910      * @return boolean The operation result
911      * @throws FileNotFoundException If the initial directory not exists
912      * @throws IOException If initial directory couldn't be checked
913      * @throws InvalidCommandDefinitionException If the command has an invalid definition
914      * @throws NoSuchFileOrDirectory If the file or directory was not found
915      * @throws ConsoleAllocException If the console can't be allocated
916      * @throws InsufficientPermissionsException If an operation requires elevated permissions
917      * @throws CommandNotFoundException If the command was not found
918      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
919      * @throws ExecutionException If the operation returns a invalid exit code
920      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
921      * @throws CancelledOperationException If the operation was cancelled
922      * @see CopyExecutable
923      */
924     public static boolean copy(Context context, String src, String dst, Console console)
925             throws FileNotFoundException, IOException, ConsoleAllocException,
926             NoSuchFileOrDirectory, InsufficientPermissionsException,
927             CommandNotFoundException, OperationTimeoutException,
928             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
929             CancelledOperationException {
930
931         Console cSrc = ensureConsoleForFile(context, console, src);
932         Console cDst = ensureConsoleForFile(context, console, dst);
933         boolean ret = true;
934         if (cSrc.equals(cDst) && !FileHelper.isSamePath(src, dst)) {
935             // Is safe to use the same console
936             CopyExecutable executable =
937                     cSrc.getExecutableFactory().newCreator().createCopyExecutable(src, dst);
938             writableExecute(context, executable, cSrc);
939             ret = executable.getResult().booleanValue();
940         } else {
941             // We need to create a temporary file in the external filesystem to make it
942             // available to virtual consoles
943
944             // 1.- Copy to a temporary file with the source console (destination
945             // is a safe location)
946             File tmp = FileHelper.createTempFilename(context, true);
947             try {
948                 CopyExecutable copyExecutable =
949                         cSrc.getExecutableFactory().newCreator().createCopyExecutable(
950                                 src, tmp.getAbsolutePath());
951                 writableExecute(context, copyExecutable, cSrc);
952                 if (!copyExecutable.getResult().booleanValue()) {
953                     ret = false;
954                 }
955
956                 // 2.- Move the temporary file to the final filesystem with the destination console
957                 if (ret) {
958                     MoveExecutable moveExecutable =
959                             cDst.getExecutableFactory().newCreator().createMoveExecutable(
960                                     tmp.getAbsolutePath(), dst);
961                     writableExecute(context, moveExecutable, cDst);
962                     if (!moveExecutable.getResult().booleanValue()) {
963                         ret = false;
964                     }
965                 }
966
967             } finally {
968                 FileHelper.deleteFileOrFolder(tmp);
969             }
970         }
971
972         // Do media scan (don't scan the file if is virtual file)
973         if (ret) {
974             if (!VirtualMountPointConsole.isVirtualStorageResource(dst)) {
975                 recursiveScan(context, null, dst);
976             }
977         }
978
979         return ret;
980     }
981
982     /**
983      * Method that executes a command.
984      *
985      * @param context The current context (needed if console == null)
986      * @param cmd The command to execute
987      * @param asyncResultListener The partial result listener
988      * @param console The console in which execute the program.
989      * <code>null</code> to attach to the default console
990      * @return ExecExecutable The command executed in background
991      * @throws FileNotFoundException If the initial directory not exists
992      * @throws IOException If initial directory couldn't be checked
993      * @throws InvalidCommandDefinitionException If the command has an invalid definition
994      * @throws NoSuchFileOrDirectory If the file or directory was not found
995      * @throws ConsoleAllocException If the console can't be allocated
996      * @throws InsufficientPermissionsException If an operation requires elevated permissions
997      * @throws CommandNotFoundException If the command was not found
998      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
999      * @throws ExecutionException If the operation returns a invalid exit code
1000      * @throws CancelledOperationException If the operation was cancelled
1001      * @see ExecExecutable
1002      */
1003     public static ExecExecutable exec(
1004             Context context, String cmd, AsyncResultListener asyncResultListener, Console console)
1005             throws FileNotFoundException, IOException, ConsoleAllocException,
1006             NoSuchFileOrDirectory, InsufficientPermissionsException,
1007             CommandNotFoundException, OperationTimeoutException,
1008             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1009         Console c = ensureConsole(context, console);
1010         ExecExecutable executable =
1011                 c.getExecutableFactory().newCreator().
1012                     createExecExecutable(cmd, asyncResultListener);
1013         execute(context, executable, c);
1014         return executable;
1015     }
1016
1017     /**
1018      * Method that does a search in a directory tree seeking for some terms.
1019      *
1020      * @param context The current context (needed if console == null)
1021      * @param directory The "absolute" directory where start the search
1022      * @param search The terms to be searched
1023      * @param asyncResultListener The partial result listener
1024      * @param console The console in which execute the program.
1025      * <code>null</code> to attach to the default console
1026      * @return FindExecutable The command executed in background
1027      * @throws FileNotFoundException If the initial directory not exists
1028      * @throws IOException If initial directory couldn't be checked
1029      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1030      * @throws NoSuchFileOrDirectory If the file or directory was not found
1031      * @throws ConsoleAllocException If the console can't be allocated
1032      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1033      * @throws CommandNotFoundException If the command was not found
1034      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1035      * @throws ExecutionException If the operation returns a invalid exit code
1036      * @throws CancelledOperationException If the operation was cancelled
1037      * @see SearchResult
1038      * @see FindExecutable
1039      */
1040     public static FindExecutable findFiles(
1041             Context context, String directory, Query search,
1042             ConcurrentAsyncResultListener asyncResultListener, Console console)
1043             throws FileNotFoundException, IOException, ConsoleAllocException,
1044             NoSuchFileOrDirectory, InsufficientPermissionsException,
1045             CommandNotFoundException, OperationTimeoutException,
1046             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1047         List<Console> consoles = new ArrayList<Console>();
1048         List<FindExecutable> executables = new ArrayList<FindExecutable>();
1049         Console c = ensureConsoleForFile(context, console, directory);
1050         consoles.add(c);
1051
1052         // Obtain all the rest of console that will participate in the search, that aren't the
1053         // current console
1054         List<Console> vcs = VirtualMountPointConsole.getVirtualConsoleForSearchPath(directory);
1055         for (int i = vcs.size() - 1; i >= 0; i--) {
1056             Console vc = vcs.get(i);
1057             if (vc.equals(c)) {
1058                 vcs.remove(i);
1059             }
1060         }
1061         consoles.addAll(vcs);
1062
1063         // Register all the executables
1064         for (Console cc : consoles) {
1065             executables.add(
1066                     cc.getExecutableFactory().newCreator().
1067                         createFindExecutable(directory, search, asyncResultListener));
1068         }
1069
1070         // Launch every executable
1071         int count = executables.size();
1072         for (int i = 0; i < count; i++) {
1073             execute(context, executables.get(i), consoles.get(i));
1074         }
1075
1076         // Return the first of the executables
1077         return executables.get(0);
1078     }
1079
1080     /**
1081      * Method that compute the disk usage of a folder.
1082      *
1083      * @param context The current context (needed if console == null)
1084      * @param directory The "absolute" directory where start the search
1085      * @param asyncResultListener The partial result listener
1086      * @param console The console in which execute the program.
1087      * <code>null</code> to attach to the default console
1088      * @return FolderUsageExecutable The command executed in background
1089      * @throws FileNotFoundException If the initial directory not exists
1090      * @throws IOException If initial directory couldn't be checked
1091      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1092      * @throws NoSuchFileOrDirectory If the file or directory was not found
1093      * @throws ConsoleAllocException If the console can't be allocated
1094      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1095      * @throws CommandNotFoundException If the command was not found
1096      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1097      * @throws ExecutionException If the operation returns a invalid exit code
1098      * @throws CancelledOperationException If the operation was cancelled
1099      * @see FolderUsage
1100      * @see FolderUsageExecutable
1101      */
1102     public static FolderUsageExecutable getFolderUsage(
1103             Context context, String directory,
1104             AsyncResultListener asyncResultListener, Console console)
1105             throws FileNotFoundException, IOException, ConsoleAllocException,
1106             NoSuchFileOrDirectory, InsufficientPermissionsException,
1107             CommandNotFoundException, OperationTimeoutException,
1108             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1109         Console c = ensureConsoleForFile(context, console, directory);
1110         FolderUsageExecutable executable =
1111                 c.getExecutableFactory().newCreator().
1112                     createFolderUsageExecutable(directory, asyncResultListener);
1113         execute(context, executable, c);
1114         return executable;
1115     }
1116
1117     /**
1118      * Method that retrieves the disk usage of all the mount points.
1119      *
1120      * @param context The current context (needed if console == null)
1121      * @param console The console in which execute the program. <code>null</code>
1122      * to attach to the default console
1123      * @return List<DiskUsage> The disk usage of all the mount points
1124      * @throws FileNotFoundException If the initial directory not exists
1125      * @throws IOException If initial directory couldn't be checked
1126      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1127      * @throws NoSuchFileOrDirectory If the file or directory was not found
1128      * @throws ConsoleAllocException If the console can't be allocated
1129      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1130      * @throws CommandNotFoundException If the command was not found
1131      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1132      * @throws ExecutionException If the operation returns a invalid exit code
1133      * @throws CancelledOperationException If the operation was cancelled
1134      * @see DiskUsageExecutable
1135      */
1136     public static List<DiskUsage> getDiskUsage(Context context, Console console)
1137             throws FileNotFoundException, IOException, ConsoleAllocException,
1138             NoSuchFileOrDirectory, InsufficientPermissionsException,
1139             CommandNotFoundException, OperationTimeoutException,
1140             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1141         Console c = ensureConsole(context, console);
1142         DiskUsageExecutable executable =
1143                 c.getExecutableFactory().newCreator().createDiskUsageExecutable();
1144         execute(context, executable, c);
1145         List<DiskUsage> diskUsage = executable.getResult();
1146         diskUsage.addAll(VirtualMountPointConsole.getVirtualDiskUsage());
1147         return diskUsage;
1148     }
1149
1150     /**
1151      * Method that retrieves the disk usage of all mount points.
1152      *
1153      * @param context The current context (needed if console == null)
1154      * @param dir The directory of which obtain its disk usage
1155      * @param console The console in which execute the program. <code>null</code>
1156      * to attach to the default console
1157      * @return DiskUsage The disk usage information
1158      * @throws FileNotFoundException If the initial directory not exists
1159      * @throws IOException If initial directory couldn't be checked
1160      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1161      * @throws NoSuchFileOrDirectory If the file or directory was not found
1162      * @throws ConsoleAllocException If the console can't be allocated
1163      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1164      * @throws CommandNotFoundException If the command was not found
1165      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1166      * @throws ExecutionException If the operation returns a invalid exit code
1167      * @throws CancelledOperationException If the operation was cancelled
1168      * @see DiskUsageExecutable
1169      */
1170     public static DiskUsage getDiskUsage(Context context, String dir, Console console)
1171             throws FileNotFoundException, IOException, ConsoleAllocException,
1172             NoSuchFileOrDirectory, InsufficientPermissionsException,
1173             CommandNotFoundException, OperationTimeoutException,
1174             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1175
1176         // Virtual directories don't implement a disk usage command, just return the data if
1177         // the directory belongs to a virtual filesystem
1178         VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(dir);
1179         if (vc != null) {
1180             return vc.getDiskUsage(dir);
1181         } else {
1182             Console c = ensureConsole(context, console);
1183             DiskUsageExecutable executable =
1184                     c.getExecutableFactory().newCreator().createDiskUsageExecutable(dir);
1185             execute(context, executable, c);
1186             List<DiskUsage> du = executable.getResult();
1187             for (DiskUsage d : du) {
1188                 if (d.getMountPoint().equals(dir)) {
1189                     return d;
1190                 }
1191             }
1192         }
1193         return null;
1194     }
1195
1196     /**
1197      * Method that retrieves the information about all mount points.
1198      *
1199      * @param context The current context (needed if console == null)
1200      * @param console The console in which execute the program. <code>null</code>
1201      * to attach to the default console
1202      * @return List<MountPoint> The filesystem mount points
1203      * @throws FileNotFoundException If the initial directory not exists
1204      * @throws IOException If initial directory couldn't be checked
1205      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1206      * @throws NoSuchFileOrDirectory If the file or directory was not found
1207      * @throws ConsoleAllocException If the console can't be allocated
1208      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1209      * @throws CommandNotFoundException If the command was not found
1210      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1211      * @throws ExecutionException If the operation returns a invalid exit code
1212      * @throws CancelledOperationException If the operation was cancelled
1213      * @see MountPointInfoExecutable
1214      */
1215     public static List<MountPoint> getMountPoints(Context context, Console console)
1216             throws FileNotFoundException, IOException, ConsoleAllocException,
1217             NoSuchFileOrDirectory, InsufficientPermissionsException,
1218             CommandNotFoundException, OperationTimeoutException,
1219             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1220         Console c = ensureConsole(context, console);
1221         MountPointInfoExecutable executable =
1222                 c.getExecutableFactory().newCreator().createMountPointInfoExecutable();
1223         execute(context, executable, c);
1224         List<MountPoint> mountPoints = executable.getResult();
1225         mountPoints.addAll(VirtualMountPointConsole.getVirtualMountPoints());
1226         return mountPoints;
1227     }
1228
1229     /**
1230      * Method that re-mounts a filesystem from his mount point info.
1231      *
1232      * @param context The current context (needed if console == null)
1233      * @param mp The mount point to re-mount
1234      * @param rw Indicates if the operation re-mounted the device as read-write
1235      * @param console The console in which execute the program. <code>null</code>
1236      * to attach to the default console
1237      * @return boolean The operation result
1238      * @throws FileNotFoundException If the initial directory not exists
1239      * @throws IOException If initial directory couldn't be checked
1240      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1241      * @throws NoSuchFileOrDirectory If the file or directory was not found
1242      * @throws ConsoleAllocException If the console can't be allocated
1243      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1244      * @throws CommandNotFoundException If the command was not found
1245      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1246      * @throws ExecutionException If the operation returns a invalid exit code
1247      * @throws CancelledOperationException If the operation was cancelled
1248      * @see MountExecutable
1249      */
1250     public static boolean remount(Context context, MountPoint mp, boolean rw, Console console)
1251             throws FileNotFoundException, IOException, ConsoleAllocException,
1252             NoSuchFileOrDirectory, InsufficientPermissionsException,
1253             CommandNotFoundException, OperationTimeoutException,
1254             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1255         boolean ret = false;
1256         if (mp.isSecure()) {
1257             // Unmount the secure file system
1258             SecureConsole sc = (SecureConsole) ensureConsoleForFile(
1259                     context, console, mp.getMountPoint());
1260             if (rw) {
1261                 sc.mount(context);
1262             } else {
1263                 sc.unmount();
1264             }
1265             ret = true;
1266         } else {
1267             Console c = ensureConsole(context, console);
1268             MountExecutable executable =
1269                     c.getExecutableFactory().newCreator().createMountExecutable(mp, rw);
1270             execute(context, executable, c);
1271             ret = executable.getResult().booleanValue();
1272         }
1273
1274         if (ret) {
1275             // Send an broadcast to notify that the mount state of this filesystem changed
1276             Intent intent = new Intent(FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED);
1277             intent.putExtra(FileManagerSettings.EXTRA_MOUNTPOINT, mp.getMountPoint());
1278             intent.putExtra(FileManagerSettings.EXTRA_STATUS, rw
1279                     ? MountExecutable.READWRITE : MountExecutable.READONLY);
1280             context.sendBroadcast(intent);
1281         }
1282
1283         return ret;
1284     }
1285
1286     /**
1287      * Method that makes a quick folder search for the passed expression.
1288      *
1289      * @param context The current context (needed if console == null)
1290      * @param regexp The expression to search
1291      * @param console The console in which execute the program. <code>null</code>
1292      * to attach to the default console
1293      * @return List<String> The list of directories found
1294      * @throws FileNotFoundException If the initial directory not exists
1295      * @throws IOException If initial directory couldn't be checked
1296      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1297      * @throws NoSuchFileOrDirectory If the file or directory was not found
1298      * @throws ConsoleAllocException If the console can't be allocated
1299      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1300      * @throws CommandNotFoundException If the command was not found
1301      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1302      * @throws ExecutionException If the operation returns a invalid exit code
1303      * @throws CancelledOperationException If the operation was cancelled
1304      * @see QuickFolderSearchExecutable
1305      */
1306     public static List<String> quickFolderSearch(Context context, String regexp, Console console)
1307             throws FileNotFoundException, IOException, ConsoleAllocException,
1308             NoSuchFileOrDirectory, InsufficientPermissionsException,
1309             CommandNotFoundException, OperationTimeoutException,
1310             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1311         Console c = ensureConsole(context, console);
1312         QuickFolderSearchExecutable executable =
1313                 c.getExecutableFactory().newCreator().createQuickFolderSearchExecutable(regexp);
1314         execute(context, executable, c);
1315         return executable.getResult();
1316     }
1317
1318     /**
1319      * Method that retrieves the process identifier of all the processes (a program
1320      * owned by the main process of this application).
1321      *
1322      * @param context The current context (needed if console == null)
1323      * @param pid The process id of the shell where the command is running
1324      * @param console The console in which execute the program. <code>null</code>
1325      * to attach to the default console
1326      * @return List<Integer> The processes identifiers of the program or <code>null</code> if not exists
1327      * @throws FileNotFoundException If the initial directory not exists
1328      * @throws IOException If initial directory couldn't be checked
1329      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1330      * @throws NoSuchFileOrDirectory If the file or directory was not found
1331      * @throws ConsoleAllocException If the console can't be allocated
1332      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1333      * @throws CommandNotFoundException If the command was not found
1334      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1335      * @throws ExecutionException If the operation returns a invalid exit code
1336      * @throws CancelledOperationException If the operation was cancelled
1337      * @see ProcessIdExecutable
1338      */
1339     public static List<Integer> getProcessesIds(
1340             Context context, int pid, Console console)
1341             throws FileNotFoundException, IOException, ConsoleAllocException,
1342             NoSuchFileOrDirectory, InsufficientPermissionsException,
1343             CommandNotFoundException, OperationTimeoutException,
1344             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1345         Console c = ensureConsole(context, console);
1346         ProcessIdExecutable executable =
1347                 c.getExecutableFactory().newCreator().createProcessIdExecutable(pid);
1348         execute(context, executable, c);
1349         return executable.getResult();
1350     }
1351
1352     /**
1353      * Method that retrieves the process identifier of a process (a program
1354      * owned by the main process of this application).
1355      *
1356      * @param context The current context (needed if console == null)
1357      * @param pid The process id of the shell where the command is running
1358      * @param processName The process name
1359      * @param console The console in which execute the program. <code>null</code>
1360      * to attach to the default console
1361      * @return Integer The process identifier of the program or <code>null</code> if not exists
1362      * @throws FileNotFoundException If the initial directory not exists
1363      * @throws IOException If initial directory couldn't be checked
1364      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1365      * @throws NoSuchFileOrDirectory If the file or directory was not found
1366      * @throws ConsoleAllocException If the console can't be allocated
1367      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1368      * @throws CommandNotFoundException If the command was not found
1369      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1370      * @throws ExecutionException If the operation returns a invalid exit code
1371      * @throws CancelledOperationException If the operation was cancelled
1372      * @see ProcessIdExecutable
1373      */
1374     public static Integer getProcessId(
1375             Context context, int pid, String processName, Console console)
1376             throws FileNotFoundException, IOException, ConsoleAllocException,
1377             NoSuchFileOrDirectory, InsufficientPermissionsException,
1378             CommandNotFoundException, OperationTimeoutException,
1379             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1380         Console c = ensureConsole(context, console);
1381         ProcessIdExecutable executable =
1382                 c.getExecutableFactory().newCreator().createProcessIdExecutable(pid, processName);
1383         execute(context, executable, c);
1384         List<Integer> pids = executable.getResult();
1385         if (pids != null && pids.size() > 0) {
1386             return pids.get(0);
1387         }
1388         return null;
1389     }
1390
1391     /**
1392      * Method that send a signal to a process.
1393      *
1394      * @param context The current context (needed if console == null)
1395      * @param process The process which to send the signal
1396      * @param signal The signal to send
1397      * @param console The console in which execute the program. <code>null</code>
1398      * to attach to the default console
1399      * @throws FileNotFoundException If the initial directory not exists
1400      * @throws IOException If initial directory couldn't be checked
1401      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1402      * @throws NoSuchFileOrDirectory If the file or directory was not found
1403      * @throws ConsoleAllocException If the console can't be allocated
1404      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1405      * @throws CommandNotFoundException If the command was not found
1406      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1407      * @throws ExecutionException If the operation returns a invalid exit code
1408      * @throws CancelledOperationException If the operation was cancelled
1409      * @see ProcessIdExecutable
1410      */
1411     public static void sendSignal(
1412             Context context, int process, SIGNAL signal, Console console)
1413             throws FileNotFoundException, IOException, ConsoleAllocException,
1414             NoSuchFileOrDirectory, InsufficientPermissionsException,
1415             CommandNotFoundException, OperationTimeoutException,
1416             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1417         Console c = ensureConsole(context, console);
1418         SendSignalExecutable executable =
1419                 c.getExecutableFactory().newCreator().createSendSignalExecutable(process, signal);
1420         execute(context, executable, c);
1421     }
1422
1423     /**
1424      * Method that send a kill signal to a process.
1425      *
1426      * @param context The current context (needed if console == null)
1427      * @param process The process which to send the signal
1428      * @param console The console in which execute the program. <code>null</code>
1429      * to attach to the default console
1430      * @throws FileNotFoundException If the initial directory not exists
1431      * @throws IOException If initial directory couldn't be checked
1432      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1433      * @throws NoSuchFileOrDirectory If the file or directory was not found
1434      * @throws ConsoleAllocException If the console can't be allocated
1435      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1436      * @throws CommandNotFoundException If the command was not found
1437      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1438      * @throws ExecutionException If the operation returns a invalid exit code
1439      * @throws CancelledOperationException If the operation was cancelled
1440      * @see ProcessIdExecutable
1441      */
1442     public static void sendSignal(
1443             Context context, int process, Console console)
1444             throws FileNotFoundException, IOException, ConsoleAllocException,
1445             NoSuchFileOrDirectory, InsufficientPermissionsException,
1446             CommandNotFoundException, OperationTimeoutException,
1447             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1448         Console c = ensureConsole(context, console);
1449         SendSignalExecutable executable =
1450                 c.getExecutableFactory().newCreator().createKillExecutable(process);
1451         execute(context, executable, c);
1452     }
1453
1454     /**
1455      * Method that read data from disk.
1456      *
1457      * @param context The current context (needed if console == null)
1458      * @param file The file where to read the data
1459      * @param asyncResultListener The partial result listener
1460      * @param console The console in which execute the program.
1461      * <code>null</code> to attach to the default console
1462      * @return ReadExecutable The command executed in background
1463      * @throws FileNotFoundException If the initial directory not exists
1464      * @throws IOException If initial directory couldn't be checked
1465      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1466      * @throws NoSuchFileOrDirectory If the file or directory was not found
1467      * @throws ConsoleAllocException If the console can't be allocated
1468      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1469      * @throws CommandNotFoundException If the command was not found
1470      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1471      * @throws ExecutionException If the operation returns a invalid exit code
1472      * @throws CancelledOperationException If the operation was cancelled
1473      * @see "byte[]"
1474      * @see ReadExecutable
1475      */
1476     public static ReadExecutable read(
1477             Context context, String file,
1478             AsyncResultListener asyncResultListener, Console console)
1479             throws FileNotFoundException, IOException, ConsoleAllocException,
1480             NoSuchFileOrDirectory, InsufficientPermissionsException,
1481             CommandNotFoundException, OperationTimeoutException,
1482             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1483         Console c = ensureConsoleForFile(context, console, file);
1484         ReadExecutable executable =
1485                 c.getExecutableFactory().newCreator().
1486                     createReadExecutable(file, asyncResultListener);
1487         execute(context, executable, c);
1488         return executable;
1489     }
1490
1491     /**
1492      * Method that writes data to disk.
1493      *
1494      * @param context The current context (needed if console == null)
1495      * @param file The file where to write the data
1496      * @param asyncResultListener The partial result listener
1497      * @param console The console in which execute the program.
1498      * <code>null</code> to attach to the default console
1499      * @return WriteExecutable The command executed in background
1500      * @throws FileNotFoundException If the initial directory not exists
1501      * @throws IOException If initial directory couldn't be checked
1502      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1503      * @throws NoSuchFileOrDirectory If the file or directory was not found
1504      * @throws ConsoleAllocException If the console can't be allocated
1505      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1506      * @throws CommandNotFoundException If the command was not found
1507      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1508      * @throws ExecutionException If the operation returns a invalid exit code
1509      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
1510      * @throws CancelledOperationException If the operation was cancelled
1511      * @see WriteExecutable
1512      */
1513     public static WriteExecutable write(
1514             Context context, String file,
1515             AsyncResultListener asyncResultListener, Console console)
1516             throws FileNotFoundException, IOException, ConsoleAllocException,
1517             NoSuchFileOrDirectory, InsufficientPermissionsException,
1518             CommandNotFoundException, OperationTimeoutException,
1519             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
1520             CancelledOperationException {
1521         Console c = ensureConsoleForFile(context, console, file);
1522
1523         // Create a wrapper listener, for unmount the filesystem if necessary
1524         UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener();
1525         wrapperListener.mCtx = context;
1526         wrapperListener.mConsole = c;
1527         wrapperListener.mRef = asyncResultListener;
1528
1529         // Prior to write to disk the data, ensure that can write to the disk using
1530         // createFile method
1531         //- Create
1532         CreateFileExecutable executable1 =
1533                 c.getExecutableFactory().newCreator().createCreateFileExecutable(file);
1534         boolean unmount = writableExecute(context, executable1, c, true);
1535         if (executable1.getResult().booleanValue()) {
1536             // Configure the rest of attributes of the wrapper listener
1537             wrapperListener.mUnmount = unmount;
1538             wrapperListener.mMountPoint = executable1.getDstWritableMountPoint();
1539
1540             //- Write
1541             WriteExecutable executable2 =
1542                     c.getExecutableFactory().newCreator().
1543                         createWriteExecutable(file, wrapperListener);
1544             execute(context, executable2, c);
1545             return executable2;
1546         }
1547         throw new ExecutionException(String.format("Fail to create file %s", file)); //$NON-NLS-1$
1548     }
1549
1550     /**
1551      * Method that archive-compress file system objects.
1552      *
1553      * @param context The current context (needed if console == null)
1554      * @param mode The compression mode
1555      * @param dst The destination compressed file
1556      * @param src The array of source files to compress
1557      * @param asyncResultListener The partial result listener
1558      * @param console The console in which execute the program.
1559      * <code>null</code> to attach to the default console
1560      * @return CompressExecutable The command executed in background
1561      * @throws FileNotFoundException If the initial directory not exists
1562      * @throws IOException If initial directory couldn't be checked
1563      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1564      * @throws NoSuchFileOrDirectory If the file or directory was not found
1565      * @throws ConsoleAllocException If the console can't be allocated
1566      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1567      * @throws CommandNotFoundException If the command was not found
1568      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1569      * @throws ExecutionException If the operation returns a invalid exit code
1570      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
1571      * @throws CancelledOperationException If the operation was cancelled
1572      * @see CompressExecutable
1573      */
1574     public static CompressExecutable compress(
1575             Context context, CompressionMode mode, String dst, String[] src,
1576             AsyncResultListener asyncResultListener, Console console)
1577             throws FileNotFoundException, IOException, ConsoleAllocException,
1578             NoSuchFileOrDirectory, InsufficientPermissionsException,
1579             CommandNotFoundException, OperationTimeoutException,
1580             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
1581             CancelledOperationException {
1582         Console c = ensureConsole(context, console);
1583
1584         // Create a wrapper listener, for unmount the filesystem if necessary
1585         UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener();
1586         wrapperListener.mCtx = context;
1587         wrapperListener.mConsole = c;
1588         wrapperListener.mRef = asyncResultListener;
1589
1590         CompressExecutable executable1 =
1591                 c.getExecutableFactory().newCreator().
1592                     createCompressExecutable(mode, dst, src, wrapperListener);
1593
1594         // Prior to write to disk the data, ensure that can write to the disk using
1595         // createFile method
1596         //- Create
1597         String compressOutFile = executable1.getOutCompressedFile();
1598         CreateFileExecutable executable2 =
1599                 c.getExecutableFactory().
1600                     newCreator().
1601                         createCreateFileExecutable(compressOutFile);
1602         boolean unmount = writableExecute(context, executable2, c, true);
1603         if (executable2.getResult().booleanValue()) {
1604             // Configure the rest of attributes of the wrapper listener
1605             wrapperListener.mUnmount = unmount;
1606             wrapperListener.mMountPoint = executable2.getDstWritableMountPoint();
1607
1608             // Some archive modes requires a new file. Ensure that the created
1609             // file doesn't exists
1610             DeleteFileExecutable executable3 =
1611                                 c.getExecutableFactory().
1612                                     newCreator().
1613                                         createDeleteFileExecutable(compressOutFile);
1614             writableExecute(context, executable3, c, true);
1615             if (executable3.getResult().booleanValue()) {
1616                 //- Compress
1617                 execute(context, executable1, c);
1618                 return executable1;
1619             }
1620         }
1621         throw new ExecutionException(
1622                 String.format("Fail to create file %s", compressOutFile)); //$NON-NLS-1$
1623     }
1624
1625     /**
1626      * Method that compress a file system object.
1627      *
1628      * @param context The current context (needed if console == null)
1629      * @param mode The compression mode
1630      * @param src The file to compress
1631      * @param asyncResultListener The partial result listener
1632      * @param console The console in which execute the program.
1633      * <code>null</code> to attach to the default console
1634      * @return CompressExecutable The command executed in background
1635      * @throws FileNotFoundException If the initial directory not exists
1636      * @throws IOException If initial directory couldn't be checked
1637      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1638      * @throws NoSuchFileOrDirectory If the file or directory was not found
1639      * @throws ConsoleAllocException If the console can't be allocated
1640      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1641      * @throws CommandNotFoundException If the command was not found
1642      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1643      * @throws ExecutionException If the operation returns a invalid exit code
1644      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
1645      * @throws CancelledOperationException If the operation was cancelled
1646      * @see CompressExecutable
1647      */
1648     public static CompressExecutable compress(
1649             Context context, CompressionMode mode, String src,
1650             AsyncResultListener asyncResultListener, Console console)
1651             throws FileNotFoundException, IOException, ConsoleAllocException,
1652             NoSuchFileOrDirectory, InsufficientPermissionsException,
1653             CommandNotFoundException, OperationTimeoutException,
1654             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
1655             CancelledOperationException {
1656         Console c = ensureConsole(context, console);
1657
1658         // Create a wrapper listener, for unmount the filesystem if necessary
1659         UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener();
1660         wrapperListener.mCtx = context;
1661         wrapperListener.mConsole = c;
1662         wrapperListener.mRef = asyncResultListener;
1663
1664         CompressExecutable executable1 =
1665                 c.getExecutableFactory().newCreator().
1666                     createCompressExecutable(mode, src, wrapperListener);
1667
1668         // Prior to write to disk the data, ensure that can write to the disk using
1669         // createFile method
1670         //- Create
1671         String compressOutFile = executable1.getOutCompressedFile();
1672         CreateFileExecutable executable2 =
1673                 c.getExecutableFactory().
1674                     newCreator().
1675                         createCreateFileExecutable(compressOutFile);
1676         boolean unmount = writableExecute(context, executable2, c, true);
1677         if (executable2.getResult().booleanValue()) {
1678             // Configure the rest of attributes of the wrapper listener
1679             wrapperListener.mUnmount = unmount;
1680             wrapperListener.mMountPoint = executable2.getDstWritableMountPoint();
1681
1682             //- Compress
1683             execute(context, executable1, c);
1684             return executable1;
1685         }
1686         throw new ExecutionException(
1687                 String.format("Fail to compress to file %s", compressOutFile)); //$NON-NLS-1$
1688     }
1689
1690     /**
1691      * Method that uncompress file system objects.
1692      *
1693      * @param context The current context (needed if console == null)
1694      * @param src The file to compress
1695      * @param dst The destination file of folder (if null this method resolve with the best
1696      * fit based on the src)
1697      * @param asyncResultListener The partial result listener
1698      * @param console The console in which execute the program.
1699      * <code>null</code> to attach to the default console
1700      * @return UncompressExecutable The command executed in background
1701      * @throws FileNotFoundException If the initial directory not exists
1702      * @throws IOException If initial directory couldn't be checked
1703      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1704      * @throws NoSuchFileOrDirectory If the file or directory was not found
1705      * @throws ConsoleAllocException If the console can't be allocated
1706      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1707      * @throws CommandNotFoundException If the command was not found
1708      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1709      * @throws ExecutionException If the operation returns a invalid exit code
1710      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
1711      * @throws CancelledOperationException If the operation was cancelled
1712      * @see CompressExecutable
1713      */
1714     public static UncompressExecutable uncompress(
1715             Context context, String src, String dst,
1716             AsyncResultListener asyncResultListener, Console console)
1717             throws FileNotFoundException, IOException, ConsoleAllocException,
1718             NoSuchFileOrDirectory, InsufficientPermissionsException,
1719             CommandNotFoundException, OperationTimeoutException,
1720             ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException,
1721             CancelledOperationException {
1722         Console c = ensureConsole(context, console);
1723
1724         // Create a wrapper listener, for unmount the filesystem if necessary
1725         UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener();
1726         wrapperListener.mCtx = context;
1727         wrapperListener.mConsole = c;
1728         wrapperListener.mRef = asyncResultListener;
1729
1730         UncompressExecutable executable1 =
1731                 c.getExecutableFactory().newCreator().
1732                     createUncompressExecutable(src, dst, wrapperListener);
1733
1734         // Prior to write to disk the data, ensure that can write to the disk using
1735         // createFile or createFolder method
1736
1737         String compressOutFile = executable1.getOutUncompressedFile();
1738         WritableExecutable executable2 = null;
1739         if (executable1.IsArchive()) {
1740             //- Create Folder
1741             executable2 =
1742                     c.getExecutableFactory().
1743                         newCreator().
1744                             createCreateDirectoryExecutable(compressOutFile);
1745         } else {
1746             //- Create File
1747             executable2 =
1748                     c.getExecutableFactory().
1749                         newCreator().
1750                             createCreateFileExecutable(compressOutFile);
1751         }
1752         boolean unmount = writableExecute(context, executable2, c, true);
1753         if (((Boolean)executable2.getResult()).booleanValue()) {
1754             // Configure the rest of attributes of the wrapper listener
1755             wrapperListener.mUnmount = unmount;
1756             wrapperListener.mMountPoint = executable2.getDstWritableMountPoint();
1757
1758             //- Compress
1759             execute(context, executable1, c);
1760
1761             // Do media scan
1762             MediaScannerConnection.scanFile(context, new String[]{
1763                     MediaHelper.normalizeMediaPath(compressOutFile)}, null, null);
1764
1765             return executable1;
1766         }
1767         throw new ExecutionException(
1768                 String.format("Fail to uncompress to %s", compressOutFile)); //$NON-NLS-1$
1769     }
1770
1771     /**
1772      * Method that calculates the checksum of a file system object.
1773      *
1774      * @param context The current context (needed if console == null)
1775      * @param src The source file
1776      * @param asyncResultListener The partial result listener
1777      * @param console The console in which execute the program.
1778      * <code>null</code> to attach to the default console
1779      * @return ChecksumExecutable The command executed in background
1780      * @throws FileNotFoundException If the initial directory not exists
1781      * @throws IOException If initial directory couldn't be checked
1782      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1783      * @throws NoSuchFileOrDirectory If the file or directory was not found
1784      * @throws ConsoleAllocException If the console can't be allocated
1785      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1786      * @throws CommandNotFoundException If the command was not found
1787      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1788      * @throws ExecutionException If the operation returns a invalid exit code
1789      * @throws CancelledOperationException If the operation was cancelled
1790      * @see ChecksumExecutable
1791      */
1792     public static ChecksumExecutable checksum(Context context, String src,
1793             AsyncResultListener asyncResultListener, Console console)
1794             throws FileNotFoundException, IOException, ConsoleAllocException,
1795             NoSuchFileOrDirectory, InsufficientPermissionsException,
1796             CommandNotFoundException, OperationTimeoutException,
1797             ExecutionException, InvalidCommandDefinitionException, CancelledOperationException {
1798         Console c = ensureConsoleForFile(context, console, src);
1799         ChecksumExecutable executable =
1800                 c.getExecutableFactory().newCreator().
1801                     createChecksumExecutable(src, asyncResultListener);
1802         execute(context, executable, c);
1803         return executable;
1804     }
1805
1806     /**
1807      * Method that re-execute the command.
1808      *
1809      * @param context The current context (needed if console == null)
1810      * @param executable The executable program to execute
1811      * @param console The console in which execute the program. <code>null</code>
1812      * to attach to the default console
1813      * @return Object The result of the re-execution
1814      * @throws NoSuchFileOrDirectory If the file or directory was not found
1815      * @throws ConsoleAllocException If the console can't be allocated
1816      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1817      * @throws CommandNotFoundException If the command was not found
1818      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1819      * @throws ExecutionException If the operation returns a invalid exit code
1820      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
1821      * @throws InvalidCommandDefinitionException If the command has an invalid definition
1822      * @throws IOException If initial directory couldn't be checked
1823      * @throws CancelledOperationException If the operation was cancelled
1824      * @throws FileNotFoundException If the initial directory not exists
1825      */
1826     public static Object reexecute(
1827             Context context , SyncResultExecutable executable, Console console)
1828             throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory,
1829             OperationTimeoutException, ExecutionException,
1830             CommandNotFoundException, ReadOnlyFilesystemException,
1831             FileNotFoundException, IOException, InvalidCommandDefinitionException,
1832             CancelledOperationException {
1833         Console c = ensureConsole(context, console);
1834         c.execute(executable, context);
1835         return executable.getResult();
1836     }
1837
1838
1839     /**
1840      * Method that execute a program.
1841      *
1842      * @param context The current context (needed if console == null)
1843      * @param executable The executable program to execute
1844      * @param console The console in which execute the program. <code>null</code> to attach
1845      * to the default console
1846      * @throws NoSuchFileOrDirectory If the file or directory was not found
1847      * @throws ConsoleAllocException If the console can't be allocated
1848      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1849      * @throws CommandNotFoundException If the command was not found
1850      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1851      * @throws ExecutionException If the operation returns a invalid exit code
1852      * @throws CancelledOperationException If the operation was cancelled
1853      * @throws AuthenticationFailedException If the operation failed caused by an
1854      * authentication failure
1855      */
1856     private static void execute(Context context, Executable executable, Console console)
1857             throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory,
1858             OperationTimeoutException, ExecutionException, CommandNotFoundException,
1859             CancelledOperationException, AuthenticationFailedException {
1860         try {
1861             console.execute(executable, context);
1862         } catch (ReadOnlyFilesystemException rofEx) {
1863             // ReadOnlyFilesystemException don't have sense if command is not writable
1864             // WritableExecutable must be used with "writableExecute" method
1865             throw new ExecutionException(rofEx.getMessage(), rofEx);
1866         }
1867     }
1868
1869     /**
1870      * Method that execute a program that requires write permissions over the filesystem. This
1871      * method ensure mount/unmount the filesystem before/after executing the operation.
1872      *
1873      * @param context The current context (needed if console == null)
1874      * @param executable The writable executable program to execute
1875      * @param console The console in which execute the program. <code>null</code> to attach
1876      * to the default console
1877      * @throws NoSuchFileOrDirectory If the file or directory was not found
1878      * @throws ConsoleAllocException If the console can't be allocated
1879      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1880      * @throws CommandNotFoundException If the command was not found
1881      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1882      * @throws ExecutionException If the operation returns a invalid exit code
1883      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
1884      * @throws CancelledOperationException If the operation was cancelled
1885      * @throws AuthenticationFailedException If the operation failed caused by an
1886      * authentication failure
1887      */
1888     private static void writableExecute(Context context, WritableExecutable executable,
1889             Console console) throws ConsoleAllocException, InsufficientPermissionsException,
1890             NoSuchFileOrDirectory, OperationTimeoutException, ExecutionException,
1891             CommandNotFoundException, ReadOnlyFilesystemException, CancelledOperationException,
1892             AuthenticationFailedException{
1893         writableExecute(context, executable, console, false);
1894     }
1895
1896     /**
1897      * Method that execute a program that requires write permissions over the filesystem. This
1898      * method ensure mount/unmount the filesystem before/after executing the operation.
1899      *
1900      * @param context The current context (needed if console == null)
1901      * @param executable The writable executable program to execute
1902      * @param console The console in which execute the program. <code>null</code> to attach
1903      * to the default console
1904      * @param leaveDeviceMounted If the operation must leave the filesystem mounted after
1905      * the execution
1906      * @return boolean If the filesystem was left unmount
1907      * @throws NoSuchFileOrDirectory If the file or directory was not found
1908      * @throws ConsoleAllocException If the console can't be allocated
1909      * @throws InsufficientPermissionsException If an operation requires elevated permissions
1910      * @throws CommandNotFoundException If the command was not found
1911      * @throws OperationTimeoutException If the operation exceeded the maximum time of wait
1912      * @throws ExecutionException If the operation returns a invalid exit code
1913      * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
1914      * @throws CancelledOperationException If the operation was cancelled
1915      * @throws AuthenticationFailedException If the operation failed caused by an
1916      * authentication failure
1917      */
1918     private static boolean writableExecute(Context context, WritableExecutable executable,
1919             Console console, boolean leaveDeviceMounted) throws ConsoleAllocException,
1920             InsufficientPermissionsException, NoSuchFileOrDirectory, OperationTimeoutException,
1921             ExecutionException, CommandNotFoundException, ReadOnlyFilesystemException,
1922             CancelledOperationException, AuthenticationFailedException {
1923
1924         //Retrieve the mount point information to check if a remount operation is required
1925         //There are 2 mount points: destination and source. Check both
1926         // - Destination
1927         boolean needMountDst = false;
1928         MountPoint mpDst = executable.getDstWritableMountPoint();
1929         if (mpDst != null) {
1930             if (MountPointHelper.isMountAllowed(mpDst)) {
1931                 if (!MountPointHelper.isReadWrite(mpDst)) {
1932                     needMountDst = true;
1933                 } else {
1934                     //Mount point is already read-write
1935                 }
1936             } else {
1937                 //For security or physical reasons the mount point can't be
1938                 //mounted as read-write. Execute the command
1939                 //and notify to the user
1940             }
1941         } else {
1942             //Don't have information about the mount point. Execute the command
1943             //and notify to the user
1944         }
1945         // - Source
1946         boolean needMountSrc = false;
1947         MountPoint mpSrc = executable.getSrcWritableMountPoint();
1948         if (mpSrc != null) {
1949             if (MountPointHelper.isMountAllowed(mpSrc)) {
1950                 if (!MountPointHelper.isReadWrite(mpSrc)) {
1951                     needMountSrc = true;
1952                 } else {
1953                     //Mount point is already read-write
1954                 }
1955             } else {
1956                 //For security or physical reasons the mount point can't be
1957                 //mounted as read-write. Execute the command
1958                 //and notify to the user
1959             }
1960         } else {
1961             //Don't have information about the mount point. Execute the command
1962             //and notify to the user
1963         }
1964
1965         //Create the mount/unmount executables
1966         MountExecutable mountDstExecutable = null;
1967         MountExecutable unmountDstExecutable = null;
1968         if (needMountDst) {
1969             mountDstExecutable =
1970                     console.getExecutableFactory().newCreator().
1971                         createMountExecutable(mpDst, true);
1972             unmountDstExecutable =
1973                     console.getExecutableFactory().newCreator().
1974                         createMountExecutable(mpDst, false);
1975         }
1976         MountExecutable mountSrcExecutable = null;
1977         MountExecutable unmountSrcExecutable = null;
1978         if (needMountSrc) {
1979             mountSrcExecutable =
1980                     console.getExecutableFactory().newCreator().
1981                         createMountExecutable(mpSrc, true);
1982             unmountSrcExecutable =
1983                     console.getExecutableFactory().newCreator().
1984                         createMountExecutable(mpSrc, false);
1985         }
1986
1987         //Execute the commands
1988         boolean mountExecutedDst = false;
1989         boolean mountExecutedSrc = false;
1990         try {
1991             if (needMountDst) {
1992                 //Execute the mount command
1993                 console.execute(mountDstExecutable, context);
1994                 mountExecutedDst = true;
1995             }
1996             if (needMountSrc) {
1997                 //Execute the mount command
1998                 console.execute(mountSrcExecutable, context);
1999                 mountExecutedSrc = true;
2000             }
2001
2002             //Execute the command
2003             console.execute(executable, context);
2004
2005         } catch (InsufficientPermissionsException ipEx) {
2006             //Configure the commands to execute
2007             if (needMountDst && !mountExecutedDst) {
2008                 //The failed operation was the mount rw operation
2009                 //This operations is already in the exception in the fifo queue
2010                 ipEx.addExecutable(executable);
2011             } else if (needMountSrc && !mountExecutedSrc) {
2012                 //The failed operation was the mount rw operation
2013                 //This operations is already in the exception in the fifo queue
2014                 ipEx.addExecutable(executable);
2015             }
2016             if (needMountDst) {
2017                 //A mount operation was executed or will be executed
2018                 ipEx.addExecutable(unmountDstExecutable);
2019             }
2020             if (needMountSrc) {
2021                 //A mount operation was executed or will be executed
2022                 ipEx.addExecutable(unmountSrcExecutable);
2023             }
2024
2025             //Rethrow the exception
2026             throw ipEx;
2027
2028         } finally {
2029             //If previously was a mount successful execution, then execute
2030             //and unmount operation
2031             if (mountExecutedDst && !leaveDeviceMounted) {
2032                 //Execute the unmount command
2033                 console.execute(unmountDstExecutable, context);
2034             }
2035             if (mountExecutedSrc && !leaveDeviceMounted) {
2036                 //Execute the unmount command
2037                 console.execute(unmountSrcExecutable, context);
2038             }
2039         }
2040
2041         // If the needed unmount was executed
2042         return (mountExecutedDst || mountExecutedSrc) && leaveDeviceMounted;
2043     }
2044
2045     /**
2046      * Method that ensure the console retrieve the default console if a console
2047      * is not passed.
2048      *
2049      * @param context The current context (needed if console == null)
2050      * @param console The console passed
2051      * @return Console The console passed if not is null. Otherwise, the default console
2052      * @throws InsufficientPermissionsException If an operation requires elevated permissions
2053      * @throws ConsoleAllocException If the console can't be allocated
2054      * @throws InvalidCommandDefinitionException If the command has an invalid definition
2055      * @throws IOException If initial directory couldn't be checked
2056      * @throws FileNotFoundException If the initial directory not exists
2057      */
2058     private static Console ensureConsole(Context context, Console console)
2059             throws FileNotFoundException, IOException, InvalidCommandDefinitionException,
2060             ConsoleAllocException, InsufficientPermissionsException {
2061         Console c = console;
2062         if (c == null) {
2063             c = ConsoleBuilder.getConsole(context);
2064         }
2065         return c;
2066     }
2067
2068     /**
2069      * Method that ensure the console retrieve the default console if a console
2070      * is not passed.
2071      *
2072      * @param context The current context (needed if console == null)
2073      * @param console The console passed
2074      * @param src The source file to check
2075      * @return Console The console passed if not is null. Otherwise, the default console
2076      * @throws InsufficientPermissionsException If an operation requires elevated permissions
2077      * @throws ConsoleAllocException If the console can't be allocated
2078      * @throws InvalidCommandDefinitionException If the command has an invalid definition
2079      * @throws IOException If initial directory couldn't be checked
2080      * @throws FileNotFoundException If the initial directory not exists
2081      */
2082     public static Console ensureConsoleForFile(Context context, Console console, String src)
2083             throws FileNotFoundException, IOException, InvalidCommandDefinitionException,
2084             ConsoleAllocException, InsufficientPermissionsException {
2085
2086         // Check if the path belongs to a virtual mount point
2087         Console c = VirtualMountPointConsole.getVirtualConsoleForPath(src);
2088         if (c != null) {
2089             return c;
2090         }
2091
2092         // Recover a real console
2093         c = console;
2094         if (c == null) {
2095             c = ConsoleBuilder.getConsole(context);
2096         }
2097         return c;
2098     }
2099
2100 }