/******************************************************************************* * Copyright (c) 2014, 2016 Red Hat Inc. and others. * 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: * Red Hat - Initial Contribution *******************************************************************************/ package org.eclipse.linuxtools.internal.docker.ui.commands; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.IHandler; import org.eclipse.core.commands.ParameterizedCommand; import org.eclipse.core.expressions.EvaluationContext; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerContainer; import org.eclipse.linuxtools.docker.core.IDockerImage; import org.eclipse.linuxtools.docker.core.IDockerPortMapping; import org.eclipse.linuxtools.docker.ui.Activator; import org.eclipse.linuxtools.internal.docker.ui.DockerConnectionWatcher; import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants; import org.eclipse.linuxtools.internal.docker.ui.views.DockerContainersView; import org.eclipse.linuxtools.internal.docker.ui.views.DockerExplorerContentProvider.DockerContainerVolume; import org.eclipse.linuxtools.internal.docker.ui.views.DockerExplorerView; import org.eclipse.linuxtools.internal.docker.ui.views.DockerImageHierarchyView; import org.eclipse.linuxtools.internal.docker.ui.views.DockerImagesView; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.ISources; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.handlers.IHandlerService; /** * Utility class for all {@link IHandler} command handlers * @author xcoulon * */ public class CommandUtils { /** * Refreshes (async) the {@link Viewer}. * * @param viewer * - the {@link Viewer} to refresh */ public static void asyncRefresh(final Viewer viewer) { Display.getDefault().asyncExec(() -> { if (viewer != null && !viewer.getControl().isDisposed()) { viewer.refresh(); } }); } /** * @return the current {@link IDockerConnection} associated with the given * {@link IWorkbenchPart} or {@code null} if none could be found. * @param activePart * - active Workbench part */ public static IDockerConnection getCurrentConnection( final IWorkbenchPart activePart) { if (DockerConnectionWatcher.getInstance().getConnection() != null) return DockerConnectionWatcher.getInstance().getConnection(); else if (activePart instanceof DockerContainersView) { return ((DockerContainersView) activePart).getConnection(); } else if (activePart instanceof DockerImagesView) { return ((DockerImagesView) activePart).getConnection(); } // fall back to first active connection in list if one exists return Stream.of(DockerConnectionManager.getInstance().getConnections()) .filter(c -> c.isOpen()).findFirst().orElse(null); } /** * @param activePart * the active {@link IWorkbenchPart} * @return the {@link List} of selected elements in the given active part or * {@link Collections#emptyList()} if none was selected */ public static List<Object> getSelectedElements( final IWorkbenchPart activePart) { return getSelectedElements(activePart, Object.class); } /** * @param activePart * the active {@link IWorkbenchPart} * @return the of selected element in the given active part or * <code>null</code> if none was found */ public static Object getSelectedElement(final IWorkbenchPart activePart) { final List<Object> selectedElements = getSelectedElements(activePart, Object.class); if (selectedElements != null && !selectedElements.isEmpty()) { return selectedElements.get(0); } return null; } /** * @param activePart * the active {@link IWorkbenchPart} * @param targetClass * @return the {@link List} of selected {@link IDockerContainer} in the * given active part of {@link Collections#emptyList()} if none was * selected */ private static <T> List<T> getSelectedElements( final IWorkbenchPart activePart, final Class<T> targetClass) { if (activePart instanceof DockerContainersView) { final ISelection selection = ((DockerContainersView) activePart) .getSelection(); return castSelectionTo(selection, targetClass); } else if (activePart instanceof DockerImagesView) { final ISelection selection = ((DockerImagesView) activePart) .getSelection(); return castSelectionTo(selection, targetClass); } else if (activePart instanceof DockerExplorerView) { final ISelection selection = ((DockerExplorerView) activePart) .getCommonViewer().getSelection(); return castSelectionTo(selection, targetClass); } else if (activePart instanceof DockerImageHierarchyView) { final ISelection selection = ((DockerImageHierarchyView) activePart) .getCommonViewer().getSelection(); return adaptSelectionTo(selection, targetClass); } return Collections.emptyList(); } /** * @param activePart * the active {@link IWorkbenchPart} * @return the {@link List} of selected {@link IDockerContainer} in the * given active part of {@link Collections#emptyList()} if none was * selected */ public static List<IDockerContainer> getSelectedContainers( final IWorkbenchPart activePart) { return getSelectedElements(activePart, IDockerContainer.class); } /** * @param activePart * the active {@link IWorkbenchPart} * @return the {@link List} of selected {@link DockerContainerPortMapping} * in the given active part of {@link Collections#emptyList()} if * none was selected */ public static List<IDockerPortMapping> getSelectedPortMappings( final IWorkbenchPart activePart) { return getSelectedElements(activePart, IDockerPortMapping.class); } /** * @param activePart * the active {@link IWorkbenchPart} * @return the {@link List} of selected {@link DockerContainerVolume} in the * given active part of {@link Collections#emptyList()} if none was * selected */ public static List<DockerContainerVolume> getSelectedVolumes( final IWorkbenchPart activePart) { return getSelectedElements(activePart, DockerContainerVolume.class); } /** * @param activePart * the active {@link IWorkbenchPart} * @return the {@link List} of selected {@link IDockerImage} in the given * active part of {@link Collections#emptyList()} if none was * selected */ public static List<IDockerImage> getSelectedImages( final IWorkbenchPart activePart) { return getSelectedElements(activePart, IDockerImage.class); } /** * @param activePart * the active {@link IWorkbenchPart} * @return the selected {@link IDockerImage} in the given active part of * <code>null</code> if none was selected */ public static IDockerImage getSelectedImage( final IWorkbenchPart activePart) { final List<IDockerImage> selectedImages = getSelectedImages(activePart); if (selectedImages == null || selectedImages.isEmpty()) { return null; } return selectedImages.get(0); } /** * Returns the given {@link List} <strong>typed</strong> with the given * {@code targetClass}. * * @param selection * the current selection * @return Returns the given {@link List} typed with the * {@code targetClass}. */ @SuppressWarnings("unchecked") private static <T> List<T> castSelectionTo(final ISelection selection, final Class<T> targetClass) { if (selection instanceof IStructuredSelection) { final IStructuredSelection structuredSelection = (IStructuredSelection) selection; return (List<T>) structuredSelection.toList().stream() .filter(selectedElement -> targetClass .isAssignableFrom(selectedElement.getClass())) .map(selectedElement -> (T) selectedElement) .collect(Collectors.toList()); } return Collections.emptyList(); } /** * Returns the given {@link List} <strong>adapted</strong> to the given * {@code targetClass}. * * @param selection * the current selection * @param targetClass * the target class in which the elements of the given * {@code selection} should be adapted * @return Returns the given {@link List} adapted to the * {@code targetClass}. */ @SuppressWarnings("unchecked") private static <T> List<T> adaptSelectionTo(final ISelection selection, final Class<T> targetClass) { if (selection instanceof IStructuredSelection) { final IStructuredSelection structuredSelection = (IStructuredSelection) selection; return (List<T>) structuredSelection.toList().stream() .filter(selectedElement -> selectedElement instanceof IAdaptable && ((IAdaptable) selectedElement) .getAdapter(targetClass) != null) .map(selectedElement -> ((IAdaptable) selectedElement) .getAdapter(targetClass)) .collect(Collectors.toList()); } return Collections.emptyList(); } /** * Finds and returns a cleared {@link RunConsole} if the preference * {@link PreferenceConstants#AUTOLOG_ON_START} is set to {@code true}. * * @param connection * the current Docker connection * @param container * the container whose log should be sent in the * {@link RunConsole}. * @return the {@link RunConsole} or {@code null} */ public static RunConsole getRunConsole(final IDockerConnection connection, final IDockerContainer container) { if (container != null && connection.getContainerInfo(container.id()) != null && connection.getContainerInfo(container.id()).config() != null && connection.getContainerInfo(container.id()).config().tty()) { RunConsole.attachToTerminal(connection, container.id()); return null; } final boolean autoLogOnStart = Activator.getDefault().getPreferenceStore() .getBoolean(PreferenceConstants.AUTOLOG_ON_START); // if we are auto-logging, grab the // console for the container id and get // its stream. if (autoLogOnStart) { final RunConsole console = RunConsole.findConsole(container); if (console != null) { console.attachToConsole(connection); console.clearConsole(); return console; } } return null; } /** * Opens the given {@link IWizard} and returns <code>true</code> if the user * finished the operation, <code>false</code> if he cancelled it. * * @param wizard * the wizard to open * @param shell * the current {@link Shell} * @return <code>true</code> if the wizard completed, <code>false</code> * otherwise. */ public static boolean openWizard(final IWizard wizard, final Shell shell) { final WizardDialog wizardDialog = new WizardDialog(shell, wizard); wizardDialog.create(); return wizardDialog.open() == Window.OK; } /** * Opens the given {@link IWizard} and returns <code>true</code> if the user * finished the operation, <code>false</code> if he cancelled it. * * @param wizard * the wizard to open * @param shell * the current {@link Shell} * @param width * width of the wizard * @param height * height of the wizard * @return <code>true</code> if the wizard completed, <code>false</code> * otherwise. */ public static boolean openWizard(final IWizard wizard, final Shell shell, final int width, final int height) { final WizardDialog wizardDialog = new WizardDialog(shell, wizard); wizardDialog.setPageSize(width, height); wizardDialog.create(); return wizardDialog.open() == Window.OK; } /** * Executes the command identified by the given {@code id} on a context * based on the given selection * * @param id * the id of the command to execute * @param selection * the selection to use as a context to run the command */ public static void execute(final String id, final IStructuredSelection selection) { final ICommandService service = PlatformUI.getWorkbench() .getService(ICommandService.class); final Command command = service != null ? service.getCommand(id) : null; if (command != null && command.isDefined()) { try { ParameterizedCommand pCmd = ParameterizedCommand.generateCommand(command, null); IHandlerService handlerSvc = PlatformUI.getWorkbench().getService(IHandlerService.class); IEvaluationContext ctx = handlerSvc.getCurrentState(); ctx = new EvaluationContext(ctx, selection); ctx.addVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME, selection); handlerSvc.executeCommandInContext(pCmd, null, ctx); } catch (Exception e) { Activator.log(e); } } } }