org.eclipse.jubula.client.ui.rcp.widgets.autconfig.AutConfigComponent.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jubula.client.ui.rcp.widgets.autconfig.AutConfigComponent.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2010 BREDEX GmbH.
 * 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:
 *     BREDEX GmbH - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.jubula.client.ui.rcp.widgets.autconfig;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jubula.client.core.communication.ConnectionException;
import org.eclipse.jubula.client.core.communication.AutAgentConnection;
import org.eclipse.jubula.client.core.events.DataEventDispatcher;
import org.eclipse.jubula.client.ui.constants.Constants;
import org.eclipse.jubula.client.ui.rcp.Plugin;
import org.eclipse.jubula.client.ui.rcp.businessprocess.ConnectAutAgentBP;
import org.eclipse.jubula.client.ui.rcp.dialogs.RemoteFileBrowserDialog;
import org.eclipse.jubula.client.ui.rcp.i18n.Messages;
import org.eclipse.jubula.client.ui.rcp.provider.ControlDecorator;
import org.eclipse.jubula.client.ui.rcp.utils.DialogStatusParameter;
import org.eclipse.jubula.client.ui.rcp.utils.RemoteFileStore;
import org.eclipse.jubula.client.ui.rcp.utils.AutAgentManager;
import org.eclipse.jubula.client.ui.rcp.utils.AutAgentManager.AutAgent;
import org.eclipse.jubula.client.ui.rcp.utils.Utils;
import org.eclipse.jubula.client.ui.utils.DialogUtils;
import org.eclipse.jubula.client.ui.utils.ErrorHandlingUtil;
import org.eclipse.jubula.client.ui.utils.LayoutUtil;
import org.eclipse.jubula.client.ui.widgets.DirectCombo;
import org.eclipse.jubula.client.ui.widgets.UIComponentHelper;
import org.eclipse.jubula.tools.constants.AutConfigConstants;
import org.eclipse.jubula.tools.constants.ConfigurationConstants;
import org.eclipse.jubula.tools.constants.StringConstants;
import org.eclipse.jubula.tools.exception.Assert;
import org.eclipse.jubula.tools.i18n.I18n;
import org.eclipse.jubula.tools.messagehandling.MessageIDs;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
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.DirectoryDialog;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;

/**
 * @author BREDEX GmbH
 * @created Sep 12, 2007
 * 
 */
public abstract class AutConfigComponent extends ScrolledComposite {

    /** layout for buttons */
    public static final GridData BUTTON_LAYOUT;
    /** number of columns for layout purposes */
    public static final int NUM_COLUMNS = 3;

    static {
        BUTTON_LAYOUT = new GridData();
        BUTTON_LAYOUT.horizontalAlignment = GridData.FILL;
        BUTTON_LAYOUT.grabExcessHorizontalSpace = true;
    }

    /**
     * This private inner class contains a new ModifyListener.
     * 
     * @author BREDEX GmbH
     * @created 22.11.2006
     */
    private class WidgetModifyListener implements ModifyListener {

        /**
         * {@inheritDoc}
         */
        @SuppressWarnings("synthetic-access")
        public void modifyText(ModifyEvent e) {
            Object source = e.getSource();
            boolean checked = false;
            if (source.equals(m_autConfigNameTextField)) {
                checked = true;
            } else if (source.equals(m_autIdTextField)) {
                checked = true;
            } else if (source.equals(m_autWorkingDirectoryTextField)) {
                checked = true;
            }
            if (checked) {
                checkAll();
                return;
            }
            Assert.notReached(Messages.EventActivatedByUnknownWidget + StringConstants.DOT);
        }
    }

    /**
     * This private inner class contains a new SelectionListener.
     * 
     * @author BREDEX GmbH
     * @created 13.07.2005
     */
    private class WidgetSelectionListener implements SelectionListener {

        /**
         * {@inheritDoc}
         */
        @SuppressWarnings("synthetic-access")
        public void widgetSelected(SelectionEvent e) {
            Object source = e.getSource();
            if (source.equals(m_addServerButton)) {
                handleAddServerButtonEvent();
                return;
            } else if (source.equals(m_basicModeButton) || source.equals(m_advancedModeButton)
                    || source.equals(m_expertModeButton)) {

                selectModeButton((Button) source);
                return;
            } else if (source.equals(m_autWorkingDirectoryButton)) {
                if (isRemoteRequest()) {
                    remoteBrowse(true, AutConfigConstants.WORKING_DIR, m_autWorkingDirectoryTextField,
                            Messages.AUTConfigComponentSelectWorkDir);
                } else {
                    DirectoryDialog directoryDialog = new DirectoryDialog(Plugin.getShell(),
                            SWT.APPLICATION_MODAL | SWT.ON_TOP);
                    handleWorkDirButtonEvent(directoryDialog);

                }
                return;
            }
            Assert.notReached(Messages.EventActivatedByUnknownWidget + StringConstants.LEFT_PARENTHESES + source
                    + StringConstants.RIGHT_PARENTHESES + StringConstants.DOT);
        }

        /**
         * {@inheritDoc}
         */
        public void widgetDefaultSelected(SelectionEvent e) {
            // nothing
        }
    }

    /**
     * Possible modes for the dialog
     *
     * @author BREDEX GmbH
     * @created Sep 10, 2007
     */
    public static enum Mode {
        /** basic mode */
        BASIC,
        /** advanced mode */
        ADVANCED,
        /** expert mode */
        EXPERT
    }

    /** the current mode */
    private Mode m_mode;
    /** mapping from mode buttons to modes */
    private Map<Button, Mode> m_buttonToModeMap = new HashMap<Button, Mode>();

