/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sebastian Davids: sdavids@gmx.de bug: 26293, 27889
 *     David Saff (saff@mit.edu) - bug 102632: [JUnit] Support for JUnit 4.
 *     Robert Konigsberg <konigsberg@google.com> - [JUnit] Improve discoverability of the ability to run a single method under JUnit Tests - https://bugs.eclipse.org/bugs/show_bug.cgi?id=285637
 *******************************************************************************/
package org.eclipse.jdt.junit.launcher;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;

import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.SelectionDialog;

import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;

import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;

import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;

import org.eclipse.jdt.internal.junit.BasicElementLabels;
import org.eclipse.jdt.internal.junit.JUnitCorePlugin;
import org.eclipse.jdt.internal.junit.Messages;
import org.eclipse.jdt.internal.junit.launcher.ITestKind;
import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants;
import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchIncludeExcludeTagsDialog;
import org.eclipse.jdt.internal.junit.launcher.JUnitMigrationDelegate;
import org.eclipse.jdt.internal.junit.launcher.TestKind;
import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry;
import org.eclipse.jdt.internal.junit.ui.IJUnitHelpContextIds;
import org.eclipse.jdt.internal.junit.ui.JUnitMessages;
import org.eclipse.jdt.internal.junit.ui.JUnitPlugin;
import org.eclipse.jdt.internal.junit.util.CoreTestSearchEngine;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility;
import org.eclipse.jdt.internal.junit.util.LayoutUtil;
import org.eclipse.jdt.internal.junit.util.TestSearchEngine;

import org.eclipse.jdt.launching.AbstractVMInstall;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;

import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaElementComparator;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
import org.eclipse.jdt.ui.dialogs.ITypeInfoFilterExtension;
import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension;

import org.eclipse.jdt.internal.ui.util.SWTUtil;
import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator;
import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;


/**
 * The launch configuration tab for JUnit.
 * <p>
 * This class may be instantiated but is not intended to be subclassed.
 * </p>
 * @since 3.3
 *
 * @noextend This class is not intended to be subclassed by clients.
 */
public class JUnitLaunchConfigurationTab extends AbstractLaunchConfigurationTab {

	// Project UI widgets
	private Label fProjLabel;
	private Text fProjText;
	private Button fProjButton;
	private Button fKeepRunning;

	// Test class UI widgets
	private Text fTestText;
	private Button fSearchButton;
	private final Image fTestIcon= createImage("obj16/test.png"); //$NON-NLS-1$
	private String fOriginalTestMethodName;
	private Label fTestMethodLabel;
	private Text fTestMethodText;
	private Button fTestMethodSearchButton;
	private Text fContainerText;
	private IJavaElement fContainerElement;
	private final ILabelProvider fJavaElementLabelProvider= new JavaElementLabelProvider();

	private Button fContainerSearchButton;
	private Button fTestContainerRadioButton;
	private Button fTestRadioButton;
	private Label fTestLabel;

	private Label fIncludeExcludeTagsLabel;
	private Button fIncludeExcludeTagsButton;

	private ComboViewer fTestLoaderViewer;

	private ILaunchConfiguration fLaunchConfiguration;

	private boolean fIsValid= true;

	private Set<String> fMethodsCache;
	private String fMethodsCacheKey;

	/**
	 * Creates a JUnit launch configuration tab.
	 */
	public JUnitLaunchConfigurationTab() {
	}


