use of com.mucommander.ui.dialog.DialogAction in project mucommander by mucommander.
the class BrowseLocationThread method run.
@Override
public void run() {
LOGGER.debug("starting folder change...");
boolean folderChangedSuccessfully = false;
// Show some progress in the progress bar to give hope
folderPanel.setProgressValue(10);
boolean userCancelled = false;
CredentialsMapping newCredentialsMapping = null;
// True if Guest authentication was selected in the authentication dialog (guest credentials must not be
// added to CredentialsManager)
boolean guestCredentialsSelected = false;
AuthenticationType authenticationType = folderURL.getAuthenticationType();
if (credentialsMapping != null) {
newCredentialsMapping = credentialsMapping;
CredentialsManager.authenticate(folderURL, newCredentialsMapping);
} else // avoid waiting for an AuthException to be thrown.
if (!folderURL.containsCredentials() && ((authenticationType == AuthenticationType.AUTHENTICATION_REQUIRED) || (authenticationType == AuthenticationType.AUTHENTICATION_OPTIONAL && CredentialsManager.getMatchingCredentials(folderURL).length > 0))) {
AuthDialog authDialog = popAuthDialog(folderURL, false, null);
newCredentialsMapping = authDialog.getCredentialsMapping();
guestCredentialsSelected = authDialog.guestCredentialsSelected();
// User cancelled the authentication dialog, stop
if (newCredentialsMapping == null)
userCancelled = true;
else // Use the provided credentials and invalidate the folder AbstractFile instance (if any) so that
// it gets recreated with the new credentials
{
CredentialsManager.authenticate(folderURL, newCredentialsMapping);
folder = null;
}
}
if (!userCancelled) {
boolean canonicalPathFollowed = false;
do {
// Set cursor to hourglass/wait
mainFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
// Render all actions inactive while changing folder
mainFrame.setNoEventsMode(true);
try {
// Thread was created using a FileURL
if (folder == null) {
AbstractFile file = FileFactory.getFile(folderURL, true);
synchronized (KILL_LOCK) {
if (killed) {
LOGGER.debug("this thread has been killed, returning");
break;
}
}
// File resolved -> 25% complete
folderPanel.setProgressValue(25);
// or doesn't exist
if (file == null || !file.exists()) {
// Restore default cursor
mainFrame.setCursor(Cursor.getDefaultCursor());
locationChanger.showFolderDoesNotExistDialog();
break;
}
if (!file.canRead()) {
// Restore default cursor
mainFrame.setCursor(Cursor.getDefaultCursor());
showFailedToReadFolderDialog();
break;
}
// File is a regular directory, all good
if (file.isDirectory()) {
// Just continue
} else // File is a browsable file (Zip archive for instance) but not a directory : Browse or Download ? => ask the user
if (file.isBrowsable()) {
// of the OpenAction (enter pressed on the file). This works well enough in practice.
if (!globalHistory.contains(folderURL) && !file.equals(folderPanel.getFileTable().getSelectedFile())) {
// Restore default cursor
mainFrame.setCursor(Cursor.getDefaultCursor());
// Download or browse file ?
QuestionDialog dialog = new QuestionDialog(mainFrame, null, Translator.get("table.download_or_browse"), mainFrame, Arrays.asList(BrowseLocationThreadAction.BROWSE, BrowseLocationThreadAction.DOWNLOAD, BrowseLocationThreadAction.CANCEL), 0);
DialogAction ret = dialog.getActionValue();
if (ret == DIALOG_DISPOSED_ACTION || ret == BrowseLocationThreadAction.CANCEL)
break;
// Download file
if (ret == BrowseLocationThreadAction.DOWNLOAD) {
showDownloadDialog(file);
break;
}
// Continue if BROWSE
// Set cursor to hourglass/wait
mainFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
}
// else just continue and browse file's contents
} else // File is a regular file: show download dialog which allows to download (copy) the file
// to a directory specified by the user
{
showDownloadDialog(file);
break;
}
this.folder = file;
} else // Thread was created using an AbstractFile instance, check file existence
if (!folder.exists()) {
// Find a 'workable' folder if the requested folder doesn't exist anymore
if (findWorkableFolder) {
AbstractFile newFolder = locationChanger.getWorkableFolder(folder);
if (newFolder.equals(folder)) {
// If we've already tried the returned folder, give up (avoids a potentially endless loop)
locationChanger.showFolderDoesNotExistDialog();
break;
}
// Try again with the new folder
folder = newFolder;
folderURL = folder.getURL();
// Discard the file to select, if any
fileToSelect = null;
continue;
} else {
locationChanger.showFolderDoesNotExistDialog();
break;
}
} else if (!folder.canRead()) {
showFailedToReadFolderDialog();
break;
}
// resolved again.
if (!canonicalPathFollowed && followCanonicalPath(folder)) {
try {
// Recreate the FileURL using the file's canonical path
FileURL newURL = FileURL.getFileURL(folder.getCanonicalPath());
// Keep the credentials and properties (if any)
newURL.setCredentials(folderURL.getCredentials());
newURL.importProperties(folderURL);
this.folderURL = newURL;
// Invalidate the AbstractFile instance
this.folder = null;
// There won't be any further attempts after this one
canonicalPathFollowed = true;
// Loop the resolve the file
continue;
} catch (MalformedURLException e) {
// In the unlikely event of the canonical path being malformed, the AbstractFile
// and FileURL instances are left untouched
}
}
synchronized (KILL_LOCK) {
if (killed) {
LOGGER.debug("this thread has been killed, returning");
break;
}
}
// File tested -> 50% complete
folderPanel.setProgressValue(50);
synchronized (KILL_LOCK) {
if (killed) {
LOGGER.debug("this thread has been killed, returning");
break;
}
// From now on, thread cannot be killed (would comprise table integrity)
doNotKill = true;
}
// files listed -> 75% complete
folderPanel.setProgressValue(75);
LOGGER.trace("calling setCurrentFolder");
// Change the file table's current folder and select the specified file (if any)
locationChanger.setCurrentFolder(folder, fileToSelect, changeLockedTab, true);
// folder set -> 95% complete
folderPanel.setProgressValue(95);
// Do not add the credentials if guest credentials were selected by the user.
if (newCredentialsMapping != null && !guestCredentialsSelected)
CredentialsManager.addCredentials(newCredentialsMapping);
// All good !
folderChangedSuccessfully = true;
break;
} catch (Exception e) {
LOGGER.debug("Caught exception", e);
if (killed) {
// If #tryKill() called #interrupt(), the exception we just caught was most likely
// thrown as a result of the thread being interrupted.
//
// The exception can be a java.lang.InterruptedException (Thread throws those),
// a java.nio.channels.ClosedByInterruptException (InterruptibleChannel throws those)
// or any other exception thrown by some code that swallowed the original exception
// and threw a new one.
LOGGER.debug("Thread was interrupted, ignoring exception");
break;
}
// Restore default cursor
mainFrame.setCursor(Cursor.getDefaultCursor());
if (e instanceof AuthException) {
AuthException authException = (AuthException) e;
// Retry (loop) if user provided new credentials, if not stop
AuthDialog authDialog = popAuthDialog(authException.getURL(), true, authException.getMessage());
newCredentialsMapping = authDialog.getCredentialsMapping();
guestCredentialsSelected = authDialog.guestCredentialsSelected();
if (newCredentialsMapping != null) {
// Invalidate the existing AbstractFile instance
folder = null;
// Use the provided credentials
CredentialsManager.authenticate(folderURL, newCredentialsMapping);
continue;
}
} else {
// Find a 'workable' folder if the requested folder doesn't exist anymore
if (findWorkableFolder) {
AbstractFile newFolder = locationChanger.getWorkableFolder(folder);
if (newFolder.equals(folder)) {
// If we've already tried the returned folder, give up (avoids a potentially endless loop)
locationChanger.showFolderDoesNotExistDialog();
break;
}
// Try again with the new folder
folder = newFolder;
folderURL = folder.getURL();
// Discard the file to select, if any
fileToSelect = null;
continue;
}
showAccessErrorDialog(e);
}
// Stop looping!
break;
}
} while (true);
}
synchronized (KILL_LOCK) {
// Clean things up
cleanup(folderChangedSuccessfully);
}
}
use of com.mucommander.ui.dialog.DialogAction in project mucommander by mucommander.
the class DeleteJob method processFile.
// //////////////////////////
// FileJob implementation //
// //////////////////////////
/**
* Deletes recursively the given file or folder.
*
* @param file the file or folder to delete
* @param recurseParams not used
*
* @return <code>true</code> if the file has been completely deleted.
*/
@Override
protected boolean processFile(AbstractFile file, Object recurseParams) {
if (getState() == FileJobState.INTERRUPTED)
return false;
// Delete files recursively, only if trash is not used.
DialogAction ret;
if (!moveToTrash && file.isDirectory()) {
String filePath = file.getAbsolutePath();
filePath = filePath.substring(getBaseSourceFolder().getAbsolutePath(false).length() + 1, filePath.length());
// Important: symlinks must *not* be followed -- following symlinks could have disastrous effects.
if (!file.isSymlink()) {
do {
// Delete each file in this folder
try {
AbstractFile[] subFiles = file.ls();
for (int i = 0; i < subFiles.length && getState() != FileJobState.INTERRUPTED; i++) {
// Notify job that we're starting to process this file (needed for recursive calls to processFile)
nextFile(subFiles[i]);
processFile(subFiles[i], null);
}
break;
} catch (IOException e) {
LOGGER.debug("IOException caught", e);
ret = showErrorDialog(errorDialogTitle, Translator.get("cannot_read_file", filePath));
// Retry loops
if (ret == FileJobAction.RETRY)
continue;
// Cancel, skip or close dialog returns false
return false;
}
} while (true);
}
}
// Return now if the job was interrupted, so that we do not attempt to delete this folder
if (getState() == FileJobState.INTERRUPTED)
return false;
do {
// Loop for retry
try {
deleteFile(file);
return true;
} catch (IOException e) {
LOGGER.debug("IOException caught", e);
ret = showErrorDialog(errorDialogTitle, Translator.get(file.isDirectory() ? "cannot_delete_folder" : "cannot_delete_file", file.getName()));
// Retry loops
if (ret == FileJobAction.RETRY)
continue;
// Cancel, skip or close dialog returns false
return false;
}
} while (true);
}
use of com.mucommander.ui.dialog.DialogAction in project mucommander by mucommander.
the class MkdirJob method processFile.
// //////////////////////////
// FileJob implementation //
// //////////////////////////
/**
* Creates the new directory in the destination folder.
*/
@Override
protected boolean processFile(AbstractFile file, Object recurseParams) {
// Stop if interrupted (although there is no way to stop the job at this time)
if (getState() == FileJobState.INTERRUPTED)
return false;
do {
try {
LOGGER.debug("Creating: {}", file);
// Check for file collisions, i.e. if the file already exists in the destination
int collision = FileCollisionChecker.checkForCollision(null, file);
if (collision != FileCollisionChecker.NO_COLLISION) {
// File already exists in destination, ask the user what to do (cancel, overwrite,...) but
// do not offer the multiple files' mode options such as 'skip' and 'apply to all'.
DialogAction choice = waitForUserResponse(new FileCollisionDialog(getMainFrame(), getMainFrame(), collision, null, file, false, false));
// Overwrite file
if (choice == FileCollisionDialog.FileCollisionAction.OVERWRITE) {
// Delete the file
file.delete();
} else // Cancel or dialog close (return)
// else if (choice==-1 || choice==FileCollisionDialog.OverwriteAction.CANCEL) {
{
interrupt();
return false;
}
}
// Create file
if (mkfileMode) {
// Use mkfile
if (allocateSpace == -1) {
file.mkfile();
} else // Allocate the requested number of bytes
{
OutputStream mkfileOut = null;
try {
// using RandomAccessOutputStream if we can have one
if (file.isFileOperationSupported(FileOperation.RANDOM_WRITE_FILE)) {
mkfileOut = file.getRandomAccessOutputStream();
((RandomAccessOutputStream) mkfileOut).setLength(allocateSpace);
} else // manually otherwise
{
mkfileOut = file.getOutputStream();
// Use BufferPool to avoid excessive memory allocation and garbage collection
byte[] buffer = BufferPool.getByteArray();
int bufferSize = buffer.length;
try {
long remaining = allocateSpace;
int nbWrite;
while (remaining > 0 && getState() != FileJobState.INTERRUPTED) {
nbWrite = (int) (remaining > bufferSize ? bufferSize : remaining);
mkfileOut.write(buffer, 0, nbWrite);
remaining -= nbWrite;
}
} finally {
BufferPool.releaseByteArray(buffer);
}
}
} finally {
if (mkfileOut != null)
try {
mkfileOut.close();
} catch (IOException e) {
}
}
}
} else // Create directory
{
file.mkdir();
}
// Resolve new file instance now that it exists: remote files do not update file attributes after
// creation, we need to get an instance that reflects the newly created file attributes
file = FileFactory.getFile(file.getURL());
// Select newly created file when job is finished
selectFileWhenFinished(file);
// Return Success
return true;
} catch (IOException e) {
// thrown, this is normal behavior
if (mkfileMode && getState() == FileJobState.INTERRUPTED)
return false;
LOGGER.debug("IOException caught", e);
DialogAction action = showErrorDialog(Translator.get("error"), Translator.get(mkfileMode ? "cannot_write_file" : "cannot_create_folder", file.getAbsolutePath()), Arrays.asList(FileJobAction.RETRY, FileJobAction.CANCEL));
// Retry (loop)
if (action == FileJobAction.RETRY)
continue;
// Return Failure
return false;
}
} while (true);
}
use of com.mucommander.ui.dialog.DialogAction in project mucommander by mucommander.
the class SearchUpdaterThread method run.
@Override
public void run() {
LOGGER.debug("starting search updater...");
boolean searchEndedSuccessfully = false;
// Show some progress in the progress bar to give hope
folderPanel.setProgressValue(10);
try {
// Set cursor to hourglass/wait
mainFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
// Render all actions inactive while changing folder
mainFrame.setNoEventsMode(true);
search = (SearchFile) FileFactory.getFile(folderURL, true);
// Initiate the search thread
search.start(SearchBuilder.newSearch().mainFrame(mainFrame));
// Retrieve the timestamp of the latest search results
long date = search.getDate();
// Update the file table, most likely with empty result set
setCurrentFolder(false);
// Search started, advance progress
folderPanel.setProgressValue(50);
while (true) {
if (killed)
throw new InterruptedException("search-updater thread stopped");
sleep(1000);
boolean searchCompleted = COMPLETED_SEARCH_STATUSES.contains(search.getSearchPhase());
// Retrieve the timestamp of the latest search results
long currentDate = search.getDate();
boolean searchResultsChanged = currentDate != date;
if (searchCompleted) {
synchronized (KILL_LOCK) {
if (killed)
throw new InterruptedException("search-updater thread stopped");
doNotKill = true;
}
if (searchResultsChanged) {
folderPanel.setProgressValue(75);
setCurrentFolder(true);
} else {
folderPanel.setProgressValue(90);
folderPanel.getLocationManager().fireLocationChanged(search.getURL());
}
// folder set -> 95% complete
folderPanel.setProgressValue(95);
searchEndedSuccessfully = true;
break;
}
if (searchResultsChanged) {
date = currentDate;
// Change the file table's current folder and select the specified file (if any)
setCurrentFolder(false);
if (search.isPausedToDueMaxResults()) {
// Restore default cursor
mainFrame.setCursor(Cursor.getDefaultCursor());
// Download or browse file ?
DialogAction ret = showSearchExceededMaxResults();
if (ret == DIALOG_DISPOSED_ACTION || ret == SearchUpdaterThreadAction.STOP) {
stoppedDueToMaxResults = true;
folderPanel.getLocationManager().fireLocationChanged(search.getURL());
break;
}
// Set cursor to hourglass/wait
mainFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
// continue the paused search
search.continueSearch();
}
}
}
} catch (Exception e) {
LOGGER.debug("Caught exception", e);
if (search == null) {
locationChanger.showFolderDoesNotExistDialog();
} else {
search.stop();
if (killed)
setCurrentFolderDismissException();
}
}
synchronized (KILL_LOCK) {
// Clean things up
cleanup(searchEndedSuccessfully);
}
}
use of com.mucommander.ui.dialog.DialogAction in project mucommander by mucommander.
the class FileJob method showErrorDialog.
/**
* Displays an error dialog with the specified title and message and returns the selection action's value.
*/
protected DialogAction showErrorDialog(String title, String message, List<DialogAction> actionChoices) {
// Return SKIP_ACTION if 'skip all' has previously been selected and 'skip' is in the list of actions.
if (autoSkipErrors) {
for (DialogAction action : actionChoices) if (action == FileJobAction.SKIP)
return FileJobAction.SKIP;
}
// Send a system notification if a notifier is available and enabled
if (NotifierProvider.isAvailable() && NotifierProvider.getNotifier().isEnabled())
NotifierProvider.displayBackgroundNotification(NotificationType.JOB_ERROR, title, message);
QuestionDialog dialog;
if (getProgressDialog() == null)
dialog = new QuestionDialog(getMainFrame(), title, message, getMainFrame(), actionChoices, 0);
else
dialog = new QuestionDialog(getProgressDialog(), title, message, getMainFrame(), actionChoices, 0);
// Cancel or close dialog stops this job
DialogAction userChoice = waitForUserResponse(dialog);
if (userChoice == QuestionDialog.DIALOG_DISPOSED_ACTION || userChoice == FileJobAction.CANCEL)
interrupt();
else // Keep 'skip all' choice for further error and return SKIP
if (userChoice == FileJobAction.SKIP_ALL) {
autoSkipErrors = true;
return FileJobAction.SKIP;
}
return userChoice;
}
Aggregations