tern.eclipse.ide.server.nodejs.ui.debugger.launchConfigurations.AbstractNodejsCliFileLaunchConfigurationTab.java Source code

Java tutorial

Introduction

Here is the source code for tern.eclipse.ide.server.nodejs.ui.debugger.launchConfigurations.AbstractNodejsCliFileLaunchConfigurationTab.java

Source

/**
 *  Copyright (c) 2013-2016 Angelo ZERR.
 *  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:
 *  Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
 */
package tern.eclipse.ide.server.nodejs.ui.debugger.launchConfigurations;

import java.io.File;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ResourceSelectionDialog;
import tern.eclipse.ide.server.nodejs.core.IDENodejsProcessHelper;
import tern.eclipse.ide.server.nodejs.core.INodejsInstall;
import tern.eclipse.ide.server.nodejs.core.INodejsInstallManager;
import tern.eclipse.ide.server.nodejs.core.TernNodejsCorePlugin;
import tern.eclipse.ide.server.nodejs.core.debugger.launchConfigurations.INodejsCliFileLaunchConfigurationConstants;
import tern.eclipse.ide.server.nodejs.core.debugger.launchConfigurations.NodejsCliFileHelper;
import tern.eclipse.ide.server.nodejs.internal.ui.TernNodejsUIMessages;
import tern.eclipse.ide.server.nodejs.internal.ui.TernNodejsUIPlugin;
import tern.eclipse.ide.server.nodejs.internal.ui.preferences.DebuggerFieldEditor;
import tern.eclipse.ide.server.nodejs.internal.ui.preferences.NodeJSConfigEditor;
import tern.utils.StringUtils;

/**
 * Abstract class for tab of launch of client file (ex: protractor tab).
 */
public abstract class AbstractNodejsCliFileLaunchConfigurationTab extends AbstractLaunchConfigurationTab {

    private Text cliFileField;
    private Button workspaceLocationButton;
    private Button variablesLocationButton;

    protected boolean fInitializing = false;
    private boolean userEdited = false;
    protected WidgetListener fListener = new WidgetListener();
    private Combo debuggerField;
    private String[][] debuggers;

    private Label nodePathTitle;
    private Text nodePathInfo;
    private Combo nodeInstallField;
    private String[][] nodeInstalls;
    private Combo nodePathField;
    private Button nodePathButton;

    /**
     * A listener to update for text modification and widget selection.
     */
    protected class WidgetListener extends SelectionAdapter implements ModifyListener {
        @Override
        public void modifyText(ModifyEvent e) {
            updateLaunchConfiguration();
        }

        protected void updateLaunchConfiguration() {
            if (!fInitializing) {
                setDirty(true);
                userEdited = true;
                updateLaunchConfigurationDialog();
            }
        }

        @Override
        public void widgetSelected(SelectionEvent e) {
            setDirty(true);
            Object source = e.getSource();
            if (source == workspaceLocationButton) {
                handleWorkspaceLocationButtonSelected();
            } else if (source == debuggerField || source == nodeInstallField || source == nodePathField) {
                updateLaunchConfiguration();
            } else if (source == nodePathButton) {
                handleNodePathButtonSelected();
            }
        }
    }

    @Override
    public void createControl(Composite parent) {
        Composite mainComposite = new Composite(parent, SWT.NONE);
        setControl(mainComposite);
        mainComposite.setFont(parent.getFont());
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        mainComposite.setLayout(layout);
        mainComposite.setLayoutData(gridData);

        createCliFileComponent(mainComposite);
        createDebuggerComponent(mainComposite);
        createNodeInstallComponent(mainComposite);
    }

