KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > junit > launcher > JUnitLaunchShortcut


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * David Saff (saff@mit.edu) - bug 102632: [JUnit] Support for JUnit 4.
11  *******************************************************************************/

12 package org.eclipse.jdt.junit.launcher;
13
14 import java.lang.reflect.InvocationTargetException JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IAdaptable;
20 import org.eclipse.core.runtime.IPath;
21
22 import org.eclipse.swt.widgets.Shell;
23
24 import org.eclipse.jface.dialogs.MessageDialog;
25 import org.eclipse.jface.viewers.ISelection;
26 import org.eclipse.jface.viewers.IStructuredSelection;
27 import org.eclipse.jface.window.Window;
28
29 import org.eclipse.ui.IEditorPart;
30 import org.eclipse.ui.PlatformUI;
31 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
32
33 import org.eclipse.debug.core.DebugPlugin;
34 import org.eclipse.debug.core.ILaunchConfiguration;
35 import org.eclipse.debug.core.ILaunchConfigurationType;
36 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
37 import org.eclipse.debug.core.ILaunchManager;
38
39 import org.eclipse.debug.ui.DebugUITools;
40 import org.eclipse.debug.ui.IDebugModelPresentation;
41 import org.eclipse.debug.ui.ILaunchShortcut;
42
43 import org.eclipse.jdt.core.IClassFile;
44 import org.eclipse.jdt.core.ICompilationUnit;
45 import org.eclipse.jdt.core.IJavaElement;
46 import org.eclipse.jdt.core.IJavaProject;
47 import org.eclipse.jdt.core.IMethod;
48 import org.eclipse.jdt.core.IPackageFragment;
49 import org.eclipse.jdt.core.IPackageFragmentRoot;
50 import org.eclipse.jdt.core.IType;
51
52 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
53
54 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
55
56 import org.eclipse.jdt.ui.JavaElementLabelProvider;
57 import org.eclipse.jdt.ui.JavaElementLabels;
58 import org.eclipse.jdt.ui.JavaUI;
59
60 import org.eclipse.jdt.internal.junit.launcher.AssertionVMArg;
61 import org.eclipse.jdt.internal.junit.launcher.ITestKind;
62 import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants;
63 import org.eclipse.jdt.internal.junit.launcher.JUnitMigrationDelegate;
64 import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry;
65 import org.eclipse.jdt.internal.junit.ui.JUnitMessages;
66 import org.eclipse.jdt.internal.junit.ui.JUnitPlugin;
67 import org.eclipse.jdt.internal.junit.util.ExceptionHandler;
68 import org.eclipse.jdt.internal.junit.util.TestSearchEngine;
69
70 /**
71  * The launch shortcut to launch JUnit tests.
72  *
73  * <p>
74  * This class may be instantiated and subclassed.
75  * </p>
76  * @since 3.3
77  */

