/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.testunit.launcher; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Status; 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.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.dialogs.ElementListSelectionDialog; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.debug.ui.RdtDebugUiConstants; import org.rubypeople.rdt.internal.debug.ui.launcher.RubyApplicationShortcut; import org.rubypeople.rdt.internal.testunit.ui.TestUnitMessages; import org.rubypeople.rdt.internal.testunit.ui.TestunitPlugin; import org.rubypeople.rdt.launching.IRubyLaunchConfigurationConstants; import org.rubypeople.rdt.launching.IRuntimeLoadpathEntry; import org.rubypeople.rdt.launching.RubyRuntime; public class TestUnitLaunchShortcut extends RubyApplicationShortcut { /** * @param mode * @param rubyElement */ protected void doLaunch(IRubyElement rubyElement, String mode) throws CoreException { String container = getContainer(rubyElement); ILaunchConfiguration config = findOrCreateLaunchConfiguration(rubyElement, mode, container, "", ""); if (config != null) { DebugUITools.launch(config, mode); } } protected ILaunchConfiguration findOrCreateLaunchConfiguration(IRubyElement rubyElement, String mode, String container, String testClass, String testName) throws CoreException { IFile rubyFile = (IFile) rubyElement.getUnderlyingResource(); ILaunchConfigurationType configType = getRubyLaunchConfigType(); List<ILaunchConfiguration> candidateConfigs = null; ILaunchConfiguration[] configs = getLaunchManager().getLaunchConfigurations(configType); candidateConfigs = new ArrayList<ILaunchConfiguration>(configs.length); for (int i = 0; i < configs.length; i++) { ILaunchConfiguration config = configs[i]; if ((config.getAttribute(TestUnitLaunchConfigurationDelegate.LAUNCH_CONTAINER_ATTR, "").equals(container)) && (config.getAttribute(TestUnitLaunchConfigurationDelegate.TESTTYPE_ATTR, "").equals("")) && (config.getAttribute(TestUnitLaunchConfigurationDelegate.TESTNAME_ATTR, "").equals(testName)) && (config.getAttribute(IRubyLaunchConfigurationConstants.ATTR_PROJECT_NAME, "").equals(rubyFile .getProject().getName()))) { candidateConfigs.add(config); } } switch (candidateConfigs.size()) { case 0: return createConfiguration(rubyFile, container, testName); case 1: return candidateConfigs.get(0); default: ILaunchConfiguration config = chooseConfiguration(candidateConfigs, mode); if (config != null) { return config; } return null; } } /** * Show a selection dialog that allows the user to choose one of the specified launch configurations. Return the * chosen config, or <code>null</code> if the user cancelled the dialog. */ protected ILaunchConfiguration chooseConfiguration(List configList, String mode) { IDebugModelPresentation labelProvider = DebugUITools.newDebugModelPresentation(); ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider); dialog.setElements(configList.toArray()); dialog.setTitle(TestUnitMessages.LaunchTestAction_message_selectConfiguration); if (mode.equals(ILaunchManager.DEBUG_MODE)) { dialog.setMessage(TestUnitMessages.LaunchTestAction_message_selectDebugConfiguration); } else { dialog.setMessage(TestUnitMessages.LaunchTestAction_message_selectRunConfiguration); } dialog.setMultipleSelection(false); int result = dialog.open(); labelProvider.dispose(); if (result == Window.OK) { return (ILaunchConfiguration) dialog.getFirstResult(); } return null; } /** * Convenience method to get the window that owns this action's Shell. */ protected Shell getShell() { return TestunitPlugin.getActiveWorkbenchShell(); } /** * @param rubyElement * @return */ private String getContainer(IRubyElement rubyElement) { return rubyElement.getHandleIdentifier(); } protected ILaunchConfiguration createConfiguration(IFile rubyFile, String container, String testName) { return createConfiguration(rubyFile.getLocation().toOSString(), container, rubyFile.getProject(), testName); } protected ILaunchConfiguration createConfiguration(String rubyFile, String container, IProject project, String testName) { if (RubyRuntime.getDefaultVMInstall() == null) { showNoInterpreterDialog(); return null; } // Force project's lib and test folders to be added to loadpath for testing runs String[] commonLoadPathFolders = new String[] { "lib", "test" }; List<String> loadpath = new ArrayList<String>(); try { for (int i = 0; i < commonLoadPathFolders.length; i++) { if (project.getFolder(commonLoadPathFolders[i]).exists()) { IRuntimeLoadpathEntry entry = RubyRuntime.newArchiveRuntimeLoadpathEntry(project.getLocation() .append(commonLoadPathFolders[i])); loadpath.add(entry.getMemento()); } } } catch (CoreException e) { log(e); } ILaunchConfiguration config = null; try { ILaunchConfigurationType configType = getRubyLaunchConfigType(); ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, RubyRuntime.generateUniqueLaunchConfigurationNameFrom(rubyFile)); wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_FILE_NAME, TestUnitLaunchConfigurationDelegate .getTestRunnerPath()); wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, TestUnitLaunchShortcut .getDefaultWorkingDirectory(project)); wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, RubyRuntime.getDefaultVMInstall() .getName()); wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, RubyRuntime.getDefaultVMInstall() .getVMInstallType().getId()); wc.setAttribute(TestUnitLaunchConfigurationDelegate.LAUNCH_CONTAINER_ATTR, container); wc.setAttribute(TestUnitLaunchConfigurationDelegate.TESTNAME_ATTR, testName); wc.setAttribute(TestUnitLaunchConfigurationDelegate.TESTTYPE_ATTR, ""); if (loadpath != null && !loadpath.isEmpty()) { wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_DEFAULT_LOADPATH, false); wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_LOADPATH, loadpath); } wc.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, RdtDebugUiConstants.RUBY_SOURCE_LOCATOR); config = wc.doSave(); } catch (CoreException ce) { log(ce); } return config; } protected ILaunchConfigurationType getRubyLaunchConfigType() { return getLaunchManager().getLaunchConfigurationType( TestUnitLaunchConfigurationDelegate.ID_TESTUNIT_APPLICATION); } protected ILaunchManager getLaunchManager() { return DebugPlugin.getDefault().getLaunchManager(); } protected void log(String message) { TestunitPlugin.log(new Status(Status.INFO, TestunitPlugin.PLUGIN_ID, Status.INFO, message, null)); } protected void log(Throwable t) { TestunitPlugin.log(t); } protected void showNoInterpreterDialog() { MessageDialog.openInformation(TestunitPlugin.getActiveWorkbenchShell(), TestUnitMessages.Dialog_launchWithoutSelectedInterpreter_title, TestUnitMessages.Dialog_launchWithoutSelectedInterpreter); } protected static String getDefaultWorkingDirectory(IProject project) { if (project != null && project.exists()) { return project.getLocation().toOSString(); } // might have been deleted return TestunitPlugin.getWorkspace().getRoot().getLocation().toOSString(); } }