blob: fc8916975f71ce2d0e4f950907d88be1a579d3f4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 Sierra Wireless 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:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.ldt.debug.ui.internal.launchconfiguration.local;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
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.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchHistory;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.ILaunchGroup;
import org.eclipse.dltk.compiler.env.IModuleSource;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.internal.core.ProjectFragment;
import org.eclipse.dltk.internal.debug.ui.launcher.AbstractScriptLaunchShortcut;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.LaunchingMessages;
import org.eclipse.dltk.launching.ScriptLaunchConfigurationConstants;
import org.eclipse.dltk.launching.ScriptRuntime;
import org.eclipse.dltk.launching.process.ScriptRuntimeProcessFactory;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ldt.core.LuaConstants;
import org.eclipse.ldt.core.LuaNature;
import org.eclipse.ldt.core.LuaUtils;
import org.eclipse.ldt.core.internal.buildpath.LuaExecutionEnvironmentBuildpathUtil;
import org.eclipse.ldt.debug.core.internal.LuaDebugConstants;
import org.eclipse.ldt.debug.core.interpreter.LuaInterpreterUtil;
import org.eclipse.ldt.debug.ui.internal.Activator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.PlatformUI;
/**
* Run As strategy:<br>
* launch the latest launch config for the selection<br>
* if not found : <br>
* 1) A file is selected <br>
* -> create a new one <br>
* 2) A folder is selected <br>
* -> the folder have only 1 file -> do 1)<br>
* -> the folder contains several files -> prompt the one to be selected, then do 1)<br>
* 3) A project is selected<br>
* -> there is a main module -> do 1)<br>
* -> there is no main module -> do 2)<br>
*/
@SuppressWarnings("restriction")
public class LuaApplicationLaunchShortcut extends AbstractScriptLaunchShortcut {
@Override
protected ILaunchConfigurationType getConfigurationType() {
return DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(LuaDebugConstants.LOCAL_LAUNCH_CONFIGURATION_ID);
}
@Override
protected String getNatureId() {
return LuaNature.ID;
}
@Override
public void searchAndLaunch(Object[] search, String mode, String selectMessage, String emptyMessage) {
// As the Lua Application Run As menu is enable only when one item is selected (see extension point)
// the following code just take in account the first element
Object selection = search[0];
// configuration to launch :
ILaunchConfiguration config = null;
// find existing
config = findExistingLaunchConfiguration(selection, mode);
// not found create one
if (config == null)
config = createLaunchConfiguration(selection);
// Launch
if (config != null)
DebugUITools.launch(config, mode);
}
private ILaunchConfiguration createLaunchConfiguration(Object selection) {
// script selection
if (selection instanceof IFile) {
return createLaunchConfiguration((IFile) selection);
} else if (selection instanceof ISourceModule) {
try {
IResource correspondingResource = ((ISourceModule) selection).getCorrespondingResource();
if (correspondingResource instanceof IFile)
return createLaunchConfiguration((IFile) correspondingResource);
} catch (ModelException e) {
Activator.logError(NLS.bind("Unable to get corresponding resource for module {0}", selection), e); //$NON-NLS-1$
return null;
}
}
// source folder selection
else if (selection instanceof IFolder) {
IModelElement sourcefolder = DLTKCore.create((IFolder) selection);
if (sourcefolder instanceof IScriptFolder)
return createLaunchConfiguration((IScriptFolder) sourcefolder);
} else if (selection instanceof IScriptFolder) {
return createLaunchConfiguration((IScriptFolder) selection);
}
// project selection
else if (selection instanceof IProject) {
IScriptProject project = DLTKCore.create((IProject) selection);
if (project != null)
return createLaunchConfiguration(project);
} else if (selection instanceof ProjectFragment) {
IScriptProject scriptProject = ((ProjectFragment) selection).getScriptProject();
if (scriptProject != null)
return createLaunchConfiguration(scriptProject);
} else if (selection instanceof IScriptProject) {
return createLaunchConfiguration((IScriptProject) selection);
}
return null;
}
public ILaunchConfiguration createLaunchConfiguration(IFile script) {
ILaunchConfiguration config = null;
ILaunchConfigurationWorkingCopy wc = null;
try {
ILaunchConfigurationType configType = getConfigurationType();
// custom launch conf name
String fileNameWithoutExtension = script.getLocation().removeFileExtension().lastSegment();
String configNamePrefix = MessageFormat.format("{0}_{1}", script.getProject().getName(), fileNameWithoutExtension); //$NON-NLS-1$
wc = configType.newInstance(null, getLaunchManager().generateLaunchConfigurationName(configNamePrefix));
wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_SCRIPT_NATURE, getNatureId());
wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME, script.getProject().getName());
wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_MAIN_SCRIPT_NAME, script.getProjectRelativePath().toPortableString());
wc.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID, ScriptRuntimeProcessFactory.PROCESS_FACTORY_ID);
wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_DEBUG_CONSOLE, false);
// Manage interpreters.
IInterpreterInstall guessInterpreter = findBestInterpreter(script);
if (guessInterpreter != null) {
IPath interpreterContainerPath = ScriptRuntime.newInterpreterContainerPath(guessInterpreter);
if (interpreterContainerPath != null)
wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_CONTAINER_PATH, interpreterContainerPath.toPortableString());
}
wc.setMappedResources(new IResource[] { script });
config = wc.doSave();
} catch (CoreException e) {
Activator.logError("Unable to create a launch configuration from a LaunchShortcut", e); //$NON-NLS-1$
}
return config;
}
public IInterpreterInstall findBestInterpreter(IFile script) {
IProject project = script.getProject();
if (project == null)
return null;
IScriptProject scriptProject = DLTKCore.create(project);
if (scriptProject == null || !LuaUtils.isLuaProject(project))
return null;
IPath eePath = LuaUtils.getLuaExecutionEnvironmentPath(scriptProject);
if (eePath == null)
return null;
String eeid = LuaExecutionEnvironmentBuildpathUtil.getEEID(eePath);
String eeVersion = LuaExecutionEnvironmentBuildpathUtil.getEEVersion(eePath);
if (eeid == null || eeVersion == null)
return null;
// if this project has an execution environment
// check if the default one is compatible
IInterpreterInstall defaultInterpreterInstall = LuaInterpreterUtil.getDefaultInterpreter();
if (defaultInterpreterInstall != null && LuaInterpreterUtil.isExecutionEnvironmentCompatible(defaultInterpreterInstall, eeid, eeVersion))
return defaultInterpreterInstall;
// else check with other interpreters
IInterpreterInstall embeddedinterpreter = null;
for (IInterpreterInstall interpreter : LuaInterpreterUtil.getInterpreters()) {
if (LuaInterpreterUtil.isExecutionEnvironmentCompatible(interpreter, eeid, eeVersion)) {
// we give priority to non embedded interpreter
if (LuaInterpreterUtil.isEmbedded(interpreter))
embeddedinterpreter = interpreter;
else
return interpreter;
}
}
return embeddedinterpreter;
}
public ILaunchConfiguration createLaunchConfiguration(IParent sourcecontainer) {
// Search scripts contains in this container
IResource[] scripts = null;
try {
scripts = findScripts(new Object[] { sourcecontainer }, PlatformUI.getWorkbench().getProgressService());
} catch (InterruptedException e) {
return null;
} catch (CoreException e) {
MessageDialog.openError(getShell(), LaunchingMessages.ScriptLaunchShortcut_0, e.getMessage());
return null;
}
IResource script;
if (scripts.length == 0) {
// no file in folder
MessageDialog.openError(getShell(), LaunchingMessages.ScriptLaunchShortcut_1, getSelectionEmptyMessage());
} else if (scripts.length == 1) {
// create a new one for this script
return createLaunchConfiguration(scripts[0]);
} else if (scripts.length > 1) {
// prompt user to choose a script
script = chooseScript(scripts, getScriptSelectionTitle());
if (script != null) {
return createLaunchConfiguration(scripts[0]);
}
}
return null;
}
public ILaunchConfiguration createLaunchConfiguration(IScriptProject project) {
// search a main file
String defaultModuleName = new Path(LuaConstants.DEFAULT_MAIN_FILE).removeFileExtension().toString();
IModuleSource mainModule = LuaUtils.getModuleSource(defaultModuleName, project);
if (mainModule != null) {
try {
return createLaunchConfiguration(mainModule.getModelElement().getCorrespondingResource());
} catch (ModelException e) {
Activator.logWarning("Unable to find ressource corresponding to main module", e); //$NON-NLS-1$
}
}
// if not found do the same as sourcefolder
return createLaunchConfiguration((IParent) project);
}
/**
* find the last launch configuration for this container
*/
private ILaunchConfiguration findExistingLaunchConfiguration(Object container, String launchMode) {
try {
// get all existing config
List<ILaunchConfiguration> candidateConfigs = retreiveLaunchConfiguration(launchMode);
// search the first which match for this container
candidateConfigs = filterConfig(container, candidateConfigs);
if (!candidateConfigs.isEmpty()) {
return candidateConfigs.get(0);
}
} catch (CoreException e) {
Activator.logWarning("Unable to retrieve existing launch configuration.", e); //$NON-NLS-1$
} catch (InterruptedException e) {
return null;
}
return null;
}
/**
* get all existing launch configuration for the current type and launch mode sorted by favorites then history.
*/
private List<ILaunchConfiguration> retreiveLaunchConfiguration(String launchMode) throws CoreException {
ILaunchGroup group = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getLaunchGroup(getConfigurationType(), launchMode);
LaunchHistory history = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getLaunchHistory(group.getIdentifier());
List<ILaunchConfiguration> candidateConfigs = new ArrayList<ILaunchConfiguration>();
candidateConfigs.addAll(Arrays.asList(history.getFavorites()));
candidateConfigs.addAll(Arrays.asList(history.getHistory()));
// if no history for our resource, let filter existing configs
if (candidateConfigs.isEmpty()) {
candidateConfigs.addAll(Arrays.asList(DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(getConfigurationType())));
}
return candidateConfigs;
}
/**
* search the config in candidateConfigs list which match for this selection. <br>
*
* see {@link org.eclipse.dltk.internal.debug.ui.launcher.AbstractScriptLaunchShortcut.getScriptResources(Object[], IProgressMonitor)}
*/
private List<ILaunchConfiguration> filterConfig(Object selection, List<ILaunchConfiguration> candidateConfigs)
throws InterruptedException, CoreException {
IResource[] scripts = findScripts(new Object[] { selection }, PlatformUI.getWorkbench().getProgressService());
return filterConfig(Arrays.asList(scripts), candidateConfigs);
}
/**
* search the config in candidateConfigs list which match for this list of scripts.
*/
private List<ILaunchConfiguration> filterConfig(List<IResource> scripts, List<ILaunchConfiguration> configs) throws CoreException {
List<ILaunchConfiguration> candidateConfigs = new ArrayList<ILaunchConfiguration>();
for (ILaunchConfiguration config : configs) {
for (IResource script : scripts) {
if (config.getAttribute(ScriptLaunchConfigurationConstants.ATTR_MAIN_SCRIPT_NAME, Util.EMPTY_STRING)
.equals(script.getProjectRelativePath().toString())
&& config.getAttribute(ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME, Util.EMPTY_STRING)
.equals(script.getProject().getName())
&& config.getType().equals(getConfigurationType())) {
candidateConfigs.add(config);
}
}
}
return candidateConfigs;
}
@Override
protected void launch(final IResource script, final String mode) {
searchAndLaunch(new Object[] { script }, mode, null, null);
}
/**
* @Deprecated use createLaunchConfiguration
*/
@Override
@Deprecated
protected ILaunchConfiguration createConfiguration(IResource script) {
return super.createConfiguration(script);
}
}