/*******************************************************************************
* Copyright (c) 2012 GoPivotal, 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:
* GoPivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.launch.devtools;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.ILaunchShortcut;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.springframework.ide.eclipse.boot.core.BootActivator;
import org.springframework.ide.eclipse.boot.core.BootPropertyTester;
import org.springframework.ide.eclipse.boot.launch.BootLaunchConfigurationDelegate;
import org.springframework.ide.eclipse.editor.support.util.StringUtil;
@SuppressWarnings("restriction")
public class BootDevtoolsClientLaunchShortcut implements ILaunchShortcut {
@Override
public void launch(ISelection selection, String mode) {
try {
IResource rsrc = getResource(selection);
launch(rsrc, mode);
} catch (Throwable e) {
BootActivator.log(e);
}
}
public void launch(IResource rsrc, String mode) throws CoreException {
if (rsrc!=null && rsrc.getType()==IResource.PROJECT) {
ILaunchConfiguration conf = findOrCreateConfiguration((IProject) rsrc);
if (conf!=null) {
if (isLaunchable(conf)) {
DebugUITools.launch(conf, mode);
} else {
IStructuredSelection selection = new StructuredSelection(new Object[] { conf });
DebugUITools.openLaunchConfigurationDialogOnGroup(getShell(), selection, getLaunchGroup(mode));
}
}
}
}
/**
* Decide whether a launch conf is ready to launch as is or should be opened in
* launc conf editor to allow user to fill in more info.
*/
private boolean isLaunchable(ILaunchConfiguration conf) {
IProject project = BootLaunchConfigurationDelegate.getProject(conf);
String url = BootDevtoolsClientLaunchConfigurationDelegate.getRemoteUrl(conf);
return project!=null &&
BootPropertyTester.isBootProject(project) &&
BootPropertyTester.hasDevtools(project) &&
StringUtil.hasText(url);
}
private String getLaunchGroup(String launchMode) {
if (ILaunchManager.RUN_MODE.equals(launchMode)) {
return IDebugUIConstants.ID_RUN_LAUNCH_GROUP;
} else if (ILaunchManager.DEBUG_MODE.equals(launchMode)) {
return IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP;
} else {
return IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP;
}
}
private ILaunchConfiguration findOrCreateConfiguration(IProject project) throws CoreException {
List<ILaunchConfiguration> candidates = findConfigurations(project);
if (candidates.isEmpty()) {
return createConfiguration(project);
} else if (candidates.size()==1) {
return candidates.get(0);
} else {
return chooseConfiguration(project, candidates);
}
}
private List<ILaunchConfiguration> findConfigurations(IProject project) throws CoreException {
ILaunchManager lm = getLaunchManager();
List<ILaunchConfiguration> configs = new ArrayList<ILaunchConfiguration>();
for (ILaunchConfiguration c : lm.getLaunchConfigurations(getLaunchType())) {
if (Objects.equals(BootLaunchConfigurationDelegate.getProject(c), project)) {
configs.add(c);
}
}
return configs;
}
/**
* Returns a configuration from the given collection of configurations that should be launched,
* or <code>null</code> to cancel. Default implementation opens a selection dialog that allows
* the user to choose one of the specified launch configurations. Returns the chosen configuration,
* or <code>null</code> if the user cancels.
*
* @param configList list of configurations to choose from
* @return configuration to launch or <code>null</code> to cancel
*/
private ILaunchConfiguration chooseConfiguration(IProject project, List<ILaunchConfiguration> configList) {
IDebugModelPresentation labelProvider = DebugUITools.newDebugModelPresentation();
ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), labelProvider);
dialog.setElements(configList.toArray());
dialog.setTitle("Several Devtools Client Configs found for "+project.getName());
dialog.setMessage("Select an existing configuration");
dialog.setMultipleSelection(false);
int result = dialog.open();
labelProvider.dispose();
if (result == Window.OK) {
return (ILaunchConfiguration) dialog.getFirstResult();
}
return null;
}
/**
* Convenience method to return the active workbench window shell.
*
* @return active workbench window shell
*/
protected Shell getShell() {
return JDIDebugUIPlugin.getActiveWorkbenchShell();
}
private ILaunchConfigurationType getLaunchType() {
return getLaunchManager().getLaunchConfigurationType(BootDevtoolsClientLaunchConfigurationDelegate.TYPE_ID);
}
/**
* Returns the singleton launch manager.
*
* @return launch manager
*/
private ILaunchManager getLaunchManager() {
return DebugPlugin.getDefault().getLaunchManager();
}
protected ILaunchConfiguration createConfiguration(IProject project) throws CoreException {
ILaunchConfigurationType configType = getConfigurationType();
String projectName = project.getName();
ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, getLaunchManager().generateLaunchConfigurationName("devtools-client["+projectName+"]"));
setDefaults(wc, project);
wc.setMappedResources(new IResource[] {project});
ILaunchConfiguration config = wc.doSave();
return config;
}
private void setDefaults(ILaunchConfigurationWorkingCopy wc, IProject project) {
BootLaunchConfigurationDelegate.setProject(wc, project);
}
protected ILaunchConfigurationType getConfigurationType() {
return getLaunchManager().getLaunchConfigurationType(BootDevtoolsClientLaunchConfigurationDelegate.TYPE_ID);
}
private IResource getResource(ISelection selection) {
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
Object el = ss.getFirstElement();
if (el instanceof IResource) {
return (IResource) el;
} else if (el instanceof IAdaptable) {
//Warning older Eclipse API 'getAdapter() Object not IResource
Object o = ((IAdaptable) el).getAdapter(IResource.class);
return (IResource)o;
}
}
return null;
}
@Override
public void launch(IEditorPart editor, String mode) {
try {
IEditorInput input = editor.getEditorInput();
Object rsrc = input.getAdapter(IResource.class);
if (rsrc!=null) {
launch((IResource)rsrc, mode);
}
} catch (Throwable e) {
BootActivator.log(e);
}
}
}