/* * Copyright (C) 2012 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cyanogenmod.filemanager.util; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.Intent; import android.media.MediaScannerConnection; import android.net.Uri; import android.util.Log; import com.cyanogenmod.filemanager.commands.AsyncResultListener; import com.cyanogenmod.filemanager.commands.ChangeOwnerExecutable; import com.cyanogenmod.filemanager.commands.ChangePermissionsExecutable; import com.cyanogenmod.filemanager.commands.ChecksumExecutable; import com.cyanogenmod.filemanager.commands.CompressExecutable; import com.cyanogenmod.filemanager.commands.ConcurrentAsyncResultListener; import com.cyanogenmod.filemanager.commands.CopyExecutable; import com.cyanogenmod.filemanager.commands.CreateDirExecutable; import com.cyanogenmod.filemanager.commands.CreateFileExecutable; import com.cyanogenmod.filemanager.commands.DeleteDirExecutable; import com.cyanogenmod.filemanager.commands.DeleteFileExecutable; import com.cyanogenmod.filemanager.commands.DiskUsageExecutable; import com.cyanogenmod.filemanager.commands.EchoExecutable; import com.cyanogenmod.filemanager.commands.ExecExecutable; import com.cyanogenmod.filemanager.commands.Executable; import com.cyanogenmod.filemanager.commands.FindExecutable; import com.cyanogenmod.filemanager.commands.FolderUsageExecutable; import com.cyanogenmod.filemanager.commands.GroupsExecutable; import com.cyanogenmod.filemanager.commands.IdentityExecutable; import com.cyanogenmod.filemanager.commands.LinkExecutable; import com.cyanogenmod.filemanager.commands.ListExecutable; import com.cyanogenmod.filemanager.commands.MountExecutable; import com.cyanogenmod.filemanager.commands.MountPointInfoExecutable; import com.cyanogenmod.filemanager.commands.MoveExecutable; import com.cyanogenmod.filemanager.commands.ParentDirExecutable; import com.cyanogenmod.filemanager.commands.ProcessIdExecutable; import com.cyanogenmod.filemanager.commands.QuickFolderSearchExecutable; import com.cyanogenmod.filemanager.commands.ReadExecutable; import com.cyanogenmod.filemanager.commands.ResolveLinkExecutable; import com.cyanogenmod.filemanager.commands.SIGNAL; import com.cyanogenmod.filemanager.commands.SendSignalExecutable; import com.cyanogenmod.filemanager.commands.SyncResultExecutable; import com.cyanogenmod.filemanager.commands.UncompressExecutable; import com.cyanogenmod.filemanager.commands.WritableExecutable; import com.cyanogenmod.filemanager.commands.WriteExecutable; import com.cyanogenmod.filemanager.commands.shell.InvalidCommandDefinitionException; import com.cyanogenmod.filemanager.console.AuthenticationFailedException; import com.cyanogenmod.filemanager.console.CancelledOperationException; import com.cyanogenmod.filemanager.console.CommandNotFoundException; import com.cyanogenmod.filemanager.console.Console; import com.cyanogenmod.filemanager.console.ConsoleAllocException; import com.cyanogenmod.filemanager.console.ConsoleBuilder; import com.cyanogenmod.filemanager.console.ExecutionException; import com.cyanogenmod.filemanager.console.InsufficientPermissionsException; import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory; import com.cyanogenmod.filemanager.console.OperationTimeoutException; import com.cyanogenmod.filemanager.console.ReadOnlyFilesystemException; import com.cyanogenmod.filemanager.console.VirtualMountPointConsole; import com.cyanogenmod.filemanager.console.secure.SecureConsole; import com.cyanogenmod.filemanager.model.Directory; import com.cyanogenmod.filemanager.model.DiskUsage; import com.cyanogenmod.filemanager.model.FileSystemObject; import com.cyanogenmod.filemanager.model.FolderUsage; import com.cyanogenmod.filemanager.model.Group; import com.cyanogenmod.filemanager.model.Identity; import com.cyanogenmod.filemanager.model.MountPoint; import com.cyanogenmod.filemanager.model.ParentDirectory; import com.cyanogenmod.filemanager.model.Permissions; import com.cyanogenmod.filemanager.model.Query; import com.cyanogenmod.filemanager.model.SearchResult; import com.cyanogenmod.filemanager.model.User; import com.cyanogenmod.filemanager.preferences.CompressionMode; import com.cyanogenmod.filemanager.preferences.FileManagerSettings; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Stack; /** * A helper class with useful methods for deal with commands. */ public final class CommandHelper { private static final String TAG = "CommandHelper"; /** * A wrapper class for asynchronous operations that need restore the filesystem * after the operation. */ private static class UnmountAsyncResultListener implements AsyncResultListener { Context mCtx; AsyncResultListener mRef; boolean mUnmount = false; Console mConsole; MountPoint mMountPoint; /** * Constructor of UnmountAsyncResultListener */ public UnmountAsyncResultListener() { super(); } /** * {@inheritDoc} */ @Override public void onAsyncStart() { if (this.mRef != null) { this.mRef.onAsyncStart(); } } /** * {@inheritDoc} */ @Override public void onAsyncEnd(boolean cancelled) { if (this.mRef != null) { this.mRef.onAsyncEnd(cancelled); } } /** * {@inheritDoc} */ @Override public void onAsyncExitCode(int exitCode) { if (this.mRef != null) { this.mRef.onAsyncExitCode(exitCode); } // Now if that the process has finished check if the operation // requires to unmount the filesystem if (this.mUnmount && this.mConsole != null && this.mMountPoint != null && this.mCtx != null) { // Run in background because the console is still executing // the command Thread t = new Thread() { @Override public void run() { try { MountExecutable unmountExecutable = UnmountAsyncResultListener.this.mConsole. getExecutableFactory().newCreator(). createMountExecutable( UnmountAsyncResultListener.this.mMountPoint, false); UnmountAsyncResultListener.this.mConsole.execute( unmountExecutable, mCtx); } catch (Exception e) { // Capture the exception but not show to the user ExceptionUtil.translateException( UnmountAsyncResultListener.this.mCtx, e, true, false); } } }; t.start(); } } /** * {@inheritDoc} */ @Override public void onPartialResult(Object result) { if (this.mRef != null) { this.mRef.onPartialResult(result); } } /** * {@inheritDoc} */ @Override public void onException(Exception cause) { if (this.mRef != null) { this.mRef.onException(cause); } } } /** * Constructor of CommandHelper. */ private CommandHelper() { super(); } /** * Method that changes the owner of a file system object. * * @param context The current context (needed if console == null) * @param src The file system object to change its permissions * @param user The new user owner of the file system object * @param group The new group owner of the file system object * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see ChangeOwnerExecutable */ public static boolean changeOwner( Context context, String src, User user, Group group, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsole(context, console); ChangeOwnerExecutable executable = c.getExecutableFactory(). newCreator().createChangeOwnerExecutable(src, user, group); writableExecute(context, executable, c); return executable.getResult().booleanValue(); } /** * Method that changes the permissions of a file system object. * * @param context The current context (needed if console == null) * @param src The file system object to change its permissions * @param permissions The new permissions of the file system object * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see ChangePermissionsExecutable */ public static boolean changePermissions( Context context, String src, Permissions permissions, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsole(context, console); ChangePermissionsExecutable executable = c.getExecutableFactory().newCreator(). createChangePermissionsExecutable(src, permissions); writableExecute(context, executable, c); return executable.getResult().booleanValue(); } /** * Method that creates a directory. * * @param context The current context (needed if console == null) * @param directory The directory to create * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see CreateDirExecutable */ public static boolean createDirectory(Context context, String directory, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, directory); CreateDirExecutable executable = c.getExecutableFactory().newCreator().createCreateDirectoryExecutable(directory); writableExecute(context, executable, c); // Do media scan MediaScannerConnection.scanFile(context, new String[]{ MediaHelper.normalizeMediaPath(directory)}, null, null); return executable.getResult().booleanValue(); } /** * Method that creates a file. * * @param context The current context (needed if console == null) * @param file The file to create * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see CreateFileExecutable */ public static boolean createFile(Context context, String file, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, file); CreateFileExecutable executable = c.getExecutableFactory().newCreator().createCreateFileExecutable(file); writableExecute(context, executable, c); // Do media scan MediaScannerConnection.scanFile(context, new String[]{ MediaHelper.normalizeMediaPath(file)}, null, null); return executable.getResult().booleanValue(); } private static String[] collectScanPaths(final Context context, String path) { ArrayList paths = new ArrayList<>(); Stack pathsToScan = new Stack<>(); try { FileSystemObject fso = getFileInfo(context, path, null); if (fso == null) { return new String[0]; } pathsToScan.push(fso); while (!pathsToScan.isEmpty()) { fso = pathsToScan.pop(); paths.add(MediaHelper.normalizeMediaPath(fso.getFullPath())); if (fso instanceof Directory) { List files = CommandHelper.listFiles(context, fso.getFullPath(), null); if (files == null) { continue; } for (FileSystemObject file : files) { if (file instanceof ParentDirectory) { continue; } pathsToScan.push(file); } } } return paths.toArray(new String[paths.size()]); } catch (IOException | ConsoleAllocException | NoSuchFileOrDirectory | InsufficientPermissionsException | CommandNotFoundException | OperationTimeoutException | ExecutionException | InvalidCommandDefinitionException e) { // Just stop scanning Log.e(TAG, "Recursive Delete Failed with: ", e); return new String[0]; } } /** * Method that deletes a directory. * * @param context The current context (needed if console == null) * @param directory The directory to delete * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see DeleteDirExecutable */ public static boolean deleteDirectory(Context context, String directory, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { String[] pathsToScan = collectScanPaths(context, directory); Console c = ensureConsoleForFile(context, console, directory); DeleteDirExecutable executable = c.getExecutableFactory().newCreator().createDeleteDirExecutable(directory); writableExecute(context, executable, c); // Remove from mediascanner MediaScannerConnection.scanFile(context, pathsToScan, null, null); return executable.getResult().booleanValue(); } /** * Method that deletes a file. * * @param context The current context (needed if console == null) * @param file The file to delete * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see DeleteFileExecutable */ public static boolean deleteFile(Context context, String file, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { String[] pathsToScan = collectScanPaths(context, file); Console c = ensureConsoleForFile(context, console, file); DeleteFileExecutable executable = c.getExecutableFactory().newCreator().createDeleteFileExecutable(file); writableExecute(context, executable, c); // Remove from mediascanner MediaScannerConnection.scanFile(context, pathsToScan, null, null); return executable.getResult().booleanValue(); } /** * Method that resolves a symlink to its real file system object. * * @param context The current context (needed if console == null) * @param symlink The link to be resolved * @param console The console in which execute the program. null * to attach to the default console * @return String The resolved link * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ResolveLinkExecutable */ public static FileSystemObject resolveSymlink(Context context, String symlink, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); ResolveLinkExecutable executable = c.getExecutableFactory().newCreator().createResolveLinkExecutable(symlink); execute(context, executable, c); return executable.getResult(); } /** * Method that retrieves the information of a file system object. * * @param context The current context (needed if console == null) * @param src The file system object * @param console The console in which execute the program. null * to attach to the default console * @return FileSystemObject The file system object reference * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ListExecutable */ public static FileSystemObject getFileInfo(Context context, String src, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { return getFileInfo(context, src, true, console); } /** * Method that retrieves the information of a file system object. * * @param context The current context (needed if console == null) * @param src The file system object * @param followSymlinks It should be follow the symlinks * @param console The console in which execute the program. null * to attach to the default console * @return FileSystemObject The file system object reference * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ListExecutable */ public static FileSystemObject getFileInfo( Context context, String src, boolean followSymlinks, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, src); ListExecutable executable = c.getExecutableFactory(). newCreator().createFileInfoExecutable(src, followSymlinks); execute(context, executable, c); List files = executable.getResult(); if (files != null && files.size() > 0) { // Resolve symlinks prior to return the object if (followSymlinks) { FileHelper.resolveSymlinks(context, files); } return files.get(0); } return null; } /** * Method that retrieves the information of the groups of the current user. * * @param context The current context (needed if console == null) * @param console The console in which execute the program. null * to attach to the default console * @return List The groups of the current user * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see GroupsExecutable */ public static List getGroups(Context context, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); GroupsExecutable executable = c.getExecutableFactory().newCreator().createGroupsExecutable(); execute(context, executable, c); return executable.getResult(); } /** * Method that retrieves the identity of the current user. * * @param context The current context (needed if console == null) * @param console The console in which execute the program. null * to attach to the default console * @return Identity The identity of the current user * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see IdentityExecutable */ public static Identity getIdentity(Context context, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); IdentityExecutable executable = c.getExecutableFactory().newCreator().createIdentityExecutable(); execute(context, executable, c); return executable.getResult(); } /** * Method that creates a symlink of an other file system object. * * @param context The current context (needed if console == null) * @param src The absolute path to the source fso * @param link The absolute path to the link fso * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see LinkExecutable */ public static boolean createLink(Context context, String src, String link, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsole(context, console); LinkExecutable executable = c.getExecutableFactory().newCreator().createLinkExecutable(src, link); writableExecute(context, executable, c); return executable.getResult().booleanValue(); } /** * Method that retrieves the parent directory of a file system object. * * @param context The current context (needed if console == null) * @param src The file system object * @param console The console in which execute the program. null * to attach to the default console * @return String The current directory * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ParentDirExecutable */ public static String getParentDir(Context context, String src, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, src); ParentDirExecutable executable = c.getExecutableFactory().newCreator().createParentDirExecutable(src); execute(context, executable, c); return executable.getResult(); } /** * Method that retrieves the value of a variable. * * @param context The current context (needed if console == null) * @param msg The message to echo. This message can have one or multiple variables * and text. xe: "This is $VAR_1 the value of $VAR2" or simple "$PATH" * @param console The console in which execute the program. null * to attach to the default console * @return String The value of the variable * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see EchoExecutable */ public static String getVariable(Context context, String msg, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); EchoExecutable executable = c.getExecutableFactory().newCreator().createEchoExecutable(msg); execute(context, executable, c); return executable.getResult(); } /** * Method that lists a directory. * * @param context The current context (needed if console == null) * @param directory The path of the directory to list * @param console The console in which execute the program. null * to attach to the default console * @return List The list of files of the directory * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ListExecutable */ public static List listFiles( Context context, String directory, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, directory); ListExecutable executable = c.getExecutableFactory().newCreator(). createListExecutable(directory); execute(context, executable, c); List result = executable.getResult(); FileHelper.resolveSymlinks(context, result); // And now we need to verify if the directory is the if (VirtualMountPointConsole.isVirtualStorageDir(directory)) { result.addAll(VirtualMountPointConsole.getVirtualMountableDirectories()); } return result; } private static void recursiveScan(@NonNull final Context context, @Nullable String srcPath, @NonNull String destPath) { recursiveScan(context, srcPath, destPath, -1); } private static class FileSystemObjectWithDepth { public FileSystemObject fso; public int depth; public FileSystemObjectWithDepth(FileSystemObject fso, int depth) { this.fso = fso; this.depth = depth; } } /** * * @param context * @param srcPath null or the source in which the file is being moved from * @param destPath the root of the path being created */ private static void recursiveScan(@NonNull final Context context, @Nullable String srcPath, @NonNull String destPath, int maxDepth) { ArrayList paths = new ArrayList<>(); Stack pathsToScan = new Stack<>(); try { FileSystemObject fso = getFileInfo(context, destPath, null); if (fso == null) { return; } pathsToScan.push(new FileSystemObjectWithDepth(fso, 0)); while (!pathsToScan.isEmpty()) { FileSystemObjectWithDepth fsowd = pathsToScan.pop(); fso = fsowd.fso; if (srcPath != null) { String src = fso.getFullPath().replace(destPath, srcPath); // Add the path to be deleted paths.add(MediaHelper.normalizeMediaPath(src)); } // Add the path to be added paths.add(MediaHelper.normalizeMediaPath(fso.getFullPath())); if (fso instanceof Directory && (maxDepth == -1 || fsowd.depth < maxDepth)) { try { List files = CommandHelper.listFiles(context, fso.getFullPath(), null); if (files == null) { continue; } for (FileSystemObject file : files) { if (file instanceof ParentDirectory) { continue; } pathsToScan.push(new FileSystemObjectWithDepth(file, fsowd.depth + 1)); } } catch (IOException | ConsoleAllocException | NoSuchFileOrDirectory | InsufficientPermissionsException | CommandNotFoundException | OperationTimeoutException | ExecutionException | InvalidCommandDefinitionException e) { // Just skip this directory } } if (paths.size() > 100) { MediaScannerConnection.scanFile(context, paths.toArray(new String[paths.size()]), null, null); paths.clear(); } } MediaScannerConnection.scanFile(context, paths.toArray(new String[paths.size()]), null, null); } catch (IOException | ConsoleAllocException | NoSuchFileOrDirectory | InsufficientPermissionsException | CommandNotFoundException | OperationTimeoutException | ExecutionException | InvalidCommandDefinitionException e) { // Just stop scanning } } /** * Method that moves a file system object. * * @param context The current context (needed if console == null) * @param src The file system object to move * @param dst The destination file system object * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see MoveExecutable */ public static boolean move(Context context, String src, String dst, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console cSrc = ensureConsoleForFile(context, console, src); Console cDst = ensureConsoleForFile(context, console, dst); boolean ret = true; if (cSrc.equals(cDst) && !FileHelper.isSamePath(src, dst)) { // Is safe to use the same console MoveExecutable executable = cSrc.getExecutableFactory().newCreator().createMoveExecutable(src, dst); writableExecute(context, executable, cSrc); ret = executable.getResult().booleanValue(); } else { // We need to create a temporary file in the external filesystem to make it // available to virtual consoles // 1.- Move to a temporary file with the source console (destination // is a safe location) File tmp = FileHelper.createTempFilename(context, true); try { MoveExecutable moveExecutable = cSrc.getExecutableFactory().newCreator().createMoveExecutable( src, tmp.getAbsolutePath()); writableExecute(context, moveExecutable, cSrc); if (!moveExecutable.getResult().booleanValue()) { ret = false; } // 2.- Move the temporary file to the final filesystem with the destination console if (ret) { moveExecutable = cDst.getExecutableFactory().newCreator().createMoveExecutable( tmp.getAbsolutePath(), dst); writableExecute(context, moveExecutable, cDst); if (!moveExecutable.getResult().booleanValue()) { ret = false; } } } finally { FileHelper.deleteFileOrFolder(tmp); } } // Do media scan (don't scan the file if is virtual file) if (ret) { File parent = new File(dst).getParentFile(); if ((parent != null && !VirtualMountPointConsole.isVirtualStorageResource(parent .getAbsolutePath()))) { // Scan source MediaScannerConnection.scanFile(context, new String[] { MediaHelper.normalizeMediaPath(src) }, null, null); // Recursive scan of the parent dir of the dest. This mitigates a VFAT // issue where a file named "foo." will silently be renamed as "foo". // This ensures that we report the correct filename to the media scanner // by re-reading the filename from the file system. recursiveScan(context, null, parent.getAbsolutePath(), 1); } } return ret; } /** * Method that copies a file system object. * * @param context The current context (needed if console == null) * @param src The file system object to copy * @param dst The destination file system object * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see CopyExecutable */ public static boolean copy(Context context, String src, String dst, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console cSrc = ensureConsoleForFile(context, console, src); Console cDst = ensureConsoleForFile(context, console, dst); boolean ret = true; if (cSrc.equals(cDst) && !FileHelper.isSamePath(src, dst)) { // Is safe to use the same console CopyExecutable executable = cSrc.getExecutableFactory().newCreator().createCopyExecutable(src, dst); writableExecute(context, executable, cSrc); ret = executable.getResult().booleanValue(); } else { // We need to create a temporary file in the external filesystem to make it // available to virtual consoles // 1.- Copy to a temporary file with the source console (destination // is a safe location) File tmp = FileHelper.createTempFilename(context, true); try { CopyExecutable copyExecutable = cSrc.getExecutableFactory().newCreator().createCopyExecutable( src, tmp.getAbsolutePath()); writableExecute(context, copyExecutable, cSrc); if (!copyExecutable.getResult().booleanValue()) { ret = false; } // 2.- Move the temporary file to the final filesystem with the destination console if (ret) { MoveExecutable moveExecutable = cDst.getExecutableFactory().newCreator().createMoveExecutable( tmp.getAbsolutePath(), dst); writableExecute(context, moveExecutable, cDst); if (!moveExecutable.getResult().booleanValue()) { ret = false; } } } finally { FileHelper.deleteFileOrFolder(tmp); } } // Do media scan (don't scan the file if is virtual file) if (ret) { if (!VirtualMountPointConsole.isVirtualStorageResource(dst)) { recursiveScan(context, null, dst); } } return ret; } /** * Method that executes a command. * * @param context The current context (needed if console == null) * @param cmd The command to execute * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return ExecExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ExecExecutable */ public static ExecExecutable exec( Context context, String cmd, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); ExecExecutable executable = c.getExecutableFactory().newCreator(). createExecExecutable(cmd, asyncResultListener); execute(context, executable, c); return executable; } /** * Method that does a search in a directory tree seeking for some terms. * * @param context The current context (needed if console == null) * @param directory The "absolute" directory where start the search * @param search The terms to be searched * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return FindExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see SearchResult * @see FindExecutable */ public static FindExecutable findFiles( Context context, String directory, Query search, ConcurrentAsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { List consoles = new ArrayList(); List executables = new ArrayList(); Console c = ensureConsoleForFile(context, console, directory); consoles.add(c); // Obtain all the rest of console that will participate in the search, that aren't the // current console List vcs = VirtualMountPointConsole.getVirtualConsoleForSearchPath(directory); for (int i = vcs.size() - 1; i >= 0; i--) { Console vc = vcs.get(i); if (vc.equals(c)) { vcs.remove(i); } } consoles.addAll(vcs); // Register all the executables for (Console cc : consoles) { executables.add( cc.getExecutableFactory().newCreator(). createFindExecutable(directory, search, asyncResultListener)); } // Launch every executable int count = executables.size(); for (int i = 0; i < count; i++) { execute(context, executables.get(i), consoles.get(i)); } // Return the first of the executables return executables.get(0); } /** * Method that compute the disk usage of a folder. * * @param context The current context (needed if console == null) * @param directory The "absolute" directory where start the search * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return FolderUsageExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see FolderUsage * @see FolderUsageExecutable */ public static FolderUsageExecutable getFolderUsage( Context context, String directory, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, directory); FolderUsageExecutable executable = c.getExecutableFactory().newCreator(). createFolderUsageExecutable(directory, asyncResultListener); execute(context, executable, c); return executable; } /** * Method that retrieves the disk usage of all the mount points. * * @param context The current context (needed if console == null) * @param console The console in which execute the program. null * to attach to the default console * @return List The disk usage of all the mount points * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see DiskUsageExecutable */ public static List getDiskUsage(Context context, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); DiskUsageExecutable executable = c.getExecutableFactory().newCreator().createDiskUsageExecutable(); execute(context, executable, c); List diskUsage = executable.getResult(); diskUsage.addAll(VirtualMountPointConsole.getVirtualDiskUsage()); return diskUsage; } /** * Method that retrieves the disk usage of all mount points. * * @param context The current context (needed if console == null) * @param dir The directory of which obtain its disk usage * @param console The console in which execute the program. null * to attach to the default console * @return DiskUsage The disk usage information * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see DiskUsageExecutable */ public static DiskUsage getDiskUsage(Context context, String dir, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { // Virtual directories don't implement a disk usage command, just return the data if // the directory belongs to a virtual filesystem VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(dir); if (vc != null) { return vc.getDiskUsage(dir); } else { Console c = ensureConsole(context, console); DiskUsageExecutable executable = c.getExecutableFactory().newCreator().createDiskUsageExecutable(dir); execute(context, executable, c); List du = executable.getResult(); for (DiskUsage d : du) { if (d.getMountPoint().equals(dir)) { return d; } } } return null; } /** * Method that retrieves the information about all mount points. * * @param context The current context (needed if console == null) * @param console The console in which execute the program. null * to attach to the default console * @return List The filesystem mount points * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see MountPointInfoExecutable */ public static List getMountPoints(Context context, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); MountPointInfoExecutable executable = c.getExecutableFactory().newCreator().createMountPointInfoExecutable(); execute(context, executable, c); List mountPoints = executable.getResult(); mountPoints.addAll(VirtualMountPointConsole.getVirtualMountPoints()); return mountPoints; } /** * Method that re-mounts a filesystem from his mount point info. * * @param context The current context (needed if console == null) * @param mp The mount point to re-mount * @param rw Indicates if the operation re-mounted the device as read-write * @param console The console in which execute the program. null * to attach to the default console * @return boolean The operation result * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see MountExecutable */ public static boolean remount(Context context, MountPoint mp, boolean rw, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { boolean ret = false; if (mp.isSecure()) { // Unmount the secure file system SecureConsole sc = (SecureConsole) ensureConsoleForFile( context, console, mp.getMountPoint()); if (rw) { sc.mount(context); } else { sc.unmount(); } ret = true; } else { Console c = ensureConsole(context, console); MountExecutable executable = c.getExecutableFactory().newCreator().createMountExecutable(mp, rw); execute(context, executable, c); ret = executable.getResult().booleanValue(); } if (ret) { // Send an broadcast to notify that the mount state of this filesystem changed Intent intent = new Intent(FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED); intent.putExtra(FileManagerSettings.EXTRA_MOUNTPOINT, mp.getMountPoint()); intent.putExtra(FileManagerSettings.EXTRA_STATUS, rw ? MountExecutable.READWRITE : MountExecutable.READONLY); context.sendBroadcast(intent); } return ret; } /** * Method that makes a quick folder search for the passed expression. * * @param context The current context (needed if console == null) * @param regexp The expression to search * @param console The console in which execute the program. null * to attach to the default console * @return List The list of directories found * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see QuickFolderSearchExecutable */ public static List quickFolderSearch(Context context, String regexp, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); QuickFolderSearchExecutable executable = c.getExecutableFactory().newCreator().createQuickFolderSearchExecutable(regexp); execute(context, executable, c); return executable.getResult(); } /** * Method that retrieves the process identifier of all the processes (a program * owned by the main process of this application). * * @param context The current context (needed if console == null) * @param pid The process id of the shell where the command is running * @param console The console in which execute the program. null * to attach to the default console * @return List The processes identifiers of the program or null if not exists * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ProcessIdExecutable */ public static List getProcessesIds( Context context, int pid, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); ProcessIdExecutable executable = c.getExecutableFactory().newCreator().createProcessIdExecutable(pid); execute(context, executable, c); return executable.getResult(); } /** * Method that retrieves the process identifier of a process (a program * owned by the main process of this application). * * @param context The current context (needed if console == null) * @param pid The process id of the shell where the command is running * @param processName The process name * @param console The console in which execute the program. null * to attach to the default console * @return Integer The process identifier of the program or null if not exists * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ProcessIdExecutable */ public static Integer getProcessId( Context context, int pid, String processName, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); ProcessIdExecutable executable = c.getExecutableFactory().newCreator().createProcessIdExecutable(pid, processName); execute(context, executable, c); List pids = executable.getResult(); if (pids != null && pids.size() > 0) { return pids.get(0); } return null; } /** * Method that send a signal to a process. * * @param context The current context (needed if console == null) * @param process The process which to send the signal * @param signal The signal to send * @param console The console in which execute the program. null * to attach to the default console * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ProcessIdExecutable */ public static void sendSignal( Context context, int process, SIGNAL signal, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); SendSignalExecutable executable = c.getExecutableFactory().newCreator().createSendSignalExecutable(process, signal); execute(context, executable, c); } /** * Method that send a kill signal to a process. * * @param context The current context (needed if console == null) * @param process The process which to send the signal * @param console The console in which execute the program. null * to attach to the default console * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ProcessIdExecutable */ public static void sendSignal( Context context, int process, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); SendSignalExecutable executable = c.getExecutableFactory().newCreator().createKillExecutable(process); execute(context, executable, c); } /** * Method that read data from disk. * * @param context The current context (needed if console == null) * @param file The file where to read the data * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return ReadExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see "byte[]" * @see ReadExecutable */ public static ReadExecutable read( Context context, String file, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, file); ReadExecutable executable = c.getExecutableFactory().newCreator(). createReadExecutable(file, asyncResultListener); execute(context, executable, c); return executable; } /** * Method that writes data to disk. * * @param context The current context (needed if console == null) * @param file The file where to write the data * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return WriteExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see WriteExecutable */ public static WriteExecutable write( Context context, String file, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, file); // Create a wrapper listener, for unmount the filesystem if necessary UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener(); wrapperListener.mCtx = context; wrapperListener.mConsole = c; wrapperListener.mRef = asyncResultListener; // Prior to write to disk the data, ensure that can write to the disk using // createFile method //- Create CreateFileExecutable executable1 = c.getExecutableFactory().newCreator().createCreateFileExecutable(file); boolean unmount = writableExecute(context, executable1, c, true); if (executable1.getResult().booleanValue()) { // Configure the rest of attributes of the wrapper listener wrapperListener.mUnmount = unmount; wrapperListener.mMountPoint = executable1.getDstWritableMountPoint(); //- Write WriteExecutable executable2 = c.getExecutableFactory().newCreator(). createWriteExecutable(file, wrapperListener); execute(context, executable2, c); return executable2; } throw new ExecutionException(String.format("Fail to create file %s", file)); //$NON-NLS-1$ } /** * Method that archive-compress file system objects. * * @param context The current context (needed if console == null) * @param mode The compression mode * @param dst The destination compressed file * @param src The array of source files to compress * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return CompressExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see CompressExecutable */ public static CompressExecutable compress( Context context, CompressionMode mode, String dst, String[] src, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsole(context, console); // Create a wrapper listener, for unmount the filesystem if necessary UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener(); wrapperListener.mCtx = context; wrapperListener.mConsole = c; wrapperListener.mRef = asyncResultListener; CompressExecutable executable1 = c.getExecutableFactory().newCreator(). createCompressExecutable(mode, dst, src, wrapperListener); // Prior to write to disk the data, ensure that can write to the disk using // createFile method //- Create String compressOutFile = executable1.getOutCompressedFile(); CreateFileExecutable executable2 = c.getExecutableFactory(). newCreator(). createCreateFileExecutable(compressOutFile); boolean unmount = writableExecute(context, executable2, c, true); if (executable2.getResult().booleanValue()) { // Configure the rest of attributes of the wrapper listener wrapperListener.mUnmount = unmount; wrapperListener.mMountPoint = executable2.getDstWritableMountPoint(); // Some archive modes requires a new file. Ensure that the created // file doesn't exists DeleteFileExecutable executable3 = c.getExecutableFactory(). newCreator(). createDeleteFileExecutable(compressOutFile); writableExecute(context, executable3, c, true); if (executable3.getResult().booleanValue()) { //- Compress execute(context, executable1, c); return executable1; } } throw new ExecutionException( String.format("Fail to create file %s", compressOutFile)); //$NON-NLS-1$ } /** * Method that compress a file system object. * * @param context The current context (needed if console == null) * @param mode The compression mode * @param src The file to compress * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return CompressExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see CompressExecutable */ public static CompressExecutable compress( Context context, CompressionMode mode, String src, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsole(context, console); // Create a wrapper listener, for unmount the filesystem if necessary UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener(); wrapperListener.mCtx = context; wrapperListener.mConsole = c; wrapperListener.mRef = asyncResultListener; CompressExecutable executable1 = c.getExecutableFactory().newCreator(). createCompressExecutable(mode, src, wrapperListener); // Prior to write to disk the data, ensure that can write to the disk using // createFile method //- Create String compressOutFile = executable1.getOutCompressedFile(); CreateFileExecutable executable2 = c.getExecutableFactory(). newCreator(). createCreateFileExecutable(compressOutFile); boolean unmount = writableExecute(context, executable2, c, true); if (executable2.getResult().booleanValue()) { // Configure the rest of attributes of the wrapper listener wrapperListener.mUnmount = unmount; wrapperListener.mMountPoint = executable2.getDstWritableMountPoint(); //- Compress execute(context, executable1, c); return executable1; } throw new ExecutionException( String.format("Fail to compress to file %s", compressOutFile)); //$NON-NLS-1$ } /** * Method that uncompress file system objects. * * @param context The current context (needed if console == null) * @param src The file to compress * @param dst The destination file of folder (if null this method resolve with the best * fit based on the src) * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return UncompressExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @see CompressExecutable */ public static UncompressExecutable uncompress( Context context, String src, String dst, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException, CancelledOperationException { Console c = ensureConsole(context, console); // Create a wrapper listener, for unmount the filesystem if necessary UnmountAsyncResultListener wrapperListener = new UnmountAsyncResultListener(); wrapperListener.mCtx = context; wrapperListener.mConsole = c; wrapperListener.mRef = asyncResultListener; UncompressExecutable executable1 = c.getExecutableFactory().newCreator(). createUncompressExecutable(src, dst, wrapperListener); // Prior to write to disk the data, ensure that can write to the disk using // createFile or createFolder method String compressOutFile = executable1.getOutUncompressedFile(); WritableExecutable executable2 = null; if (executable1.IsArchive()) { //- Create Folder executable2 = c.getExecutableFactory(). newCreator(). createCreateDirectoryExecutable(compressOutFile); } else { //- Create File executable2 = c.getExecutableFactory(). newCreator(). createCreateFileExecutable(compressOutFile); } boolean unmount = writableExecute(context, executable2, c, true); if (((Boolean)executable2.getResult()).booleanValue()) { // Configure the rest of attributes of the wrapper listener wrapperListener.mUnmount = unmount; wrapperListener.mMountPoint = executable2.getDstWritableMountPoint(); //- Compress execute(context, executable1, c); // Do media scan MediaScannerConnection.scanFile(context, new String[]{ MediaHelper.normalizeMediaPath(compressOutFile)}, null, null); return executable1; } throw new ExecutionException( String.format("Fail to uncompress to %s", compressOutFile)); //$NON-NLS-1$ } /** * Method that calculates the checksum of a file system object. * * @param context The current context (needed if console == null) * @param src The source file * @param asyncResultListener The partial result listener * @param console The console in which execute the program. * null to attach to the default console * @return ChecksumExecutable The command executed in background * @throws FileNotFoundException If the initial directory not exists * @throws IOException If initial directory couldn't be checked * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @see ChecksumExecutable */ public static ChecksumExecutable checksum(Context context, String src, AsyncResultListener asyncResultListener, Console console) throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsoleForFile(context, console, src); ChecksumExecutable executable = c.getExecutableFactory().newCreator(). createChecksumExecutable(src, asyncResultListener); execute(context, executable, c); return executable; } /** * Method that re-execute the command. * * @param context The current context (needed if console == null) * @param executable The executable program to execute * @param console The console in which execute the program. null * to attach to the default console * @return Object The result of the re-execution * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws IOException If initial directory couldn't be checked * @throws CancelledOperationException If the operation was cancelled * @throws FileNotFoundException If the initial directory not exists */ public static Object reexecute( Context context , SyncResultExecutable executable, Console console) throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory, OperationTimeoutException, ExecutionException, CommandNotFoundException, ReadOnlyFilesystemException, FileNotFoundException, IOException, InvalidCommandDefinitionException, CancelledOperationException { Console c = ensureConsole(context, console); c.execute(executable, context); return executable.getResult(); } /** * Method that execute a program. * * @param context The current context (needed if console == null) * @param executable The executable program to execute * @param console The console in which execute the program. null to attach * to the default console * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws CancelledOperationException If the operation was cancelled * @throws AuthenticationFailedException If the operation failed caused by an * authentication failure */ private static void execute(Context context, Executable executable, Console console) throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory, OperationTimeoutException, ExecutionException, CommandNotFoundException, CancelledOperationException, AuthenticationFailedException { try { console.execute(executable, context); } catch (ReadOnlyFilesystemException rofEx) { // ReadOnlyFilesystemException don't have sense if command is not writable // WritableExecutable must be used with "writableExecute" method throw new ExecutionException(rofEx.getMessage(), rofEx); } } /** * Method that execute a program that requires write permissions over the filesystem. This * method ensure mount/unmount the filesystem before/after executing the operation. * * @param context The current context (needed if console == null) * @param executable The writable executable program to execute * @param console The console in which execute the program. null to attach * to the default console * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @throws AuthenticationFailedException If the operation failed caused by an * authentication failure */ private static void writableExecute(Context context, WritableExecutable executable, Console console) throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory, OperationTimeoutException, ExecutionException, CommandNotFoundException, ReadOnlyFilesystemException, CancelledOperationException, AuthenticationFailedException{ writableExecute(context, executable, console, false); } /** * Method that execute a program that requires write permissions over the filesystem. This * method ensure mount/unmount the filesystem before/after executing the operation. * * @param context The current context (needed if console == null) * @param executable The writable executable program to execute * @param console The console in which execute the program. null to attach * to the default console * @param leaveDeviceMounted If the operation must leave the filesystem mounted after * the execution * @return boolean If the filesystem was left unmount * @throws NoSuchFileOrDirectory If the file or directory was not found * @throws ConsoleAllocException If the console can't be allocated * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws CommandNotFoundException If the command was not found * @throws OperationTimeoutException If the operation exceeded the maximum time of wait * @throws ExecutionException If the operation returns a invalid exit code * @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem * @throws CancelledOperationException If the operation was cancelled * @throws AuthenticationFailedException If the operation failed caused by an * authentication failure */ private static boolean writableExecute(Context context, WritableExecutable executable, Console console, boolean leaveDeviceMounted) throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory, OperationTimeoutException, ExecutionException, CommandNotFoundException, ReadOnlyFilesystemException, CancelledOperationException, AuthenticationFailedException { //Retrieve the mount point information to check if a remount operation is required //There are 2 mount points: destination and source. Check both // - Destination boolean needMountDst = false; MountPoint mpDst = executable.getDstWritableMountPoint(); if (mpDst != null) { if (MountPointHelper.isMountAllowed(mpDst)) { if (!MountPointHelper.isReadWrite(mpDst)) { needMountDst = true; } else { //Mount point is already read-write } } else { //For security or physical reasons the mount point can't be //mounted as read-write. Execute the command //and notify to the user } } else { //Don't have information about the mount point. Execute the command //and notify to the user } // - Source boolean needMountSrc = false; MountPoint mpSrc = executable.getSrcWritableMountPoint(); if (mpSrc != null) { if (MountPointHelper.isMountAllowed(mpSrc)) { if (!MountPointHelper.isReadWrite(mpSrc)) { needMountSrc = true; } else { //Mount point is already read-write } } else { //For security or physical reasons the mount point can't be //mounted as read-write. Execute the command //and notify to the user } } else { //Don't have information about the mount point. Execute the command //and notify to the user } //Create the mount/unmount executables MountExecutable mountDstExecutable = null; MountExecutable unmountDstExecutable = null; if (needMountDst) { mountDstExecutable = console.getExecutableFactory().newCreator(). createMountExecutable(mpDst, true); unmountDstExecutable = console.getExecutableFactory().newCreator(). createMountExecutable(mpDst, false); } MountExecutable mountSrcExecutable = null; MountExecutable unmountSrcExecutable = null; if (needMountSrc) { mountSrcExecutable = console.getExecutableFactory().newCreator(). createMountExecutable(mpSrc, true); unmountSrcExecutable = console.getExecutableFactory().newCreator(). createMountExecutable(mpSrc, false); } //Execute the commands boolean mountExecutedDst = false; boolean mountExecutedSrc = false; try { if (needMountDst) { //Execute the mount command console.execute(mountDstExecutable, context); mountExecutedDst = true; } if (needMountSrc) { //Execute the mount command console.execute(mountSrcExecutable, context); mountExecutedSrc = true; } //Execute the command console.execute(executable, context); } catch (InsufficientPermissionsException ipEx) { //Configure the commands to execute if (needMountDst && !mountExecutedDst) { //The failed operation was the mount rw operation //This operations is already in the exception in the fifo queue ipEx.addExecutable(executable); } else if (needMountSrc && !mountExecutedSrc) { //The failed operation was the mount rw operation //This operations is already in the exception in the fifo queue ipEx.addExecutable(executable); } if (needMountDst) { //A mount operation was executed or will be executed ipEx.addExecutable(unmountDstExecutable); } if (needMountSrc) { //A mount operation was executed or will be executed ipEx.addExecutable(unmountSrcExecutable); } //Rethrow the exception throw ipEx; } finally { //If previously was a mount successful execution, then execute //and unmount operation if (mountExecutedDst && !leaveDeviceMounted) { //Execute the unmount command console.execute(unmountDstExecutable, context); } if (mountExecutedSrc && !leaveDeviceMounted) { //Execute the unmount command console.execute(unmountSrcExecutable, context); } } // If the needed unmount was executed return (mountExecutedDst || mountExecutedSrc) && leaveDeviceMounted; } /** * Method that ensure the console retrieve the default console if a console * is not passed. * * @param context The current context (needed if console == null) * @param console The console passed * @return Console The console passed if not is null. Otherwise, the default console * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws ConsoleAllocException If the console can't be allocated * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws IOException If initial directory couldn't be checked * @throws FileNotFoundException If the initial directory not exists */ private static Console ensureConsole(Context context, Console console) throws FileNotFoundException, IOException, InvalidCommandDefinitionException, ConsoleAllocException, InsufficientPermissionsException { Console c = console; if (c == null) { c = ConsoleBuilder.getConsole(context); } return c; } /** * Method that ensure the console retrieve the default console if a console * is not passed. * * @param context The current context (needed if console == null) * @param console The console passed * @param src The source file to check * @return Console The console passed if not is null. Otherwise, the default console * @throws InsufficientPermissionsException If an operation requires elevated permissions * @throws ConsoleAllocException If the console can't be allocated * @throws InvalidCommandDefinitionException If the command has an invalid definition * @throws IOException If initial directory couldn't be checked * @throws FileNotFoundException If the initial directory not exists */ public static Console ensureConsoleForFile(Context context, Console console, String src) throws FileNotFoundException, IOException, InvalidCommandDefinitionException, ConsoleAllocException, InsufficientPermissionsException { // Check if the path belongs to a virtual mount point Console c = VirtualMountPointConsole.getVirtualConsoleForPath(src); if (c != null) { return c; } // Recover a real console c = console; if (c == null) { c = ConsoleBuilder.getConsole(context); } return c; } }