	@Override
	public void createControl(Composite parent) {
		Composite comp = new Composite(parent, SWT.NONE);
		setControl(comp);

		GridLayout topLayout = new GridLayout();
		topLayout.numColumns= 3;
		comp.setLayout(topLayout);

		createSingleTestSection(comp);
		createSpacer(comp);

		createTestContainerSelectionGroup(comp);
		createSpacer(comp);

		createTagsGroup(comp);
		createSpacer(comp);

		createTestLoaderGroup(comp);
		createSpacer(comp);

		createKeepAliveGroup(comp);
		Dialog.applyDialogFont(comp);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJUnitHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_JUNIT_MAIN_TAB);
		validatePage();
	}

	private void createTagsGroup(Composite comp) {
		GridData gd;

		fIncludeExcludeTagsLabel= new Label(comp, SWT.NONE);
		fIncludeExcludeTagsLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_addtag_text);
		gd= new GridData();
		gd.horizontalSpan= 1;
		fIncludeExcludeTagsLabel.setLayoutData(gd);
		fIncludeExcludeTagsButton= new Button(comp, SWT.PUSH);
		fIncludeExcludeTagsButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_addtag_label);
		fIncludeExcludeTagsButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				configureIncludeExcludeTags();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});
		gd= new GridData();
		gd.horizontalSpan= 1;
		fIncludeExcludeTagsButton.setLayoutData(gd);
	}

	private void createTestLoaderGroup(Composite comp) {
		Label loaderLabel= new Label(comp, SWT.NONE);
		loaderLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_Test_Loader);
		GridData gd= new GridData();
		gd.horizontalIndent= 0;
		loaderLabel.setLayoutData(gd);

		fTestLoaderViewer= new ComboViewer(comp, SWT.DROP_DOWN | SWT.READ_ONLY);
		fTestLoaderViewer.getCombo().setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		ArrayList<TestKind> items= TestKindRegistry.getDefault().getAllKinds();
		fTestLoaderViewer.setContentProvider(ArrayContentProvider.getInstance());
		fTestLoaderViewer.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				return ((TestKind) element).getDisplayName();
			}
		});
		fTestLoaderViewer.setInput(items);
		fTestLoaderViewer.addSelectionChangedListener(event -> {
			setEnableTagsGroup(event);
			validatePage();
			updateLaunchConfigurationDialog();
		});
	}

	private void setEnableTagsGroup(SelectionChangedEvent event) {
		ISelection selection= event.getSelection();
		if (selection instanceof IStructuredSelection) {
			IStructuredSelection ss= (IStructuredSelection) selection;
			if (ss.size() == 1) {
				Object first= ss.getFirstElement();
				if (first instanceof ITestKind) {
					boolean isJUnit5= TestKindRegistry.JUNIT5_TEST_KIND_ID.equals(((ITestKind) first).getId());
					fIncludeExcludeTagsButton.setEnabled(isJUnit5);
				}
			}
		}
	}

	private void createSpacer(Composite comp) {
		Label label= new Label(comp, SWT.NONE);
		GridData gd= new GridData();
		gd.horizontalSpan= 3;
		label.setLayoutData(gd);
	}

	private void createSingleTestSection(Composite comp) {
		fTestRadioButton= new Button(comp, SWT.RADIO);
		fTestRadioButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_oneTest);
		GridData gd = new GridData();
		gd.horizontalSpan = 3;
		fTestRadioButton.setLayoutData(gd);
		fTestRadioButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (fTestRadioButton.getSelection())
					testModeChanged();
			}
		});

		fProjLabel = new Label(comp, SWT.NONE);
		fProjLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_project);
		gd= new GridData();
		gd.horizontalIndent = 25;
		fProjLabel.setLayoutData(gd);

		fProjText= new Text(comp, SWT.SINGLE | SWT.BORDER);
		fProjText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fProjText.addModifyListener(evt -> {
			validatePage();
			updateLaunchConfigurationDialog();
			fSearchButton.setEnabled(fTestRadioButton.getSelection() && fProjText.getText().length() > 0);
		});

		fProjButton = new Button(comp, SWT.PUSH);
		fProjButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_browse);
		fProjButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent evt) {
				handleProjectButtonSelected();
			}
		});
		setButtonGridData(fProjButton);

		fTestLabel = new Label(comp, SWT.NONE);
		gd = new GridData();
		gd.horizontalIndent = 25;
		fTestLabel.setLayoutData(gd);
		fTestLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_test);


		fTestText = new Text(comp, SWT.SINGLE | SWT.BORDER);
		fTestText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fTestText.addModifyListener(evt -> {
			fTestMethodSearchButton.setEnabled(fTestText.getText().length() > 0);
			validatePage();
			updateLaunchConfigurationDialog();
		});

		fSearchButton = new Button(comp, SWT.PUSH);
		fSearchButton.setEnabled(fProjText.getText().length() > 0);
		fSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search);
		fSearchButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent evt) {
				handleSearchButtonSelected();
			}
		});
		setButtonGridData(fSearchButton);

		fTestMethodLabel = new Label(comp, SWT.NONE);
		gd = new GridData();
		gd.horizontalIndent = 25;
		fTestMethodLabel.setLayoutData(gd);
		fTestMethodLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_method);


		fTestMethodText= new Text(comp, SWT.SINGLE | SWT.BORDER);
		gd= new GridData(GridData.FILL_HORIZONTAL);
		fTestMethodText.setLayoutData(gd);

		fTestMethodText.addModifyListener(evt -> {
			validatePage();
			updateLaunchConfigurationDialog();
		});
		fTestMethodText.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_all_methods_text);


		fTestMethodSearchButton = new Button(comp, SWT.PUSH);
		fTestMethodSearchButton.setEnabled(fTestText.getText().length() > 0);
		fTestMethodSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search_method);
		fTestMethodSearchButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent evt) {
				handleTestMethodSearchButtonSelected();
			}
		});

		setButtonGridData(fTestMethodSearchButton);
	}

	private void createTestContainerSelectionGroup(Composite comp) {
		fTestContainerRadioButton= new Button(comp, SWT.RADIO);
		fTestContainerRadioButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_containerTest);
		GridData gd = new GridData();
		gd.horizontalSpan = 3;
		fTestContainerRadioButton.setLayoutData(gd);
		fTestContainerRadioButton.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (fTestContainerRadioButton.getSelection())
					testModeChanged();
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});

		fContainerText = new Text(comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
		SWTUtil.fixReadonlyTextBackground(fContainerText);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalIndent= 25;
		gd.horizontalSpan = 2;
		fContainerText.setLayoutData(gd);
		fContainerText.addModifyListener(evt -> updateLaunchConfigurationDialog());

		fContainerSearchButton = new Button(comp, SWT.PUSH);
		fContainerSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search);
		fContainerSearchButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent evt) {
				handleContainerSearchButtonSelected();
			}
		});
		setButtonGridData(fContainerSearchButton);
	}

	private void handleContainerSearchButtonSelected() {
		IJavaElement javaElement= chooseContainer(fContainerElement);
		if (javaElement != null)
			setContainerElement(javaElement);
	}

	private void setContainerElement(IJavaElement javaElement) {
		fContainerElement= javaElement;
		fContainerText.setText(getPresentationName(javaElement));
		validatePage();
		updateLaunchConfigurationDialog();
	}

	private void createKeepAliveGroup(Composite comp) {
		GridData gd;
		fKeepRunning = new Button(comp, SWT.CHECK);
		fKeepRunning.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				updateLaunchConfigurationDialog();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});
		fKeepRunning.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_keeprunning);
		gd= new GridData();
		gd.horizontalAlignment= GridData.FILL;
		gd.horizontalSpan= 2;
		fKeepRunning.setLayoutData(gd);
	}

	private static Image createImage(String path) {
		return JUnitPlugin.getImageDescriptor(path).createImage();
	}

	@Override
	public void initializeFrom(ILaunchConfiguration config) {
		fLaunchConfiguration= config;

		updateProjectFromConfig(config);
		String containerHandle= ""; //$NON-NLS-1$
		try {
			containerHandle = config.getAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, ""); //$NON-NLS-1$
		} catch (CoreException ce) {
		}

		if (containerHandle.length() > 0)
			updateTestContainerFromConfig(config);
		else
			updateTestTypeFromConfig(config);
		updateKeepRunning(config);
		updateTestLoaderFromConfig(config);

		validatePage();
	}


	private void updateTestLoaderFromConfig(ILaunchConfiguration config) {
		ITestKind testKind= JUnitLaunchConfigurationConstants.getTestRunnerKind(config);
		if (testKind.isNull()) {
			if (fContainerElement != null) {
				testKind= TestKindRegistry.getContainerTestKind(fContainerElement);
			}
			if (testKind.isNull()) {
				testKind= TestKindRegistry.getDefault().getKind(TestKindRegistry.JUNIT3_TEST_KIND_ID);
			}
		}
		fTestLoaderViewer.setSelection(new StructuredSelection(testKind));
	}

	private TestKind getSelectedTestKind() {
		IStructuredSelection selection= (IStructuredSelection) fTestLoaderViewer.getSelection();
		return (TestKind) selection.getFirstElement();
	}

	private void updateKeepRunning(ILaunchConfiguration config) {
		boolean running= false;
		try {
			running= config.getAttribute(JUnitLaunchConfigurationConstants.ATTR_KEEPRUNNING, false);
		} catch (CoreException ce) {
		}
		fKeepRunning.setSelection(running);
	}

	private void updateProjectFromConfig(ILaunchConfiguration config) {
		String projectName= ""; //$NON-NLS-1$
		try {
			projectName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
		} catch (CoreException ce) {
		}
		fProjText.setText(projectName);
	}

	private void updateTestTypeFromConfig(ILaunchConfiguration config) {
		String testTypeName= ""; //$NON-NLS-1$
		fOriginalTestMethodName= ""; //$NON-NLS-1$
		try {
			testTypeName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); //$NON-NLS-1$
			fOriginalTestMethodName = config.getAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_NAME, ""); //$NON-NLS-1$
		} catch (CoreException ce) {
		}
		fTestRadioButton.setSelection(true);
		setEnableSingleTestGroup(true);
		setEnableContainerTestGroup(false);
		fTestContainerRadioButton.setSelection(false);
		fTestText.setText(testTypeName);
		fContainerText.setText(""); //$NON-NLS-1$
		fTestMethodText.setText(fOriginalTestMethodName);
	}

	private void updateTestContainerFromConfig(ILaunchConfiguration config) {
		String containerHandle= ""; //$NON-NLS-1$
		IJavaElement containerElement = null;
		try {
			containerHandle = config.getAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, ""); //$NON-NLS-1$
			if (containerHandle.length() > 0) {
				containerElement= JavaCore.create(containerHandle);
			}
		} catch (CoreException ce) {
		}
		if (containerElement != null)
			fContainerElement = containerElement;
		fTestContainerRadioButton.setSelection(true);
		setEnableSingleTestGroup(false);
		setEnableContainerTestGroup(true);
		fTestRadioButton.setSelection(false);
		if (fContainerElement != null)
			fContainerText.setText(getPresentationName(fContainerElement));
		fTestText.setText(""); //$NON-NLS-1$
	}

	@Override
	public void performApply(ILaunchConfigurationWorkingCopy config) {
		if (fTestContainerRadioButton.getSelection() && fContainerElement != null) {
			config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, fContainerElement.getJavaProject().getElementName());
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, fContainerElement.getHandleIdentifier());
			config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); //$NON-NLS-1$
			 //workaround for bug 65399
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_NAME, ""); //$NON-NLS-1$
		} else {
			config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, fProjText.getText());
			config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, fTestText.getText());
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, ""); //$NON-NLS-1$
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_NAME, fTestMethodText.getText());
		}
		config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_KEEPRUNNING, fKeepRunning.getSelection());
		try {
			mapResources(config);
		} catch (CoreException e) {
			JUnitPlugin.log(e.getStatus());
		}
		IStructuredSelection testKindSelection= (IStructuredSelection) fTestLoaderViewer.getSelection();
		if (! testKindSelection.isEmpty()) {
			TestKind testKind= (TestKind) testKindSelection.getFirstElement();
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND, testKind.getId());
		}
	}

	private void mapResources(ILaunchConfigurationWorkingCopy config)  throws CoreException {
		JUnitMigrationDelegate.mapResources(config);
	}


	@Override
	public void dispose() {
		super.dispose();
		fTestIcon.dispose();
		fJavaElementLabelProvider.dispose();
	}

	@Override
	public Image getImage() {
		return fTestIcon;
	}

	/*
	 * Show a dialog that lists all main types
	 */
	private void handleSearchButtonSelected() {
		Shell shell = getShell();

		IJavaProject javaProject = getJavaProject();

		IType[] types= new IType[0];
		boolean[] radioSetting= new boolean[2];
		try {
			// fix for 66922 Wrong radio behaviour when switching
			// remember the selected radio button
			radioSetting[0]= fTestRadioButton.getSelection();
			radioSetting[1]= fTestContainerRadioButton.getSelection();

			types= TestSearchEngine.findTests(getLaunchConfigurationDialog(), javaProject, getSelectedTestKind());
		} catch (InterruptedException e) {
			setErrorMessage(e.getMessage());
			return;
		} catch (InvocationTargetException e) {
			JUnitPlugin.log(e.getTargetException());
			return;
		} finally {
			fTestRadioButton.setSelection(radioSetting[0]);
			fTestContainerRadioButton.setSelection(radioSetting[1]);
		}

		final HashSet<String> typeLookup= new HashSet<>();
		for (IType type : types) {
			typeLookup.add(type.getPackageFragment().getElementName() + '/' + type.getTypeQualifiedName('.'));
		}
		SelectionDialog dialog= null;
		try {
			dialog= JavaUI.createTypeDialog(shell,
					getLaunchConfigurationDialog(),
					SearchEngine.createJavaSearchScope(new IJavaElement[] { javaProject }, IJavaSearchScope.SOURCES),
					IJavaElementSearchConstants.CONSIDER_ALL_TYPES,
					false,
					"**", //$NON-NLS-1$
					new TypeSelectionExtension() {
						@Override
						public ITypeInfoFilterExtension getFilterExtension() {
							return requestor -> {
								StringBuilder buf= new StringBuilder();
								buf.append(requestor.getPackageName()).append('/');
								String enclosingName= requestor.getEnclosingName();
								if (enclosingName.length() > 0)
									buf.append(enclosingName).append('.');
								buf.append(requestor.getTypeName());
								return typeLookup.contains(buf.toString());
							};
						}
					});
		} catch (JavaModelException e) {
			JUnitPlugin.log(e);
			return;
		}

		dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_testdialog_title);
		dialog.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_testdialog_message);
		if (dialog.open() == Window.CANCEL) {
			return;
		}

		Object[] results = dialog.getResult();
		if ((results == null) || (results.length < 1)) {
			return;
		}
		IType type = (IType)results[0];

		if (type != null) {
			fTestText.setText(type.getFullyQualifiedName('.'));
			javaProject = type.getJavaProject();
			fProjText.setText(javaProject.getElementName());
		}
	}

	/*
	 * Show a dialog that lets the user select a project.  This in turn provides
	 * context for the main type, allowing the user to key a main type name, or
	 * constraining the search for main types to the specified project.
	 */
	private void handleProjectButtonSelected() {
		IJavaProject project = chooseJavaProject();
		if (project == null) {
			return;
		}

		String projectName = project.getElementName();
		fProjText.setText(projectName);
	}

	private void handleTestMethodSearchButtonSelected() {
		try {
			IJavaProject javaProject = getJavaProject();
			IType testType= javaProject.findType(fTestText.getText());
			Set<String> methodNames= getMethodsForType(javaProject, testType, getSelectedTestKind());
			String methodName= chooseMethodName(methodNames);

			if (methodName != null) {
				fTestMethodText.setText(methodName);
				validatePage();
				updateLaunchConfigurationDialog();
			}
		} catch (JavaModelException e) {
			JUnitPlugin.log(e.getStatus());
		}
	}

	private Set<String> getMethodsForType(IJavaProject javaProject, IType type, TestKind testKind) throws JavaModelException {
		if (javaProject == null || type == null || testKind == null)
			return Collections.emptySet();

		String testKindId= testKind.getId();
		String methodsCacheKey= javaProject.getElementName() + '\n' + type.getFullyQualifiedName() + '\n' + testKindId;
		if (methodsCacheKey.equals(fMethodsCacheKey))
			return fMethodsCache;

		Set<String> methodNames= new HashSet<>();
		fMethodsCache= methodNames;
		fMethodsCacheKey= methodsCacheKey;

		collectMethodNames(type, javaProject, testKindId, methodNames);

		return methodNames;
	}

	private void collectMethodNames(IType type, IJavaProject javaProject, String testKindId, Set<String> methodNames) throws JavaModelException {
		if (type == null) {
			return;
		}
		collectDeclaredMethodNames(type, javaProject, testKindId, methodNames);

		String superclassName= type.getSuperclassName();
		IType superType= getResolvedType(superclassName, type, javaProject);
		collectMethodNames(superType, javaProject, testKindId, methodNames);

		String[] superInterfaceNames= type.getSuperInterfaceNames();
		for (String interfaceName : superInterfaceNames) {
			superType= getResolvedType(interfaceName, type, javaProject);
			collectMethodNames(superType, javaProject, testKindId, methodNames);
		}
	}

	private IType getResolvedType(String typeName, IType type, IJavaProject javaProject) throws JavaModelException {
		IType resolvedType= null;
		if (typeName != null) {
			int pos= typeName.indexOf('<');
			if (pos != -1) {
				typeName= typeName.substring(0, pos);
			}
			String[][] resolvedTypeNames= type.resolveType(typeName);
			if (resolvedTypeNames != null && resolvedTypeNames.length > 0) {
				String[] resolvedTypeName= resolvedTypeNames[0];
				resolvedType= javaProject.findType(resolvedTypeName[0], resolvedTypeName[1]); // secondary types not found by this API
			}
		}
		return resolvedType;
	}

	private void collectDeclaredMethodNames(IType type, IJavaProject javaProject, String testKindId, Set<String> methodNames) throws JavaModelException {
		IMethod[] methods= type.getMethods();
		for (IMethod method : methods) {
			String methodName= method.getElementName();
			int flags= method.getFlags();
			// Only include public, non-static, no-arg methods that return void and start with "test":
			if (Modifier.isPublic(flags) && !Modifier.isStatic(flags) &&
					method.getNumberOfParameters() == 0 && Signature.SIG_VOID.equals(method.getReturnType()) &&
					methodName.startsWith("test")) { //$NON-NLS-1$
				methodNames.add(methodName);
			}
			boolean isJUnit3= TestKindRegistry.JUNIT3_TEST_KIND_ID.equals(testKindId);
			boolean isJUnit5= TestKindRegistry.JUNIT5_TEST_KIND_ID.equals(testKindId);
			if (!isJUnit3 && !Modifier.isPrivate(flags) && !Modifier.isStatic(flags)) {
				IAnnotation annotation= method.getAnnotation("Test"); //$NON-NLS-1$
				if (annotation.exists()) {
					methodNames.add(methodName + JUnitStubUtility.getParameterTypes(method, false));
				} else if (isJUnit5) {
					boolean hasAnyTestAnnotation= method.getAnnotation("TestFactory").exists() //$NON-NLS-1$
							|| method.getAnnotation("Testable").exists() //$NON-NLS-1$
							|| method.getAnnotation("TestTemplate").exists() //$NON-NLS-1$
							|| method.getAnnotation("ParameterizedTest").exists() //$NON-NLS-1$
							|| method.getAnnotation("RepeatedTest").exists(); //$NON-NLS-1$
					if (hasAnyTestAnnotation || isAnnotatedWithTestable(method, type, javaProject)) {
						methodNames.add(methodName + JUnitStubUtility.getParameterTypes(method, false));
					}
				}
			}
		}
	}

	// See JUnit5TestFinder.Annotation#annotates also.
	private boolean isAnnotatedWithTestable(IMethod method, IType declaringType, IJavaProject javaProject) throws JavaModelException {
		for (IAnnotation annotation : method.getAnnotations()) {
			IType annotationType= getResolvedType(annotation.getElementName(), declaringType, javaProject);
			if (annotationType != null) {
				if (matchesTestable(annotationType)) {
					return true;
				}
				Set<IType> hierarchy= new HashSet<>();
				if (matchesTestableInAnnotationHierarchy(annotationType, javaProject, hierarchy)) {
					return true;
				}
			}
		}
		return false;
	}

	private boolean matchesTestable(IType annotationType) {
		return annotationType != null && JUnitCorePlugin.JUNIT5_TESTABLE_ANNOTATION_NAME.equals(annotationType.getFullyQualifiedName());
	}

	private boolean matchesTestableInAnnotationHierarchy(IType annotationType, IJavaProject javaProject, Set<IType> hierarchy) throws JavaModelException {
		if (annotationType != null) {
			for (IAnnotation annotation : annotationType.getAnnotations()) {
				IType annType= getResolvedType(annotation.getElementName(), annotationType, javaProject);
				if (annType != null && hierarchy.add(annType)) {
					if (matchesTestable(annType) || matchesTestableInAnnotationHierarchy(annType, javaProject, hierarchy)) {
						return true;
					}
				}
			}
		}
		return false;
	}

	private String chooseMethodName(Set<String> methodNames) {
		Shell shell= getShell();

		ElementListSelectionDialog dialog= new ElementListSelectionDialog(shell, new LabelProvider());
		dialog.setMessage(Messages.format(JUnitMessages.JUnitLaunchConfigurationTab_select_method_header, fTestText.getText()));
		dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_select_method_title);

		int methodCount= methodNames.size();
		String[] elements= new String[methodCount + 1];
		methodNames.toArray(elements);
		elements[methodCount]= JUnitMessages.JUnitLaunchConfigurationTab_all_methods_text;

		dialog.setElements(elements);

		String methodName= fTestMethodText.getText();

		if (methodNames.contains(methodName)) {
			dialog.setInitialSelections(methodName);
		}

		dialog.setAllowDuplicates(false);
		dialog.setMultipleSelection(false);
		if (dialog.open() == Window.OK) {
			String result= (String)dialog.getFirstResult();
			return (result == null || result.equals(JUnitMessages.JUnitLaunchConfigurationTab_all_methods_text))
					? "" : result; //$NON-NLS-1$
		}
		return null;
	}

	/*
	 * Realize a Java Project selection dialog and return the first selected project,
	 * or null if there was none.
	 */
	private IJavaProject chooseJavaProject() {
		IJavaProject[] projects;
		try {
			projects= JavaCore.create(getWorkspaceRoot()).getJavaProjects();
		} catch (JavaModelException e) {
			JUnitPlugin.log(e.getStatus());
			projects= new IJavaProject[0];
		}

		ILabelProvider labelProvider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
		ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), labelProvider);
		dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_projectdialog_title);
		dialog.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_projectdialog_message);
		dialog.setElements(projects);

		IJavaProject javaProject = getJavaProject();
		if (javaProject != null) {
			dialog.setInitialSelections(javaProject);
		}
		if (dialog.open() == Window.OK) {
			return (IJavaProject) dialog.getFirstResult();
		}
		return null;
	}

	/*
	 * Return the IJavaProject corresponding to the project name in the project name
	 * text field, or null if the text does not match a project name.
	 */
	private IJavaProject getJavaProject() {
		String projectName = fProjText.getText().trim();
		if (projectName.length() < 1) {
			return null;
		}
		return getJavaModel().getJavaProject(projectName);
	}

	/*
	 * Convenience method to get the workspace root.
	 */
	private IWorkspaceRoot getWorkspaceRoot() {
		return ResourcesPlugin.getWorkspace().getRoot();
	}

	/*
	 * Convenience method to get access to the java model.
	 */
	private IJavaModel getJavaModel() {
		return JavaCore.create(getWorkspaceRoot());
	}


	@Override
	public boolean isValid(ILaunchConfiguration config) {
		validatePage();
		return fIsValid;
	}

	private void testModeChanged() {
		boolean isSingleTestMode= fTestRadioButton.getSelection();
		setEnableSingleTestGroup(isSingleTestMode);
		setEnableContainerTestGroup(!isSingleTestMode);
		if (!isSingleTestMode && fContainerText.getText().length() == 0) {
			String projText= fProjText.getText();
			if (Path.EMPTY.isValidSegment(projText)) {
				IJavaProject javaProject= getJavaModel().getJavaProject(projText);
				if (javaProject != null && javaProject.exists())
					setContainerElement(javaProject);
			}
		}
		validatePage();
		updateLaunchConfigurationDialog();
	}

	/*
	 * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#setErrorMessage(java.lang.String)
	 * @since 3.6
	 */
	@Override
	protected void setErrorMessage(String errorMessage) {
		fIsValid= errorMessage == null;
		super.setErrorMessage(errorMessage);
	}

	private void validatePage() {

		setErrorMessage(null);
		setMessage(null);

		if (fTestContainerRadioButton.getSelection()) {
			if (fContainerElement == null) {
				setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_noContainer);
				return;
			}
			validateJavaProject(fContainerElement.getJavaProject());

		} else {
			String projectName= fProjText.getText().trim();
			if (projectName.length() == 0) {
				setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_projectnotdefined);
				return;
			}

			IStatus status= ResourcesPlugin.getWorkspace().validatePath(IPath.SEPARATOR + projectName, IResource.PROJECT);
			if (!status.isOK() || !Path.ROOT.isValidSegment(projectName)) {
				setErrorMessage(Messages.format(JUnitMessages.JUnitLaunchConfigurationTab_error_invalidProjectName, BasicElementLabels.getResourceName(projectName)));
				return;
			}

			IProject project= getWorkspaceRoot().getProject(projectName);
			if (!project.exists()) {
				setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_projectnotexists);
				return;
			}
			IJavaProject javaProject= JavaCore.create(project);
			validateJavaProject(javaProject);

			try {
				if (!project.hasNature(JavaCore.NATURE_ID)) {
					setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_notJavaProject);
					return;
				}
				String className= fTestText.getText().trim();
				if (className.length() == 0) {
					setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testnotdefined);
					return;
				}
				IType type= javaProject.findType(className);
				if (type == null) {
					setErrorMessage(Messages.format(JUnitMessages.JUnitLaunchConfigurationTab_error_test_class_not_found, new String[] { className, projectName }));
					return;
				}
				String methodName= fTestMethodText.getText();
				if (methodName.length() > 0) {
					Set<String> methodsForType= getMethodsForType(javaProject, type, getSelectedTestKind());
					if (!methodsForType.contains(methodName)) {
						super.setErrorMessage(Messages.format(JUnitMessages.JUnitLaunchConfigurationTab_error_test_method_not_found, new String[] { className, methodName, projectName }));
						return;
					}
				}
			} catch (CoreException e) {
				JUnitPlugin.log(e);
			}
		}

		validateTestLoaderJVM();
	}

	private void validateJavaProject(IJavaProject javaProject) {
		TestKind testKind = getSelectedTestKind();
		if (testKind != null) {
			if (!TestKindRegistry.JUNIT5_TEST_KIND_ID.equals(testKind.getId()) && !CoreTestSearchEngine.hasTestCaseType(javaProject)) {
				setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testcasenotonpath);
				return;
			}

			String msg= JUnitMessages.JUnitLaunchConfigurationTab_error_testannotationnotonpath;
			if (TestKindRegistry.JUNIT4_TEST_KIND_ID.equals(testKind.getId()) && !CoreTestSearchEngine.hasJUnit4TestAnnotation(javaProject)) {
				setErrorMessage(Messages.format(msg, JUnitCorePlugin.JUNIT4_ANNOTATION_NAME));
				return;
			}
			if (TestKindRegistry.JUNIT5_TEST_KIND_ID.equals(testKind.getId()) && !CoreTestSearchEngine.hasJUnit5TestAnnotation(javaProject)) {
				setErrorMessage(Messages.format(msg, JUnitCorePlugin.JUNIT5_TESTABLE_ANNOTATION_NAME));
				return;
			}
		}

	}

	private void validateTestLoaderJVM() {
		if (fLaunchConfiguration == null)
			return;

		TestKind testKind = getSelectedTestKind();
		if (testKind == null || TestKindRegistry.JUNIT3_TEST_KIND_ID.equals(testKind.getId()))
			return;
		try {
			String path = fLaunchConfiguration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, (String)null);
			if (path != null) {
				IVMInstall vm = JavaRuntime.getVMInstall(Path.fromPortableString(path));
				if (vm instanceof AbstractVMInstall) {
					String compliance= ((AbstractVMInstall)vm).getJavaVersion();
					if (compliance != null) {
						String testKindId= testKind.getId();
						if (TestKindRegistry.JUNIT4_TEST_KIND_ID.equals(testKindId) && !JUnitStubUtility.is50OrHigher(compliance)) {
							setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_JDK15_required);
						} else if (TestKindRegistry.JUNIT5_TEST_KIND_ID.equals(testKindId) && !JUnitStubUtility.is18OrHigher(compliance)) {
							setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_JDK18_required);
						}
					}
				}
			}
		} catch (CoreException e) {
		}
	}

	private void setEnableContainerTestGroup(boolean enabled) {
		fContainerSearchButton.setEnabled(enabled);
		fContainerText.setEnabled(enabled);
	}

	private void setEnableSingleTestGroup(boolean enabled) {
		fProjLabel.setEnabled(enabled);
		fProjText.setEnabled(enabled);
		fProjButton.setEnabled(enabled);
		fTestLabel.setEnabled(enabled);
		fTestText.setEnabled(enabled);
		boolean projectTextHasContents= fProjText.getText().length() > 0;
		fSearchButton.setEnabled(enabled && projectTextHasContents);
		fTestMethodLabel.setEnabled(enabled);
		fTestMethodText.setEnabled(enabled);
		fTestMethodSearchButton.setEnabled(enabled && projectTextHasContents &&  fTestText.getText().length() > 0);
	}

	@Override
	public void setDefaults(ILaunchConfigurationWorkingCopy config) {
		IJavaElement javaElement = getContext();
		if (javaElement != null) {
			initializeJavaProject(javaElement, config);
		} else {
			// We set empty attributes for project & main type so that when one config is
			// compared to another, the existence of empty attributes doesn't cause an
			// incorrect result (the performApply() method can result in empty values
			// for these attributes being set on a config if there is nothing in the
			// corresponding text boxes)
			config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, ""); //$NON-NLS-1$
		}
		initializeTestAttributes(javaElement, config);
	}

	private void initializeTestAttributes(IJavaElement javaElement, ILaunchConfigurationWorkingCopy config) {
		if (javaElement != null && javaElement.getElementType() < IJavaElement.COMPILATION_UNIT)
			initializeTestContainer(javaElement, config);
		else
			initializeTestType(javaElement, config);
	}

	private void initializeTestContainer(IJavaElement javaElement, ILaunchConfigurationWorkingCopy config) {
		config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, javaElement.getHandleIdentifier());
		initializeName(config, javaElement.getElementName());
	}

	private void initializeName(ILaunchConfigurationWorkingCopy config, String name) {
		if (name == null) {
			name= ""; //$NON-NLS-1$
		}
		if (name.length() > 0) {
			int index = name.lastIndexOf('.');
			if (index > 0) {
				name = name.substring(index + 1);
			}
			name= getLaunchConfigurationDialog().generateName(name);
			config.rename(name);
		}
	}

	/*
	 * Set the main type & name attributes on the working copy based on the IJavaElement
	 */
	private void initializeTestType(IJavaElement javaElement, ILaunchConfigurationWorkingCopy config) {
		String name= ""; //$NON-NLS-1$
		String testKindId= null;
		try {
			// we only do a search for compilation units or class files or
			// or source references
			if (javaElement instanceof ISourceReference) {
				ITestKind testKind= TestKindRegistry.getContainerTestKind(javaElement);
				testKindId= testKind.getId();

				IType[] types = TestSearchEngine.findTests(getLaunchConfigurationDialog(), javaElement, testKind);
				if ((types == null) || (types.length < 1)) {
					return;
				}
				// Simply grab the first main type found in the searched element
				name= types[0].getFullyQualifiedName('.');

			}
		} catch (InterruptedException | InvocationTargetException ite) {
		}
		config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, name);
		if (testKindId != null)
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND, testKindId);
		initializeName(config, name);
		boolean isRunWithJUnitPlatform= TestKindRegistry.isRunWithJUnitPlatform(javaElement);
		if (isRunWithJUnitPlatform) {
			config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_RUN_WITH_JUNIT_PLATFORM_ANNOTATION, true);
		}
	}

	@Override
	public String getName() {
		return JUnitMessages.JUnitLaunchConfigurationTab_tab_label;
	}

	private IJavaElement chooseContainer(IJavaElement initElement) {
		Class<?>[] acceptedClasses= new Class[] { IPackageFragmentRoot.class, IJavaProject.class, IPackageFragment.class };
		TypedElementSelectionValidator validator= new TypedElementSelectionValidator(acceptedClasses, false) {
			@Override
			public boolean isSelectedValid(Object element) {
				return true;
			}
		};

		acceptedClasses= new Class[] { IJavaModel.class, IPackageFragmentRoot.class, IJavaProject.class, IPackageFragment.class };
		ViewerFilter filter= new TypedViewerFilter(acceptedClasses) {
			@Override
			public boolean select(Viewer viewer, Object parent, Object element) {
			    if (element instanceof IPackageFragmentRoot && ((IPackageFragmentRoot)element).isArchive())
			        return false;
			    try {
					if (element instanceof IPackageFragment && !((IPackageFragment) element).hasChildren()) {
						return false;
					}
				} catch (JavaModelException e) {
					return false;
				}
				return super.select(viewer, parent, element);
			}
		};

		StandardJavaElementContentProvider provider= new StandardJavaElementContentProvider();
		ILabelProvider labelProvider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
		ElementTreeSelectionDialog dialog= new ElementTreeSelectionDialog(getShell(), labelProvider, provider);
		dialog.setValidator(validator);
		dialog.setComparator(new JavaElementComparator());
		dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_folderdialog_title);
		dialog.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_folderdialog_message);
		dialog.addFilter(filter);
		dialog.setInput(JavaCore.create(getWorkspaceRoot()));
		dialog.setInitialSelection(initElement);
		dialog.setAllowMultiple(false);

		if (dialog.open() == Window.OK) {
			Object element= dialog.getFirstResult();
			return (IJavaElement)element;
		}
		return null;
	}

	private String getPresentationName(IJavaElement element) {
		return fJavaElementLabelProvider.getText(element);
	}

	/*
	 * Returns the current Java element context from which to initialize
	 * default settings, or <code>null</code> if none.
	 *
	 * @return Java element context.
	 */
	private IJavaElement getContext() {
		IWorkbenchWindow activeWorkbenchWindow= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		if (activeWorkbenchWindow == null) {
			return null;
		}
		IWorkbenchPage page = activeWorkbenchWindow.getActivePage();
		if (page != null) {
			ISelection selection = page.getSelection();
			if (selection instanceof IStructuredSelection) {
				IStructuredSelection ss = (IStructuredSelection)selection;
				if (!ss.isEmpty()) {
					Object obj = ss.getFirstElement();
					if (obj instanceof IJavaElement) {
						return (IJavaElement)obj;
					}
					if (obj instanceof IResource) {
						IJavaElement je = JavaCore.create((IResource)obj);
						if (je == null) {
							IProject pro = ((IResource)obj).getProject();
							je = JavaCore.create(pro);
						}
						if (je != null) {
							return je;
						}
					}
				}
			}
			IEditorPart part = page.getActiveEditor();
			if (part != null) {
				IEditorInput input = part.getEditorInput();
				return input.getAdapter(IJavaElement.class);
			}
		}
		return null;
	}

	private void initializeJavaProject(IJavaElement javaElement, ILaunchConfigurationWorkingCopy config) {
		IJavaProject javaProject = javaElement.getJavaProject();
		String name = null;
		if (javaProject != null && javaProject.exists()) {
			name = javaProject.getElementName();
		}
		config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, name);
	}

	private void setButtonGridData(Button button) {
		GridData gridData= new GridData();
		button.setLayoutData(gridData);
		LayoutUtil.setButtonDimensionHint(button);
	}

	@Override
	public String getId() {
		return "org.eclipse.jdt.junit.JUnitLaunchConfigurationTab"; //$NON-NLS-1$
	}

	private void configureIncludeExcludeTags() {
		JUnitLaunchIncludeExcludeTagsDialog dialog= new JUnitLaunchIncludeExcludeTagsDialog(getShell(), fLaunchConfiguration);

		if (dialog.open() == Window.OK) {
			try {
				ILaunchConfigurationWorkingCopy workingCopy= fLaunchConfiguration.getWorkingCopy();
				workingCopy.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_HAS_INCLUDE_TAGS, dialog.hasIncludeTags());
				workingCopy.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_HAS_EXCLUDE_TAGS, dialog.hasExcludeTags());
				workingCopy.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_INCLUDE_TAGS, dialog.getIncludeTags());
				workingCopy.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_EXCLUDE_TAGS, dialog.getExcludeTags());
				workingCopy.doSave();
				validatePage();
				updateLaunchConfigurationDialog();
			} catch (CoreException e) {
			}
		}
	}
}