    private void createCliFileComponent(Composite parent) {
        Group group = new Group(parent, SWT.NONE);
        String cliFileLabel = getCliFileLabel();
        group.setText(cliFileLabel);
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        group.setLayout(layout);
        group.setLayoutData(gridData);

        cliFileField = new Text(group, SWT.BORDER);
        gridData = new GridData(GridData.FILL_HORIZONTAL);
        gridData.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
        cliFileField.setLayoutData(gridData);
        cliFileField.addModifyListener(fListener);
        addControlAccessibleListener(cliFileField, group.getText());

        Composite buttonComposite = new Composite(group, SWT.NONE);
        layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        layout.numColumns = 3;
        gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
        buttonComposite.setLayout(layout);
        buttonComposite.setLayoutData(gridData);
        buttonComposite.setFont(parent.getFont());

        workspaceLocationButton = createPushButton(buttonComposite, TernNodejsUIMessages.Button_browse_workspace,
                null);
        workspaceLocationButton.addSelectionListener(fListener);
        addControlAccessibleListener(workspaceLocationButton,
                group.getText() + " " + workspaceLocationButton.getText()); //$NON-NLS-1$

        // fileLocationButton= createPushButton(buttonComposite,
        // TernNodejsUIMessages.ExternalToolsMainTab_Brows_e_File_System____4,
        // null);
        // fileLocationButton.addSelectionListener(fListener);
        // addControlAccessibleListener(fileLocationButton, group.getText() + "
        // " + fileLocationButton.getText()); //$NON-NLS-1$

        variablesLocationButton = createPushButton(buttonComposite, TernNodejsUIMessages.Button_variables, null);
        variablesLocationButton.addSelectionListener(fListener);
        addControlAccessibleListener(variablesLocationButton,
                group.getText() + " " + variablesLocationButton.getText()); //$NON-NLS-1$

    }

    private void createDebuggerComponent(Composite parent) {
        Group group = new Group(parent, SWT.NONE);
        String debuggerLabel = TernNodejsUIMessages.TernNodejsPreferencesPage_debugger_label;
        group.setText(debuggerLabel);
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        group.setLayout(layout);
        group.setLayoutData(gridData);

        debuggers = DebuggerFieldEditor.createDebuggers();
        debuggerField = new Combo(group, SWT.READ_ONLY);
        debuggerField.setFont(group.getFont());
        for (int i = 0; i < debuggers.length; i++) {
            debuggerField.add(debuggers[i][0], i);
        }
        debuggerField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        debuggerField.addSelectionListener(fListener);
        addControlAccessibleListener(debuggerField, group.getText());

        Link debuggerWikiLink = DebuggerFieldEditor.newWikiLink(group, SWT.NONE);
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        debuggerWikiLink.setLayoutData(gd);
    }