    /** name of the AUT that will be using this configuration */
    private String m_autName;
    /** if the name of the aut config has been modified from its default */
    private boolean m_nameModified;
    /** The IAUTConfigPO this component displays/edits */
    private Map<String, String> m_autConfig;

    /** list of the stored servers */
    private AutAgentManager m_listOfServers = AutAgentManager.getInstance();
    /** parameter list for callback method of the <code>IDialogStatusListener</code> */
    private java.util.List<DialogStatusParameter> m_paramList = new ArrayList<DialogStatusParameter>();

    /** the the WidgetSelectionListener */
    private WidgetSelectionListener m_selectionListener;
    /** the WidgetModifyListener */
    private WidgetModifyListener m_modifyListener;

    /** Composite representing the basic area */
    private Composite m_basicAreaComposite;
    /** Composite representing the advanced area */
    private Composite m_advancedAreaComposite;
    /** Composite representing the expert area */
    private Composite m_expertAreaComposite;
    /** Composite representing the monitoring area */
    private Composite m_monitoringAreaComposite;
    /** Composite holding the entire contents of this config component */
    private Composite m_contentComposite;
    /** gui component */
    private Text m_autConfigNameTextField;
    /** gui component */
    private Combo m_serverCombo;
    /** gui component */
    private Button m_addServerButton;
    /** gui component */
    private Text m_autWorkingDirectoryTextField;
    /** gui component */
    private Button m_autWorkingDirectoryButton;
    /** gui component */
    private Text m_autIdTextField;
    /** validator for the AUT ID text field */
    private IValidator m_autIdValidator;

    /** The basic mode button. */
    private Button m_basicModeButton;
    /** The advanced button. */
    private Button m_advancedModeButton;
    /** The expert mode button. */
    private Button m_expertModeButton;
    /** Whether the AUT config component supports multiple modes */
    private boolean m_isMultiMode;
    /** Whether this object has finished initializing */
    private boolean m_isinitialized;

    /**
     * @param parent {@inheritDoc}
     * @param style {@inheritDoc}
     * @param autConfig data to be displayed/edited
     * @param autName the name of the AUT that will be using this configuration.
     * @param isMultiMode whether this component supports multiple modes.
     */
    public AutConfigComponent(Composite parent, int style, Map<String, String> autConfig, String autName,
            boolean isMultiMode) {

        super(parent, style);
        m_isinitialized = false;
        m_autConfig = autConfig;
        m_autName = autName;
        m_nameModified = !isDataNew(autConfig) && autConfig.get(AutConfigConstants.CONFIG_NAME)
                .equals(NLS.bind(Messages.AUTConfigComponentDefaultAUTConfigName,
                        new String[] { autName, autConfig.get(AutConfigConstants.SERVER) }));
        m_isMultiMode = isMultiMode;
        if (m_isMultiMode) {
            IPreferenceStore prefStore = PlatformUI.getPreferenceStore();
            String prefMode = prefStore.getString(Constants.AUT_CONFIG_DIALOG_MODE);
            if (prefMode != null && prefMode.length() != 0) {
                m_mode = Mode.valueOf(prefMode);
            } else {
                m_mode = Mode.BASIC;
            }
        }
        createGUI();
        populateGUI(autConfig);
        init();

        if (m_isMultiMode) {
            setCurrentMode(m_mode);
        } else {
            setCompositeVisible(m_basicAreaComposite, true);
        }
        getDisplay().asyncExec(new Runnable() {
            public void run() {
                // Since we're resizing after everything is initialized,
                // it's possible that the dialog is already disposed here.
                if (!isDisposed()) {
                    resize();
                    getShell().pack(true);
                }
            }
        });
        m_isinitialized = true;
    }

    /**
     * transmits that a Java toolkit is to be used
     * @return true if Java toolkit is used
     */
    protected boolean isJavaAut() {
        return false;
    }

    /**
     * @return the text field for the AUT working directory
     */
    protected Text getAutWorkingDirField() {
        return m_autWorkingDirectoryTextField;
    }

    /**
     * @return the monitoringAreaComposite
     */
    public Composite getMonitoringAreaComposite() {
        return m_monitoringAreaComposite;
    }

    /**
     * Populates all areas with data from the given map.
     * 
     * @param data The data to use for population.
     */
    private void populateGUI(Map<String, String> data) {
        populateBasicArea(data);
        populateAdvancedArea(data);
        populateExpertArea(data);
        populateMonitoringArea(data);
    }

    /**
     * {@inheritDoc}
     */
    public void setVisible(boolean visible) {
        if (StringConstants.EMPTY.equals(m_autConfigNameTextField.getText())) {
            m_autConfigNameTextField.setFocus();
            m_autConfigNameTextField.setText(NLS.bind(Messages.AUTConfigComponentDefaultAUTConfigName,
                    new String[] { m_autName, m_serverCombo.getText() }));
            m_autConfigNameTextField.setSelection(0, m_autConfigNameTextField.getText().length());
        }
    }

    /**
     * @return the AUT-Config-Map
     */
    private Map<String, String> getAutConfig() {
        return m_autConfig;
    }

    /** initialize the GUI components */
    private void createGUI() {
        m_contentComposite = new Composite(this, SWT.NONE);
        initGuiLayout(m_contentComposite);
        if (m_isMultiMode) {
            createModeButtons(m_contentComposite);
        }
        m_basicAreaComposite = new Composite(m_contentComposite, SWT.NONE);
        m_advancedAreaComposite = new Composite(m_contentComposite, SWT.NONE);
        m_expertAreaComposite = new Composite(m_contentComposite, SWT.NONE);
        m_monitoringAreaComposite = new Composite(m_contentComposite, SWT.NONE);

        createLayout(m_basicAreaComposite);
        createLayout(m_advancedAreaComposite);
        createLayout(m_expertAreaComposite);
        createLayout(m_monitoringAreaComposite);

        createBasicArea(m_basicAreaComposite);
        createAdvancedArea(m_advancedAreaComposite);
        createExpertArea(m_expertAreaComposite);
        createMonitoringArea(m_monitoringAreaComposite);

        setContent(m_contentComposite);

    }