78 public class JUnitLaunchShortcut implements ILaunchShortcut {
79
80     private static final String JavaDoc EMPTY_STRING= ""; //$NON-NLS-1$
81

82     /**
83      * Default constructor.
84      */

85     public JUnitLaunchShortcut() {
86     }
87     
88     
89     /* (non-Javadoc)
90      * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.ui.IEditorPart, java.lang.String)
91      */

92     public void launch(IEditorPart editor, String JavaDoc mode) {
93         IJavaElement element= JavaUI.getEditorInputJavaElement(editor.getEditorInput());
94         if (element != null) {
95             launch(new Object JavaDoc[] { element }, mode);
96         } else {
97             showNoTestsFoundDialog();
98         }
99     }
100
101     /* (non-Javadoc)
102      * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.jface.viewers.ISelection, java.lang.String)
103      */

104     public void launch(ISelection selection, String JavaDoc mode) {
105         if (selection instanceof IStructuredSelection) {
106             launch(((IStructuredSelection) selection).toArray(), mode);
107         } else {
108             showNoTestsFoundDialog();
109         }
110     }
111
112     private void launch(Object JavaDoc[] elements, String JavaDoc mode) {
113         try {
114             IJavaElement elementToLaunch= null;
115             
116             if (elements.length == 1) {
117                 Object JavaDoc selected= elements[0];
118                 if (!(selected instanceof IJavaElement) && selected instanceof IAdaptable) {
119                     selected= ((IAdaptable) selected).getAdapter(IJavaElement.class);
120                 }
121                 if (selected instanceof IJavaElement) {
122                     IJavaElement element= (IJavaElement) selected;
123                     switch (element.getElementType()) {
124                         case IJavaElement.JAVA_PROJECT:
125                         case IJavaElement.PACKAGE_FRAGMENT_ROOT:
126                         case IJavaElement.PACKAGE_FRAGMENT:
127                         case IJavaElement.TYPE:
128                         case IJavaElement.METHOD:
129                             elementToLaunch= element;
130                             break;
131                         case IJavaElement.CLASS_FILE:
132                             elementToLaunch= ((IClassFile) element).getType();
133                             break;
134                         case IJavaElement.COMPILATION_UNIT:
135                             elementToLaunch= findTypeToLaunch((ICompilationUnit) element, mode);
136                             break;
137                     }
138                 }
139             }
140             if (elementToLaunch == null) {
141                 showNoTestsFoundDialog();
142                 return;
143             }
144             performLaunch(elementToLaunch, mode);
145         } catch (InterruptedException JavaDoc e) {
146             // OK, silently move on
147
} catch (CoreException e) {
148             ExceptionHandler.handle(e, getShell(), JUnitMessages.JUnitLaunchShortcut_dialog_title, JUnitMessages.JUnitLaunchShortcut_message_launchfailed);
149         } catch (InvocationTargetException JavaDoc e) {
150             ExceptionHandler.handle(e, getShell(), JUnitMessages.JUnitLaunchShortcut_dialog_title, JUnitMessages.JUnitLaunchShortcut_message_launchfailed);
151         }
152     }
153
154     private void showNoTestsFoundDialog() {
155         MessageDialog.openInformation(getShell(), JUnitMessages.JUnitLaunchShortcut_dialog_title, JUnitMessages.JUnitLaunchShortcut_message_notests);
156     }
157
158     private IType findTypeToLaunch(ICompilationUnit cu, String JavaDoc mode) throws CoreException, InterruptedException JavaDoc, InvocationTargetException JavaDoc {
159         ITestKind testKind= TestKindRegistry.getContainerTestKind(cu);
160         IType[] types= TestSearchEngine.findTests(PlatformUI.getWorkbench().getActiveWorkbenchWindow(), cu, testKind);
161         if (types.length == 0) {
162             return null;
163         } else if (types.length > 1) {
164             return chooseType(types, mode);
165         }
166         return types[0];
167     }
168
169     private void performLaunch(IJavaElement element, String JavaDoc mode) throws InterruptedException JavaDoc, CoreException {
170         ILaunchConfigurationWorkingCopy temparary= createLaunchConfiguration(element);
171         ILaunchConfiguration config= findExistingLaunchConfiguration(temparary, mode);
172         if (config == null) {
173             // no existing found: create a new one
174
config= temparary.doSave();
175         }
176         DebugUITools.launch(config, mode);
177     }
178
179     private IType chooseType(IType[] types, String JavaDoc mode) throws InterruptedException JavaDoc {
180         ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_POST_QUALIFIED));
181         dialog.setElements(types);
182         dialog.setTitle(JUnitMessages.JUnitLaunchShortcut_dialog_title2);
183         if (mode.equals(ILaunchManager.DEBUG_MODE)) {
184             dialog.setMessage(JUnitMessages.JUnitLaunchShortcut_message_selectTestToDebug);
185         } else {
186             dialog.setMessage(JUnitMessages.JUnitLaunchShortcut_message_selectTestToRun);
187         }
188         dialog.setMultipleSelection(false);
189         if (dialog.open() == Window.OK) {
190             return (IType) dialog.getFirstResult();
191         }
192         throw new InterruptedException JavaDoc(); // cancelled by user
193
}
194
195     private Shell getShell() {
196         return JUnitPlugin.getActiveWorkbenchShell();
197     }
198
199     private ILaunchManager getLaunchManager() {
200         return DebugPlugin.getDefault().getLaunchManager();
201     }
202
203     /**
204      * Show a selection dialog that allows the user to choose one of the
205      * specified launch configurations. Return the chosen config, or
206      * <code>null</code> if the user cancelled the dialog.
207      *
208      * @param configList
209      * @param mode
210      * @return ILaunchConfiguration
211      * @throws InterruptedException
212      */

