001: /*******************************************************************************
002: * Copyright (c) 2006, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * David Saff (saff@mit.edu) - bug 102632: [JUnit] Support for JUnit 4.
011: *******************************************************************************/package org.eclipse.pde.ui.launcher;
012:
013: import java.io.File;
014: import java.util.List;
015: import java.util.Map;
016:
017: import org.eclipse.core.resources.IProject;
018: import org.eclipse.core.runtime.CoreException;
019: import org.eclipse.core.runtime.IPath;
020: import org.eclipse.core.runtime.IProgressMonitor;
021: import org.eclipse.core.runtime.IStatus;
022: import org.eclipse.core.runtime.Path;
023: import org.eclipse.core.runtime.Status;
024: import org.eclipse.core.runtime.SubProgressMonitor;
025: import org.eclipse.debug.core.DebugPlugin;
026: import org.eclipse.debug.core.ILaunch;
027: import org.eclipse.debug.core.ILaunchConfiguration;
028: import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
029: import org.eclipse.jdt.core.IJavaProject;
030: import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
031: import org.eclipse.jdt.launching.IVMInstall;
032: import org.eclipse.jdt.launching.IVMRunner;
033: import org.eclipse.osgi.service.resolver.BundleDescription;
034: import org.eclipse.osgi.util.NLS;
035: import org.eclipse.pde.core.plugin.IFragmentModel;
036: import org.eclipse.pde.core.plugin.IPluginModelBase;
037: import org.eclipse.pde.core.plugin.PluginRegistry;
038: import org.eclipse.pde.core.plugin.TargetPlatform;
039: import org.eclipse.pde.internal.core.ClasspathHelper;
040: import org.eclipse.pde.internal.core.PDECore;
041: import org.eclipse.pde.internal.core.TargetPlatformHelper;
042: import org.eclipse.pde.internal.core.util.CoreUtility;
043: import org.eclipse.pde.internal.core.util.VersionUtil;
044: import org.eclipse.pde.internal.ui.IPDEUIConstants;
045: import org.eclipse.pde.internal.ui.PDEPlugin;
046: import org.eclipse.pde.internal.ui.PDEUIMessages;
047: import org.eclipse.pde.internal.ui.launcher.EclipsePluginValidationOperation;
048: import org.eclipse.pde.internal.ui.launcher.LaunchArgumentsHelper;
049: import org.eclipse.pde.internal.ui.launcher.LaunchConfigurationHelper;
050: import org.eclipse.pde.internal.ui.launcher.LaunchPluginValidator;
051: import org.eclipse.pde.internal.ui.launcher.LauncherUtils;
052: import org.eclipse.pde.internal.ui.launcher.VMHelper;
053: import org.osgi.framework.Version;
054:
055: /**
056: * A launch delegate for launching JUnit Plug-in tests.
057: *
058: * @since 3.3
059: */
060: public class JUnitLaunchConfigurationDelegate extends
061: org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate {
062:
063: private static String[] REQUIRED_PLUGINS = {
064: "org.junit", "org.eclipse.jdt.junit.runtime", "org.eclipse.pde.junit.runtime" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
065:
066: protected File fConfigDir = null;
067:
068: private Map fPluginMap;
069:
070: /*
071: * (non-Javadoc)
072: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getVMRunner(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String)
073: */
074: public IVMRunner getVMRunner(ILaunchConfiguration configuration,
075: String mode) throws CoreException {
076: IVMInstall launcher = VMHelper.createLauncher(configuration);
077: return launcher.getVMRunner(mode);
078: }
079:
080: /* (non-Javadoc)
081: * @see org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate#verifyMainTypeName(org.eclipse.debug.core.ILaunchConfiguration)
082: */
083: public String verifyMainTypeName(ILaunchConfiguration configuration)
084: throws CoreException {
085: if (TargetPlatformHelper.getTargetVersion() >= 3.3)
086: return "org.eclipse.equinox.launcher.Main"; //$NON-NLS-1$
087: return "org.eclipse.core.launcher.Main"; //$NON-NLS-1$
088: }
089:
090: private String getTestPluginId(ILaunchConfiguration configuration)
091: throws CoreException {
092: IJavaProject javaProject = getJavaProject(configuration);
093: IPluginModelBase model = PluginRegistry.findModel(javaProject
094: .getProject());
095: if (model == null)
096: abort(
097: NLS
098: .bind(
099: PDEUIMessages.JUnitLaunchConfiguration_error_notaplugin,
100: javaProject.getProject().getName()),
101: null, IStatus.OK);
102: if (model instanceof IFragmentModel)
103: return ((IFragmentModel) model).getFragment().getPluginId();
104:
105: return model.getPluginBase().getId();
106: }
107:
108: /*
109: * (non-Javadoc)
110: * @see org.eclipse.jdt.internal.junit.launcher.JUnitBaseLaunchConfiguration#abort(java.lang.String, java.lang.Throwable, int)
111: */
112: protected void abort(String message, Throwable exception, int code)
113: throws CoreException {
114: throw new CoreException(new Status(IStatus.ERROR,
115: IPDEUIConstants.PLUGIN_ID, code, message, exception));
116: }
117:
118: /* (non-Javadoc)
119: * @see org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate#collectExecutionArguments(org.eclipse.debug.core.ILaunchConfiguration, java.util.List, java.util.List)
120: */
121: protected void collectExecutionArguments(
122: ILaunchConfiguration configuration,
123: List/*String*/vmArguments, List/*String*/programArgs)
124: throws CoreException {
125: super .collectExecutionArguments(configuration, vmArguments,
126: programArgs);
127:
128: // Specify the JUnit Plug-in test application to launch
129: programArgs.add("-application"); //$NON-NLS-1$
130: String application = null;
131: try {
132: // if application is set, it must be a headless app.
133: application = configuration.getAttribute(
134: IPDELauncherConstants.APPLICATION, (String) null);
135: } catch (CoreException e) {
136: }
137:
138: // if application is not set, we should launch the default UI test app
139: // Check to see if we should launch the legacy UI app
140: if (application == null) {
141: IPluginModelBase model = (IPluginModelBase) fPluginMap
142: .get("org.eclipse.pde.junit.runtime"); //$NON-NLS-1$
143: BundleDescription desc = model != null ? model
144: .getBundleDescription() : null;
145: if (desc != null) {
146: Version version = desc.getVersion();
147: int major = version.getMajor();
148: // launch legacy UI app only if we are launching a target that does
149: // not use the new application model and we are launching with a
150: // org.eclipse.pde.junit.runtime whose version is >= 3.3
151: if (major >= 3
152: && version.getMinor() >= 3
153: && !TargetPlatformHelper
154: .usesNewApplicationModel()) {
155: application = IPDEUIConstants.LEGACY_UI_TEST_APPLICATION;
156: }
157: }
158: }
159:
160: // launch the UI test application
161: if (application == null)
162: application = IPDEUIConstants.UI_TEST_APPLICATION;
163:
164: programArgs.add(application);
165:
166: // If a product is specified, then add it to the program args
167: if (configuration.getAttribute(
168: IPDELauncherConstants.USE_PRODUCT, false)) {
169: programArgs.add("-product"); //$NON-NLS-1$
170: programArgs.add(configuration.getAttribute(
171: IPDELauncherConstants.PRODUCT, "")); //$NON-NLS-1$
172: } else {
173: // Specify the application to test
174: String defaultApplication = IPDEUIConstants.CORE_TEST_APPLICATION
175: .equals(application) ? null : TargetPlatform
176: .getDefaultApplication();
177: String testApplication = configuration.getAttribute(
178: IPDELauncherConstants.APP_TO_TEST,
179: defaultApplication);
180: if (testApplication != null) {
181: programArgs.add("-testApplication"); //$NON-NLS-1$
182: programArgs.add(testApplication);
183: }
184: }
185:
186: // Specify the location of the runtime workbench
187: String targetWorkspace = LaunchArgumentsHelper
188: .getWorkspaceLocation(configuration);
189: if (targetWorkspace.length() > 0) {
190: programArgs.add("-data"); //$NON-NLS-1$
191: programArgs.add(targetWorkspace);
192: }
193:
194: // Create the platform configuration for the runtime workbench
195: String productID = LaunchConfigurationHelper
196: .getProductID(configuration);
197: LaunchConfigurationHelper.createConfigIniFile(configuration,
198: productID, fPluginMap,
199: getConfigurationDirectory(configuration));
200: String brandingId = LaunchConfigurationHelper
201: .getContributingPlugin(productID);
202: TargetPlatform.createPlatformConfiguration(
203: getConfigurationDirectory(configuration),
204: (IPluginModelBase[]) fPluginMap.values().toArray(
205: new IPluginModelBase[fPluginMap.size()]),
206: brandingId != null ? (IPluginModelBase) fPluginMap
207: .get(brandingId) : null);
208: TargetPlatformHelper.checkPluginPropertiesConsistency(
209: fPluginMap, getConfigurationDirectory(configuration));
210:
211: programArgs.add("-configuration"); //$NON-NLS-1$
212: programArgs
213: .add("file:" + new Path(getConfigurationDirectory(configuration).getPath()).addTrailingSeparator().toString()); //$NON-NLS-1$
214:
215: // Specify the output folder names
216: programArgs.add("-dev"); //$NON-NLS-1$
217: programArgs.add(ClasspathHelper.getDevEntriesProperties(
218: getConfigurationDirectory(configuration).toString()
219: + "/dev.properties", fPluginMap)); //$NON-NLS-1$
220:
221: // necessary for PDE to know how to load plugins when target platform = host platform
222: // see PluginPathFinder.getPluginPaths()
223: IPluginModelBase base = findPlugin(PDECore.PLUGIN_ID);
224: if (base != null
225: && VersionUtil.compareMacroMinorMicro(base
226: .getBundleDescription().getVersion(),
227: new Version("3.3.1")) < 0) //$NON-NLS-1$
228: programArgs.add("-pdelaunch"); //$NON-NLS-1$
229:
230: // Create the .options file if tracing is turned on
231: if (configuration.getAttribute(IPDELauncherConstants.TRACING,
232: false)
233: && !IPDELauncherConstants.TRACING_NONE
234: .equals(configuration.getAttribute(
235: IPDELauncherConstants.TRACING_CHECKED,
236: (String) null))) {
237: programArgs.add("-debug"); //$NON-NLS-1$
238: String path = getConfigurationDirectory(configuration)
239: .getPath()
240: + IPath.SEPARATOR + ".options"; //$NON-NLS-1$
241: programArgs.add(LaunchArgumentsHelper
242: .getTracingFileArgument(configuration, path));
243: }
244:
245: // add the program args specified by the user
246: String[] userArgs = LaunchArgumentsHelper
247: .getUserProgramArgumentArray(configuration);
248: for (int i = 0; i < userArgs.length; i++) {
249: // be forgiving if people have tracing turned on and forgot
250: // to remove the -debug from the program args field.
251: if (userArgs[i].equals("-debug") && programArgs.contains("-debug")) //$NON-NLS-1$ //$NON-NLS-2$
252: continue;
253: programArgs.add(userArgs[i]);
254: }
255:
256: if (!configuration.getAttribute(
257: IPDEUIConstants.APPEND_ARGS_EXPLICITLY, false)) {
258: if (!programArgs.contains("-os")) { //$NON-NLS-1$
259: programArgs.add("-os"); //$NON-NLS-1$
260: programArgs.add(TargetPlatform.getOS());
261: }
262: if (!programArgs.contains("-ws")) { //$NON-NLS-1$
263: programArgs.add("-ws"); //$NON-NLS-1$
264: programArgs.add(TargetPlatform.getWS());
265: }
266: if (!programArgs.contains("-arch")) { //$NON-NLS-1$
267: programArgs.add("-arch"); //$NON-NLS-1$
268: programArgs.add(TargetPlatform.getOSArch());
269: }
270: }
271:
272: programArgs.add("-testpluginname"); //$NON-NLS-1$
273: programArgs.add(getTestPluginId(configuration));
274: }
275:
276: private IPluginModelBase findPlugin(String id) throws CoreException {
277: IPluginModelBase model = PluginRegistry.findModel(id);
278: if (model == null)
279: model = PDECore.getDefault().findPluginInHost(id);
280: if (model == null)
281: abort(
282: NLS
283: .bind(
284: PDEUIMessages.JUnitLaunchConfiguration_error_missingPlugin,
285: id), null, IStatus.OK);
286: return model;
287: }
288:
289: /*
290: * (non-Javadoc)
291: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getProgramArguments(org.eclipse.debug.core.ILaunchConfiguration)
292: */
293: public String getProgramArguments(ILaunchConfiguration configuration)
294: throws CoreException {
295: return LaunchArgumentsHelper
296: .getUserProgramArguments(configuration);
297: }
298:
299: /*
300: * (non-Javadoc)
301: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getVMArguments(org.eclipse.debug.core.ILaunchConfiguration)
302: */
303: public String getVMArguments(ILaunchConfiguration configuration)
304: throws CoreException {
305: String vmArgs = LaunchArgumentsHelper
306: .getUserVMArguments(configuration);
307:
308: // necessary for PDE to know how to load plugins when target platform = host platform
309: // see PluginPathFinder.getPluginPaths() and PluginPathFinder.isDevLaunchMode()
310: IPluginModelBase base = (IPluginModelBase) LaunchPluginValidator
311: .getPluginsToRun(configuration).get(PDECore.PLUGIN_ID);
312: if (base != null
313: && VersionUtil.compareMacroMinorMicro(base
314: .getBundleDescription().getVersion(),
315: new Version("3.3.1")) >= 0) { //$NON-NLS-1$
316: if (vmArgs.length() > 0 && !vmArgs.endsWith(" ")) //$NON-NLS-1$
317: vmArgs = vmArgs.concat(" "); //$NON-NLS-1$
318: vmArgs = vmArgs.concat("-Declipse.pde.launch=true"); //$NON-NLS-1$
319: }
320: return vmArgs;
321: }
322:
323: /*
324: * (non-Javadoc)
325: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getEnvironment(org.eclipse.debug.core.ILaunchConfiguration)
326: */
327: public String[] getEnvironment(ILaunchConfiguration configuration)
328: throws CoreException {
329: return DebugPlugin.getDefault().getLaunchManager()
330: .getEnvironment(configuration);
331: }
332:
333: /*
334: * (non-Javadoc)
335: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getClasspath(org.eclipse.debug.core.ILaunchConfiguration)
336: */
337: public String[] getClasspath(ILaunchConfiguration configuration)
338: throws CoreException {
339: String[] classpath = LaunchArgumentsHelper
340: .constructClasspath(configuration);
341: if (classpath == null) {
342: abort(
343: PDEUIMessages.WorkbenchLauncherConfigurationDelegate_noStartup,
344: null, IStatus.OK);
345: }
346: return classpath;
347: }
348:
349: /*
350: * (non-Javadoc)
351: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getWorkingDirectory(org.eclipse.debug.core.ILaunchConfiguration)
352: */
353: public File getWorkingDirectory(ILaunchConfiguration configuration)
354: throws CoreException {
355: return LaunchArgumentsHelper.getWorkingDirectory(configuration);
356: }
357:
358: /*
359: * (non-Javadoc)
360: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getVMSpecificAttributesMap(org.eclipse.debug.core.ILaunchConfiguration)
361: */
362: public Map getVMSpecificAttributesMap(
363: ILaunchConfiguration configuration) throws CoreException {
364: return LaunchArgumentsHelper
365: .getVMSpecificAttributesMap(configuration);
366: }
367:
368: /*
369: * (non-Javadoc)
370: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#setDefaultSourceLocator(org.eclipse.debug.core.ILaunch, org.eclipse.debug.core.ILaunchConfiguration)
371: */
372: protected void setDefaultSourceLocator(ILaunch launch,
373: ILaunchConfiguration configuration) throws CoreException {
374: ILaunchConfigurationWorkingCopy wc = null;
375: if (configuration.isWorkingCopy()) {
376: wc = (ILaunchConfigurationWorkingCopy) configuration;
377: } else {
378: wc = configuration.getWorkingCopy();
379: }
380: String id = configuration
381: .getAttribute(
382: IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER,
383: (String) null);
384: if (!PDESourcePathProvider.ID.equals(id)) {
385: wc
386: .setAttribute(
387: IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER,
388: PDESourcePathProvider.ID);
389: wc.doSave();
390: }
391:
392: manageLaunch(launch);
393: }
394:
395: /**
396: * Returns the location of the configuration area
397: *
398: * @param configuration
399: * the launch configuration
400: * @return a directory where the configuration area is located
401: */
402: protected File getConfigurationDirectory(
403: ILaunchConfiguration configuration) {
404: if (fConfigDir == null)
405: fConfigDir = LaunchConfigurationHelper
406: .getConfigurationArea(configuration);
407: return fConfigDir;
408: }
409:
410: /*
411: * (non-Javadoc)
412: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getBuildOrder(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String)
413: */
414: protected IProject[] getBuildOrder(
415: ILaunchConfiguration configuration, String mode)
416: throws CoreException {
417: return computeBuildOrder(LaunchPluginValidator
418: .getAffectedProjects(configuration));
419: }
420:
421: /*
422: * (non-Javadoc)
423: * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getProjectsForProblemSearch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String)
424: */
425: protected IProject[] getProjectsForProblemSearch(
426: ILaunchConfiguration configuration, String mode)
427: throws CoreException {
428: return LaunchPluginValidator.getAffectedProjects(configuration);
429: }
430:
431: /**
432: * Adds a listener to the launch to be notified at interesting launch lifecycle
433: * events such as when the launch terminates.
434: *
435: * @param launch
436: * the launch
437: */
438: protected void manageLaunch(ILaunch launch) {
439: PDEPlugin.getDefault().getLaunchListener().manage(launch);
440: }
441:
442: /* (non-Javadoc)
443: * @see org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate#preLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
444: */
445: protected void preLaunchCheck(ILaunchConfiguration configuration,
446: ILaunch launch, IProgressMonitor monitor)
447: throws CoreException {
448: // Get the list of plug-ins to run
449: fPluginMap = LaunchPluginValidator
450: .getPluginsToRun(configuration);
451:
452: // implicitly add the plug-ins required for JUnit testing if necessary
453: for (int i = 0; i < REQUIRED_PLUGINS.length; i++) {
454: String id = REQUIRED_PLUGINS[i];
455: if (!fPluginMap.containsKey(id)) {
456: fPluginMap.put(id, findPlugin(id));
457: }
458: }
459:
460: boolean autoValidate = configuration.getAttribute(
461: IPDELauncherConstants.AUTOMATIC_VALIDATE, false);
462: monitor.beginTask("", autoValidate ? 3 : 4); //$NON-NLS-1$
463: if (autoValidate)
464: validatePluginDependencies(configuration,
465: new SubProgressMonitor(monitor, 1));
466: validateProjectDependencies(configuration,
467: new SubProgressMonitor(monitor, 1));
468: clear(configuration, new SubProgressMonitor(monitor, 1));
469: launch.setAttribute(IPDELauncherConstants.CONFIG_LOCATION,
470: getConfigurationDirectory(configuration).toString());
471: synchronizeManifests(configuration, new SubProgressMonitor(
472: monitor, 1));
473: }
474:
475: /**
476: * Checks for old-style plugin.xml files that have become stale since the last launch.
477: * For any stale plugin.xml files found, the corresponding MANIFEST.MF is deleted
478: * from the runtime configuration area so that it gets regenerated upon startup.
479: *
480: * @param configuration
481: * the launch configuration
482: * @param monitor
483: * the progress monitor
484: */
485: protected void synchronizeManifests(
486: ILaunchConfiguration configuration, IProgressMonitor monitor) {
487: LaunchConfigurationHelper.synchronizeManifests(configuration,
488: getConfigurationDirectory(configuration));
489: monitor.done();
490: }
491:
492: /**
493: * Clears the workspace prior to launching if the workspace exists and the option to
494: * clear it is turned on. Also clears the configuration area if that option is chosen.
495: *
496: * @param configuration
497: * the launch configuration
498: * @param monitor
499: * the progress monitor
500: * @throws CoreException
501: * if unable to retrieve launch attribute values
502: * @since 3.3
503: */
504: protected void clear(ILaunchConfiguration configuration,
505: IProgressMonitor monitor) throws CoreException {
506: String workspace = LaunchArgumentsHelper
507: .getWorkspaceLocation(configuration);
508: // Clear workspace and prompt, if necessary
509: if (!LauncherUtils.clearWorkspace(configuration, workspace,
510: new SubProgressMonitor(monitor, 1))) {
511: monitor.setCanceled(true);
512: return;
513: }
514:
515: // clear config area, if necessary
516: if (configuration.getAttribute(
517: IPDELauncherConstants.CONFIG_CLEAR_AREA, false))
518: CoreUtility
519: .deleteContent(getConfigurationDirectory(configuration));
520: }
521:
522: /**
523: * Checks if the Automated Management of Dependencies option is turned on.
524: * If so, it makes aure all manifests are updated with the correct dependencies.
525: *
526: * @param configuration
527: * the launch configuration
528: * @param monitor
529: * a progress monitor
530: */
531: protected void validateProjectDependencies(
532: ILaunchConfiguration configuration, IProgressMonitor monitor) {
533: LauncherUtils.validateProjectDependencies(configuration,
534: monitor);
535: }
536:
537: /**
538: * Validates inter-bundle dependencies automatically prior to launching
539: * if that option is turned on.
540: *
541: * @param configuration
542: * the launch configuration
543: * @param monitor
544: * a progress monitor
545: */
546: protected void validatePluginDependencies(
547: ILaunchConfiguration configuration, IProgressMonitor monitor)
548: throws CoreException {
549: EclipsePluginValidationOperation op = new EclipsePluginValidationOperation(
550: configuration);
551: LaunchPluginValidator.runValidationOperation(op, monitor);
552: }
553: }
|