    /**
     * @param areaComposite The composite for which to create and set a layout.
     */
    private void createLayout(Composite areaComposite) {
        areaComposite.setLayout(createDefaultGridLayout(NUM_COLUMNS));
        GridData gridData = new GridData(GridData.BEGINNING);
        gridData.horizontalSpan = NUM_COLUMNS;
        areaComposite.setLayoutData(gridData);
    }

    /**
     * creates the default GridLayout to be used 
     * @param numColumns the number of the columns
     * @return a new instance of GridLayout
     */
    public static GridLayout createDefaultGridLayout(int numColumns) {
        GridLayout result = new GridLayout();
        result.numColumns = numColumns;
        result.horizontalSpacing = 5;
        result.verticalSpacing = 5;
        result.marginWidth = 0;
        result.marginHeight = 0;
        return result;
    }

    /**
     * Populates GUI for the advanced configuration section.
     * 
     * @param data Map representing the data to use for population.
     */
    protected abstract void populateExpertArea(Map<String, String> data);

    /**
     * Populates GUI for the advanced configuration section. Subclasses may
     * override this empty implementation.
     * 
     * @param data
     *            Map representing the data to use for population.
     */
    protected void populateMonitoringArea(Map<String, String> data) {
        // by default do nothing 
    }

    /**
     * Populates GUI for the advanced configuration section.
     * 
     * @param data Map representing the data to use for population.
     */
    protected abstract void populateAdvancedArea(Map<String, String> data);

    /**
     * Populates GUI for the basic configuration section.
     * 
     * @param data Map representing the data to use for population.
     */
    protected void populateBasicArea(Map<String, String> data) {
        fillServerCombo();
        if (!isDataNew(data)) {
            m_serverCombo
                    .select(m_serverCombo.indexOf(StringUtils.defaultString(data.get(AutConfigConstants.SERVER))));
            m_autConfigNameTextField.setText(StringUtils.defaultString(data.get(AutConfigConstants.CONFIG_NAME),
                    NLS.bind(Messages.AUTConfigComponentDefaultAUTConfigName,
                            new String[] { m_autName, m_serverCombo.getText() })));
            m_autIdTextField.setText(StringUtils.defaultString(data.get(AutConfigConstants.AUT_ID)));
            m_autWorkingDirectoryTextField
                    .setText(StringUtils.defaultString(data.get(AutConfigConstants.WORKING_DIR)));
        } else {
            // set some default values
            m_serverCombo.select(m_serverCombo.indexOf(StringUtils.defaultString(Constants.LOCALHOST1)));

            m_autConfigNameTextField.setText(NLS.bind(Messages.AUTConfigComponentDefaultAUTConfigName,
                    new String[] { m_autName, m_serverCombo.getText() }));
        }
    }

    /**
     * @param data The map to check.
     * @return <code>true</code> if the given map is newly created and defaults
     *         should be used. Otherwise, <code>false</code>.
     */
    protected boolean isDataNew(Map<String, String> data) {
        return data == null || data.isEmpty();
    }

    /**
     * @param basicAreaComposite The composite that represents the basic area.
     */
    protected void createBasicArea(Composite basicAreaComposite) {
        initGUIConfigAndServer(basicAreaComposite);
    }

    /**
     * Create this dialog's advanced area component.
     * 
     * @param advancedAreaComposite Composite representing the advanced area.
     */
    protected void createAdvancedArea(Composite advancedAreaComposite) {
        setCompositeVisible(advancedAreaComposite, false);
    }

    /**
     * Create this dialog's expert area component.
     * 
     * @param expertAreaComposite Composite representing the expert area.
     */
    protected void createExpertArea(Composite expertAreaComposite) {
        setCompositeVisible(expertAreaComposite, false);

    }

    /**
     * Create this dialog's monitoring area component  
     * @param monitoringComposite Compostie representing the ccArea
     * 
     */
    protected void createMonitoringArea(Composite monitoringComposite) {
        setCompositeVisible(monitoringComposite, true);
    }

    /**
     * Inits the AUT-Configuration and AutAgent area.
     * 
     * @param parent The parent Composite.
     */
    private void initGUIConfigAndServer(Composite parent) {
        // name property
        UIComponentHelper.createLabel(parent, "AUTConfigComponent.configName"); //$NON-NLS-1$ 
        m_autConfigNameTextField = UIComponentHelper.createTextField(parent, 2);

        // server chooser
        initGuiServerChooser(parent);

        // AUT ID field
        ControlDecorator.decorateInfo(UIComponentHelper.createLabel(parent, "AUTConfigComponent.autId"), //$NON-NLS-1$, 
                "AUTConfigComponent.autId.helpText", false); //$NON-NLS-1$

        m_autIdTextField = UIComponentHelper.createTextField(parent, 2);

        UIComponentHelper.createSeparator(parent, NUM_COLUMNS);

        // AUT directory editor
        if (!isJavaAut()) {
            createAutDirectoryEditor(parent);
        }
    }

    /**
     * Inits the AUT working dir area.
     * 
     * @param parent The parent Composite.
     */
    protected void createAutDirectoryEditor(Composite parent) {

        UIComponentHelper.createLabel(parent, "AUTConfigComponent.workDir"); //$NON-NLS-1$ 
        m_autWorkingDirectoryTextField = UIComponentHelper.createTextField(parent, 1);

        m_autWorkingDirectoryButton = new Button(UIComponentHelper.createLayoutComposite(parent), SWT.PUSH);
        m_autWorkingDirectoryButton.setText(Messages.AUTConfigComponentBrowse);
        m_autWorkingDirectoryButton.setLayoutData(BUTTON_LAYOUT);
    }