213     private ILaunchConfiguration chooseConfiguration(List JavaDoc configList, String JavaDoc mode) throws InterruptedException JavaDoc {
214         IDebugModelPresentation labelProvider= DebugUITools.newDebugModelPresentation();
215         ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), labelProvider);
216         dialog.setElements(configList.toArray());
217         dialog.setTitle(JUnitMessages.JUnitLaunchShortcut_message_selectConfiguration);
218         if (mode.equals(ILaunchManager.DEBUG_MODE)) {
219             dialog.setMessage(JUnitMessages.JUnitLaunchShortcut_message_selectDebugConfiguration);
220         } else {
221             dialog.setMessage(JUnitMessages.JUnitLaunchShortcut_message_selectRunConfiguration);
222         }
223         dialog.setMultipleSelection(false);
224         int result= dialog.open();
225         if (result == Window.OK) {
226             return (ILaunchConfiguration) dialog.getFirstResult();
227         }
228         throw new InterruptedException JavaDoc(); // cancelled by user
229
}
230
231     /**
232      * Returns the launch configuration type id of the launch configuration this shortcut will create. Clients can override this method to
233      * return the id of their launch configuration.
234      *
235      * @return the launch configuration type id of the launch configuration this shortcut will create
236      */

237     protected String JavaDoc getLaunchConfigurationTypeId() {
238         return JUnitLaunchConfigurationConstants.ID_JUNIT_APPLICATION;
239     }
240     
241     /**
242      * Creates a launch configuration working copy for the given element. The launch configuration type created will be of the type returned by {@link #getLaunchConfigurationTypeId}.
243      * The element type can only be of type {@link IJavaProject}, {@link IPackageFragmentRoot}, {@link IPackageFragment}, {@link IType} or {@link IMethod}.
244      *
245      * Clients can extend this method (should call super) to configure additional attributes on the launch configuration working copy.
246      *
247      * @return a launch configuration working copy for the given element
248      */

