import android.util.Log;
import com.cyanogenmod.filemanager.commands.CopyExecutable;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
*/
@Override
public void execute()
- throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException {
+ throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException,
+ CancelledOperationException {
if (isTrace()) {
Log.v(TAG,
String.format("Moving from %s to %s", //$NON-NLS-1$
}
//Copy recursively
- if (!FileHelper.copyRecursive(s, d, getBufferSize())) {
+ if (!FileHelper.copyRecursive(s, d, getBufferSize(), this)) {
if (isTrace()) {
Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$
}
import android.util.Log;
import com.cyanogenmod.filemanager.commands.MoveExecutable;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
*/
@Override
public void execute()
- throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException {
+ throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException,
+ CancelledOperationException {
if (isTrace()) {
Log.v(TAG,
String.format("Creating from %s to %s", this.mSrc, this.mDst)); //$NON-NLS-1$
//Move or copy recursively
if (d.exists()) {
- if (!FileHelper.copyRecursive(s, d, getBufferSize())) {
+ if (!FileHelper.copyRecursive(s, d, getBufferSize(), this)) {
if (isTrace()) {
Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$
}
} else {
// Move between filesystem is not allow. If rename fails then use copy operation
if (!s.renameTo(d)) {
- if (!FileHelper.copyRecursive(s, d, getBufferSize())) {
+ if (!FileHelper.copyRecursive(s, d, getBufferSize(), this)) {
if (isTrace()) {
Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$
}
package com.cyanogenmod.filemanager.commands.java;
import com.cyanogenmod.filemanager.commands.Executable;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
private boolean mTrace;
private int mBufferSize;
+ private boolean mCancelled = false;
/**
* Constructor of <code>Program</code>
* @throws ExecutionException If the operation returns a invalid exit code
*/
public abstract void execute()
- throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException;
+ throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException,
+ CancelledOperationException;
+ public void requestCancel() {
+ mCancelled = true;
+ }
+
+ public boolean isCancelled() {
+ return mCancelled;
+ }
}
import com.cyanogenmod.filemanager.commands.ExecutableFactory;
import com.cyanogenmod.filemanager.commands.java.JavaExecutableFactory;
import com.cyanogenmod.filemanager.commands.java.Program;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.CommandNotFoundException;
import com.cyanogenmod.filemanager.console.ConsoleAllocException;
import com.cyanogenmod.filemanager.console.ExecutionException;
private static final String TAG = "JavaConsole"; //$NON-NLS-1$
private final int mBufferSize;
+ private Program mActiveProgram;
/**
* Constructor of <code>JavaConsole</code>
@Override
public synchronized void execute(Executable executable, Context ctx)
throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory,
- OperationTimeoutException, ExecutionException, CommandNotFoundException,
- ReadOnlyFilesystemException {
+ OperationTimeoutException, ExecutionException, CommandNotFoundException,
+ CancelledOperationException, ReadOnlyFilesystemException {
// Check that the program is a java program
try {
Program p = (Program)executable;
// Execute the program
final Program program = (Program)executable;
+ mActiveProgram = program;
program.setTrace(isTrace());
program.setBufferSize(this.mBufferSize);
if (program.isAsynchronous()) {
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onCancel() {
+ mActiveProgram.requestCancel();
+ return true;
+ }
}
\ No newline at end of file
}
} catch (Throwable ex) {
Log.w(TAG,
- String.format("Unable to kill current program: %s", //$NON-NLS-1$
- this.mActiveCommand.getCommand()), ex);
+ String.format("Unable to kill current program: %s",
+ (
+ (this.mActiveCommand == null) ?
+ "" :
+ this.mActiveCommand.getCommand()
+ )
+ ), ex);
}
}
}
* Method invoked when the operation was successfully
*/
void onSuccess();
+
+ /**
+ * Method invoked to handle cancelling
+ */
+ void onCancel();
+
}
/**
this.mDialog.setOnCancelListener(new MessageProgressDialog.OnCancelListener() {
@Override
public boolean onCancel() {
- return task.cancel(true);
+ mCallable.onCancel();
+ task.cancel(true);
+ return true;
}
});
Spanned progress = this.mCallable.requestProgress();
@Override
protected void onCancelled() {
- //Operation complete.
- this.mCallable.onSuccess();
+ this.mCallable.onCancel();
}
@Override
protected static void showOperationSuccessMsg(Context ctx) {
DialogHelper.showToast(ctx, R.string.msgs_success, Toast.LENGTH_SHORT);
}
-}
\ No newline at end of file
+}
}
@Override
+ public void onCancel() {
+ // nop
+ }
+
+ @Override
public void doInBackground(Object... params) throws Throwable {
this.mCause = null;
this.mStarted = true;
}
@Override
+ public void onCancel() {
+ // nop
+ }
+
+ @Override
public void doInBackground(Object... params) throws Throwable {
this.mCause = null;
this.mStarted = true;
protected static void showOperationSuccessMsg(Context ctx, int res, String dst) {
DialogHelper.showToast(ctx, ctx.getString(res, dst), Toast.LENGTH_SHORT);
}
-}
\ No newline at end of file
+}
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
import android.text.Html;
import android.text.Spanned;
import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
+import com.cyanogenmod.filemanager.console.Console;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
import com.cyanogenmod.filemanager.console.RelaunchableException;
import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
}
@Override
public boolean isDialogCancellable() {
- return false;
+ return true;
}
@Override
return Html.fromHtml(progress);
}
- @Override
- public void onSuccess() {
+ private void refreshUIAfterCompletion() {
// Remove orphan bookmark paths
if (files != null) {
for (LinkedResource linkedFiles : files) {
// The reference is not the same, so refresh the complete navigation view
this.mOnRequestRefreshListener.onRequestRefresh(null, true);
}
+ }
+
+ @Override
+ public void onSuccess() {
+ refreshUIAfterCompletion();
ActionsPolicy.showOperationSuccessMsg(ctx);
}
}
}
+ @Override
+ public void onCancel() {
+ if (mSrcConsole != null) {
+ mSrcConsole.onCancel();
+ }
+ if (mDstConsole != null) {
+ mDstConsole.onCancel();
+ }
+ refreshUIAfterCompletion();
+ }
+
+ // Handles required for issuing command death to the consoles
+ private Console mSrcConsole;
+ private Console mDstConsole;
+
/**
* Method that copy or move the file to another location
*
// under using absolute paths) Issue: CYAN-2791
String source = src.getAbsolutePath() +
(src.isDirectory() ? File.separator : "");
+ String dest = dst.getAbsolutePath() +
+ (dst.isDirectory() ? File.separator : "");
+
+ /*
+ There is a possibility that the src and dst can have different consoles.
+ A possible case:
+ - src is from sd card and dst is secure storage
+ This could happen with anything that goes from a real console to a virtual
+ console or visa versa. Here we grab a handle on the console such that we
+ may explicitly kill the actions happening in both consoles.
+ */
+ // Need to derive the console for the source
+ mSrcConsole = CommandHelper.ensureConsoleForFile(ctx, null, source);
+ // Need to derive the console for the destination
+ mDstConsole = CommandHelper.ensureConsoleForFile(ctx, null, dest);
// Copy or move?
if (operation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
ctx,
source,
dst.getAbsolutePath(),
- null);
+ mSrcConsole);
} else {
CommandHelper.copy(
ctx,
source,
dst.getAbsolutePath(),
- null);
+ mSrcConsole);
}
} catch (Exception e) {
// Need to be relaunched?
}
return true;
}
-}
\ No newline at end of file
+}
}
@Override
+ public void onCancel() {
+
+ }
+
+ @Override
public void doInBackground(Object... params) throws Throwable {
this.mCause = null;
}
return true;
}
-}
\ No newline at end of file
+}
* @throws IOException If initial directory couldn't be checked
* @throws FileNotFoundException If the initial directory not exists
*/
- private static Console ensureConsoleForFile(Context context, Console console, String src)
+ public static Console ensureConsoleForFile(Context context, Console console, String src)
throws FileNotFoundException, IOException, InvalidCommandDefinitionException,
ConsoleAllocException, InsufficientPermissionsException {
import com.cyanogenmod.filemanager.FileManagerApplication;
import com.cyanogenmod.filemanager.R;
import com.cyanogenmod.filemanager.commands.SyncResultExecutable;
+import com.cyanogenmod.filemanager.commands.java.Program;
import com.cyanogenmod.filemanager.commands.shell.ResolveLinkCommand;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.Console;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
* @throws ExecutionException If a problem was detected in the operation
*/
public static boolean copyRecursive(
- final File src, final File dst, int bufferSize) throws ExecutionException {
+ final File src, final File dst, int bufferSize, Program program)
+ throws ExecutionException, CancelledOperationException {
if (src.isDirectory()) {
// Create the directory
if (dst.exists() && !dst.isDirectory()) {
File[] files = src.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
- if (!copyRecursive(files[i], new File(dst, files[i].getName()), bufferSize)) {
+ // Short circuit if we've been cancelled. Show's over :(
+ if (program.isCancelled()) {
+ throw new CancelledOperationException();
+ }
+
+ if (!copyRecursive(files[i], new File(dst, files[i].getName()), bufferSize,
+ program)) {
return false;
}
}
}
} else {
// Copy the directory
- if (!bufferedCopy(src, dst,bufferSize)) {
+ if (!bufferedCopy(src, dst,bufferSize, program)) {
return false;
}
}
* @return boolean If the operation complete successfully
*/
public static boolean bufferedCopy(final File src, final File dst,
- int bufferSize) throws ExecutionException {
+ int bufferSize, Program program)
+ throws ExecutionException, CancelledOperationException {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
int read = 0;
byte[] data = new byte[bufferSize];
while ((read = bis.read(data, 0, bufferSize)) != -1) {
+ // Short circuit if we've been cancelled. Show's over :(
+ if (program.isCancelled()) {
+ throw new CancelledOperationException();
+ }
bos.write(data, 0, read);
}
return true;
if (e.getCause() instanceof ErrnoException
&& ((ErrnoException)e.getCause()).errno == OsConstants.ENOSPC) {
throw new ExecutionException(R.string.msgs_no_disk_space);
+ } if (e instanceof CancelledOperationException) {
+ // If the user cancelled this operation, let it through.
+ throw (CancelledOperationException)e;
}
return false;