    /**
     * 
     * @param parent The parent Composite.
     */
    private void initGuiServerChooser(Composite parent) {
        UIComponentHelper.createLabel(parent, "AUTConfigComponent.server"); //$NON-NLS-1$ 
        m_serverCombo = new Combo(parent, SWT.READ_ONLY);
        GridData comboGrid = new GridData(GridData.FILL, GridData.CENTER, true, false, 1, 1);
        LayoutUtil.addToolTipAndMaxWidth(comboGrid, m_serverCombo);
        m_serverCombo.setLayoutData(comboGrid);
        m_addServerButton = new Button(UIComponentHelper.createLayoutComposite(parent), SWT.PUSH);
        m_addServerButton.setText(Messages.AUTConfigComponentAddServer);
        m_addServerButton.setLayoutData(BUTTON_LAYOUT);
    }

    /**
     * Sets the current mode for the dialog (ex. basic, advanced, expert).
     * 
     * @param mode Button representing the mode to activate.
     */
    private void setCurrentMode(Mode mode) {
        m_basicModeButton.setSelection(false);
        m_advancedModeButton.setSelection(false);
        m_expertModeButton.setSelection(false);
        for (Button key : m_buttonToModeMap.keySet()) {
            if (m_buttonToModeMap.get(key) == mode) {
                key.setSelection(true);
                break;
            }
        }
        IPreferenceStore prefStore = PlatformUI.getPreferenceStore();
        if (mode == Mode.BASIC) {
            prefStore.setValue(Constants.AUT_CONFIG_DIALOG_MODE, Mode.BASIC.name());
            setCompositeVisible(m_advancedAreaComposite, false);
            setCompositeVisible(m_expertAreaComposite, false);
            setCompositeVisible(m_monitoringAreaComposite, false);
        } else if (mode == Mode.ADVANCED) {
            prefStore.setValue(Constants.AUT_CONFIG_DIALOG_MODE, Mode.ADVANCED.name());
            setCompositeVisible(m_advancedAreaComposite, true);
            setCompositeVisible(m_expertAreaComposite, false);
            setCompositeVisible(m_monitoringAreaComposite, false);
        } else if (mode == Mode.EXPERT) {
            prefStore.setValue(Constants.AUT_CONFIG_DIALOG_MODE, Mode.EXPERT.name());
            setCompositeVisible(m_advancedAreaComposite, true);
            setCompositeVisible(m_expertAreaComposite, true);
            setCompositeVisible(m_monitoringAreaComposite, true);
        }
        resize();
        getShell().pack(true);
    }

    /**
     * checks if BASIC mode is selected
     * @return mode == BASIC
     */
    protected boolean isBasicMode() {
        IPreferenceStore prefStore = PlatformUI.getPreferenceStore();
        String mode = prefStore.getString(Constants.AUT_CONFIG_DIALOG_MODE);
        return mode.equals(Mode.BASIC.name());
    }

    /**
     * Resizes the content composite based on added/removed components.
     */
    protected void resize() {
        Point newSize = m_contentComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
        m_contentComposite.setSize(newSize);
        m_contentComposite.layout();
    }

    /**
     * Sets the visibility of the given composite and adjusts the parent
     * layout as necessary. Assumes that the composite is part of a grid layout.
     * 
     * @param composite The composite for which to set the visibility.
     * @param visible Whether the composite should be made visible or invisible.
     */
    private void setCompositeVisible(Composite composite, boolean visible) {
        composite.setVisible(visible);
        ((GridData) composite.getLayoutData()).exclude = !visible;
    }

    /**
     * set the layout for the component
     * @param comp the composite to set the layout for
     */
    private void initGuiLayout(Composite comp) {
        GridLayout compositeLayout = new GridLayout();
        compositeLayout.numColumns = NUM_COLUMNS;
        compositeLayout.horizontalSpacing = LayoutUtil.SMALL_HORIZONTAL_SPACING;
        compositeLayout.verticalSpacing = LayoutUtil.SMALL_VERTICAL_SPACING;
        compositeLayout.marginHeight = LayoutUtil.SMALL_MARGIN_HEIGHT;
        compositeLayout.marginWidth = LayoutUtil.SMALL_MARGIN_WIDTH;
        comp.setLayout(compositeLayout);
        GridData compositeData = new GridData(SWT.FILL, SWT.FILL, true, true);
        compositeData.grabExcessHorizontalSpace = false;
        compositeData.grabExcessVerticalSpace = true;
        comp.setLayoutData(compositeData);
    }

    /**
     * Fills the server combo box.
     */
    private void fillServerCombo() {
        boolean checkListeners = m_selectionListener != null;
        if (checkListeners) {
            deinstallListeners();
        }

        m_serverCombo.removeAll();
        String currentlySelectedServer = getConfigValue(AutConfigConstants.SERVER);
        if (currentlySelectedServer != null && currentlySelectedServer.trim().length() != 0
                && !m_listOfServers.getAutAgentNames().contains(currentlySelectedServer)) {

            int defaultServerPort = ConfigurationConstants.AUT_AGENT_DEFAULT_PORT;
            m_listOfServers.addServer(new AutAgentManager.AutAgent(currentlySelectedServer, defaultServerPort));

            ErrorHandlingUtil.createMessageDialog(MessageIDs.I_SERVER_NAME_ADDED, null,
                    new String[] { Messages.ServerName + StringConstants.COLON + StringConstants.SPACE
                            + currentlySelectedServer + StringConstants.NEWLINE + Messages.ServerPortDefault
                            + defaultServerPort });
        }
        for (String serverName : m_listOfServers.getAutAgentNames()) {
            m_serverCombo.add(serverName);
        }

        if (checkListeners) {
            installListeners();
        }
    }

