/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.svn.ide.common;
import org.eclipse.che.api.core.ErrorCodes;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.notification.NotificationManager;
import org.eclipse.che.ide.api.notification.StatusNotification;
import org.eclipse.che.ide.api.resources.Container;
import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.api.user.Credentials;
import org.eclipse.che.ide.api.user.AskCredentialsDialog;
import org.eclipse.che.ide.processes.panel.ProcessesPanelPresenter;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.util.Arrays;
import org.eclipse.che.plugin.svn.ide.SubversionExtensionLocalizationConstants;
import org.eclipse.che.plugin.svn.ide.action.SubversionAction;
import java.util.List;
import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.PROGRESS;
import static org.eclipse.che.ide.util.ExceptionUtils.getErrorCode;
/**
* Presenter to be extended by all {@link SubversionAction} presenters.
*/
public class SubversionActionPresenter {
protected final AppContext appContext;
private final SubversionOutputConsoleFactory consoleFactory;
private final ProcessesPanelPresenter consolesPanelPresenter;
private final StatusColors statusColors;
private final SubversionExtensionLocalizationConstants locale;
private final NotificationManager notificationManager;
private final AskCredentialsDialog credentialsDialog;
protected SubversionActionPresenter(AppContext appContext,
SubversionOutputConsoleFactory consoleFactory,
ProcessesPanelPresenter processesPanelPresenter,
StatusColors statusColors,
SubversionExtensionLocalizationConstants locale,
NotificationManager notificationManager,
AskCredentialsDialog credentialsDialog) {
this.appContext = appContext;
this.consoleFactory = consoleFactory;
this.consolesPanelPresenter = processesPanelPresenter;
this.statusColors = statusColors;
this.locale = locale;
this.notificationManager = notificationManager;
this.credentialsDialog = credentialsDialog;
}
protected Path[] toRelative(Container project, Resource[] paths) {
if (paths == null || paths.length == 0) {
return new Path[0];
}
Path[] rel = new Path[0];
for (Resource resource : paths) {
if (project.getLocation().isPrefixOf(resource.getLocation())) {
Path temp = resource.getLocation().removeFirstSegments(project.getLocation().segmentCount());
if (temp.segmentCount() == 0) {
temp = Path.valueOf(".");
}
rel = Arrays.add(rel, temp);
}
}
return rel;
}
protected Path toRelative(Container project, Resource path) {
return toRelative(project, new Resource[]{path})[0];
}
/**
* Prints errors output in console.
*
* @param errors
* the error output
* @param consoleTitle
* the title of the console to use
*/
protected void printErrors(final List<String> errors, final String consoleTitle) {
final SubversionOutputConsole console = consoleFactory.create(consoleTitle);
for (final String line : errors) {
console.printError(line);
}
consolesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
}
/**
* Colorizes and prints response outputs in console.
*
* @param command
* the SVN command that was executed
* @param output
* the command output
* @param errors
* the error output
* @param consoleTitle
* the title of the console to use
*/
protected void printResponse(final String command, final List<String> output, final List<String> errors, final String consoleTitle) {
final SubversionOutputConsole console = consoleFactory.create(consoleTitle);
if (command != null) {
printCommand(command, console);
}
if (output != null) {
printOutput(output, console);
}
if (errors != null) {
for (final String line : errors) {
console.printError(line);
}
}
consolesPanelPresenter.addCommandOutput(appContext.getDevMachine().getId(), console);
}
/**
* Performs subversion operation. If this operations fails with authorization error
* the operation will be recalled with requested credentials
*
* @param notification
* progress notification to set operation status
*/
protected <Y> Promise<Y> performOperationWithCredentialsRequestIfNeeded(final RemoteSubversionOperation<Y> operation,
@Nullable final StatusNotification notification) {
return operation.perform(null)
.catchErrorPromise(new Function<PromiseError, Promise<Y>>() {
@Override
public Promise<Y> apply(PromiseError error) throws FunctionException {
if (getErrorCode(error.getCause()) == ErrorCodes.UNAUTHORIZED_SVN_OPERATION) {
if (notification != null) {
notification.setTitle(locale.waitingCredentials());
notification.setStatus(PROGRESS);
} else {
notificationManager.notify(error.getMessage(), FAIL, FLOAT_MODE);
}
return credentialsDialog.askCredentials()
.thenPromise(new Function<Credentials, Promise<Y>>() {
@Override
public Promise<Y> apply(Credentials credentials) throws FunctionException {
return operation.perform(credentials);
}
});
}
return Promises.reject(error);
}
});
}
/**
* Remote Subversion operation that can require credentials.
*/
protected interface RemoteSubversionOperation<Y> {
Promise<Y> perform(Credentials credentials);
}
/**
* Prints an executed command line in given console.
*
* @param command
* the SVN command that was executed
* @param console
* the console to use to print
*/
private void printCommand(String command, final SubversionOutputConsole console) {
if (command.startsWith("'") || command.startsWith("\"")) {
command += command.substring(1, command.length() - 1);
}
console.printCommand(command);
console.print("");
}
/**
* Prints output in given console.
*
* @param output
* the command output
* @param console
* the console to use to print
*/
private void printOutput(List<String> output, SubversionOutputConsole console) {
for (final String line : output) {
String trimLine = line.trim();
if (!trimLine.isEmpty()) {
String prefix = trimLine.substring(0, 1);
final String color = statusColors.getStatusColor(prefix);
if (color != null) {
// TODO: Turn the file paths into links (where appropriate)
console.print(line, color);
} else {
console.print(line);
}
}
}
console.print("");
}
}