    private void createNodeInstallComponent(Composite parent) {
        Group group = new Group(parent, SWT.NONE);
        String nodeInstallLabel = TernNodejsUIMessages.TernNodejsPreferencesPage_nodeJSInstall;
        group.setText(nodeInstallLabel);
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        group.setLayout(layout);

        nodeInstalls = NodeJSConfigEditor.createNodeInstalls();
        nodeInstallField = new Combo(group, SWT.READ_ONLY);
        nodeInstallField.setFont(group.getFont());
        for (int i = 0; i < nodeInstalls.length; i++) {
            nodeInstallField.add(nodeInstalls[i][0], i);
        }
        nodeInstallField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        nodeInstallField.addSelectionListener(fListener);
        nodeInstallField.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                int nodeInstallSelectionIndex = nodeInstallField.getSelectionIndex();
                String nodeInstallId = nodeInstalls[nodeInstallSelectionIndex][1];
                INodejsInstall install = TernNodejsCorePlugin.getNodejsInstallManager()
                        .findNodejsInstall(nodeInstallId);
                if (install == null || install.isNative()) {
                    nodePathField.setEnabled(true);
                    String defaultPath = IDENodejsProcessHelper.getNodejsPath();
                    nodePathField.setText(defaultPath);
                    nodePathInfo.setText(defaultPath);

                } else {
                    nodePathField.setEnabled(false);
                    nodePathInfo.setText(install.getPath().getAbsolutePath());
                }
            }
        });
        addControlAccessibleListener(nodeInstallField, group.getText());

        Composite pathComponent = new Composite(group, SWT.NONE);
        pathComponent.setLayout(new GridLayout(2, false));
        pathComponent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        nodePathField = new Combo(pathComponent, SWT.NONE);
        nodePathField.setFont(pathComponent.getFont());
        nodePathField.setItems(IDENodejsProcessHelper.getDefaultNodejsPaths());
        nodePathField.addSelectionListener(fListener);
        nodePathField.addModifyListener(fListener);
        nodePathField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        addControlAccessibleListener(nodePathField, group.getText());

        nodePathButton = createPushButton(pathComponent, TernNodejsUIMessages.Button_browse, null);
        nodePathButton.addSelectionListener(fListener);
        addControlAccessibleListener(nodePathButton, group.getText() + " " + nodePathButton.getText()); //$NON-NLS-1$

        group.setLayoutData(gridData);

        createNodePathInfo(group);
    }

    private void createNodePathInfo(Composite parent) {
        // Node path label
        nodePathTitle = new Label(parent, SWT.NONE);
        nodePathTitle.setText(TernNodejsUIMessages.TernNodejsPreferencesPage_nodeJSPath);
        GridData gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
        nodePathTitle.setLayoutData(gridData);

        nodePathInfo = new Text(parent, SWT.WRAP | SWT.READ_ONLY);
        nodePathInfo.setText(""); //$NON-NLS-1$
        gridData = new GridData(GridData.FILL_BOTH);
        gridData.horizontalSpan = 2;
        gridData.widthHint = 200;
        nodePathInfo.setLayoutData(gridData);
    }

    @Override
    public void initializeFrom(ILaunchConfiguration configuration) {
        fInitializing = true;
        updateCliFile(configuration);
        updateDebugger(configuration);
        updateNodeInstallPath(configuration);
        fInitializing = false;
        setDirty(false);
    }

    private void updateCliFile(ILaunchConfiguration configuration) {
        String cliFile = "";
        try {
            cliFile = configuration.getAttribute(getCliFileLaunchAttrId(), "");
        } catch (CoreException ce) {
            TernNodejsUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TernNodejsUIPlugin.PLUGIN_ID,
                    TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_Error_reading_configuration,
                    ce));
        }
        cliFileField.setText(cliFile);
    }

    private void updateDebugger(ILaunchConfiguration configuration) {
        try {
            String debuggerId = configuration.getAttribute(getDebuggerLaunchAttrId(), "");
            for (int i = 0; i < debuggers.length; i++) {
                if (debuggers[i][1].equals(debuggerId)) {
                    debuggerField.setText(debuggers[i][0]);
                    break;
                }
            }
        } catch (CoreException ce) {
            TernNodejsUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TernNodejsUIPlugin.PLUGIN_ID,
                    TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_Error_reading_configuration,
                    ce));
        }
    }

    private void updateNodeInstallPath(ILaunchConfiguration configuration) {
        try {
            String nodeInstall = configuration.getAttribute(getNodeInstallLaunchAttrId(), "");
            for (int i = 0; i < nodeInstalls.length; i++) {
                if (nodeInstalls[i][1].equals(nodeInstall)) {
                    nodeInstallField.setText(nodeInstalls[i][0]);
                    break;
                }
            }
            String nodePath = configuration.getAttribute(getNodePathLaunchAttrId(), "");
            nodePathField.setText(nodePath);
            INodejsInstallManager installManager = TernNodejsCorePlugin.getNodejsInstallManager();
            INodejsInstall nodejsInstall = installManager.findNodejsInstall(nodeInstall);
            nodePathField.setEnabled(nodejsInstall != null && nodejsInstall.isNative());
        } catch (CoreException ce) {
            TernNodejsUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TernNodejsUIPlugin.PLUGIN_ID,
                    TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_Error_reading_configuration,
                    ce));
        }
    }

    @Override
    public void performApply(ILaunchConfigurationWorkingCopy configuration) {
        // cli file
        String cliFile = cliFileField.getText().trim();
        if (cliFile.length() == 0) {
            configuration.setAttribute(getCliFileLaunchAttrId(), (String) null);
        } else {
            configuration.setAttribute(getCliFileLaunchAttrId(), cliFile);
        }
        // debugger
        int debuggerSelectionIndex = debuggerField.getSelectionIndex();
        if (debuggerSelectionIndex >= 0) {
            configuration.setAttribute(getDebuggerLaunchAttrId(), debuggers[debuggerSelectionIndex][1]);
        }
        // node install
        int nodeInstallSelectionIndex = nodeInstallField.getSelectionIndex();
        if (nodeInstallSelectionIndex >= 0) {
            configuration.setAttribute(getNodeInstallLaunchAttrId(), nodeInstalls[nodeInstallSelectionIndex][1]);
        }
        // node path
        String nodePath = nodePathField.getText();
        if (nodePath.length() == 0) {
            configuration.setAttribute(getNodePathLaunchAttrId(), (String) null);
        } else {
            configuration.setAttribute(getNodePathLaunchAttrId(), nodePath);
        }
    }

    @Override
    public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
        // cli file
        IFile cliFile = getDefaultCliFile();
        if (cliFile == null) {
            configuration.setAttribute(getCliFileLaunchAttrId(), (String) null);
        } else {
            configuration.setAttribute(getCliFileLaunchAttrId(), NodejsCliFileHelper.getWorkspaceLoc(cliFile));
        }
        // debugger
        String debugger = getDefaultDebugger();
        if (StringUtils.isEmpty(debugger)) {
            configuration.setAttribute(getDebuggerLaunchAttrId(), (String) null);
        } else {
            configuration.setAttribute(getDebuggerLaunchAttrId(), debugger);
        }
        // node install
        String nodeInstall = getDefaultNodeInstall();
        if (StringUtils.isEmpty(nodeInstall)) {
            configuration.setAttribute(getNodeInstallLaunchAttrId(), (String) null);
        } else {
            configuration.setAttribute(getNodeInstallLaunchAttrId(), nodeInstall);
        }
        // node path
        String nodePath = getDefaultNodePath();
        if (StringUtils.isEmpty(nodePath)) {
            configuration.setAttribute(getNodePathLaunchAttrId(), (String) null);
        } else {
            configuration.setAttribute(getNodePathLaunchAttrId(), nodePath);
        }

    }

    /**
     * Prompts the user for a workspace location within the workspace and sets
     * the location as a String containing the workspace_loc variable or
     * <code>null</code> if no location was obtained from the user.
     */
    protected void handleWorkspaceLocationButtonSelected() {
        ResourceSelectionDialog dialog;
        dialog = new ResourceSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(),
                TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_Select_a_client_file);
        dialog.open();
        Object[] results = dialog.getResult();
        if (results == null || results.length < 1) {
            return;
        }
        IResource resource = (IResource) results[0];
        cliFileField.setText(NodejsCliFileHelper.getWorkspaceLoc(resource));
    }

    protected void handleNodePathButtonSelected() {
        FileDialog fileDialog = new FileDialog(getShell(), SWT.NONE);
        fileDialog.setFileName(nodePathField.getText());
        String text = fileDialog.open();
        if (text != null) {
            nodePathField.setText(text);
        }
    }

    /*
     * Fix for Bug 60163 Accessibility: New Builder Dialog missing object info
     * for textInput controls
     */
    public void addControlAccessibleListener(Control control, String controlName) {
        // strip mnemonic (&)
        String[] strs = controlName.split("&"); //$NON-NLS-1$
        StringBuffer stripped = new StringBuffer();
        for (int i = 0; i < strs.length; i++) {
            stripped.append(strs[i]);
        }
        control.getAccessible().addAccessibleListener(new ControlAccessibleListener(stripped.toString()));
    }

    private class ControlAccessibleListener extends AccessibleAdapter {
        private String controlName;

        ControlAccessibleListener(String name) {
            controlName = name;
        }

        @Override
        public void getName(AccessibleEvent e) {
            e.result = controlName;
        }

    }

    private String getCliFileLaunchAttrId() {
        return INodejsCliFileLaunchConfigurationConstants.ATTR_CLI_FILE;
    }

    private String getDebuggerLaunchAttrId() {
        return INodejsCliFileLaunchConfigurationConstants.ATTR_DEBUGGER;
    }

    private String getNodeInstallLaunchAttrId() {
        return INodejsCliFileLaunchConfigurationConstants.ATTR_NODE_INSTALL;
    }

    private String getNodePathLaunchAttrId() {
        return INodejsCliFileLaunchConfigurationConstants.ATTR_NODE_PATH;
    }

    @Override
    public boolean isValid(ILaunchConfiguration launchConfig) {
        setErrorMessage(null);
        setMessage(null);
        return (validateCliFile() && validateDebugger() && validateNodeInstallPath());
    }

    private boolean validateCliFile() {
        String cliFile = this.cliFileField.getText().trim();
        if (StringUtils.isEmpty(cliFile)) {
            return true;
        }
        String expandedLocation = null;
        try {
            expandedLocation = resolveValue(cliFile);
            if (expandedLocation == null)
                return true;
        } catch (CoreException e) {
            setErrorMessage(e.getStatus().getMessage());
            return false;
        }

        File file = new File(expandedLocation);
        if (!(file.exists())) {
            setErrorMessage(
                    TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_client_file_does_not_exist);
            return false;
        }
        if (!(file.isFile())) {
            setErrorMessage(TernNodejsUIMessages.ExternalToolsMainTab_client_file_specified_is_not_a_file);
            return false;
        }
        return true;
    }

    private String resolveValue(String expression) throws CoreException {
        String expanded = null;
        try {
            expanded = getValue(expression);
        } catch (CoreException localCoreException) {
            validateVariables(expression);
            throw localCoreException;
        }
        return expanded;
    }

    private String getValue(String expression) throws CoreException {
        IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
        return manager.performStringSubstitution(expression);
    }

    private void validateVariables(String expression) throws CoreException {
        IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
        manager.validateStringVariables(expression);
    }

    private boolean validateDebugger() {
        int debuggerSelectionIndex = debuggerField.getSelectionIndex();
        if (debuggerSelectionIndex <= 0) {
            setErrorMessage(TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_debugger_required);
            return false;
        }
        String debuggerId = debuggers[debuggerSelectionIndex][1];
        if (StringUtils.isEmpty(debuggerId)) {
            setErrorMessage(
                    TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_debugger_not_installed);
            return false;
        }
        return true;
    }

    private boolean validateNodeInstallPath() {
        int nodeInstallSelectionIndex = nodeInstallField.getSelectionIndex();
        if (nodeInstallSelectionIndex <= 0) {
            setErrorMessage(TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_nodeInstall_required);
            return false;
        }
        INodejsInstallManager installManager = TernNodejsCorePlugin.getNodejsInstallManager();
        String nodeInstallId = nodeInstalls[nodeInstallSelectionIndex][1];
        INodejsInstall nodejsInstall = installManager.findNodejsInstall(nodeInstallId);
        if (nodejsInstall == null) {
            setErrorMessage(
                    NLS.bind(TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_nodeInstall_not_found,
                            nodeInstallId));
            return false;
        }
        if (nodejsInstall.isNative()) {
            // validate node path
            String nodePath = nodePathField.getText();
            if (StringUtils.isEmpty(nodePath)) {
                setErrorMessage(TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_nodePath_required);
                return false;
            }
            if (!new File(nodePath).exists() && !nodePath.equals("node")) {
                setErrorMessage(NLS.bind(
                        TernNodejsUIMessages.AbstractNodejsCliFileLaunchConfigurationTab_nodePath_not_found,
                        nodePath));
                return false;
            }
        }
        return true;
    }

    protected abstract String getCliFileLabel();

    protected abstract IFile getDefaultCliFile();

    protected abstract String getDefaultDebugger();

    protected abstract String getDefaultNodeInstall();

    protected abstract String getDefaultNodePath();

}