    /**
     * Inits the buttons that control the mode (basic, advanced, expert).
     * 
     * @param parent The parent Composite.
     */
    protected void createModeButtons(Composite parent) {
        Composite modeButtons = UIComponentHelper.createLayoutComposite(parent, 3);
        GridData modeButtonsData = new GridData(GridData.BEGINNING);
        modeButtonsData.horizontalSpan = NUM_COLUMNS;
        modeButtons.setLayoutData(modeButtonsData);

        m_basicModeButton = new Button(modeButtons, SWT.TOGGLE);
        m_basicModeButton.setText(Messages.AUTConfigComponentShowBasic);
        m_basicModeButton.setSelection(true);
        m_buttonToModeMap.put(m_basicModeButton, Mode.BASIC);

        m_advancedModeButton = new Button(modeButtons, SWT.TOGGLE);
        m_advancedModeButton.setText(Messages.AUTConfigComponentShowAdvanced);
        m_buttonToModeMap.put(m_advancedModeButton, Mode.ADVANCED);

        m_expertModeButton = new Button(modeButtons, SWT.TOGGLE);
        m_expertModeButton.setText(Messages.AUTConfigComponentShowExpert);
        m_buttonToModeMap.put(m_expertModeButton, Mode.EXPERT);
    }

    /**
     * installs all listeners to the gui components. All components visualizing
     * a property do have some sort of modification listeners which store
     * edited data in the edited instance. Some gui components have additional
     * listeners for data validatuion or permission reevaluation.
     */
    protected void installListeners() {
        WidgetSelectionListener selectionListener = getSelectionListener();
        WidgetModifyListener modifyListener = getModifyListener();
        if (m_isMultiMode) {
            m_basicModeButton.addSelectionListener(selectionListener);
            m_advancedModeButton.addSelectionListener(selectionListener);
            m_expertModeButton.addSelectionListener(selectionListener);
        }
        m_addServerButton.addSelectionListener(selectionListener);
        m_autConfigNameTextField.addModifyListener(modifyListener);
        m_autIdTextField.addModifyListener(modifyListener);

        m_autWorkingDirectoryButton.addSelectionListener(selectionListener);
        m_autWorkingDirectoryTextField.addModifyListener(modifyListener);

    }

    /**
     * deinstalls all listeners to the gui components. All components visualizing
     * a property do have some sort of modification listeners which store
     * edited data in the edited instance. Some gui components have additional
     * listeners for data validatuion or permission reevaluation.
     */
    protected void deinstallListeners() {
        WidgetSelectionListener selectionListener = getSelectionListener();
        WidgetModifyListener modifyListener = getModifyListener();
        if (m_isMultiMode) {
            m_basicModeButton.removeSelectionListener(selectionListener);
            m_advancedModeButton.removeSelectionListener(selectionListener);
            m_expertModeButton.removeSelectionListener(selectionListener);
        }
        m_addServerButton.removeSelectionListener(selectionListener);
        m_autConfigNameTextField.removeModifyListener(modifyListener);
        m_autIdTextField.removeModifyListener(modifyListener);
        m_autWorkingDirectoryButton.removeSelectionListener(selectionListener);
        m_autWorkingDirectoryTextField.removeModifyListener(modifyListener);

    }

    /**
     * Maps the given value to the given key for the AUT Configuration. If
     * the given key already has a value mapped to it, this value will be 
     * overwritten.
     *  
     * Updates the enablement of all fields based on the new status of 
     * the AUT Configuration. Subclasses should extend this method to update the
     * fields that they define.
     * 
     * @param key The key for the mapping.
     * @param value The value for the mapping.
     * @return <code>true</code> if the configuration was changed as a result 
     *         of this method call (i.e. if <code>value</code> was <em>not</em>
     *         already mapped to <code>key</code>). Otherwise 
     *         <code>false</code>. Note that there is no need to update fields
     *         if the mapping has not changed.
     */
    protected boolean putConfigValue(String key, String value) {

        String previousValue = StringUtils.defaultString(getAutConfig().put(key, value));
        boolean wasEmpty = previousValue.length() == 0;
        boolean isEmpty = StringUtils.defaultString(value).length() == 0;
        boolean areBothEmpty = wasEmpty && isEmpty;

        if (isEmpty) {
            getAutConfig().remove(key);
        }

        return (!m_isinitialized && !areBothEmpty) || !value.equals(previousValue);
    }

    /**
     * 
     * @param key The key being searched for in the AUT Configuration.
     * @return The value mapped to <code>key</code> in the AUT Configuration.
     */
    protected String getConfigValue(String key) {
        final String value = getAutConfig().get(key);
        return value != null ? value : StringConstants.EMPTY;
    }

    /**
     * Overwrites the AUT Configuration with keys and values from the given
     * map.
     * 
     * @param newConfig The new configuration data.
     */
    protected void setConfig(Map<String, String> newConfig) {
        Utils.makeAutConfigCopy(newConfig, getAutConfig());
    }

    /**
     * Checks whether the currently selected server is localhost. Subclasses
     * may extend this method to enable/disable browse buttons.
     * @return <code>true</code>, if the currently selected server is localhost
     */
    protected boolean checkLocalhostServer() {
        boolean enable = isLocalhost();

        m_autWorkingDirectoryButton.setEnabled(enable || isRemoteRequest());

        return enable;
    }

