org.jboss.tools.arquillian.ui.internal.launcher.ArquillianLaunchConfigurationTab.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.arquillian.ui.internal.launcher.ArquillianLaunchConfigurationTab.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2014 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     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
 *     Red Hat, Inc.
 *******************************************************************************/
package org.jboss.tools.arquillian.ui.internal.launcher;

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

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.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
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.Messages;
import org.eclipse.jdt.internal.junit.launcher.ITestKind;
import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants;
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.internal.ui.wizards.TypedElementSelectionValidator;
import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
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.ITypeInfoRequestor;
import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension;
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.ISelectionChangedListener;
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.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.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.jboss.tools.arquillian.core.internal.ArquillianConstants;
import org.jboss.tools.arquillian.core.internal.util.ArquillianSearchEngine;
import org.jboss.tools.arquillian.core.internal.util.ArquillianUtility;

/**
 *
 * Based on org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationTab
 */
public class ArquillianLaunchConfigurationTab extends AbstractLaunchConfigurationTab {

    public static final String ID = "org.jboss.tools.arquillian.ui.ArquillianLaunchConfigurationTab"; //$NON-NLS-1$
    // 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.gif"); //$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 ComboViewer fTestLoaderViewer;

    private ILaunchConfiguration fLaunchConfiguration;

    private boolean fIsValid = true;

    private Set<String> fMethodsCache;
    private String fMethodsCacheKey;

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

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
     */
    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);

        createTestLoaderGroup(comp);
        createSpacer(comp);

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

    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));

        List<ITestKind> items = new ArrayList<ITestKind>();
        items.add(TestKindRegistry.getDefault().getKind(TestKindRegistry.JUNIT4_TEST_KIND_ID));
        fTestLoaderViewer.setContentProvider(new ArrayContentProvider());
        fTestLoaderViewer.setLabelProvider(new LabelProvider() {
            @Override
            public String getText(Object element) {
                return ((TestKind) element).getDisplayName();
            }
        });
        fTestLoaderViewer.setInput(items);
        fTestLoaderViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                validatePage();
                updateLaunchConfigurationDialog();
            }
        });
    }

    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(new ModifyListener() {
            public void modifyText(ModifyEvent 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(new ModifyListener() {
            public void modifyText(ModifyEvent 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(new ModifyListener() {
            public void modifyText(ModifyEvent 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() {
            public void widgetSelected(SelectionEvent e) {
                if (fTestContainerRadioButton.getSelection())
                    testModeChanged();
            }

            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });

        fContainerText = new Text(comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalIndent = 25;
        gd.horizontalSpan = 2;
        fContainerText.setLayoutData(gd);
        fContainerText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent 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() {
            public void widgetSelected(SelectionEvent e) {
                updateLaunchConfigurationDialog();
            }

            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();
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
     */
    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())
            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_METHOD_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$
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    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_METHOD_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_METHOD_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);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#dispose()
     */
    @Override
    public void dispose() {
        super.dispose();
        fTestIcon.dispose();
        fJavaElementLabelProvider.dispose();
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage()
     */
    @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 = ArquillianSearchEngine.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<String>();
        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 new ITypeInfoFilterExtension() {
                                public boolean select(ITypeInfoRequestor requestor) {
                                    StringBuffer buf = new StringBuffer();
                                    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 methodsCacheKey = javaProject.getElementName() + '\n' + type.getFullyQualifiedName() + '\n'
                + testKind.getId();
        if (methodsCacheKey.equals(fMethodsCacheKey))
            return fMethodsCache;

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

        boolean isJUnit4 = TestKindRegistry.JUNIT4_TEST_KIND_ID.equals(testKind.getId());

        while (type != null) {
            IMethod[] methods = type.getMethods();
            for (IMethod method : methods) {
                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())
                        && method.getElementName().startsWith("test")) { //$NON-NLS-1$
                    methodNames.add(method.getElementName());
                }
                if (isJUnit4) {
                    IAnnotation annotation = method.getAnnotation("Test"); //$NON-NLS-1$
                    if (annotation.exists()) {
                        methodNames.add(method.getElementName());
                    }
                }
            }
            String superclassName = type.getSuperclassName();
            if (superclassName != null) {
                int pos = superclassName.indexOf('<');
                if (pos != -1)
                    superclassName = superclassName.substring(0, pos);
                String[][] resolvedSupertype = type.resolveType(superclassName);
                if (resolvedSupertype != null && resolvedSupertype.length > 0) {
                    String[] superclass = resolvedSupertype[0];
                    type = javaProject.findType(superclass[0], superclass[1]);
                } else {
                    type = null;
                }
            } else {
                type = null;
            }
        }
        return methodNames;
    }

    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(new String[] { 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))
                    ? "" //$NON-NLS-1$
                    : result;
        }
        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(new Object[] { 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());
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
     */
    @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);
    }

    public void validatePage() {

        setErrorMessage(null);
        setMessage(null);

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

        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) {
        if (!CoreTestSearchEngine.hasTestCaseType(javaProject)) {
            setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testcasenotonpath);
            return;
        }
        if (!CoreTestSearchEngine.hasTestAnnotation(javaProject)) {
            setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testannotationnotonpath);
            return;
        }

        if (!ArquillianSearchEngine.hasArquillianType(javaProject)) {
            setErrorMessage("Cannot find class 'org.jboss.arquillian.junit.Arquillian' on project build");
            return;
        }
        String preference = ArquillianUtility.getPreference(ArquillianConstants.TEST_ARQUILLIAN_CONTAINER);
        if ("true".equals(preference)) {
            IStatus status = ArquillianSearchEngine.validateDeployableContainer(javaProject);
            if (!status.isOK()) {
                setErrorMessage(status.getMessage());
            }
        }
    }

    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 && !JUnitStubUtility.is50OrHigher(compliance)) {
                        setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_JDK15_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);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    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 ie) {

        } catch (InvocationTargetException ite) {
        }
        config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, name);
        if (testKindId != null)
            config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND, testKindId);
        initializeName(config, name);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
     */
    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 (IJavaElement) 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);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getId()
     */
    @Override
    public String getId() {
        return ID;
    }
}