com.nokia.carbide.remoteconnections.settings.ui.ConnectionSettingsPage.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.carbide.remoteconnections.settings.ui.ConnectionSettingsPage.java

Source

/*
* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/

package com.nokia.carbide.remoteconnections.settings.ui;

import java.io.File;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreeNode;
import org.eclipse.jface.viewers.TreeNodeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.wizard.IWizardContainer2;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
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.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Version;

import com.nokia.carbide.remoteconnections.Messages;
import com.nokia.carbide.remoteconnections.RemoteConnectionsActivator;
import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2;
import com.nokia.carbide.remoteconnections.interfaces.IConnectedService;
import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus;
import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatusChangedListener;
import com.nokia.carbide.remoteconnections.interfaces.IConnection;
import com.nokia.carbide.remoteconnections.interfaces.IConnectionFactory;
import com.nokia.carbide.remoteconnections.interfaces.IConnectionFactory.IValidationErrorReporter;
import com.nokia.carbide.remoteconnections.interfaces.IConnectionFactory2;
import com.nokia.carbide.remoteconnections.interfaces.IConnectionFactory2.ISettingsChangedListener;
import com.nokia.carbide.remoteconnections.interfaces.IConnectionType;
import com.nokia.carbide.remoteconnections.interfaces.IConnectionTypeProvider;
import com.nokia.carbide.remoteconnections.interfaces.IRemoteAgentInstallerProvider;
import com.nokia.carbide.remoteconnections.interfaces.IRemoteAgentInstallerProvider.IRemoteAgentInstaller;
import com.nokia.carbide.remoteconnections.interfaces.IRemoteAgentInstallerProvider.IRemoteAgentInstaller.IPackageContents;
import com.nokia.carbide.remoteconnections.interfaces.IService;
import com.nokia.carbide.remoteconnections.interfaces.IService2;
import com.nokia.carbide.remoteconnections.internal.api.IConnectedService2;
import com.nokia.carbide.remoteconnections.internal.registry.Registry;
import com.nokia.cpp.internal.api.utils.core.Check;
import com.nokia.cpp.internal.api.utils.core.FileUtils;
import com.nokia.cpp.internal.api.utils.core.HostOS;
import com.nokia.cpp.internal.api.utils.core.ObjectUtils;
import com.nokia.cpp.internal.api.utils.core.Pair;
import com.nokia.cpp.internal.api.utils.ui.BrowseDialogUtils;
import com.nokia.cpp.internal.api.utils.ui.LinkParser;
import com.nokia.cpp.internal.api.utils.ui.LinkParser.Element;

public class ConnectionSettingsPage extends WizardPage implements ISettingsChangedListener {

    public final class Tester extends Thread {
        @Override
        public void run() {
            ((AbstractConnectedService2) connectedService).setExternalTesting();
            for (int i = 0; i < 3 && connectedService != null; i++) {
                connectedService.testStatus();
                try {
                    if (i < 2)
                        sleep(AbstractConnectedService2.TIMEOUT);
                } catch (InterruptedException e) {
                    break;
                }
            }
            resetServiceTesting(false);
        }
    }

    private static final TreeNode LOADING_CONTENT_TREENODE = new TreeNode(
            Messages.getString("ConnectionSettingsPage.GettingDataMessage")); //$NON-NLS-1$
    private static final TreeNode[] LOADING_CONTENT_INPUT = new TreeNode[] { LOADING_CONTENT_TREENODE };
    private static final String STATUS_NOT_TESTED = Messages
            .getString("ConnectionSettingsPage.NotTestedStatusString"); //$NON-NLS-1$
    private static final Image FOLDER_ICON_IMG = PlatformUI.getWorkbench().getSharedImages()
            .getImageDescriptor(ISharedImages.IMG_OBJ_FOLDER).createImage();
    private static final String CONNECTION_PREFIX = "connection"; //$NON-NLS-1$
    private static final String INITIAL_NAME_FMT = "{0} {1}"; //$NON-NLS-1$
    private static final String UID = ".uid"; //$NON-NLS-1$
    private final SettingsWizard settingsWizard;
    private IConnectionType connectionType;
    private ComboViewer deviceOSComboViewer;
    private Group settingsGroup;
    private Composite setupTabComposite;
    private ComboViewer connectionTypeViewer;
    private Text nameText;
    private boolean modifiedName;
    private String generatedName;
    private boolean initialized;
    private Composite agentTestTabComposite;
    private ListViewer servicesListViewer;
    private Text serviceTestInfo;
    private Button serviceTestButton;
    private boolean isTesting;
    private Label statusLabel;
    private Text statusText;
    private IConnectionFactory connectionFactory;
    private IConnection connection;
    private IService service;
    private volatile IConnectedService connectedService;
    private IStatusChangedListener statusListener;
    private Tester tester;
    private SashForm installerSashForm;
    private TreeViewer installerTreeViewer;
    private Text installerInfoText;
    private Button installerSaveButton;
    private Button installButton;
    private String saveAsParent;
    private List<IRemoteAgentInstallerProvider> installerProviders;

    protected ConnectionSettingsPage(SettingsWizard settingsWizard) {
        super("settingspage"); //$NON-NLS-1$
        this.settingsWizard = settingsWizard;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        final TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
        tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
        tabFolder.setData(UID, "ConnectionSettingsPage"); //$NON-NLS-1$

        createSetupTabComposite(tabFolder);
        createAgentTestTabComposite(tabFolder);
        createInstallTabComposite(tabFolder);
        int index = settingsWizard.getSelectedTabIndexInConnectionSettingsPage();
        if (index >= 0 && index < 3)
            tabFolder.setSelection(index);

        RemoteConnectionsActivator.setHelp(tabFolder, ".connection_settings_page"); //$NON-NLS-1$

        setControl(tabFolder);
    }

    private void createSetupTabComposite(TabFolder tabFolder) {
        TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
        tabItem.setText(Messages.getString("ConnectionSettingsPage.SetupTabLabel")); //$NON-NLS-1$
        tabItem.setData(UID, "setupTab"); //$NON-NLS-1$
        setupTabComposite = new Composite(tabFolder, SWT.NONE);
        setupTabComposite.setLayout(new GridLayout(2, false));
        tabItem.setControl(setupTabComposite);

        boolean canEditConnection = !settingsWizard.isConnectionToEditDynamic();

        Label viewerLabel = new Label(setupTabComposite, SWT.NONE);
        viewerLabel.setText(Messages.getString("ConnectionTypePage.ViewerLabel")); //$NON-NLS-1$

        connectionTypeViewer = new ComboViewer(setupTabComposite, SWT.READ_ONLY);
        connectionTypeViewer.setLabelProvider(new LabelProvider() {
            @Override
            public String getText(Object element) {
                Check.checkState(element instanceof IConnectionType);
                IConnectionType connectionType = (IConnectionType) element;
                return connectionType.getDisplayName() + " (" + getServicesString(connectionType) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
            }
        });
        connectionTypeViewer.setContentProvider(new ArrayContentProvider());
        connectionTypeViewer.setInput(getConnectionTypes());
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
        connectionTypeViewer.getControl().setLayoutData(gd);
        connectionTypeViewer.getControl().setData(UID, "viewer"); //$NON-NLS-1$
        connectionTypeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            private IConnectionType previousSelection;

            public void selectionChanged(SelectionChangedEvent event) {
                Object currentSelection = ((IStructuredSelection) event.getSelection()).getFirstElement();
                if (!currentSelection.equals(previousSelection)) {
                    settingsWizard.connectionTypeChanged();
                    previousSelection = (IConnectionType) currentSelection;
                }
            }
        });
        connectionTypeViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                getWizard().getContainer().showPage(getNextPage());
            }
        });
        connectionTypeViewer.setSorter(new ViewerSorter() {
            @Override
            public int compare(Viewer viewer, Object e1, Object e2) {
                IConnectionType t1 = (IConnectionType) e1;
                IConnectionType t2 = (IConnectionType) e2;
                return t1.getDisplayName().compareToIgnoreCase(t2.getDisplayName());
            }
        });
        connectionTypeViewer.getCombo().select(getCurrentTypeIndex());
        connectionTypeViewer.getCombo().setEnabled(canEditConnection);

        Label nameLabel = new Label(setupTabComposite, SWT.NONE);
        nameLabel.setText(Messages.getString("ConnectionTypePage.NameLabel")); //$NON-NLS-1$
        nameText = new Text(setupTabComposite, SWT.BORDER);
        gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
        nameText.setLayoutData(gd);
        nameText.setToolTipText(Messages.getString("ConnectionTypePage.NameTextToolTip")); //$NON-NLS-1$
        nameText.setData(UID, "nameText"); //$NON-NLS-1$
        nameText.setText(getInitialNameText());
        nameText.selectAll();
        nameText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                modifiedName = true;
                setPageComplete(validatePage());
            }
        });
        nameText.setEnabled(canEditConnection);

        createSettingsGroup(setupTabComposite);
    }

    private void createAgentTestTabComposite(TabFolder tabFolder) {
        TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
        tabItem.setText(Messages.getString("ConnectionSettingsPage.AgentTestTabLabel")); //$NON-NLS-1$
        tabItem.setData(UID, "testTab"); //$NON-NLS-1$
        agentTestTabComposite = new Composite(tabFolder, SWT.NONE);
        GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        agentTestTabComposite.setLayout(gridLayout);
        tabItem.setControl(agentTestTabComposite);

        Group group = new Group(agentTestTabComposite, SWT.NONE);
        group.setText(Messages.getString("ConnectionSettingsPage.ConnectionTestingLabel")); //$NON-NLS-1$
        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(group);
        GridDataFactory.fillDefaults().span(2, 1).grab(true, true).applyTo(group);

        createDeviceOSCombo(group);

        createServiceTestComposite(group);
    }

    private void createDeviceOSCombo(Composite parent) {
        Composite comboComposite = new Composite(parent, SWT.NONE);
        GridData gd_composite = new GridData(SWT.FILL, SWT.CENTER, true, false);
        gd_composite.horizontalSpan = 2;
        comboComposite.setLayoutData(gd_composite);
        GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        comboComposite.setLayout(gridLayout);

        Label deviceOSLabel = new Label(comboComposite, SWT.NONE);
        GridData gd_sdkLabel = new GridData();
        deviceOSLabel.setLayoutData(gd_sdkLabel);
        deviceOSLabel.setText(Messages.getString("ConnectionSettingsPage.DeviceOSLabel")); //$NON-NLS-1$

        deviceOSComboViewer = new ComboViewer(comboComposite, SWT.READ_ONLY);
        GridData gd_sdkcombo = new GridData(SWT.LEFT, SWT.CENTER, true, false);
        gd_sdkcombo.widthHint = 150;
        deviceOSComboViewer.getCombo().setLayoutData(gd_sdkcombo);
        deviceOSComboViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @SuppressWarnings("unchecked")
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) deviceOSComboViewer.getSelection();
                Pair<String, String> pair = (Pair<String, String>) selection.getFirstElement();
                setSelectionToInstallComposite(pair);
                if (connectedService instanceof IConnectedService2)
                    ((IConnectedService2) connectedService).setDeviceOS(pair.first, pair.second);
            }
        });
        deviceOSComboViewer.setContentProvider(new ArrayContentProvider());
        deviceOSComboViewer.setLabelProvider(new LabelProvider() {
            @SuppressWarnings({ "unchecked", "rawtypes" })
            @Override
            public String getText(Object element) {
                Check.checkState(element instanceof Pair);
                Pair<String, Version> pair = (Pair) element;
                return MessageFormat.format("{0} {1}", pair.first, pair.second); //$NON-NLS-1$
            }
        });
        deviceOSComboViewer.getControl()
                .setToolTipText(Messages.getString("ConnectionSettingsPage.DeviceOSComboToolTip")); //$NON-NLS-1$
        deviceOSComboViewer.getControl().setData(UID, "deviceOSComboViewer"); //$NON-NLS-1$
    }

    private void createSettingsGroup(Composite parent) {
        settingsGroup = new Group(parent, SWT.NONE);
        GridLayout settingsLayout = new GridLayout();
        settingsGroup.setLayout(settingsLayout);
        GridData gd_settings = new GridData(GridData.FILL_HORIZONTAL);
        gd_settings.horizontalSpan = 2;
        settingsGroup.setLayoutData(gd_settings);
        settingsGroup.setText(Messages.getString("ConnectionSettingsPage.ConnectionSettingsGroupLabel")); //$NON-NLS-1$
    }

    private void createServiceTestComposite(Composite parent) {
        Composite serviceSelectionComposite = new Composite(parent, SWT.NONE);
        serviceSelectionComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        serviceSelectionComposite.setLayout(new GridLayout());
        Label label = new Label(serviceSelectionComposite, SWT.NONE);
        label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        label.setText(Messages.getString("ConnectionSettingsPage.ServicesListLabel")); //$NON-NLS-1$
        servicesListViewer = new ListViewer(serviceSelectionComposite,
                SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        GridData gd_viewer = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
        servicesListViewer.getControl().setLayoutData(gd_viewer);
        servicesListViewer.setContentProvider(new ArrayContentProvider());
        servicesListViewer.setLabelProvider(new LabelProvider() {
            @Override
            public String getText(Object element) {
                if (element instanceof IService)
                    return ((IService) element).getDisplayName();
                return null;
            }
        });
        servicesListViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) servicesListViewer.getSelection();
                IService curService = (IService) selection.getFirstElement();
                if (!curService.equals(service)) {
                    service = curService;
                    serviceTestButton.setEnabled(service.isTestable());
                    resetServiceTesting(true);
                }
            }
        });
        servicesListViewer.getControl()
                .setToolTipText(Messages.getString("ConnectionSettingsPage.ServicesListToolTip")); //$NON-NLS-1$
        servicesListViewer.getControl().setData(UID, "servicesListViewer"); //$NON-NLS-1$

        Composite testButtonComposite = new Composite(parent, SWT.NONE);
        testButtonComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
        testButtonComposite.setLayout(new GridLayout());
        serviceTestInfo = new Text(testButtonComposite, SWT.READ_ONLY | SWT.WRAP);
        serviceTestButton = new Button(testButtonComposite, SWT.PUSH);
        GridData gd_button = new GridData(SWT.CENTER, SWT.CENTER, false, false);
        int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        serviceTestButton.setText(Messages.getString("ConnectionSettingsPage.StartServiceTestButtonLabel")); //$NON-NLS-1$
        Point minSize = serviceTestButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
        gd_button.widthHint = Math.max(widthHint, minSize.x);
        GridData gd_text = new GridData(SWT.CENTER, SWT.FILL, true, true);
        gd_text.widthHint = gd_button.widthHint;
        serviceTestInfo.setLayoutData(gd_text);
        serviceTestInfo.setData(UID, "serviceTestInfo"); //$NON-NLS-1$
        serviceTestButton.setLayoutData(gd_button);
        serviceTestButton.setToolTipText(Messages.getString("ConnectionSettingsPage.ServiceTestButtonToolTip")); //$NON-NLS-1$
        serviceTestButton.setData(UID, "serviceTestButton"); //$NON-NLS-1$
        serviceTestButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (isTesting) {
                    serviceTestButton
                            .setText(Messages.getString("ConnectionSettingsPage.StartServiceTestButtonLabel")); //$NON-NLS-1$
                    resetServiceTesting(true);
                } else {
                    serviceTestButton
                            .setText(Messages.getString("ConnectionSettingsPage.StopServiceTestButtonLabel")); //$NON-NLS-1$
                    testService();
                }
            }
        });

        Composite statusComposite = new Composite(parent, SWT.NONE);
        statusComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
        statusComposite.setLayout(new GridLayout());
        statusLabel = new Label(statusComposite, SWT.NONE);
        statusLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
        statusLabel.setText(Messages.getString("ConnectionSettingsPage.StatusLabel")); //$NON-NLS-1$
        statusText = new Text(statusComposite, SWT.MULTI | SWT.READ_ONLY | SWT.BORDER | SWT.WRAP);
        statusText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        statusText.setText(STATUS_NOT_TESTED);
        statusText.setData(UID, "statusText"); //$NON-NLS-1$
    }

    private void createInstallTabComposite(TabFolder tabFolder) {
        TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
        tabItem.setText(Messages.getString("ConnectionSettingsPage.InstallTabLabel")); //$NON-NLS-1$
        tabItem.setData(UID, "installTab"); //$NON-NLS-1$
        Composite composite = new Composite(tabFolder, SWT.NONE);
        GridLayout gridLayout = new GridLayout();
        composite.setLayout(gridLayout);
        tabItem.setControl(composite);

        Composite installDebugAgentComposite = new Composite(tabFolder, SWT.NONE);
        installDebugAgentComposite.setLayout(new GridLayout(1, false));
        tabItem.setControl(installDebugAgentComposite);

        installerSashForm = new SashForm(installDebugAgentComposite, SWT.HORIZONTAL);
        GridData gd_sash = new GridData(SWT.FILL, SWT.FILL, true, true);
        gd_sash.widthHint = 420;
        gd_sash.heightHint = 280;
        installerSashForm.setLayoutData(gd_sash);

        installerTreeViewer = new TreeViewer(installerSashForm, SWT.BORDER);
        GridData gd_tree = new GridData(SWT.CENTER, SWT.CENTER, false, false);
        installerTreeViewer.getTree().setLayoutData(gd_tree);
        installerTreeViewer.getControl().setData(UID, "installerTreeViewer"); //$NON-NLS-1$
        installerTreeViewer.setContentProvider(new TreeNodeContentProvider());
        installerTreeViewer.setLabelProvider(new LabelProvider() {
            @Override
            public String getText(Object element) {
                TreeNode node = (TreeNode) element;
                Object value = node.getValue();
                if (value instanceof IRemoteAgentInstaller) {
                    String label = ((IRemoteAgentInstaller) value).getLabel();
                    return label == null ? Messages.getString("ConnectionSettingsPage.UnlabeledPackageLabel") //$NON-NLS-1$
                            : label;
                }
                return value.toString();
            }

            @Override
            public Image getImage(Object element) {
                if (element.equals(LOADING_CONTENT_TREENODE))
                    return null;

                TreeNode node = (TreeNode) element;
                Object value = node.getValue();
                if (value instanceof IRemoteAgentInstaller)
                    return ((IRemoteAgentInstaller) value).getImage();

                return FOLDER_ICON_IMG;
            }
        });
        installerTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                TreeNode node = (TreeNode) ((StructuredSelection) event.getSelection()).getFirstElement();
                if (node == null)
                    return;
                Object value = node.getValue();
                boolean isPackage = value instanceof IRemoteAgentInstaller;
                boolean installable = false;
                String information = null;
                if (isPackage) {
                    IRemoteAgentInstaller installer = (IRemoteAgentInstaller) value;
                    installable = installer.fileSupportsInstall();
                    information = installer.getInformation();
                }
                if (information != null)
                    installerInfoText.setText(information);
                else
                    installerInfoText.setText(""); //$NON-NLS-1$
                installButton.setEnabled(isPackage && installable);
                installerSaveButton.setEnabled(isPackage);
            }
        });

        installerInfoText = new Text(installerSashForm, SWT.READ_ONLY | SWT.BORDER | SWT.WRAP);
        String errorText = Messages.getString("ConnectionSettingsPage.NoInstallerDataInfoString"); //$NON-NLS-1$
        errorText += "\n" + Messages.getString("ConnectionSettingsPage.NoInstallerDataInfoString2"); //$NON-NLS-1$ //$NON-NLS-2$
        installerInfoText.setText(errorText);
        installerInfoText.setData(UID, "installerInfoText"); //$NON-NLS-1$
        installerSashForm.setWeights(new int[] { 160, 100 });

        Composite buttonsArea = new Composite(installDebugAgentComposite, SWT.NONE);
        buttonsArea.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
        gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        buttonsArea.setLayout(gridLayout);

        installerSaveButton = new Button(buttonsArea, SWT.NONE);
        final GridData gd_saveButton = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
        gd_saveButton.widthHint = 125;
        installerSaveButton.setLayoutData(gd_saveButton);
        installerSaveButton.setText(Messages.getString("ConnectionSettingsPage.SaveButtonLabel")); //$NON-NLS-1$
        installerSaveButton.setEnabled(false);
        installerSaveButton.setToolTipText(Messages.getString("ConnectionSettingsPage.SaveButtonToolTip")); //$NON-NLS-1$
        installerSaveButton.setData(UID, "installerSaveButton"); //$NON-NLS-1$
        installerSaveButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        try {
                            IRemoteAgentInstaller installer = getCurrentInstaller();
                            saveAs(installer.getPackageContents(getContainer()));
                        } catch (Exception e) {
                            RemoteConnectionsActivator.logError(e);
                        }
                    }
                });
            }
        });

        installButton = new Button(buttonsArea, SWT.NONE);
        final GridData gd_installButton = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
        gd_installButton.widthHint = 125;
        installButton.setLayoutData(gd_installButton);
        installButton.setText(Messages.getString("ConnectionSettingsPage.InstallButtonLabel")); //$NON-NLS-1$
        installButton.setEnabled(false);
        installButton.setToolTipText(Messages.getString("ConnectionSettingsPage.InstallButtonToolTip")); //$NON-NLS-1$
        installButton.setData(UID, "installButton"); //$NON-NLS-1$
        installButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        try {
                            IRemoteAgentInstaller installer = getCurrentInstaller();
                            attemptInstall(installer.getPackageContents(getContainer()));
                        } catch (Exception e) {
                            RemoteConnectionsActivator.logError(e);
                        }
                    }
                });
            }
        });
    }

    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible) {
            if (!initialized) {
                initialized = true;
                connectionTypeViewer.setSelection(connectionTypeViewer.getSelection());
            }
            settingsWizard.connectionTypeChanged();
        }
    }

    public void updateDynamicUI() {
        IConnectionType currentConnectionType = getConnectionType();
        if (currentConnectionType != null && !currentConnectionType.equals(connectionType)) {
            setErrorMessage(null);
            setPageComplete(true);
            String buttonLabel = Messages.getString("ConnectionSettingsPage.StartServiceTestButtonLabel"); //$NON-NLS-1$
            serviceTestButton.setText(buttonLabel);
            connectionType = currentConnectionType;
            setTitle(MessageFormat.format(Messages.getString("ConnectionSettingsPage.PageTitleFmt"), //$NON-NLS-1$
                    connectionType.getDisplayName()));
            setDescription(connectionType.getDescription());

            // update settings editing UI
            Control[] settingsUI = settingsGroup.getChildren();
            if (settingsUI.length > 0) {
                for (Control control : settingsUI) {
                    control.dispose();
                }
            }
            connectionFactory = connectionType.getConnectionFactory();
            Map<String, String> initialSettings = null;
            IConnection connectionToEdit = settingsWizard.getConnectionToEdit();
            if (connectionToEdit != null && connectionToEdit.getConnectionType().equals(connectionType)) // show existing settings
                initialSettings = connectionToEdit.getSettings();
            IValidationErrorReporter errorReporter = new IValidationErrorReporter() {
                public void setErrorMessage(String newMessage) {
                    ConnectionSettingsPage.this.setErrorMessage(newMessage);
                    boolean noError = newMessage == null;
                    setPageComplete(noError);
                    String buttonLabel = Messages.getString("ConnectionSettingsPage.StartServiceTestButtonLabel"); //$NON-NLS-1$
                    serviceTestButton.setText(buttonLabel);
                }
            };
            if (connectionFactory instanceof IConnectionFactory2) {
                ((IConnectionFactory2) connectionFactory).createEditingUI(settingsGroup, errorReporter,
                        initialSettings, this);
                settingsChanged();
            } else {
                connectionFactory.createEditingUI(settingsGroup, errorReporter, initialSettings);
                if (!modifiedName) {
                    nameText.setText(getInitialNameText());
                    modifiedName = false;
                }
            }
            settingsUI = settingsGroup.getChildren();
            if (settingsUI.length == 0) {
                CLabel label = new CLabel(settingsGroup, SWT.NONE);
                label.setText(MessageFormat.format(Messages.getString("ConnectionSettingsPage.NoSettingsString"), //$NON-NLS-1$
                        connectionType.getDisplayName()));
                GridData gd = new GridData(SWT.LEFT, SWT.TOP, true, true);
                label.setLayoutData(gd);
            } else if (settingsWizard.isConnectionToEditDynamic()) {
                disableControls(settingsUI);
            }

            // update services list
            Collection<IService> compatibleServices = Registry.instance().getCompatibleServices(connectionType);
            servicesListViewer.setInput(compatibleServices);
            if (!compatibleServices.isEmpty()) {
                servicesListViewer.getList().select(0);
                servicesListViewer.setSelection(servicesListViewer.getSelection());
            }
            servicesListViewer.getList().addFocusListener(new FocusAdapter() {
                public void focusGained(FocusEvent e) {
                    resetServiceTesting(true);
                }
            });

            Thread t = new Thread() {
                @Override
                public void run() {
                    initializeInstallerData();
                }
            };
            t.start();
        }

        if (getControl().isVisible()) {
            setupTabComposite.layout(true, true);
            agentTestTabComposite.layout(true, true);
        }

        if (getControl().isVisible())
            ((IWizardContainer2) getWizard().getContainer()).updateSize();
    }

    public void settingsChanged() {
        if (!modifiedName) {
            String currentName = nameText.getText();
            if (currentName == null || currentName.length() == 0 || currentName.equals(generatedName)) {
                String preferredName = connectionFactory.getSettingsFromUI()
                        .get(IConnectionFactory2.PREFERRED_CONNECTION_NAME);
                if (preferredName != null) {
                    preferredName = ensureUniquePreferredName(preferredName);
                    generatedName = preferredName;
                    nameText.setText(preferredName);
                } else {
                    nameText.setText(getInitialNameText());
                }
            }
            modifiedName = false;
        }
    }

    private void disableControls(Control[] controls) {
        for (Control control : controls) {
            if (control instanceof Composite)
                disableControls(((Composite) control).getChildren());
            control.setEnabled(false);
        }
    }

    private synchronized void initializeInstallerData() {
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                Control control = installerTreeViewer.getControl();
                if (control == null || control.isDisposed())
                    return;

                if (installerTreeViewer.getContentProvider() == null)
                    installerTreeViewer.setContentProvider(new TreeNodeContentProvider());
                installerTreeViewer.setInput(LOADING_CONTENT_INPUT);
                installerInfoText.setText(""); //$NON-NLS-1$
                deviceOSComboViewer.setInput(Collections.EMPTY_LIST);
            }
        });

        IConnectionTypeProvider connectionTypeProvider = RemoteConnectionsActivator.getConnectionTypeProvider();
        Collection<IService> services = connectionTypeProvider.getCompatibleServices(connectionType);
        getInstallerProviders(services);
        final TreeNode[] treeNodes = createTreeNodes(); // gets actual data from server

        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                Control control = installerTreeViewer.getControl();
                if (control == null || control.isDisposed())
                    return;

                // update installer tree
                if (installerTreeViewer.getContentProvider() == null)
                    installerTreeViewer.setContentProvider(new TreeNodeContentProvider());
                installerTreeViewer.setInput(treeNodes);
                installerTreeViewer.refresh(true);

                if (treeNodes.length == 0) {
                    String errorText;
                    // TODO: the actual error condition needs to be recorded... 
                    if (HostOS.IS_UNIX) {
                        errorText = Messages.getString("ConnectionSettingsPage.NoInstallerSupport"); //$NON-NLS-1$
                    } else {
                        errorText = Messages.getString("ConnectionSettingsPage.NoInstallerDataInfoString"); //$NON-NLS-1$
                        errorText += "\n" + Messages.getString("ConnectionSettingsPage.NoInstallerDataInfoString2"); //$NON-NLS-1$ //$NON-NLS-2$
                    }
                    installerInfoText.setText(errorText);
                }

                // update sdk combo
                List<Pair<String, String>> deviceOSPairs = createDeviceOSPairs();
                deviceOSComboViewer.setInput(deviceOSPairs);
                if (!deviceOSPairs.isEmpty()) {
                    deviceOSComboViewer.getCombo().select(0);
                    deviceOSComboViewer.setSelection(deviceOSComboViewer.getSelection());
                } else {
                    String errorLabel = Messages.getString("ConnectionSettingsPage.NoInstallerDataInfoString"); //$NON-NLS-1$
                    deviceOSComboViewer.getCombo().setItems(new String[] { errorLabel });
                    deviceOSComboViewer.getCombo().select(0);
                    deviceOSComboViewer.getCombo().setEnabled(false);
                }
                deviceOSComboViewer.getCombo().addFocusListener(new FocusAdapter() {
                    public void focusGained(FocusEvent e) {
                        resetServiceTesting(true);
                    }
                });
            }
        });

    }

    protected void setSelectionToInstallComposite(Pair<String, String> pair) {
        Object input = installerTreeViewer.getInput();
        if (input instanceof TreeNode[]) {
            TreeNode node = findTreeNodeForPair((TreeNode[]) input, pair);
            if (node != null) {
                installerTreeViewer.collapseAll();
                installerTreeViewer.setSelection(new StructuredSelection(node));
            }
        }
    }

    private TreeNode findTreeNodeForPair(TreeNode[] treeNodes, Pair<String, String> pair) {
        for (TreeNode treeNode : treeNodes) {
            Object value = treeNode.getValue();
            if (value instanceof IRemoteAgentInstaller) {
                TreeNode versionNode = treeNode.getParent();
                TreeNode familyNode = versionNode.getParent();
                if (ObjectUtils.equals(pair.first, familyNode.getValue())
                        && ObjectUtils.equals(pair.second, versionNode.getValue()))
                    return treeNode;
            }
            TreeNode[] children = treeNode.getChildren();
            if (children != null) {
                TreeNode treeNodeFromChildren = findTreeNodeForPair(children, pair);
                if (treeNodeFromChildren != null)
                    return treeNodeFromChildren;
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    protected void testService() {
        Map<String, String> settings = connectionFactory.getSettingsFromUI();
        boolean newConnection = connection == null || !connectionType.equals(connection.getConnectionType());
        if (newConnection) {
            if (connection != null)
                connection.dispose();
            connection = connectionFactory.createConnection(settings);
            connection.setDisplayName("TestConnection:" + connectionType.getDisplayName()); //$NON-NLS-1$
        } else {
            connection.updateSettings(settings);
        }
        if (newConnection || connectedService == null || !connectedService.getService().equals(service)) {
            disposeConnectedService();
            connectedService = Registry.instance().createConnectedService(service, connection);
            IStructuredSelection selection = (IStructuredSelection) deviceOSComboViewer.getSelection();
            Pair<String, String> pair = (Pair<String, String>) selection.getFirstElement();
            if (pair != null && connectedService instanceof IConnectedService2) {
                ((IConnectedService2) connectedService).setDeviceOS(pair.first, pair.second);
            }
            connectedService.addStatusChangedListener(statusListener = new IStatusChangedListener() {
                public void statusChanged(final IStatus status) {
                    Display.getDefault().asyncExec(new Runnable() {
                        public void run() {
                            if (!statusText.isDisposed()) {
                                String longDescription = status.getLongDescription();
                                if (longDescription != null) {
                                    List<Element> elements = LinkParser.parseText(longDescription);
                                    StyledString styledString = LinkParser.getStyledString(elements);
                                    longDescription = styledString.getString();
                                }
                                statusText.setText(longDescription);
                            }
                            if (status.getEStatus().equals(EStatus.UP))
                                resetServiceTesting(false);
                        }
                    });
                }
            });
            if (connectedService instanceof AbstractConnectedService2) {
                ((AbstractConnectedService2) connectedService).setRunnableContext(getContainer());
                tester = new Tester();
                tester.start();
            }
            isTesting = true;
        }
    }

    @Override
    public void dispose() {
        disposeInstallerProviders();
        disposeConnectedService();
        if (connection != null)
            connection.dispose();
        super.dispose();
    }

    private void disposeConnectedService() {
        if (connectedService != null) {
            connectedService.removeStatusChangedListener(statusListener);
            connectedService.dispose();
            connectedService = null;
        }
    }

    public Map<String, String> getSettings() {
        if (connectionFactory == null) {
            IConnection connectionToEdit = settingsWizard.getConnectionToEdit();
            if (connectionToEdit == null || !connectionToEdit.getConnectionType().equals(getConnectionType())) {
                return null;
            }
            return connectionToEdit.getSettings();
        }
        return connectionFactory.getSettingsFromUI();
    }

    private void saveAs(IPackageContents packageContents) throws Exception {
        InputStream is = packageContents.getInputStream();
        if (is != null) {
            Shell shell = getShell();
            FileDialog dialog = new FileDialog(shell, SWT.SAVE);
            dialog.setText(Messages.getString("ConnectionSettingsPage.SaveAsDialogTitle")); //$NON-NLS-1$
            if (saveAsParent == null)
                saveAsParent = System.getProperty("user.home"); //$NON-NLS-1$
            BrowseDialogUtils.initializeFrom(dialog,
                    new Path(saveAsParent).append(packageContents.getDefaultNameFileName()));
            dialog.setOverwrite(true); // prompt for overwrite
            String path = dialog.open();
            if (path != null) {
                IPath saveAsPath = new Path(path);
                saveAsParent = saveAsPath.removeLastSegments(1).toString();
                File file = saveAsPath.toFile();
                FileUtils.copyFile(is, file);
            }
        } else
            MessageDialog.openError(getShell(), "Package Error",
                    MessageFormat.format("Cannot locate package file ({0})\n\n(server configuration problem?)",
                            packageContents.getDefaultNameFileName()));
    }

    private void attemptInstall(IPackageContents packageContents) throws Exception {
        File tempDir = FileUtils.getTemporaryDirectory();
        IPath path = new Path(tempDir.getAbsolutePath());
        IPath tempFilePath = path.append(packageContents.getDefaultNameFileName());
        File tempFile = tempFilePath.toFile();
        if (tempFile.exists())
            tempFile.delete();
        InputStream is = packageContents.getInputStream();
        if (is != null) {
            FileUtils.copyFile(is, tempFile);
            Program.launch(tempFile.getAbsolutePath());
        } else
            MessageDialog.openError(getShell(), "Package Error",
                    MessageFormat.format("Failed to download package ({0})\n\n(server configuration problem?)",
                            packageContents.getDefaultNameFileName()));
    }

    private IRemoteAgentInstaller getCurrentInstaller() {
        TreeNode node = (TreeNode) ((StructuredSelection) installerTreeViewer.getSelection()).getFirstElement();
        if (node != null) {
            Object value = node.getValue();
            if (value instanceof IRemoteAgentInstaller)
                return (IRemoteAgentInstaller) value;
        }
        return null;
    }

    private synchronized TreeNode[] createTreeNodes() {
        Map<String, TreeNode> sdkFamilyToNodes = new LinkedHashMap<String, TreeNode>();
        for (IRemoteAgentInstallerProvider installerProvider : installerProviders) {
            List<String> familyNames = installerProvider.getSDKFamilyNames(null);
            for (String familyName : familyNames) {
                if (!sdkFamilyToNodes.containsKey(familyName))
                    sdkFamilyToNodes.put(familyName, new TreeNode(familyName));
                TreeNode familyNode = sdkFamilyToNodes.get(familyName);
                createFamilySubNodes(familyNode, installerProvider);
            }
        }
        return (TreeNode[]) sdkFamilyToNodes.values().toArray(new TreeNode[sdkFamilyToNodes.values().size()]);
    }

    private void createFamilySubNodes(TreeNode familyNode, IRemoteAgentInstallerProvider installerProvider) {
        String familyName = familyNode.getValue().toString();
        List<String> versions = installerProvider.getVersions(familyName);
        List<TreeNode> childList = new ArrayList<TreeNode>();
        TreeNode[] children = familyNode.getChildren();
        if (children != null)
            childList.addAll(Arrays.asList(children));
        for (String version : versions) {
            TreeNode versionNode = getVersionNode(familyNode, version);
            if (versionNode == null) {
                versionNode = new TreeNode(version);
                versionNode.setParent(familyNode);
                childList.add(versionNode);
            }
            createInstallerNodes(versionNode, installerProvider);
        }
        familyNode.setChildren((TreeNode[]) childList.toArray(new TreeNode[childList.size()]));
    }

    private TreeNode getVersionNode(TreeNode familyNode, String version) {
        TreeNode[] children = familyNode.getChildren();
        if (children != null) {
            for (TreeNode node : children) {
                if (node.getValue().equals(version))
                    return node;
            }
        }
        return null;
    }

    private void createInstallerNodes(TreeNode versionNode, IRemoteAgentInstallerProvider installerProvider) {
        String familyName = versionNode.getParent().getValue().toString();
        String version = versionNode.getValue().toString();
        List<IRemoteAgentInstaller> installers = installerProvider.getRemoteAgentInstallers(familyName, version);
        List<TreeNode> childList = new ArrayList<TreeNode>();
        TreeNode[] children = versionNode.getChildren();
        if (children != null)
            childList.addAll(Arrays.asList(children));
        for (IRemoteAgentInstaller installer : installers) {
            TreeNode installerNode = new TreeNode(installer);
            installerNode.setParent(versionNode);
            childList.add(installerNode);
        }
        versionNode.setChildren((TreeNode[]) childList.toArray(new TreeNode[childList.size()]));
    }

    private synchronized List<Pair<String, String>> createDeviceOSPairs() {
        List<Pair<String, String>> deviceOSPairs = new ArrayList<Pair<String, String>>();
        for (IRemoteAgentInstallerProvider installerProvider : installerProviders) {
            List<String> familyNames = installerProvider.getSDKFamilyNames(null);
            for (String familyName : familyNames) {
                List<String> versions = installerProvider.getVersions(familyName);
                for (String version : versions) {
                    Pair<String, String> pair = new Pair<String, String>(familyName, version);
                    if (!deviceOSPairs.contains(pair))
                        deviceOSPairs.add(pair);
                }
            }
        }
        return deviceOSPairs;
    }

    private synchronized void getInstallerProviders(Collection<IService> services) {
        if (installerProviders != null) {
            // check to see if we already have this set of installer providers
            Set<String> serviceIds = new TreeSet<String>();
            for (IService service : services) {
                if (service.getInstallerProvider() != null)
                    serviceIds.add(service.getIdentifier());
            }
            Set<String> existingServiceIds = new TreeSet<String>();
            for (IRemoteAgentInstallerProvider installerProvider : installerProviders) {
                existingServiceIds.add(installerProvider.getService().getIdentifier());
            }
            if (serviceIds.equals(existingServiceIds))
                return;
        }
        disposeInstallerProviders();
        installerProviders = new ArrayList<IRemoteAgentInstallerProvider>();
        for (IService service : services) {
            IRemoteAgentInstallerProvider installerProvider = service.getInstallerProvider();
            if (installerProvider != null)
                installerProviders.add(installerProvider);
        }
    }

    private synchronized void disposeInstallerProviders() {
        if (installerProviders != null) {
            for (IRemoteAgentInstallerProvider installerProvider : installerProviders) {
                installerProvider.dispose();
            }
            installerProviders.clear();
            installerProviders = null;
        }
    }

    private void resetServiceTesting(final boolean resetAll) {
        isTesting = false;
        if (service == null)
            return;
        // may be called from a test thread
        Display.getDefault().syncExec(new Runnable() {
            public void run() {
                if (resetAll) {
                    statusText.setText(STATUS_NOT_TESTED);
                    serviceTestInfo.setText(service.getAdditionalServiceInfo());
                    agentTestTabComposite.layout(true, true);
                    boolean wantsDeviceOS = service.getInstallerProvider() != null;
                    if (service instanceof IService2)
                        wantsDeviceOS &= ((IService2) service).wantsDeviceOS();
                    deviceOSComboViewer.getCombo().setEnabled(wantsDeviceOS);
                }
                disposeConnectedService();
                if (!serviceTestButton.isDisposed()) {
                    String buttonLabel = Messages.getString("ConnectionSettingsPage.StartServiceTestButtonLabel"); //$NON-NLS-1$
                    serviceTestButton.setText(buttonLabel);
                }
            }
        });
    }

    public IConnectionType getConnectionType() {
        return (IConnectionType) ((IStructuredSelection) connectionTypeViewer.getSelection()).getFirstElement();
    }

    public String getName() {
        return nameText.getText().trim();
    }

    @SuppressWarnings("unchecked")
    private int getCurrentTypeIndex() {
        IConnection connectionToEdit = settingsWizard.getConnectionToEdit();
        if (connectionToEdit != null) {
            Object input = connectionTypeViewer.getInput();
            if (input != null) {
                Collection<IConnectionType> connectionTypes = (Collection<IConnectionType>) input;
                for (int i = 0; i < connectionTypes.size(); i++) {
                    IConnectionType connectionType = (IConnectionType) connectionTypeViewer.getElementAt(i);
                    if (connectionToEdit.getConnectionType().equals(connectionType))
                        return i;
                }
            }
        }
        return 0;
    }

    private Collection<IConnectionType> getConnectionTypes() {
        Collection<IConnectionType> connectionTypes = getValidConnectionTypes();
        IService serviceToRestrict = settingsWizard.getServiceToRestrict();
        if (serviceToRestrict != null) {
            List<IConnectionType> restrictedConnectionTypes = new ArrayList<IConnectionType>();
            Collection<String> compatibleConnectionTypeIds = Registry.instance()
                    .getCompatibleConnectionTypeIds(serviceToRestrict);
            for (String connectionTypeId : compatibleConnectionTypeIds) {
                IConnectionType connectionType = Registry.instance().getConnectionType(connectionTypeId);
                if (connectionTypes.contains(connectionType))
                    restrictedConnectionTypes.add(connectionType);
            }
            return restrictedConnectionTypes;
        }

        return connectionTypes;
    }

    private String getInitialNameText() {
        IConnection connectionToEdit = settingsWizard.getConnectionToEdit();
        if (connectionToEdit != null) {
            generatedName = ""; //$NON-NLS-1$
            return connectionToEdit.getDisplayName();
        }

        long i = 1;
        while (true) {
            String name = MessageFormat.format(INITIAL_NAME_FMT, CONNECTION_PREFIX, Long.toString(i++));
            if (isNameUnique(name)) {
                generatedName = name;
                return name;
            }
        }
    }

    private String ensureUniquePreferredName(String preferredName) {
        if (isNameUnique(preferredName)) {
            return preferredName;
        }

        long i = 1;
        while (true) {
            String name = MessageFormat.format(INITIAL_NAME_FMT, preferredName, Long.toString(i++));
            if (isNameUnique(name)) {
                return name;
            }
        }
    }

    private String getServicesString(IConnectionType connectionType) {
        StringBuilder servicesString = new StringBuilder();
        Collection<IService> services = Registry.instance().getCompatibleServices(connectionType);
        if (services == null || services.isEmpty())
            return ""; //$NON-NLS-1$
        for (Iterator<IService> iterator = services.iterator(); iterator.hasNext();) {
            servicesString.append(iterator.next().getDisplayName());
            if (iterator.hasNext())
                servicesString.append(", "); //$NON-NLS-1$
        }

        return MessageFormat.format(Messages.getString("ConnectionTypePage.SupportedServicesLabel"), //$NON-NLS-1$
                new Object[] { servicesString.toString() });
    }

    private Collection<IConnectionType> getValidConnectionTypes() {
        // valid connection types have at least one compatible service, or are the actual connection type of the connection being edited
        IConnection connectionToEdit = settingsWizard.getConnectionToEdit();
        IConnectionType connectionTypeToEdit = connectionToEdit != null ? connectionToEdit.getConnectionType()
                : null;
        Collection<IConnectionType> allConnectionTypes = Registry.instance().getConnectionTypes();
        Collection<IConnectionType> connectionTypes = new ArrayList<IConnectionType>();
        for (IConnectionType connectionType : allConnectionTypes) {
            if (!Registry.instance().getCompatibleServices(connectionType).isEmpty()
                    || connectionType.equals(connectionTypeToEdit))
                connectionTypes.add(connectionType);
        }
        return connectionTypes;
    }

    private boolean isNameUnique(String name) {
        boolean inUse = Registry.instance().connectionNameInUse(name);
        IConnection connectionToEdit = settingsWizard.getConnectionToEdit();
        if (connectionToEdit != null && inUse)
            inUse = !name.equals(connectionToEdit.getDisplayName());

        return !inUse;
    }

    private boolean validatePage() {
        setErrorMessage(null);
        String name = getName();
        boolean isValid = isNameUnique(name);
        if (!isValid) {
            setErrorMessage(MessageFormat.format(Messages.getString("ConnectionTypePage.ConnectionNameInUseError"), //$NON-NLS-1$
                    new Object[] { name }));
        }

        return isValid;
    }

}