    /**
     * @return if the current aut starter is localhost
     */
    private boolean isLocalhost() {
        boolean enable;
        try {
            final String serverComboText = getServerCombo().getText();
            final InetAddress localHost = InetAddress.getLocalHost();
            final String canonicalHostName = localHost.getCanonicalHostName();
            enable = (Constants.LOCALHOST1.equals(serverComboText.toLowerCase())
                    || Constants.LOCALHOST2.equals(serverComboText)
                    || localHost.getHostName().equals(serverComboText)
                    || localHost.getHostAddress().equals(serverComboText)
                    || (canonicalHostName != null && canonicalHostName.equals(serverComboText)));
        } catch (UnknownHostException e) {
            enable = false;
        }
        return enable;
    }

    /**
     * Handles the button event.
     */
    public void handleAddServerButtonEvent() {
        openServerPrefPage();
    }

    /** 
     * The action of the AUT config name field.
     * @return <code>null</code> if the new value is valid. Otherwise, returns
     *         a status parameter indicating the cause of the problem.
     */
    public DialogStatusParameter modifyAutConfigFieldAction() {
        m_nameModified = !m_autConfigNameTextField.getText()
                .equals(NLS.bind(Messages.AUTConfigComponentDefaultAUTConfigName,
                        new String[] { m_autName, m_serverCombo.getText() }));
        DialogStatusParameter error = null;

        putConfigValue(AutConfigConstants.CONFIG_NAME, m_autConfigNameTextField.getText());

        if (!isValid(m_autConfigNameTextField, false)) {
            if (m_autConfigNameTextField.getText().length() == 0) {
                error = createErrorStatus(Messages.AUTConfigComponentEmptyAUTConfigName);
            } else {
                error = createErrorStatus(Messages.AUTConfigComponentWrongAUTConfigName);
            }
        }
        return error;
    }

    /** 
     * The action of the AUT ID field.
     * @return <code>null</code> if the new value is valid. Otherwise, returns
     *         a status parameter indicating the cause of the problem.
     */
    public DialogStatusParameter modifyAutIdFieldAction() {
        DialogStatusParameter error = null;
        String newAutIdValue = m_autIdTextField.getText();

        // FIXME zeb This null check is necessary at the moment because the creator 
        //           of AutConfigComponents is in the ToolkitSupport project, which 
        //           is not aware of model (PO) objects nor of databinding classes 
        //           (IValidator). This dependency issue should be resolved, and
        //           the validator should be set in the constructor, rather than
        //           in a separate setter method.
        if (m_autIdValidator != null) {
            IStatus validationStatus = m_autIdValidator.validate(newAutIdValue);
            if (!validationStatus.isOK()) {
                if (validationStatus.getSeverity() == IStatus.ERROR) {
                    error = createErrorStatus(validationStatus.getMessage());
                } else {
                    error = createWarningStatus(validationStatus.getMessage());
                }
            }
        }
        putConfigValue(AutConfigConstants.AUT_ID, newAutIdValue);

        return error;
    }