249     protected ILaunchConfigurationWorkingCopy createLaunchConfiguration(IJavaElement element) throws CoreException {
250         final String JavaDoc testName;
251         final String JavaDoc mainTypeQualifiedName;
252         final String JavaDoc containerHandleId;
253         
254         switch (element.getElementType()) {
255             case IJavaElement.JAVA_PROJECT:
256             case IJavaElement.PACKAGE_FRAGMENT_ROOT:
257             case IJavaElement.PACKAGE_FRAGMENT: {
258                 String JavaDoc name= JavaElementLabels.getTextLabel(element, JavaElementLabels.ALL_FULLY_QUALIFIED);
259                 containerHandleId= element.getHandleIdentifier();
260                 mainTypeQualifiedName= EMPTY_STRING;
261                 testName= name.substring(name.lastIndexOf(IPath.SEPARATOR) + 1);
262             }
263             break;
264             case IJavaElement.TYPE: {
265                 containerHandleId= EMPTY_STRING;
266                 mainTypeQualifiedName= JavaModelUtil.getFullyQualifiedName((IType) element); // don't replace, fix for binary inner types
267
testName= element.getElementName();
268             }
269             break;
270             case IJavaElement.METHOD: {
271                 IMethod method= (IMethod) element;
272                 containerHandleId= EMPTY_STRING;
273                 mainTypeQualifiedName= JavaModelUtil.getFullyQualifiedName(method.getDeclaringType());
274                 testName= method.getDeclaringType().getElementName() + '.' + method.getElementName();
275             }
276             break;
277             default:
278                 throw new IllegalArgumentException JavaDoc("Invalid element type to create a launch configuration: " + element.getClass().getName()); //$NON-NLS-1$
279
}
280         
281         String JavaDoc testKindId= TestKindRegistry.getContainerTestKindId(element);
282         
283         ILaunchConfigurationType configType= getLaunchManager().getLaunchConfigurationType(getLaunchConfigurationTypeId());
284         ILaunchConfigurationWorkingCopy wc= configType.newInstance(null, getLaunchManager().generateUniqueLaunchConfigurationNameFrom(testName));
285             
286         wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, mainTypeQualifiedName);
287         wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, element.getJavaProject().getElementName());
288         wc.setAttribute(JUnitLaunchConfigurationConstants.ATTR_KEEPRUNNING, false);
289         wc.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, containerHandleId);
290         wc.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND, testKindId);
291         JUnitMigrationDelegate.mapResources(wc);
292         AssertionVMArg.setArgDefault(wc);
293         if (element instanceof IMethod) {
294             wc.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, element.getElementName()); // only set for methods
295
}
296         return wc;
297     }
298     
299     /**
300      * Returns the attribute names of the attributes that are compared when looking for an existing similar launch configuration.
301      * Clients can override and replace to customize.
302      *
303      * @return the attribute names of the attributes that are compared
304      */

305     protected String JavaDoc[] getAttributeNamesToCompare() {
306         return new String JavaDoc[] {
307             IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER,
308             IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME
309         };
310     }
311     
312     private static boolean hasSameAttributes(ILaunchConfiguration config1, ILaunchConfiguration config2, String JavaDoc[] attributeToCompare) {
313         try {
314             for (int i= 0; i < attributeToCompare.length; i++) {
315                 String JavaDoc val1= config1.getAttribute(attributeToCompare[i], EMPTY_STRING);
316                 String JavaDoc val2= config2.getAttribute(attributeToCompare[i], EMPTY_STRING);
317                 if (!val1.equals(val2)) {
318                     return false;
319                 }
320             }
321             return true;
322         } catch (CoreException e) {
323             // ignore access problems here, return false
324
}
325         return false;
326     }
327     
328
329     private ILaunchConfiguration findExistingLaunchConfiguration(ILaunchConfigurationWorkingCopy temporary, String JavaDoc mode) throws InterruptedException JavaDoc, CoreException {
330         ILaunchConfigurationType configType= temporary.getType();
331
332         ILaunchConfiguration[] configs= getLaunchManager().getLaunchConfigurations(configType);
333         String JavaDoc[] attributeToCompare= getAttributeNamesToCompare();
334         
335         ArrayList JavaDoc candidateConfigs= new ArrayList JavaDoc(configs.length);
336         for (int i= 0; i < configs.length; i++) {
337             ILaunchConfiguration config= configs[i];
338             if (hasSameAttributes(config, temporary, attributeToCompare)) {
339                 candidateConfigs.add(config);
340             }
341         }
342
343         // If there are no existing configs associated with the IType, create
344
// one.
345
// If there is exactly one config associated with the IType, return it.
346
// Otherwise, if there is more than one config associated with the
347
// IType, prompt the
348
// user to choose one.
349
int candidateCount= candidateConfigs.size();
350         if (candidateCount == 0) {
351             return null;
352         } else if (candidateCount == 1) {
353             return (ILaunchConfiguration) candidateConfigs.get(0);
354         } else {
355             // Prompt the user to choose a config. A null result means the user
356
// cancelled the dialog, in which case this method returns null,
357
// since cancelling the dialog should also cancel launching
358
// anything.
359
ILaunchConfiguration config= chooseConfiguration(candidateConfigs, mode);
360             if (config != null) {
361                 return config;
362             }
363         }
364         return null;
365     }
366 }
367
Popular Tags