/*******************************************************************************
* Copyright (c) 2015, 2016 Pivotal, Inc.
* 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:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.dash.views;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.IAction;
import org.springframework.ide.eclipse.boot.core.BootActivator;
import org.springframework.ide.eclipse.boot.dash.BootDashActivator;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.CloudFoundryRunTargetType;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.deployment.DeployToCloudFoundryTargetAction;
import org.springframework.ide.eclipse.boot.dash.livexp.DisposingFactory;
import org.springframework.ide.eclipse.boot.dash.livexp.MultiSelection;
import org.springframework.ide.eclipse.boot.dash.model.BootDashElement;
import org.springframework.ide.eclipse.boot.dash.model.BootDashModel;
import org.springframework.ide.eclipse.boot.dash.model.BootDashViewModel;
import org.springframework.ide.eclipse.boot.dash.model.RunState;
import org.springframework.ide.eclipse.boot.dash.model.RunTarget;
import org.springframework.ide.eclipse.boot.dash.model.UserInteractions;
import org.springframework.ide.eclipse.boot.dash.model.runtargettypes.LocalRunTargetType;
import org.springframework.ide.eclipse.boot.dash.model.runtargettypes.RunTargetType;
import org.springframework.ide.eclipse.boot.dash.ngrok.NGROKInstallManager;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.ObservableSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
public class BootDashActions {
private final static String PROPERTIES_VIEW_ID = "org.eclipse.ui.views.PropertySheet"; //$NON-NLS-1$
///// context info //////////////
private BootDashViewModel model;
private MultiSelection<BootDashElement> elementsSelection;
private UserInteractions ui;
private LiveExpression<BootDashModel> sectionSelection;
///// actions ///////////////////
private RunStateAction[] runStateActions;
private AbstractBootDashElementsAction openConsoleAction;
private OpenLaunchConfigAction openConfigAction;
private OpenInBrowserAction openBrowserAction;
private OpenNgrokAdminUi openNgrokAdminUi;
private OpenInPackageExplorer openInPackageExplorerAction;
private AddRunTargetAction[] addTargetActions;
private RefreshRunTargetAction refreshAction;
private RemoveRunTargetAction removeTargetAction;
private RestartApplicationOnlyAction restartOnlyAction;
private SelectManifestAction selectManifestAction;
private RestartWithRemoteDevClientAction restartWithRemoteDevClientAction;
private OpenCloudAdminConsoleAction openCloudAdminConsoleAction;
private ReconnectCloudConsoleAction reconnectCloudConsoleAction;
private ToggleBootDashModelConnection toggleTargetConnectionAction;
private UpdatePasswordAction updatePasswordAction;
private ShowViewAction showPropertiesViewAction;
private ExposeAppAction exposeRunAppAction;
private ExposeAppAction exposeDebugAppAction;
private OpenFilterPreferencesAction openFilterPreferencesAction;
private DuplicateConfigAction duplicateConfigAction;
private DeleteElementsAction<CloudFoundryRunTargetType> deleteAppsAction;
private DeleteElementsAction<LocalRunTargetType> deleteConfigsAction;
private OpenToggleFiltersDialogAction toggleFiltersDialogAction;
private ToggleFilterAction[] toggleFilterActions;
private CustmomizeTargetLabelAction customizeTargetLabelAction;
private CustmomizeTargetAppManagerURLAction customizeTargetAppsManagerURLAction;
private DisposingFactory<RunTarget, AbstractBootDashAction> debugOnTargetActions;
private DisposingFactory<RunTarget, AbstractBootDashAction> runOnTargetActions;
public BootDashActions(BootDashViewModel model, MultiSelection<BootDashElement> selection, UserInteractions ui) {
this(
model,
selection,
null,
ui
);
}
public BootDashActions(BootDashViewModel model, MultiSelection<BootDashElement> selection, LiveExpression<BootDashModel> section, UserInteractions ui) {
Assert.isNotNull(ui);
this.model = model;
this.elementsSelection = selection;
this.sectionSelection = section;
this.ui = ui;
makeActions();
}
protected void makeActions() {
RunStateAction restartAction = new RestartAction(model, elementsSelection, ui, RunState.RUNNING);
RunStateAction rebugAction = new RedebugAction(model, elementsSelection, ui, RunState.DEBUGGING);
RunStateAction stopAction = new RunStateAction(model, elementsSelection, ui, RunState.INACTIVE) {
@Override
protected boolean currentStateAcceptable(RunState s) {
// Enable stop button so CF apps can be stopped when "STARTING"
return s != RunState.INACTIVE;
}
@Override
protected Job createJob() {
final Collection<BootDashElement> selecteds = elementsSelection.getValue();
if (!selecteds.isEmpty()) {
return new Job("Stopping " + selecteds.size() + " Boot Dash Elements") {
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("Stopping " + selecteds.size() + " Elements", selecteds.size());
try {
for (BootDashElement el : selecteds) {
monitor.subTask("Stopping: " + el.getName());
try {
el.stopAsync(ui);
} catch (Exception e) {
return BootActivator.createErrorStatus(e);
}
monitor.worked(1);
}
return Status.OK_STATUS;
} finally {
monitor.done();
}
}
};
}
return null;
}
};
stopAction.setText("Stop");
stopAction.setToolTipText("Stop the process(es) associated with the selected elements");
stopAction.setImageDescriptor(BootDashActivator.getImageDescriptor("icons/stop.gif"));
stopAction.setDisabledImageDescriptor(BootDashActivator.getImageDescriptor("icons/stop_disabled.gif"));
runStateActions = new RunStateAction[] { restartAction, rebugAction, stopAction };
openConfigAction = new OpenLaunchConfigAction(model, elementsSelection, ui);
openConsoleAction = new OpenConsoleAction(elementsSelection, model, ui);
openBrowserAction = new OpenInBrowserAction(model, elementsSelection, ui);
openNgrokAdminUi = new OpenNgrokAdminUi(model, elementsSelection, ui);
openInPackageExplorerAction = new OpenInPackageExplorer(elementsSelection, ui);
addTargetActions = createAddTargetActions();
deleteAppsAction = new DeleteElementsAction<>(CloudFoundryRunTargetType.class, elementsSelection, ui);
deleteAppsAction.setText("Delete");
deleteAppsAction.setToolTipText("Permantently removes selected artifact(s) from CloudFoundry");
deleteConfigsAction = new DeleteElementsAction<>(LocalRunTargetType.class, elementsSelection, ui);
deleteConfigsAction.setText("Delete Config");
deleteConfigsAction.setToolTipText("Permantently deletes Launch Configgurations from the workspace");
restartOnlyAction = new RestartApplicationOnlyAction(elementsSelection, ui);
reconnectCloudConsoleAction = new ReconnectCloudConsoleAction(elementsSelection, ui);
selectManifestAction = new SelectManifestAction(elementsSelection, ui);
if (sectionSelection != null) {
refreshAction = new RefreshRunTargetAction(sectionSelection, ui);
removeTargetAction = new RemoveRunTargetAction(sectionSelection, model, ui);
updatePasswordAction = new UpdatePasswordAction(sectionSelection, ui);
openCloudAdminConsoleAction = new OpenCloudAdminConsoleAction(sectionSelection, ui);
toggleTargetConnectionAction = new ToggleBootDashModelConnection(sectionSelection, ui);
customizeTargetLabelAction = new CustmomizeTargetLabelAction(sectionSelection, ui);
customizeTargetAppsManagerURLAction = new CustmomizeTargetAppManagerURLAction(sectionSelection, ui);
}
showPropertiesViewAction = new ShowViewAction(PROPERTIES_VIEW_ID);
toggleFiltersDialogAction = new OpenToggleFiltersDialogAction(model.getToggleFilters(), elementsSelection, ui);
toggleFilterActions = new ToggleFilterAction[model.getToggleFilters().getAvailableFilters().length];
for (int i = 0; i < toggleFilterActions.length; i++) {
toggleFilterActions[i] = new ToggleFilterAction(model, model.getToggleFilters().getAvailableFilters()[i], ui);
}
exposeRunAppAction = new ExposeAppAction(model, elementsSelection, ui, RunState.RUNNING, NGROKInstallManager.getInstance());
exposeRunAppAction.setText("(Re)start and Expose via ngrok");
exposeRunAppAction.setToolTipText("Start or restart the process associated with the selected elements and expose it to the outside world via an ngrok tunnel");
exposeRunAppAction.setImageDescriptor(BootDashActivator.getImageDescriptor("icons/restart.gif"));
exposeRunAppAction.setDisabledImageDescriptor(BootDashActivator.getImageDescriptor("icons/restart_disabled.gif"));
exposeDebugAppAction = new ExposeAppAction(model, elementsSelection, ui, RunState.DEBUGGING, NGROKInstallManager.getInstance());
exposeDebugAppAction.setText("(Re)debug and Expose via ngrok");
exposeDebugAppAction.setToolTipText("Start or restart the process associated with the selected elements in debug mode and expose it to the outside world via an ngrok tunnel");
exposeDebugAppAction.setImageDescriptor(BootDashActivator.getImageDescriptor("icons/rebug.png"));
exposeDebugAppAction.setDisabledImageDescriptor(BootDashActivator.getImageDescriptor("icons/rebug_disabled.png"));
restartWithRemoteDevClientAction = new RestartWithRemoteDevClientAction(model, elementsSelection, ui);
duplicateConfigAction = new DuplicateConfigAction(model, elementsSelection, ui);
debugOnTargetActions = createDeployOnTargetActions(RunState.DEBUGGING);
runOnTargetActions = createDeployOnTargetActions(RunState.RUNNING);
openFilterPreferencesAction = new OpenFilterPreferencesAction(ui);
}
private AddRunTargetAction[] createAddTargetActions() {
Set<RunTargetType> targetTypes = model.getRunTargetTypes();
ArrayList<AddRunTargetAction> actions = new ArrayList<>();
for (RunTargetType tt : targetTypes) {
if (tt.canInstantiate()) {
actions.add(new AddRunTargetAction(tt, model.getRunTargets(), ui));
}
}
return actions.toArray(new AddRunTargetAction[actions.size()]);
}
private static final class RestartAction extends RunOrDebugStateAction {
private RestartAction(BootDashViewModel model, MultiSelection<BootDashElement> selection, UserInteractions ui,
RunState goalState) {
super(model, selection, ui, goalState);
setText("(Re)start");
setToolTipText("Start or restart the process associated with the selected elements");
setImageDescriptor(BootDashActivator.getImageDescriptor("icons/restart.gif"));
setDisabledImageDescriptor(BootDashActivator.getImageDescriptor("icons/restart_disabled.gif"));
}
}
private static final class RedebugAction extends RunOrDebugStateAction {
private RedebugAction(BootDashViewModel model, MultiSelection<BootDashElement> selection, UserInteractions ui,
RunState goalState) {
super(model, selection, ui, goalState);
setText("(Re)debug");
setToolTipText("Start or restart the process associated with the selected elements in debug mode");
setImageDescriptor(BootDashActivator.getImageDescriptor("icons/rebug.png"));
setDisabledImageDescriptor(BootDashActivator.getImageDescriptor("icons/rebug_disabled.png"));
}
}
public static class RunOrDebugStateAction extends RunStateAction {
public RunOrDebugStateAction(BootDashViewModel model, MultiSelection<BootDashElement> selection,
UserInteractions ui, RunState goalState) {
super(model, selection, ui, goalState);
Assert.isLegal(goalState == RunState.RUNNING || goalState == RunState.DEBUGGING);
}
@Override
protected Job createJob() {
final Collection<BootDashElement> selecteds = getTargetElements();
if (!selecteds.isEmpty()) {
return new Job("Restarting " + selecteds.size() + " Dash Elements") {
@Override
public IStatus run(IProgressMonitor monitor) {
monitor.beginTask("Restart Boot Dash Elements", selecteds.size());
try {
for (BootDashElement el : selecteds) {
monitor.subTask("Restarting: " + el.getName());
try {
el.restart(goalState, ui);
} catch (Exception e) {
return BootActivator.createErrorStatus(e);
}
monitor.worked(1);
}
return Status.OK_STATUS;
} finally {
monitor.done();
}
}
};
}
return null;
}
/**
* Automatically retarget this action to apply to all the children of an element
* (if it has children). This way the action behaves logically if both a parent and some children
* are selected (i.e. we don't want to execute the action twice on the explicitly selected children!)
*/
public Collection<BootDashElement> getTargetElements() {
Builder<BootDashElement> builder = ImmutableSet.builder();
addTargetsFor(builder, getSelectedElements());
return builder.build();
}
private void addTargetsFor(Builder<BootDashElement> builder, Collection<BootDashElement> selecteds) {
for (BootDashElement s : selecteds) {
addTargetsFor(builder, s);
}
}
private void addTargetsFor(Builder<BootDashElement> builder, BootDashElement s) {
ImmutableSet<BootDashElement> children = s.getChildren().getValues();
if (children.isEmpty()) {
//No children, add s itself
builder.add(s);
} else {
addTargetsFor(builder, children);
}
}
}
public RunStateAction[] getRunStateActions() {
return runStateActions;
}
public AbstractBootDashElementsAction getOpenBrowserAction() {
return openBrowserAction;
}
public AbstractBootDashElementsAction getOpenNgrokAdminUi() {
return openNgrokAdminUi;
}
public AbstractBootDashElementsAction getOpenConsoleAction() {
return openConsoleAction;
}
public AbstractBootDashElementsAction getOpenInPackageExplorerAction() {
return openInPackageExplorerAction;
}
public OpenLaunchConfigAction getOpenConfigAction() {
return openConfigAction;
}
public AddRunTargetAction[] getAddRunTargetActions() {
return addTargetActions;
}
public IAction getRemoveRunTargetAction() {
return removeTargetAction;
}
/**
* @return May be null as it may not be supported on all models.
*/
public IAction getRefreshRunTargetAction() {
return refreshAction;
}
public IAction getDeleteAppsAction() {
return deleteAppsAction;
}
public IAction getDeleteConfigsAction() {
return deleteConfigsAction;
}
public IAction getRestartOnlyApplicationAction() {
return restartOnlyAction;
}
public IAction getSelectManifestAction() {
return selectManifestAction;
}
public IAction getReconnectCloudConsole() {
return reconnectCloudConsoleAction;
}
public IAction getOpenCloudAdminConsoleAction() {
return openCloudAdminConsoleAction;
}
public IAction getToggleTargetConnectionAction() {
return toggleTargetConnectionAction;
}
/**
* @return May be null as it may not be supported on all models.
*/
public IAction getUpdatePasswordAction() {
return updatePasswordAction;
}
/**
* @return show properties view action instance
*/
public IAction getShowPropertiesViewAction() {
return showPropertiesViewAction;
}
public IAction getExposeRunAppAction() {
return exposeRunAppAction;
}
public IAction getExposeDebugAppAction() {
return exposeDebugAppAction;
}
public void dispose() {
if (runStateActions != null) {
for (RunStateAction a : runStateActions) {
a.dispose();
}
runStateActions = null;
}
if (openConsoleAction != null) {
openConsoleAction.dispose();
}
if (openConfigAction != null) {
openConfigAction.dispose();
}
if (openBrowserAction != null) {
openBrowserAction.dispose();
}
if (addTargetActions != null) {
for (AddRunTargetAction a : addTargetActions) {
a.dispose();
}
addTargetActions = null;
}
if (toggleFiltersDialogAction != null) {
toggleFiltersDialogAction.dispose();
toggleFiltersDialogAction = null;
}
if (exposeRunAppAction != null) {
exposeRunAppAction.dispose();
exposeRunAppAction = null;
}
if (exposeDebugAppAction != null) {
exposeDebugAppAction.dispose();
exposeDebugAppAction = null;
}
if (duplicateConfigAction != null) {
duplicateConfigAction.dispose();
duplicateConfigAction = null;
}
if (toggleFilterActions!=null) {
for (ToggleFilterAction a : toggleFilterActions) {
a.dispose();
}
toggleFilterActions = null;
}
debugOnTargetActions.dispose();
runOnTargetActions.dispose();
}
public IAction getToggleFiltersDialogAction() {
return toggleFiltersDialogAction;
}
public RestartWithRemoteDevClientAction getRestartWithRemoteDevClientAction() {
return restartWithRemoteDevClientAction;
}
public DuplicateConfigAction getDuplicateConfigAction() {
return duplicateConfigAction;
}
public ToggleFilterAction[] getToggleFilterActions() {
return toggleFilterActions;
}
public CustmomizeTargetLabelAction getCustomizeTargetLabelAction() {
return customizeTargetLabelAction;
}
public CustmomizeTargetAppManagerURLAction getCustomizeTargetAppsManagerURLAction() {
return customizeTargetAppsManagerURLAction;
}
public ImmutableList<IAction> getDebugOnTargetActions() {
return getDeployAndStartOnTargetActions(debugOnTargetActions);
}
public ImmutableList<IAction> getRunOnTargetActions() {
return getDeployAndStartOnTargetActions(runOnTargetActions);
}
public OpenFilterPreferencesAction getOpenFilterPreferencesAction() {
return openFilterPreferencesAction;
}
private ImmutableList<IAction> getDeployAndStartOnTargetActions(
DisposingFactory<RunTarget, AbstractBootDashAction> actionFactory) {
ArrayList<RunTarget> targets = new ArrayList<>(model.getRunTargets().getValues());
Collections.sort(targets, model.getTargetComparator());
ImmutableList.Builder<IAction> builder = ImmutableList.builder();
for (RunTarget target : targets) {
if (target.getType() instanceof CloudFoundryRunTargetType) {
builder.add(actionFactory.createOrGet(target));
}
}
return builder.build();
}
private DisposingFactory<RunTarget, AbstractBootDashAction> createDeployOnTargetActions(final RunState runningOrDebugging) {
ObservableSet<RunTarget> runtargets = model.getRunTargets();
return new DisposingFactory<RunTarget, AbstractBootDashAction>(runtargets) {
@Override
protected AbstractBootDashAction create(RunTarget target) {
return new DeployToCloudFoundryTargetAction(model, target, runningOrDebugging, elementsSelection, ui);
}
};
}
}