    /**
     * Opens the server preference page
     */
    protected void openServerPrefPage() {
        PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(),
                Constants.JB_PREF_PAGE_AUTAGENT, null, null);
        DialogUtils.setWidgetNameForModalDialog(dialog);
        dialog.open();
        m_listOfServers = AutAgentManager.getInstance();
        String oldServer = m_serverCombo.getText();
        fillServerCombo();
        m_serverCombo.setText(oldServer);
    }

    /**
     * 
     * @return The server selection combo box.
     */
    protected Combo getServerCombo() {
        return m_serverCombo;
    }

    /**
     * 
     * @return The server list.
     */
    protected AutAgentManager getServerList() {
        return m_listOfServers;
    }

    /**
     * @param modifiedWidget The modified widget.
     * @param emptyAllowed true, if an empty string is allowed as input.
     * @return True, if the input of the widget is correct.False, otherwise.
     */
    protected boolean isValid(Widget modifiedWidget, boolean emptyAllowed) {
        if (modifiedWidget instanceof DirectCombo) {
            DirectCombo combo = (DirectCombo) modifiedWidget;
            int textLength = combo.getText().length();
            String text = combo.getText();
            return checkTextInput(emptyAllowed, textLength, text);
        }
        if (modifiedWidget instanceof Text) {
            Text textField = (Text) modifiedWidget;
            int textLength = textField.getText().length();
            String text = textField.getText();
            return checkTextInput(emptyAllowed, textLength, text);
        }
        return true;
    }

    /**
     * @return true if the aut config is for the currently connected AUT starter
     */
    protected boolean isRemoteRequest() {
        boolean enable;
        try {
            final AutAgent currentServer = ConnectAutAgentBP.getInstance().getCurrentAutAgent();
            if (currentServer == null) {
                return false;
            }
            if (isLocalhost()) {
                return false;
            }

            final String serverName = getServerCombo().getText().toLowerCase();
            final InetAddress serverAddress = InetAddress.getByName(serverName);
            final String canonicalServerName = serverAddress.getCanonicalHostName().toLowerCase();

            final String currentServerName = currentServer.getName().toLowerCase();
            final InetAddress currentServerAddress = InetAddress.getByName(currentServerName);
            final String canonicalCurrentServerName = currentServerAddress.getCanonicalHostName().toLowerCase();

            enable = currentServerName.equals(serverName) || currentServerAddress.equals(serverAddress)
                    || canonicalCurrentServerName.equals(canonicalServerName);
        } catch (UnknownHostException e) {
            enable = false;
        }

        return enable;
    }

    /**
     * @param emptyAllowed true, if an empty string is allowed as input.
     * @param textLength the text length
     * @param text the text input
     * @return true, if text input is validated successful
     */
    private boolean checkTextInput(boolean emptyAllowed, int textLength, String text) {

        if ((textLength == 0 && !emptyAllowed) || (text.startsWith(" ") || text.endsWith(" "))) { //$NON-NLS-1$ //$NON-NLS-2$     
            return false;
        }
        return true;
    }

    /**
     * Notifies the DialogStatusListenerManager about the text input state
     */
    private void fireError() {
        DataEventDispatcher.getInstance().getDialogStatusListenerMgr().fireNotification(m_paramList);
    }

    /**
     * Notifies the DialogStatusListenerManager about the text input state
     * @param message The message for the new status.
     * @return the new status parameter.
     */
    protected DialogStatusParameter createWarningStatus(String message) {
        DialogStatusParameter param = new DialogStatusParameter();
        param.setButtonState(true);
        param.setStatusType(IMessageProvider.WARNING);
        param.setMessage(message);
        return param;
    }

    /**
     * Notifies the DialogStatusListenerManager about the text input state
     * @param message The message for the new status.
     * @return the new status parameter.
     */
    protected DialogStatusParameter createErrorStatus(String message) {
        DialogStatusParameter param = new DialogStatusParameter();
        param.setButtonState(false);
        param.setStatusType(IMessageProvider.ERROR);
        param.setMessage(message);
        return param;
    }

    /**
     * Sets no error text / image.
     * @param noEntries true if there are neither errors nor warnings
     */
    private void setIsValid(boolean noEntries) {
        if (noEntries) {
            DialogStatusParameter param = new DialogStatusParameter();
            param.setButtonState(true);
            param.setStatusType(IMessageProvider.NONE);
            param.setMessage(Messages.ProjectWizardAUTData);
            m_paramList.clear();
            m_paramList.add(param);
        }
        DataEventDispatcher.getInstance().getDialogStatusListenerMgr().fireNotification(m_paramList);
    }

    /**
     * @return <code>true</code> if the Aut Config is newly created and defaults
     *         should be used. Otherwise, <code>false</code>.
     */
    protected boolean isConfigNew() {
        return m_autConfig == null || m_autConfig.isEmpty();
    }

    /**
     * Enables the given mode button, deselecting all other mode buttons.
     * 
     * @param button The mode button to select.
     */
    private void selectModeButton(Button button) {
        setCurrentMode(m_buttonToModeMap.get(button));
    }

    /**
     * Inits the state, installs all needed listeners, and performs an initial
     * check for validity of all fields.
     */
    protected void init() {
        initState();
        installListeners();
        checkAll(m_paramList);
    }

    /**
     * Checks validity of all fields.
     */
    public final void checkAll() {
        checkAll(m_paramList);
        if (m_paramList.isEmpty()) {
            setIsValid(true);
        } else {
            boolean isValid = true;
            for (DialogStatusParameter entry : m_paramList) {
                if (entry.getStatusType() == IMessageProvider.ERROR) {
                    isValid = false;
                    break;
                }
            }
            if (isValid) {
                setIsValid(false);
            } else {
                fireError();
            }
        }
        m_paramList.clear();
    }

    /**
     * Checks validity of all fields. Subclasses should extend this method to
     * validate their added fields.
     * 
     * @param paramList A list to which status messages (errors) can be added.
     */
    protected void checkAll(java.util.List<DialogStatusParameter> paramList) {
        addError(paramList, modifyAutConfigFieldAction());
        addError(paramList, modifyAutIdFieldAction());
        addError(paramList, modifyServerComboAction());
        addError(paramList, modifyWorkingDirFieldAction());
    }

    /**
     * Adds the given error to the list, if the error exists.
     * 
     * @param paramList The list to which the error will be added.
     * @param error The error to be added. If this value is <code>null</code>,
     *              the list is not changed.
     */
    protected void addError(List<DialogStatusParameter> paramList, DialogStatusParameter error) {

        if (error != null) {
            paramList.add(error);
        }
    }

    /**
     * 
     * @param error Adds an {@link DialogStatusParameter} to the Error list.
     */
    protected void addError(DialogStatusParameter error) {

        if (error != null) {
            m_paramList.add(error);
        }
    }

    /** 
     * Sets initial editable state for components 
     */
    protected void initState() {
        m_autConfigNameTextField.setEnabled(true);
        m_serverCombo.setEnabled(true);
    }

    /** Handles the server-list event. 
     * @return False, if the server name combo box contents an error.
     */
    public DialogStatusParameter modifyServerComboAction() {
        boolean isValid = false;
        if (m_serverCombo.getSelectionIndex() != -1) {
            putConfigValue(AutConfigConstants.SERVER, m_serverCombo.getItem(m_serverCombo.getSelectionIndex()));
            isValid = true;
        }
        if (isValid) {
            if (!m_nameModified) {
                boolean checkListeners = m_selectionListener != null;

                if (checkListeners) {
                    deinstallListeners();
                }
                m_autConfigNameTextField.setText(NLS.bind(Messages.AUTConfigComponentDefaultAUTConfigName,
                        new String[] { m_autName, m_serverCombo.getText() }));
                if (checkListeners) {
                    installListeners();
                }
            }
            return null;
        }

        return createErrorStatus(Messages.AUTConfigComponentNoServer);
    }

    /**
     * 
     * @return the single instance of the selection listener.
     */
    @SuppressWarnings("synthetic-access")
    private WidgetSelectionListener getSelectionListener() {
        if (m_selectionListener == null) {
            m_selectionListener = new WidgetSelectionListener();
        }

        return m_selectionListener;
    }

    /**
     * 
     * @return the single instance of the modify listener.
     */
    @SuppressWarnings("synthetic-access")
    private WidgetModifyListener getModifyListener() {
        if (m_modifyListener == null) {
            m_modifyListener = new WidgetModifyListener();
        }

        return m_modifyListener;
    }

    /**
     * @return the Text component for the Configuration name.
     */
    protected Text getAutConfigNameTextField() {
        return m_autConfigNameTextField;
    }

    /** 
     * The action of the working directory field.
     * @return <code>null</code> if the new value is valid. Otherwise, returns
     *         a status parameter indicating the cause of the problem.
     */
    public DialogStatusParameter modifyWorkingDirFieldAction() {

        DialogStatusParameter error = null;
        boolean isEmpty = m_autWorkingDirectoryTextField.getText().length() <= 0;
        if (isValid(m_autWorkingDirectoryTextField, true) && !isEmpty) {
            if (checkLocalhostServer()) {
                File dir = new File(m_autWorkingDirectoryTextField.getText());
                if (!dir.isAbsolute()) {
                    // Start from server dir, rather than client dir
                    dir = new File("../server/" + //$NON-NLS-1$
                            m_autWorkingDirectoryTextField.getText());
                }
                if (!dir.isDirectory()) {
                    try {
                        error = createWarningStatus(
                                NLS.bind(Messages.AUTConfigComponentNoDir, dir.getCanonicalPath()));
                    } catch (IOException e) {
                        error = createWarningStatus(NLS.bind(Messages.AUTConfigComponentFileNotFound,
                                m_autWorkingDirectoryTextField.getText()));
                    }
                }
            }
        } else if (!isEmpty) {
            error = createErrorStatus(Messages.AUTConfigComponentWrongWorkDir);
        }

        putConfigValue(AutConfigConstants.WORKING_DIR, m_autWorkingDirectoryTextField.getText());

        return error;
    }

    /**
     * 
     * @return the text field for the Working Directory.
     */
    protected Text getWorkingDirTextField() {
        return m_autWorkingDirectoryTextField;
    }

    /**
     * Handles the button event.
     * @param directoryDialog The directory dialog.
     */
    public void handleWorkDirButtonEvent(DirectoryDialog directoryDialog) {
        String directory;
        directoryDialog.setMessage(Messages.AUTConfigComponentSelectWorkDir);
        File path = new File(m_autWorkingDirectoryTextField.getText());
        String filterPath = Utils.getLastDirPath();
        if (path.exists()) {
            try {
                filterPath = path.getCanonicalPath();
            } catch (IOException e) {
                // Just use the default path which is already set
            }
        }
        directoryDialog.setFilterPath(filterPath);
        directory = directoryDialog.open();
        if (directory != null) {
            m_autWorkingDirectoryTextField.setText(directory);
            Utils.storeLastDirPath(directoryDialog.getFilterPath());
            putConfigValue(AutConfigConstants.WORKING_DIR, m_autWorkingDirectoryTextField.getText());
        }
    }

    /**
     * handle the browse request
     * @param folderSelection true if only folders can be selected
     * @param configVarKey key for storing the result
     * @param textfield control for visualizing the value
     * @param title window title
     * @return true if the user selected a new entry and no error occured
     */
    protected boolean remoteBrowse(boolean folderSelection, String configVarKey, Text textfield, String title) {

        boolean valueChanged = false;

        RemoteFileBrowserDialog directoryDialog = new RemoteFileBrowserDialog(this.getShell(), false,
                folderSelection ? IResource.FOLDER : IResource.FILE);

        try {
            String oldPath = getConfigValue(configVarKey);
            if (oldPath == null || oldPath.length() == 0) {
                oldPath = "."; //$NON-NLS-1$
            }
            RemoteFileStore baseRemoteFS = new RemoteFileStore(AutAgentConnection.getInstance().getCommunicator(),
                    ".", //$NON-NLS-1$
                    folderSelection);
            StringBuilder modPath = new StringBuilder(oldPath);
            baseRemoteFS = handleOldPath(baseRemoteFS, modPath);
            directoryDialog.setInput(baseRemoteFS);
            directoryDialog.setInitialSelection(new RemoteFileStore(
                    AutAgentConnection.getInstance().getCommunicator(), oldPath.toString(), folderSelection));
            directoryDialog.setFSRoots(baseRemoteFS.getRootFSs());
            directoryDialog.setTitle(title);
            directoryDialog.setMessage(Messages.AUTConfigComponentSelectEntries);
            if (directoryDialog.open() == Window.OK) {
                final RemoteFileStore resDir = (RemoteFileStore) directoryDialog.getFirstResult();
                if (resDir != null) {
                    final String path = resDir.getPath();
                    textfield.setText(path);
                    putConfigValue(configVarKey, path);
                    valueChanged = true;
                }
            }
        } catch (ConnectionException e) {
            //FIXME: tobi NLS not found
            ErrorDialog.openError(Plugin.getShell(), I18n.getString("AutConfigComponent.ERROR_TITLE"), null, //$NON-NLS-1$
                    new Status(IStatus.WARNING, Plugin.PLUGIN_ID, I18n.getString("AutConfigComponent.ERROR_COMM"))); //$NON-NLS-1$
        }

        return valueChanged;
    }

    /**
     * check for root entries and modify the necessary values
     * @param remoteFS original remote FS
     * @param path original path
     * @return the original or a new RemoteFileStore if the path begins with
     * a root fs entry
     */
    private RemoteFileStore handleOldPath(RemoteFileStore remoteFS, StringBuilder path) {
        for (String root : remoteFS.getRootFSs()) {
            if (path.toString().startsWith(root)) {
                path.delete(0, root.length());
                return new RemoteFileStore(remoteFS.getCommunicator(), root, remoteFS.fetchInfo().isDirectory());
            }
        }
        return remoteFS;
    }

    /**
     * @param validator The validator to set.
     */
    // FIXME zeb This method is necessary at the moment because the creator 
    //           of AutConfigComponents is in the ToolkitSupport project, which 
    //           is not aware of model (PO) objects nor of databinding classes 
    //           (IValidator). This dependency issue should be resolved, and
    //           the validator should be set in the constructor, rather than
    //           in a separate setter method.
    public void setAutIdValidator(IValidator validator) {
        m_autIdValidator = validator;
    }

}