/*******************************************************************************
 * Copyright (c) 2004, 2016 Tasktop Technologies and others.
 * 
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * https://www.eclipse.org/legal/epl-2.0
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Tasktop Technologies - initial API and implementation
 *     Frank Becker - improvements
 *     Helen Bershadskaya - improvements for bug 242445
 *     Atlassian - fixes for bug 316113
 *******************************************************************************/

package org.eclipse.mylyn.tasks.ui.wizards;

import java.lang.reflect.InvocationTargetException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.URI;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
import org.eclipse.mylyn.commons.net.AuthenticationType;
import org.eclipse.mylyn.commons.ui.CommonImages;
import org.eclipse.mylyn.commons.ui.dialogs.IValidatable;
import org.eclipse.mylyn.commons.ui.dialogs.ValidatableWizardDialog;
import org.eclipse.mylyn.commons.workbench.browser.BrowserUtil;
import org.eclipse.mylyn.commons.workbench.forms.SectionComposite;
import org.eclipse.mylyn.internal.commons.repositories.ui.RepositoryUiUtil;
import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants;
import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
import org.eclipse.mylyn.internal.tasks.core.RepositoryTemplateManager;
import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager;
import org.eclipse.mylyn.internal.tasks.ui.IBrandManager;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.wizards.Messages;
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
import org.eclipse.mylyn.tasks.core.RepositoryInfo;
import org.eclipse.mylyn.tasks.core.RepositoryTemplate;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi;
import org.eclipse.mylyn.tasks.ui.TasksUi;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
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.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.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.statushandlers.StatusManager;

/**
 * Extend to provide custom repository settings. This page is typically invoked by the user requesting properties via
 * the Task Repositories view.
 *
 * @author Mik Kersten
 * @author Rob Elves
 * @author Steffen Pingel
 * @author Frank Becker
 * @author David Green
 * @author Helen Bershadskaya
 * @author Benjamin Muskalla
 * @since 2.0
 */
public abstract class AbstractRepositorySettingsPage extends AbstractTaskRepositoryPage
		implements ITaskRepositoryPage, IAdaptable {

	protected static final String PREFS_PAGE_ID_NET_PROXY = "org.eclipse.ui.net.NetPreferences"; //$NON-NLS-1$

	protected static final String LABEL_REPOSITORY_LABEL = Messages.AbstractRepositorySettingsPage_Label_;

	protected static final String LABEL_SERVER = Messages.AbstractRepositorySettingsPage_Server_;

	protected static final String LABEL_USER = Messages.AbstractRepositorySettingsPage_User_ID_;

	protected static final String LABEL_PASSWORD = Messages.AbstractRepositorySettingsPage_Password_;

	protected static final String URL_PREFIX_HTTPS = "https://"; //$NON-NLS-1$

	protected static final String URL_PREFIX_HTTP = "http://"; //$NON-NLS-1$

	protected static final String INVALID_REPOSITORY_URL = Messages.AbstractRepositorySettingsPage_Repository_url_is_invalid;

	protected static final String INVALID_LOGIN = Messages.AbstractRepositorySettingsPage_Unable_to_authenticate_with_repository;

	protected AbstractRepositoryConnector connector;

	private final AbstractRepositoryConnectorUi connectorUi;

	protected StringFieldEditor repositoryLabelEditor;

	protected Combo serverUrlCombo;

	private boolean serverUrlReadOnly = false;

	private String serverVersion = TaskRepository.NO_VERSION_SPECIFIED;

	protected StringFieldEditor repositoryUserNameEditor;

	protected StringFieldEditor repositoryPasswordEditor;

	protected StringFieldEditor httpAuthUserNameEditor;

	protected StringFieldEditor httpAuthPasswordEditor;

	private StringFieldEditor certAuthFileNameEditor;

	private Button certBrowseButton;

	private StringFieldEditor certAuthPasswordEditor;

	protected StringFieldEditor proxyHostnameEditor;

	protected StringFieldEditor proxyPortEditor;

	protected StringFieldEditor proxyUserNameEditor;

	protected StringFieldEditor proxyPasswordEditor;

	// FIXME shadows declaration in super
	protected TaskRepository repository;

	private Combo otherEncodingCombo;

	private Button defaultEncoding;

	// private Combo timeZonesCombo;

	protected Button anonymousButton;

	private String oldUsername;

	private String oldPassword;

	private String oldHttpAuthUserId;

	private String oldHttpAuthPassword;

	private String oldCertAuthFileName;

	private String oldCertAuthPassword;

	private boolean needsAnonymousLogin;

	private boolean needsTimeZone;

	private boolean needsEncoding;

	private boolean needsCertAuth;

	private boolean needsHttpAuth;

	private boolean needsValidation;

	private boolean needsValidateOnFinish;

	private boolean needsAdvanced;

	private boolean needsRepositoryCredentials;

	protected Composite compositeContainer;

	private Composite advancedComp;

	private Composite certAuthComp;

	private Composite httpAuthComp;

	private Composite proxyAuthComp;

	private Set<String> repositoryUrls;

	private String originalUrl;

	private Button otherEncoding;

	private Button certAuthButton;

	private Button httpAuthButton;

	private boolean needsProxy;

	/**
	 * @since 3.11
	 */
	protected Button systemProxyButton;

	/**
	 * @since 3.11
	 */
	protected Hyperlink changeProxySettingsLink;

	private String oldProxyUsername = ""; //$NON-NLS-1$

	private String oldProxyPassword = ""; //$NON-NLS-1$

	// private Button proxyAuthButton;

	private String oldProxyHostname = ""; //$NON-NLS-1$

	private String oldProxyPort = ""; //$NON-NLS-1$

	private Button proxyAuthButton;

	private Hyperlink createAccountHyperlink;

	private Hyperlink manageAccountHyperlink;

	/**
	 * @since 3.1
	 */
	protected Button savePasswordButton;

	private Button saveHttpPasswordButton;

	private Button saveCertPasswordButton;

	private Button saveProxyPasswordButton;

	private Button disconnectedButton;

	private Button validateOnFinishButton;

	private boolean isValid;

	/**
	 * @since 3.9
	 */
	protected SectionComposite innerComposite;

	private TaskRepository validatedTaskRepository;

	private final Map<AuthenticationType, AuthenticationCredentials> validatedAuthenticationCredentials = new HashMap<AuthenticationType, AuthenticationCredentials>();

	private String brand;

	/**
	 * @since 3.10
	 */
	public AbstractRepositorySettingsPage(String title, String description, TaskRepository taskRepository,
			AbstractRepositoryConnector connector) {
		this(title, description, taskRepository, connector, null);
	}

	/**
	 * @since 3.14
	 */
	public AbstractRepositorySettingsPage(String title, String description, TaskRepository taskRepository,
			AbstractRepositoryConnector connector, AbstractRepositoryConnectorUi connectorUi) {
		super(title, description, taskRepository);
		repository = taskRepository;
		if (connector == null) {
			connector = TasksUi.getRepositoryManager().getRepositoryConnector(getConnectorKind());
		}
		this.connector = connector;
		if (connectorUi == null) {
			connectorUi = TasksUi.getRepositoryConnectorUi(getConnectorKind());
		}
		this.connectorUi = connectorUi;
		if (repository != null && !repository.getConnectorKind().equals(getConnectorKind())) {
			throw new IllegalArgumentException(
					"connectorKind of repository does not match connectorKind of page, expected '" + getConnectorKind() //$NON-NLS-1$
							+ "', got '" + repository.getConnectorKind() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		updateBrandFromRepository();
		setNeedsRepositoryCredentials(true);
		setNeedsAnonymousLogin(false);
		setNeedsEncoding(true);
		setNeedsTimeZone(true);
		setNeedsProxy(true);
		setNeedsValidation(true);
		setNeedsAdvanced(true);
		setNeedsValidateOnFinish(false);
	}

	/**
	 * @since 3.0
	 */
	public AbstractRepositorySettingsPage(String title, String description, TaskRepository taskRepository) {
		this(title, description, taskRepository, null);
	}

	/**
	 * @since 3.0
	 */
	@Override
	public abstract String getConnectorKind();

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

//	/**
//	 * @since 2.0
//	 */
//	@Override
//	protected Control createContents(Composite parent) {
//		compositeContainer = new Composite(parent, SWT.NONE);
//		GridLayout layout = new GridLayout(3, false);
//		compositeContainer.setLayout(layout);
//
//		createSettingControls(parent);
//	}

	@Override
	public void createControl(Composite parent) {
		initializeDialogUnits(parent);
		toolkit = new FormToolkit(TasksUiPlugin.getDefault().getFormColors(parent.getDisplay()));

		innerComposite = new SectionComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL);
		createSettingControls(innerComposite.getContent());
		createValidationControls(innerComposite.getContent());
		if (needsValidateOnFinish()) {
			validateOnFinishButton = new Button(innerComposite.getContent(), SWT.CHECK);
			validateOnFinishButton.setText(Messages.AbstractRepositorySettingsPage_Validate_on_Finish);
			validateOnFinishButton.setSelection(true);
		}
		Point p = innerComposite.getContent().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
		innerComposite.setMinSize(p);
		innerComposite.getShell().layout();
		if (needsRepositoryCredentials()) {
			swapUserNameWithAnonymousInTabList();
		}
		Dialog.applyDialogFont(innerComposite);
		setControl(innerComposite);
	}

	private void swapUserNameWithAnonymousInTabList() {
		if (compositeContainer != null && anonymousButton != null && repositoryUserNameEditor != null) {
			List<Control> tabList = Arrays.asList(compositeContainer.getTabList());
			if (tabList.contains(repositoryUserNameEditor.getTextControl(compositeContainer))
					&& tabList.contains(anonymousButton)) {
				int userNameIndex = tabList.indexOf(repositoryUserNameEditor.getTextControl(compositeContainer));
				int anonymousIndex = tabList.indexOf(anonymousButton);
				Collections.swap(tabList, userNameIndex, anonymousIndex);
				compositeContainer.setTabList(tabList.toArray(new Control[tabList.size()]));
			}
		}
	}

	/**
	 * @since 3.5
	 */
	protected void createValidationControls(Composite parent) {
		if (!needsValidation() || getContainer() instanceof ValidatableWizardDialog
				|| getContainer() instanceof TaskRepositoryWizardDialog) {
			return;
		}

		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout(1, false);
		layout.marginHeight = 10;
		layout.marginWidth = 0;
		layout.horizontalSpacing = 10;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 3, 1));

		// show validation control on page since it's not provided by container
		Button validateButton = new Button(composite, SWT.PUSH);
		validateButton.setImage(CommonImages.getImage(CommonImages.VALIDATE));
		validateButton.setText(Messages.AbstractRepositorySettingsPage_Validate_Settings_Button_Label);
		validateButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				validateSettings();
			}
		});
	}

	/**
	 * @since 2.0
	 */
	@Override
	protected void createSettingControls(Composite parent) {
		compositeContainer = parent;

		initializeOldValues();

		Label serverLabel = new Label(compositeContainer, SWT.NONE);
		serverLabel.setText(LABEL_SERVER);
		serverUrlCombo = new Combo(compositeContainer, SWT.DROP_DOWN);
		if (serverUrlReadOnly) {
			serverUrlCombo.setEnabled(false);
		} else {
			serverUrlCombo.addModifyListener(new ModifyListener() {
				public void modifyText(ModifyEvent e) {
					if (getWizard() != null) {
						getWizard().getContainer().updateButtons();
					}
				}
			});
			serverUrlCombo.addFocusListener(new FocusAdapter() {

				@Override
				public void focusLost(FocusEvent e) {
					updateHyperlinks();
				}
			});
			serverUrlCombo.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					if (getWizard() != null) {
						getWizard().getContainer().updateButtons();
					}
				}
			});
		}

		GridDataFactory.fillDefaults()
				.hint(300, SWT.DEFAULT)
				.grab(true, false)
				.span(2, SWT.DEFAULT)
				.applyTo(serverUrlCombo);

		repositoryLabelEditor = new StringFieldEditor("", LABEL_REPOSITORY_LABEL, StringFieldEditor.UNLIMITED, //$NON-NLS-1$
				compositeContainer) {

			@Override
			protected boolean doCheckState() {
				return true;
				// return isValidUrl(getStringValue());
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				return 2;
			}
		};
		disconnectedButton = new Button(compositeContainer, SWT.CHECK);
		disconnectedButton.setText(Messages.AbstractRepositorySettingsPage_Disconnected);
		disconnectedButton.setSelection(repository != null ? repository.isOffline() : false);
		disconnectedButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				super.widgetSelected(e);
				isPageComplete();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}
		});

		if (needsRepositoryCredentials()) {
			createRepositoryCredentialsSection();
		}

		if (needsAdvanced() || needsEncoding()) {
			createAdvancedSection();
		}

		if (needsCertAuth()) {
			createCertAuthSection();
		}

		if (needsHttpAuth()) {
			createHttpAuthSection();
		}

		if (needsProxy()) {
			createProxySection();
		}

		createContributionControls(innerComposite);

		Composite managementComposite = new Composite(compositeContainer, SWT.NULL);
		GridLayout managementLayout = new GridLayout(4, false);
		managementLayout.marginHeight = 0;
		managementLayout.marginWidth = 0;
		managementLayout.horizontalSpacing = 10;
		managementComposite.setLayout(managementLayout);
		managementComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 2, 1));

		createAccountHyperlink = toolkit.createHyperlink(managementComposite,
				Messages.AbstractRepositorySettingsPage_Create_new_account, SWT.NONE);
		createAccountHyperlink.setBackground(managementComposite.getBackground());
		createAccountHyperlink.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
//				TaskRepository repository = getRepository();
				TaskRepository repository = createTaskRepository();
//				if (repository == null && getServerUrl() != null && getServerUrl().length() > 0) {
//					repository = createTaskRepository();
//				}
				if (repository != null) {
					String accountCreationUrl = connectorUi.getAccountCreationUrl(repository);
					if (accountCreationUrl != null) {
						BrowserUtil.openUrl(accountCreationUrl, IWorkbenchBrowserSupport.AS_EXTERNAL);
					}
				}
			}
		});

		manageAccountHyperlink = toolkit.createHyperlink(managementComposite,
				Messages.AbstractRepositorySettingsPage_Change_account_settings, SWT.NONE);
		manageAccountHyperlink.setBackground(managementComposite.getBackground());
		manageAccountHyperlink.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				TaskRepository repository = getRepository();
				if (repository == null && getRepositoryUrl() != null && getRepositoryUrl().length() > 0) {
					repository = createTaskRepository();
				}
				if (repository != null) {
					String accountManagementUrl = connectorUi.getAccountManagementUrl(repository);
					if (accountManagementUrl != null) {
						BrowserUtil.openUrl(accountManagementUrl, IWorkbenchBrowserSupport.AS_EXTERNAL);
					}
				}
			}
		});

		if (repositoryPasswordEditor != null) {
			// bug 131656: must set echo char after setting value on Mac
			((RepositoryStringFieldEditor) repositoryPasswordEditor).getTextControl().setEchoChar('*');
		}

		if (needsRepositoryCredentials()) {
			if (needsAnonymousLogin()) {
				// do this after username and password widgets have been intialized
				if (repository != null) {
					setAnonymous(isAnonymousAccess());
				}
			}
		}

		updateHyperlinks();
		if (repository != null) {
			updateLabel();
			updateUrl();
			saveToValidatedProperties(createTaskRepository());
		}
		GridLayout layout = new GridLayout(3, false);
		compositeContainer.setLayout(layout);
	}

	private void createRepositoryCredentialsSection() {
		repositoryUserNameEditor = new StringFieldEditor("", LABEL_USER, StringFieldEditor.UNLIMITED, //$NON-NLS-1$
				compositeContainer) {

			@Override
			protected boolean doCheckState() {
				return true;
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				isPageComplete();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				// always 2 columns -- if no anonymous checkbox, just leave 3rd column empty
				return 2;
			}
		};
		if (needsAnonymousLogin()) {
			// need to increase column number here, because above string editor will use them if declared beforehand
			//((GridLayout) (compositeContainer.getLayout())).numColumns++;
			anonymousButton = new Button(compositeContainer, SWT.CHECK);

			anonymousButton.setText(Messages.AbstractRepositorySettingsPage_Anonymous_Access);
			anonymousButton.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					setAnonymous(anonymousButton.getSelection());
					isPageComplete();
				}
			});
		} else {
			Label dummyLabel = new Label(compositeContainer, SWT.NONE); // dummy control to fill 3rd column when no anonymous login
			GridDataFactory.fillDefaults().applyTo(dummyLabel); // not really necessary, but to be on the safe side
		}

		repositoryPasswordEditor = new RepositoryStringFieldEditor("", LABEL_PASSWORD, StringFieldEditor.UNLIMITED, //$NON-NLS-1$
				compositeContainer) {

			@Override
			protected boolean doCheckState() {
				return true;
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				isPageComplete();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				return 2;
			}
		};

		savePasswordButton = new Button(compositeContainer, SWT.CHECK);
		savePasswordButton.setText(Messages.AbstractRepositorySettingsPage_Save_Password);
		savePasswordButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				super.widgetSelected(e);
				isPageComplete();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}
		});

		if (repository != null) {
			try {
				AuthenticationCredentials credentials = repository.getCredentials(AuthenticationType.REPOSITORY);
				if (credentials != null) {
					repositoryUserNameEditor.setStringValue(credentials.getUserName());
					repositoryPasswordEditor.setStringValue(credentials.getPassword());
				} else {
					repositoryUserNameEditor.setStringValue(""); //$NON-NLS-1$
					repositoryPasswordEditor.setStringValue(""); //$NON-NLS-1$
				}
			} catch (Throwable t) {
				StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not set field value", t)); //$NON-NLS-1$
			}
		}

		if (needsAnonymousLogin()) {
			if (repository != null) {
				setAnonymous(repository.getCredentials(AuthenticationType.REPOSITORY) == null);
			} else {
				setAnonymous(true);
			}
		}
		if (repository != null) {
			savePasswordButton.setSelection(repository.getSavePassword(AuthenticationType.REPOSITORY));
		} else {
			savePasswordButton.setSelection(false);
		}
		RepositoryUiUtil.testCredentialsStore(getRepositoryUrl(), this);
	}

	private void updateLabel() {
		String repositoryLabel = repository.getProperty(IRepositoryConstants.PROPERTY_LABEL);
		if (repositoryLabel != null && repositoryLabel.length() > 0) {
			repositoryLabelEditor.setStringValue(repositoryLabel);
		}
	}

	private void updateUrl() {
		setUrl(repository.getRepositoryUrl());
	}

	private void createAdvancedSection() {
		ExpandableComposite section = createSection(innerComposite,
				Messages.AbstractRepositorySettingsPage_Additional_Settings);

		advancedComp = toolkit.createComposite(section, SWT.NONE);
		GridLayout gridLayout2 = new GridLayout();
		gridLayout2.numColumns = 2;
		gridLayout2.verticalSpacing = 5;
		gridLayout2.marginWidth = 0;
		advancedComp.setLayout(gridLayout2);
		advancedComp.setBackground(compositeContainer.getBackground());
		section.setClient(advancedComp);

		createAdditionalControls(advancedComp);

		if (needsEncoding()) {
			Label encodingLabel = new Label(advancedComp, SWT.HORIZONTAL);
			encodingLabel.setText(Messages.AbstractRepositorySettingsPage_Character_encoding);
			GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.TOP).applyTo(encodingLabel);

			Composite encodingContainer = new Composite(advancedComp, SWT.NONE);
			GridLayout gridLayout = new GridLayout(2, false);
			gridLayout.marginWidth = 0;
			gridLayout.marginHeight = 0;
			encodingContainer.setLayout(gridLayout);

			defaultEncoding = new Button(encodingContainer, SWT.RADIO);
			defaultEncoding.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
			defaultEncoding.setText(Messages.AbstractRepositorySettingsPage_Default__
					+ TaskRepository.DEFAULT_CHARACTER_ENCODING + ")"); //$NON-NLS-1$
			defaultEncoding.setSelection(true);

			otherEncoding = new Button(encodingContainer, SWT.RADIO);
			otherEncoding.setText(Messages.AbstractRepositorySettingsPage_Other);
			otherEncodingCombo = new Combo(encodingContainer, SWT.READ_ONLY);
			try {
				for (String encoding : Charset.availableCharsets().keySet()) {
					if (!encoding.equals(TaskRepository.DEFAULT_CHARACTER_ENCODING)) {
						otherEncodingCombo.add(encoding);
					}
				}
			} catch (LinkageError e) {
				StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
						Messages.AbstractRepositorySettingsPage_Problems_encountered_determining_available_charsets,
						e));
				// bug 237972: 3rd party encodings can cause availableCharsets() to fail
				otherEncoding.setEnabled(false);
				otherEncodingCombo.setEnabled(false);
			}

			setDefaultEncoding();

			otherEncoding.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					if (otherEncoding.getSelection()) {
						defaultEncoding.setSelection(false);
						otherEncodingCombo.setEnabled(true);
					} else {
						defaultEncoding.setSelection(true);
						otherEncodingCombo.setEnabled(false);
					}
				}
			});

			if (repository != null) {
				try {
					String repositoryEncoding = repository.getCharacterEncoding();
					if (repositoryEncoding != null) {// &&
						// !repositoryEncoding.equals(defaultEncoding))
						// {
						if (otherEncodingCombo.getItemCount() > 0
								&& otherEncodingCombo.indexOf(repositoryEncoding) > -1) {
							otherEncodingCombo.setEnabled(true);
							otherEncoding.setSelection(true);
							defaultEncoding.setSelection(false);
							otherEncodingCombo.select(otherEncodingCombo.indexOf(repositoryEncoding));
						} else {
							setDefaultEncoding();
						}
					}
				} catch (Throwable t) {
					StatusHandler
							.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not set field value", t)); //$NON-NLS-1$
				}
			}
		}
	}

	private void createCertAuthSection() {
		ExpandableComposite section = createSection(innerComposite,
				Messages.AbstractRepositorySettingsPage_certificate_settings);

		certAuthComp = toolkit.createComposite(section, SWT.NONE);
		certAuthComp.setBackground(compositeContainer.getBackground());
		section.setClient(certAuthComp);

		certAuthButton = new Button(certAuthComp, SWT.CHECK);
		GridDataFactory.fillDefaults()
				.indent(0, 5)
				.align(SWT.LEFT, SWT.TOP)
				.span(3, SWT.DEFAULT)
				.applyTo(certAuthButton);

		certAuthButton.setText(Messages.AbstractRepositorySettingsPage_Enable_certificate_authentification);

		certAuthButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				setCertAuth(certAuthButton.getSelection());
			}

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

		certAuthFileNameEditor = new StringFieldEditor("", Messages.AbstractRepositorySettingsPage_CertificateFile_, //$NON-NLS-1$
				StringFieldEditor.UNLIMITED, certAuthComp) {

			@Override
			protected boolean doCheckState() {
				return true;
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				return 2;
			}
		};

		certBrowseButton = new Button(certAuthComp, SWT.PUSH);
		certBrowseButton.setText(Messages.AbstractRepositorySettingsPage_ChooseCertificateFile_);
		certBrowseButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
				fileDialog.setFilterPath(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$
				String returnFile = fileDialog.open();
				if (returnFile != null) {
					certAuthFileNameEditor.setStringValue(returnFile);
				}
			}
		});

		certAuthPasswordEditor = new RepositoryStringFieldEditor("", //$NON-NLS-1$
				Messages.AbstractRepositorySettingsPage_CertificatePassword_, StringFieldEditor.UNLIMITED,
				certAuthComp) {
			@Override
			public int getNumberOfControls() {
				return 2;
			}
		};
		((RepositoryStringFieldEditor) certAuthPasswordEditor).getTextControl().setEchoChar('*');

		saveCertPasswordButton = new Button(certAuthComp, SWT.CHECK);
		saveCertPasswordButton.setText(Messages.AbstractRepositorySettingsPage_Save_Password);

		certAuthFileNameEditor.setEnabled(certAuthButton.getSelection(), certAuthComp);
		certBrowseButton.setEnabled(certAuthButton.getSelection());
		certAuthPasswordEditor.setEnabled(certAuthButton.getSelection(), certAuthComp);
		saveCertPasswordButton.setEnabled(certAuthButton.getSelection());

		if (repository != null) {
			saveCertPasswordButton.setSelection(repository.getSavePassword(AuthenticationType.CERTIFICATE));
		} else {
			saveCertPasswordButton.setSelection(false);
		}
		setCertAuth(oldCertAuthPassword != null || oldCertAuthFileName != null);
		section.setExpanded(certAuthButton.getSelection());

		GridLayout gridLayout2 = new GridLayout();
		gridLayout2.numColumns = 3;
		gridLayout2.marginWidth = 0;
		certAuthComp.setLayout(gridLayout2);
	}

	private void createHttpAuthSection() {
		ExpandableComposite section = createSection(innerComposite,
				Messages.AbstractRepositorySettingsPage_Http_Authentication);

		httpAuthComp = toolkit.createComposite(section, SWT.NONE);
		httpAuthComp.setBackground(compositeContainer.getBackground());
		section.setClient(httpAuthComp);

		httpAuthButton = new Button(httpAuthComp, SWT.CHECK);
		GridDataFactory.fillDefaults()
				.indent(0, 5)
				.align(SWT.LEFT, SWT.TOP)
				.span(3, SWT.DEFAULT)
				.applyTo(httpAuthButton);

		httpAuthButton.setText(Messages.AbstractRepositorySettingsPage_Enable_http_authentication);

		httpAuthButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				setHttpAuth(httpAuthButton.getSelection());
			}

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

		httpAuthUserNameEditor = new StringFieldEditor("", Messages.AbstractRepositorySettingsPage_User_ID_, //$NON-NLS-1$
				StringFieldEditor.UNLIMITED, httpAuthComp) {

			@Override
			protected boolean doCheckState() {
				return true;
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				return 3;
			}
		};

		httpAuthPasswordEditor = new RepositoryStringFieldEditor("", Messages.AbstractRepositorySettingsPage_Password_, //$NON-NLS-1$
				StringFieldEditor.UNLIMITED, httpAuthComp) {
			@Override
			public int getNumberOfControls() {
				return 2;
			}
		};
		((RepositoryStringFieldEditor) httpAuthPasswordEditor).getTextControl().setEchoChar('*');

		saveHttpPasswordButton = new Button(httpAuthComp, SWT.CHECK);
		saveHttpPasswordButton.setText(Messages.AbstractRepositorySettingsPage_Save_Password);

		httpAuthUserNameEditor.setEnabled(httpAuthButton.getSelection(), httpAuthComp);
		httpAuthPasswordEditor.setEnabled(httpAuthButton.getSelection(), httpAuthComp);
		saveHttpPasswordButton.setEnabled(httpAuthButton.getSelection());

		if (repository != null) {
			saveHttpPasswordButton.setSelection(repository.getSavePassword(AuthenticationType.HTTP));
		} else {
			saveHttpPasswordButton.setSelection(false);
		}
		setHttpAuth(oldHttpAuthPassword != null || oldHttpAuthUserId != null);
		section.setExpanded(httpAuthButton.getSelection());

		GridLayout gridLayout2 = new GridLayout();
		gridLayout2.numColumns = 3;
		gridLayout2.marginWidth = 0;
		httpAuthComp.setLayout(gridLayout2);
	}

	private void initializeOldValues() {
		if (repository != null) {
			originalUrl = repository.getRepositoryUrl();
			AuthenticationCredentials oldCredentials = repository.getCredentials(AuthenticationType.REPOSITORY);
			if (oldCredentials != null) {
				oldUsername = oldCredentials.getUserName();
				oldPassword = oldCredentials.getPassword();
			} else {
				oldUsername = ""; //$NON-NLS-1$
				oldPassword = ""; //$NON-NLS-1$
			}

			AuthenticationCredentials oldCertCredentials = repository.getCredentials(AuthenticationType.CERTIFICATE);
			if (oldCertCredentials != null) {
				oldCertAuthFileName = oldCertCredentials.getUserName();
				oldCertAuthPassword = oldCertCredentials.getPassword();
			} else {
				oldCertAuthPassword = null;
				oldCertAuthFileName = null;
			}

			AuthenticationCredentials oldHttpCredentials = repository.getCredentials(AuthenticationType.HTTP);
			if (oldHttpCredentials != null) {
				oldHttpAuthUserId = oldHttpCredentials.getUserName();
				oldHttpAuthPassword = oldHttpCredentials.getPassword();
			} else {
				oldHttpAuthPassword = null;
				oldHttpAuthUserId = null;
			}

			oldProxyHostname = repository.getProperty(TaskRepository.PROXY_HOSTNAME);
			oldProxyPort = repository.getProperty(TaskRepository.PROXY_PORT);
			if (oldProxyHostname == null) {
				oldProxyHostname = ""; //$NON-NLS-1$
			}
			if (oldProxyPort == null) {
				oldProxyPort = ""; //$NON-NLS-1$
			}

			AuthenticationCredentials oldProxyCredentials = repository.getCredentials(AuthenticationType.PROXY);
			if (oldProxyCredentials != null) {
				oldProxyUsername = oldProxyCredentials.getUserName();
				oldProxyPassword = oldProxyCredentials.getPassword();
			} else {
				oldProxyUsername = null;
				oldProxyPassword = null;
			}

		} else {
			oldUsername = ""; //$NON-NLS-1$
			oldPassword = ""; //$NON-NLS-1$
			oldHttpAuthPassword = null;
			oldHttpAuthUserId = null;
			oldCertAuthFileName = null;
			oldCertAuthPassword = null;
		}
	}

	private void createProxySection() {
		ExpandableComposite section = createSection(innerComposite,
				Messages.AbstractRepositorySettingsPage_Proxy_Server_Configuration);

		proxyAuthComp = toolkit.createComposite(section, SWT.NONE);
		GridLayout gridLayout2 = new GridLayout();
		gridLayout2.verticalSpacing = 0;
		gridLayout2.numColumns = 3;
		proxyAuthComp.setLayout(gridLayout2);
		proxyAuthComp.setBackground(compositeContainer.getBackground());
		section.setClient(proxyAuthComp);

		Composite systemSettingsComposite = new Composite(proxyAuthComp, SWT.NULL);
		GridLayout gridLayout3 = new GridLayout();
		gridLayout3.verticalSpacing = 0;
		gridLayout3.numColumns = 2;
		gridLayout3.marginWidth = 0;
		systemSettingsComposite.setLayout(gridLayout3);

		systemProxyButton = new Button(systemSettingsComposite, SWT.CHECK);
		GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.TOP).span(3, SWT.DEFAULT).applyTo(systemSettingsComposite);

		systemProxyButton.setText(Messages.AbstractRepositorySettingsPage_Use_global_Network_Connections_preferences);

		systemProxyButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				setUseDefaultProxy(systemProxyButton.getSelection());
			}

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

		changeProxySettingsLink = toolkit.createHyperlink(systemSettingsComposite,
				Messages.AbstractRepositorySettingsPage_Change_Settings, SWT.NULL);
		changeProxySettingsLink.setBackground(compositeContainer.getBackground());
		changeProxySettingsLink.addHyperlinkListener(new IHyperlinkListener() {

			public void linkActivated(HyperlinkEvent e) {
				PreferenceDialog dlg = PreferencesUtil.createPreferenceDialogOn(getShell(), PREFS_PAGE_ID_NET_PROXY,
						new String[] { PREFS_PAGE_ID_NET_PROXY }, null);
				dlg.open();
			}

			public void linkEntered(HyperlinkEvent e) {
				// ignore
			}

			public void linkExited(HyperlinkEvent e) {
				// ignore
			}
		});

		proxyHostnameEditor = new StringFieldEditor("", Messages.AbstractRepositorySettingsPage_Proxy_host_address_, //$NON-NLS-1$
				StringFieldEditor.UNLIMITED, proxyAuthComp) {

			@Override
			protected boolean doCheckState() {
				return true;
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				return 3;
			}
		};
		proxyHostnameEditor.setStringValue(oldProxyHostname);

		proxyPortEditor = new RepositoryStringFieldEditor("", Messages.AbstractRepositorySettingsPage_Proxy_host_port_, //$NON-NLS-1$
				StringFieldEditor.UNLIMITED, proxyAuthComp) {

			@Override
			protected boolean doCheckState() {
				return true;
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				return 3;
			}
		};

		proxyPortEditor.setStringValue(oldProxyPort);

		proxyHostnameEditor.setEnabled(systemProxyButton.getSelection(), proxyAuthComp);
		proxyPortEditor.setEnabled(systemProxyButton.getSelection(), proxyAuthComp);

		// ************* PROXY AUTHENTICATION **************

		proxyAuthButton = new Button(proxyAuthComp, SWT.CHECK);
		GridDataFactory.fillDefaults().span(3, SWT.DEFAULT).applyTo(proxyAuthButton);
		proxyAuthButton.setText(Messages.AbstractRepositorySettingsPage_Enable_proxy_authentication);
		proxyAuthButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				setProxyAuth(proxyAuthButton.getSelection());
			}

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

		proxyUserNameEditor = new StringFieldEditor("", Messages.AbstractRepositorySettingsPage_User_ID_, //$NON-NLS-1$
				StringFieldEditor.UNLIMITED, proxyAuthComp) {

			@Override
			protected boolean doCheckState() {
				return true;
			}

			@Override
			protected void valueChanged() {
				super.valueChanged();
				if (getWizard() != null) {
					getWizard().getContainer().updateButtons();
				}
			}

			@Override
			public int getNumberOfControls() {
				return 3;
			}
		};

		proxyPasswordEditor = new RepositoryStringFieldEditor("", Messages.AbstractRepositorySettingsPage_Password_, //$NON-NLS-1$
				StringFieldEditor.UNLIMITED, proxyAuthComp) {
			@Override
			public int getNumberOfControls() {
				return 2;
			}
		};
		((RepositoryStringFieldEditor) proxyPasswordEditor).getTextControl().setEchoChar('*');

		// proxyPasswordEditor.setEnabled(httpAuthButton.getSelection(),
		// advancedComp);
		// ((StringFieldEditor)
		// httpAuthPasswordEditor).setEnabled(httpAuthButton.getSelection(),
		// advancedComp);

		// need to increase column number here, because above string editor will use them if declared beforehand
		((GridLayout) (proxyAuthComp.getLayout())).numColumns++;
		saveProxyPasswordButton = new Button(proxyAuthComp, SWT.CHECK);
		saveProxyPasswordButton.setText(Messages.AbstractRepositorySettingsPage_Save_Password);
		saveProxyPasswordButton.setEnabled(proxyAuthButton.getSelection());

		if (repository != null) {
			saveProxyPasswordButton.setSelection(repository.getSavePassword(AuthenticationType.PROXY));
		} else {
			saveProxyPasswordButton.setSelection(false);
		}

		setProxyAuth(oldProxyUsername != null || oldProxyPassword != null);

		setUseDefaultProxy(repository != null ? repository.isDefaultProxyEnabled() : true);
		section.setExpanded(!systemProxyButton.getSelection());
	}

//	private void addContributionSection() {
//		Composite composite = toolkit.createComposite(compositeContainer);
//		GridDataFactory.fillDefaults().grab(true, false).span(3, SWT.DEFAULT).applyTo(composite);
//
//		GridLayout layout = new GridLayout(1, false);
//		layout.marginWidth = 0;
//		layout.marginTop = -5;
//		composite.setLayout(layout);
//
//		composite.setBackground(compositeContainer.getBackground());
//
//		createContributionControls(composite);
//	}

	protected void setEncoding(String encoding) {
		if (encoding.equals(TaskRepository.DEFAULT_CHARACTER_ENCODING)) {
			setDefaultEncoding();
		} else {
			if (otherEncodingCombo.indexOf(encoding) != -1) {
				defaultEncoding.setSelection(false);
				otherEncodingCombo.setEnabled(true);
				otherEncoding.setSelection(true);
				otherEncodingCombo.select(otherEncodingCombo.indexOf(encoding));
			} else {
				setDefaultEncoding();
			}
		}
	}

	private void setDefaultEncoding() {
		defaultEncoding.setSelection(true);
		otherEncoding.setSelection(false);
		otherEncodingCombo.setEnabled(false);
		if (otherEncodingCombo.getItemCount() > 0) {
			otherEncodingCombo.select(0);
		}
	}

	/**
	 * @since 2.0
	 */
	public void setAnonymous(boolean selected) {
		if (!needsAnonymousLogin) {
			return;
		}

		anonymousButton.setSelection(selected);
		updateCredentialsEditors();

		if (getWizard() != null) {
			getWizard().getContainer().updateButtons();
		}
	}

	private void updateCredentialsEditors() {
		if (repositoryUserNameEditor != null && repositoryPasswordEditor != null) {
			boolean shouldEnable = needsRepositoryCredentials() && !isAnonymousAccess();
			if (shouldEnable) {
				repositoryUserNameEditor.setStringValue(oldUsername);
				repositoryPasswordEditor.setStringValue(oldPassword);
			} else {
				oldUsername = repositoryUserNameEditor.getStringValue();
				oldPassword = (repositoryPasswordEditor).getStringValue();
				repositoryUserNameEditor.setStringValue(""); //$NON-NLS-1$
				repositoryPasswordEditor.setStringValue(""); //$NON-NLS-1$
			}

			repositoryUserNameEditor.setEnabled(shouldEnable, compositeContainer);
			repositoryPasswordEditor.setEnabled(shouldEnable, compositeContainer);
			savePasswordButton.setEnabled(shouldEnable);
		}
	}

	/**
	 * @since 2.0
	 */
	public void setHttpAuth(boolean selected) {
		if (!needsHttpAuth) {
			return;
		}
		httpAuthButton.setSelection(selected);
		if (!selected) {
			oldHttpAuthUserId = httpAuthUserNameEditor.getStringValue();
			oldHttpAuthPassword = httpAuthPasswordEditor.getStringValue();
			httpAuthUserNameEditor.setStringValue(null);
			httpAuthPasswordEditor.setStringValue(null);
		} else {
			httpAuthUserNameEditor.setStringValue(oldHttpAuthUserId);
			httpAuthPasswordEditor.setStringValue(oldHttpAuthPassword);
		}
		httpAuthUserNameEditor.setEnabled(selected, httpAuthComp);
		httpAuthPasswordEditor.setEnabled(selected, httpAuthComp);
		saveHttpPasswordButton.setEnabled(selected);
	}

	/**
	 * @since 3.6
	 */
	public void setCertAuth(boolean selected) {
		if (!needsCertAuth) {
			return;
		}
		certAuthButton.setSelection(selected);
		if (!selected) {
			oldCertAuthFileName = certAuthFileNameEditor.getStringValue();
			oldCertAuthPassword = certAuthPasswordEditor.getStringValue();
			certAuthFileNameEditor.setStringValue(null);
			certAuthPasswordEditor.setStringValue(null);
		} else {
			certAuthFileNameEditor.setStringValue(oldCertAuthFileName);
			certAuthPasswordEditor.setStringValue(oldCertAuthPassword);
		}
		certAuthFileNameEditor.setEnabled(selected, certAuthComp);
		certBrowseButton.setEnabled(selected);
		certAuthPasswordEditor.setEnabled(selected, certAuthComp);
		saveCertPasswordButton.setEnabled(selected);
	}

	/**
	 * @since 2.2
	 */
	public boolean getHttpAuth() {
		return httpAuthButton.getSelection();
	}

	/**
	 * @since 3.6
	 */
	public boolean getCertAuth() {
		return certAuthButton.getSelection();
	}

	/**
	 * @since 2.0
	 */
	public void setUseDefaultProxy(boolean selected) {
		if (!needsProxy) {
			return;
		}

		systemProxyButton.setSelection(selected);

		if (selected) {
			oldProxyHostname = proxyHostnameEditor.getStringValue();
			oldProxyPort = proxyPortEditor.getStringValue();
			// proxyHostnameEditor.setStringValue(null);
			// proxyPortEditor.setStringValue(null);
		} else {
			proxyHostnameEditor.setStringValue(oldProxyHostname);
			proxyPortEditor.setStringValue(oldProxyPort);
		}
		proxyHostnameEditor.setEnabled(!selected, proxyAuthComp);
		proxyPortEditor.setEnabled(!selected, proxyAuthComp);
		proxyAuthButton.setEnabled(!selected);
		setProxyAuth(proxyAuthButton.getSelection());
	}

	/**
	 * @since 2.0
	 */
	public void setProxyAuth(boolean selected) {
		proxyAuthButton.setSelection(selected);
		proxyAuthButton.setEnabled(!systemProxyButton.getSelection());
		if (!selected) {
			oldProxyUsername = proxyUserNameEditor.getStringValue();
			oldProxyPassword = proxyPasswordEditor.getStringValue();
			proxyUserNameEditor.setStringValue(null);
			proxyPasswordEditor.setStringValue(null);
		} else {
			proxyUserNameEditor.setStringValue(oldProxyUsername);
			proxyPasswordEditor.setStringValue(oldProxyPassword);
		}

		proxyUserNameEditor.setEnabled(selected && !systemProxyButton.getSelection(), proxyAuthComp);
		proxyPasswordEditor.setEnabled(selected && !systemProxyButton.getSelection(), proxyAuthComp);
		saveProxyPasswordButton.setEnabled(selected && !systemProxyButton.getSelection());
	}

	/**
	 * @since 2.2
	 */
	public boolean getProxyAuth() {
		return proxyAuthButton.getSelection();
	}

	/**
	 * @since 3.0
	 */
	protected void addRepositoryTemplatesToServerUrlCombo() {
		final RepositoryTemplateManager templateManager = TasksUiPlugin.getRepositoryTemplateManager();
		for (RepositoryTemplate template : templateManager.getTemplates(connector.getConnectorKind())) {
			serverUrlCombo.add(template.label);
		}
		serverUrlCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				String text = serverUrlCombo.getText();
				RepositoryTemplate template = templateManager.getTemplate(connector.getConnectorKind(), text);
				if (template != null) {
					repositoryTemplateSelected(template);
					return;
				}
			}

		});
	}

	/**
	 * @since 3.0
	 */
	protected void repositoryTemplateSelected(RepositoryTemplate template) {
	}

	/**
	 * @since 2.0
	 */
	protected abstract void createAdditionalControls(@NonNull Composite parent);

	/**
	 * @since 2.0
	 */
	protected boolean isValidUrl(String url) {
		if (url.startsWith(URL_PREFIX_HTTPS) || url.startsWith(URL_PREFIX_HTTP)) {
			try {
				new URI(url, true, "UTF-8"); //$NON-NLS-1$
				return true;
			} catch (Exception e) {
				return false;
			}
		}
		return false;
	}

	private void updateHyperlinks() {
		if (getRepositoryUrl() != null && getRepositoryUrl().length() > 0) {
			TaskRepository repository = new TaskRepository(connector.getConnectorKind(), getRepositoryUrl());

			String accountCreationUrl = connectorUi.getAccountCreationUrl(repository);
			createAccountHyperlink.setEnabled(accountCreationUrl != null);
			createAccountHyperlink.setVisible(accountCreationUrl != null);

			String accountManagementUrl = connectorUi.getAccountManagementUrl(repository);
			manageAccountHyperlink.setEnabled(accountManagementUrl != null);
			manageAccountHyperlink.setVisible(accountManagementUrl != null);
		} else {
			createAccountHyperlink.setEnabled(false);
			createAccountHyperlink.setVisible(false);
			manageAccountHyperlink.setEnabled(false);
			manageAccountHyperlink.setVisible(false);
		}
	}

	/**
	 * @since 2.0
	 */
	public String getRepositoryLabel() {
		return repositoryLabelEditor.getStringValue();
	}

	/**
	 * @since 3.0
	 */
	public String getRepositoryUrl() {
		return TaskRepositoryManager.stripSlashes(serverUrlCombo.getText());
	}

	/**
	 * @since 2.0
	 */
	public String getUserName() {
		if (needsRepositoryCredentials()) {
			return repositoryUserNameEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public String getPassword() {
		if (needsRepositoryCredentials()) {
			return repositoryPasswordEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public String getHttpAuthUserId() {
		if (needsHttpAuth()) {
			return httpAuthUserNameEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public String getHttpAuthPassword() {
		if (needsHttpAuth()) {
			return httpAuthPasswordEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 3.6
	 */
	public String getCertAuthFileName() {
		if (needsCertAuth()) {
			return certAuthFileNameEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 3.6
	 */
	public String getCertAuthPassword() {
		if (needsCertAuth()) {
			return certAuthPasswordEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public String getProxyHostname() {
		if (needsProxy()) {
			return proxyHostnameEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public String getProxyPort() {
		if (needsProxy()) {
			return proxyPortEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public Boolean getUseDefaultProxy() {
		if (needsProxy()) {
			return systemProxyButton.getSelection();
		} else {
			return true;
		}
	}

	/**
	 * @since 2.0
	 */
	public String getProxyUserName() {
		if (needsProxy()) {
			return proxyUserNameEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public String getProxyPassword() {
		if (needsProxy()) {
			return proxyPasswordEditor.getStringValue();
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * @since 2.0
	 */
	public void init(IWorkbench workbench) {
		// ignore
	}

	/**
	 * @since 2.0
	 */
	public boolean isAnonymousAccess() {
		if (anonymousButton != null) {
			return anonymousButton.getSelection();
		} else {
			return false;
		}
	}

	/**
	 * Exposes StringFieldEditor.refreshValidState() TODO: is there a better way?
	 */
	private static class RepositoryStringFieldEditor extends StringFieldEditor {
		public RepositoryStringFieldEditor(String name, String labelText, int style, Composite parent) {
			super(name, labelText, style, parent);
		}

		@Override
		public void refreshValidState() {
			try {
				super.refreshValidState();
			} catch (Exception e) {
				StatusHandler.log(
						new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Problem refreshing password field", e)); //$NON-NLS-1$
			}
		}

		@Override
		public Text getTextControl() {
			return super.getTextControl();
		}

	}

	@Override
	public boolean isPageComplete() {
		String errorMessage = null;
		String url = getRepositoryUrl();
		// check for errors
		errorMessage = isUniqueUrl(url);
		if (errorMessage == null) {
			for (TaskRepository repository : TasksUi.getRepositoryManager().getAllRepositories()) {
				if (!repository.equals(getRepository())
						&& getRepositoryLabel().equals(repository.getRepositoryLabel())) {
					errorMessage = Messages.AbstractRepositorySettingsPage_A_repository_with_this_name_already_exists;
					break;
				}
			}
		}
		if (errorMessage == null) {
			// check for messages
			if (!isValidUrl(url)) {
				errorMessage = Messages.AbstractRepositorySettingsPage_Enter_a_valid_server_url;
			}
			if (errorMessage == null && needsRepositoryCredentials()
					&& (!needsAnonymousLogin() || !anonymousButton.getSelection()) && isMissingCredentials()) {
				errorMessage = Messages.AbstractRepositorySettingsPage_Enter_a_user_id_Message0;
			}
			setMessage(errorMessage, repository == null ? IMessageProvider.NONE : IMessageProvider.ERROR);
		} else {
			setMessage(errorMessage, IMessageProvider.ERROR);
		}
		return errorMessage == null && super.isPageComplete();
	}

	/**
	 * Returns true, if credentials are incomplete. Clients may override this method.
	 *
	 * @since 3.4
	 */
	protected boolean isMissingCredentials() {
		return needsRepositoryCredentials() && repositoryUserNameEditor.getStringValue().trim().equals("") //$NON-NLS-1$
				|| (getSavePassword() && repositoryPasswordEditor.getStringValue().trim().equals("")); //$NON-NLS-1$
	}

	/**
	 * @since 2.0
	 */
	protected String isUniqueUrl(String urlString) {
		if (!urlString.equals(originalUrl)) {
			if (repositoryUrls == null) {
				List<TaskRepository> repositories = TasksUi.getRepositoryManager().getAllRepositories();
				repositoryUrls = new HashSet<String>(repositories.size());
				for (TaskRepository repository : repositories) {
					repositoryUrls.add(repository.getRepositoryUrl());
				}
			}

			if (repositoryUrls.contains(urlString)) {
				return Messages.AbstractRepositorySettingsPage_Repository_already_exists;
			}
		}
		return null;
	}

	/**
	 * @since 2.0
	 */
	@Deprecated
	public void setRepository(TaskRepository repository) {
		this.repository = repository;
	}

	/**
	 * @since 2.0
	 */
	public void setVersion(String previousVersion) {
		if (previousVersion == null) {
			serverVersion = TaskRepository.NO_VERSION_SPECIFIED;
		} else {
			serverVersion = previousVersion;
		}
	}

	/**
	 * @since 2.0
	 */
	public String getVersion() {
		return serverVersion;
	}

	/**
	 * @since 2.0
	 */
	public TaskRepository getRepository() {
		return repository;
	}

	/**
	 * @since 2.0
	 */
	public String getCharacterEncoding() {
		if (defaultEncoding == null) {
			return null;
		}

		if (defaultEncoding.getSelection()) {
			return TaskRepository.DEFAULT_CHARACTER_ENCODING;
		} else {
			if (otherEncodingCombo.getSelectionIndex() > -1) {
				return otherEncodingCombo.getItem(otherEncodingCombo.getSelectionIndex());
			} else {
				return TaskRepository.DEFAULT_CHARACTER_ENCODING;
			}
		}
	}

	/**
	 * Creates a {@link TaskRepository} based on the current settings.
	 * <p>
	 * Note: The credentials of the created repository are not persisted in the platform keystore. When overriding,
	 * subclasses must either call super or call {@link TaskRepository#setShouldPersistCredentials(boolean)
	 * setShouldPersistCredentials(false)} before calling {@link #applyTo(TaskRepository)}.
	 *
	 * @since 2.0
	 */
	public TaskRepository createTaskRepository() {
		TaskRepository repository = new TaskRepository(connector.getConnectorKind(), getRepositoryUrl());
		// do not modify the secure storage for a temporary repository
		repository.setShouldPersistCredentials(false);
		applyTo(repository);
		return repository;
	}

	/**
	 * @since 2.2
	 */
	@Override
	public void applyTo(@NonNull TaskRepository repository) {
		String category = repository.getCategory();
		if (category == null || category.length() == 0) {
			connector.applyDefaultCategory(repository);
		}

		repository.setVersion(getVersion());

		if (brand != null) {
			repository.setProperty(ITasksCoreConstants.PROPERTY_BRAND_ID, brand);
		}

		if (needsEncoding()) {
			repository.setCharacterEncoding(getCharacterEncoding());
		}

		if (needsRepositoryCredentials()) {
			if (isAnonymousAccess()) {
				repository.setCredentials(AuthenticationType.REPOSITORY, null, getSavePassword());
			} else {
				AuthenticationCredentials credentials = new AuthenticationCredentials(getUserName(), getPassword());
				repository.setCredentials(AuthenticationType.REPOSITORY, credentials, getSavePassword());
			}
		}
		repository.setRepositoryLabel(getRepositoryLabel());

		if (needsCertAuth()) {
			if (getCertAuth()) {
				AuthenticationCredentials webCredentials = new AuthenticationCredentials(getCertAuthFileName(),
						getCertAuthPassword());
				repository.setCredentials(AuthenticationType.CERTIFICATE, webCredentials, getSaveCertPassword());
			} else {
				repository.setCredentials(AuthenticationType.CERTIFICATE, null, getSaveCertPassword());
			}
		}

		if (needsHttpAuth()) {
			if (getHttpAuth()) {
				AuthenticationCredentials webCredentials = new AuthenticationCredentials(getHttpAuthUserId(),
						getHttpAuthPassword());
				repository.setCredentials(AuthenticationType.HTTP, webCredentials, getSaveHttpPassword());
			} else {
				repository.setCredentials(AuthenticationType.HTTP, null, getSaveHttpPassword());
			}
		}

		if (needsProxy()) {
			repository.setDefaultProxyEnabled(getUseDefaultProxy());
			repository.setProperty(TaskRepository.PROXY_HOSTNAME, getProxyHostname());
			repository.setProperty(TaskRepository.PROXY_PORT, getProxyPort());
			if (getProxyAuth()) {
				AuthenticationCredentials webCredentials = new AuthenticationCredentials(getProxyUserName(),
						getProxyPassword());
				repository.setCredentials(AuthenticationType.PROXY, webCredentials, getSaveProxyPassword());
			} else {
				repository.setCredentials(AuthenticationType.PROXY, null, getSaveProxyPassword());
			}
		}

		if (disconnectedButton != null) {
			repository.setOffline(disconnectedButton.getSelection());
		}

		super.applyTo(repository);
	}

	/**
	 * @since 2.0
	 */
	public AbstractRepositoryConnector getConnector() {
		return connector;
	}

	/**
	 * @since 2.0
	 */
	public boolean needsEncoding() {
		return needsEncoding;
	}

	/**
	 * @since 2.0
	 */
	public boolean needsTimeZone() {
		return needsTimeZone;
	}

	/**
	 * @since 2.0
	 */
	public boolean needsAnonymousLogin() {
		return needsAnonymousLogin;
	}

	/**
	 * @since 3.11
	 */
	public boolean needsRepositoryCredentials() {
		return needsRepositoryCredentials;
	}

	/**
	 * @since 2.0
	 */
	public boolean needsAdvanced() {
		return needsAdvanced;
	}

	/**
	 * @since 2.0
	 */
	public void setNeedsEncoding(boolean needsEncoding) {
		this.needsEncoding = needsEncoding;
	}

	/**
	 * @since 2.0
	 */
	public void setNeedsTimeZone(boolean needsTimeZone) {
		this.needsTimeZone = needsTimeZone;
	}

	/**
	 * @since 2.0
	 */
	public void setNeedsAdvanced(boolean needsAdvanced) {
		this.needsAdvanced = needsAdvanced;
	}

	/**
	 * @since 3.6
	 */
	public boolean needsCertAuth() {
		return this.needsCertAuth;
	}

	/**
	 * @since 3.6
	 */
	public void setNeedsCertAuth(boolean needsCertificate) {
		this.needsCertAuth = needsCertificate;
	}

	/**
	 * @since 2.0
	 */
	public boolean needsHttpAuth() {
		return this.needsHttpAuth;
	}

	/**
	 * @since 2.0
	 */
	public void setNeedsHttpAuth(boolean needsHttpAuth) {
		this.needsHttpAuth = needsHttpAuth;
	}

	/**
	 * @since 2.0
	 */
	public void setNeedsProxy(boolean needsProxy) {
		this.needsProxy = needsProxy;
	}

	/**
	 * @since 2.0
	 */
	public boolean needsProxy() {
		return this.needsProxy;
	}

	/**
	 * @since 2.0
	 */
	public void setNeedsAnonymousLogin(boolean needsAnonymousLogin) {
		this.needsAnonymousLogin = needsAnonymousLogin;
	}

	/**
	 * @since 3.11
	 */
	public void setNeedsRepositoryCredentials(boolean needsRepositoryCredentials) {
		this.needsRepositoryCredentials = needsRepositoryCredentials;
		updateCredentialsEditors();
	}

	public void setNeedsValidation(boolean needsValidation) {
		this.needsValidation = needsValidation;
	}

	/**
	 * Returns whether this page can be validated or not.
	 * <p>
	 * This information is typically used by the wizard to set the enablement of the validation UI affordance.
	 * </p>
	 *
	 * @return <code>true</code> if this page can be validated, and <code>false</code> otherwise
	 * @see #needsValidation()
	 * @see IWizardContainer#updateButtons()
	 * @since 3.4
	 */
	public boolean canValidate() {
		return true;
	}

	/**
	 * @since 2.0
	 */
	public boolean needsValidation() {
		return needsValidation;
	}

	/**
	 * Public for testing.
	 *
	 * @since 2.0
	 */
	public void setUrl(String url) {
		serverUrlCombo.setText(url);
	}

	/**
	 * Sets the URL control is read only, or can be edited.
	 *
	 * @since 3.18
	 */
	public void setUrlReadOnly(boolean value) {
		serverUrlReadOnly = value;
	}

	/**
	 * @return if the URL control is read-only.
	 * @since 3.18
	 */
	public boolean isUrlReadOnly() {
		return serverUrlReadOnly;
	}

	/**
	 * Public for testing.
	 *
	 * @since 2.0
	 */
	public void setUserId(String id) {
		repositoryUserNameEditor.setStringValue(id);
	}

	/**
	 * Public for testing.
	 *
	 * @since 2.0
	 */
	public void setPassword(String pass) {
		repositoryPasswordEditor.setStringValue(pass);
	}

	/**
	 * @since 2.2
	 */
	public Boolean getSavePassword() {
		return savePasswordButton.getSelection();
	}

	/**
	 * @since 2.2
	 */
	public Boolean getSaveProxyPassword() {
		if (needsProxy()) {
			return saveProxyPasswordButton.getSelection();
		} else {
			return false;
		}
	}

	/**
	 * @since 3.6
	 */
	public Boolean getSaveCertPassword() {
		if (needsCertAuth()) {
			return saveCertPasswordButton.getSelection();
		} else {
			return false;
		}
	}

	/**
	 * @since 2.2
	 */
	public Boolean getSaveHttpPassword() {
		if (needsHttpAuth()) {
			return saveHttpPasswordButton.getSelection();
		} else {
			return false;
		}
	}

	/**
	 * Validate settings provided by the {@link #getValidator(TaskRepository) validator}, typically the server settings.
	 *
	 * @since 2.0
	 */
	protected void validateSettings() {
		TaskRepository newTaskRepository = createTaskRepository();
		final Validator validator = getValidator(newTaskRepository);
		if (validator == null) {
			return;
		}

		try {
			getWizard().getContainer().run(true, true, new IRunnableWithProgress() {
				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
					monitor.beginTask(Messages.AbstractRepositorySettingsPage_Validating_server_settings,
							IProgressMonitor.UNKNOWN);
					try {
						validator.run(monitor);
						if (validator.getStatus() == null) {
							validator.setStatus(Status.OK_STATUS);
						}
					} catch (CoreException e) {
						validator.setStatus(e.getStatus());
					} catch (OperationCanceledException e) {
						validator.setStatus(Status.CANCEL_STATUS);
						throw new InterruptedException();
					} catch (Exception e) {
						throw new InvocationTargetException(e);
					} finally {
						monitor.done();
					}
				}
			});
		} catch (InvocationTargetException e) {
			StatusManager.getManager()
					.handle(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN,
							Messages.AbstractRepositorySettingsPage_Internal_error_validating_repository, e),
							StatusManager.SHOW | StatusManager.LOG);
			return;
		} catch (InterruptedException e) {
			// canceled
			return;
		}

		getWizard().getContainer().updateButtons();
		applyValidatorResult(validator);
		if (isValid) {
			saveToValidatedProperties(newTaskRepository);
		}
	}

	/**
	 * @since 3.1
	 */
	@Override
	protected IStatus validate() {
		return null;
	}

	/**
	 * @since 2.0
	 */
	protected void applyValidatorResult(Validator validator) {
		IStatus status = validator.getStatus();
		String message = status.getMessage();
		if (message == null || message.length() == 0) {
			message = null;
		}
		switch (status.getSeverity()) {
		case IStatus.OK:
			if (status == Status.OK_STATUS) {
				if (getUserName().length() > 0) {
					message = Messages.AbstractRepositorySettingsPage_Authentication_credentials_are_valid;
				} else {
					message = Messages.AbstractRepositorySettingsPage_Repository_is_valid;
				}
			}
			setMessage(message, IMessageProvider.INFORMATION);
			break;
		case IStatus.INFO:
			setMessage(message, IMessageProvider.INFORMATION);
			break;
		case IStatus.WARNING:
			setMessage(message, IMessageProvider.WARNING);
			break;
		default:
			setMessage(message, IMessageProvider.ERROR);
			break;
		}
		setErrorMessage(null);

		isValid = status.getSeverity() == IStatus.OK || status.getSeverity() == IStatus.INFO;
	}

	/**
	 * For version 3.11 we change the abstract implementation to a default implementation. The default implementation
	 * creates an {@link Validator} and deligate the work to
	 * {@link AbstractRepositoryConnector#validateRepository(TaskRepository, IProgressMonitor)}
	 *
	 * @since 2.0
	 */

	protected Validator getValidator(@NonNull final TaskRepository repository) {
		return new org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositorySettingsPage.Validator() {

			@Override
			public void run(IProgressMonitor monitor) throws CoreException {
				RepositoryInfo repositoryInfo = connector.validateRepository(repository, monitor);
				setStatus(new Status(IStatus.OK, TasksUiPlugin.ID_PLUGIN,
						NLS.bind(Messages.AbstractRepositorySettingsPage_Settings_are_valid_version,
								repositoryInfo.getVersion())));
			}
		};
	}

	/**
	 * Public for testing.
	 *
	 * @since 2.0
	 */
	public abstract class Validator {

		private IStatus status;

		public abstract void run(@NonNull IProgressMonitor monitor) throws CoreException;

		public IStatus getStatus() {
			return status;
		}

		public void setStatus(IStatus status) {
			this.status = status;
		}

	}

	/**
	 * Provides an adapter for the {@link IValidatable} interface.
	 *
	 * @since 3.7
	 * @see IAdaptable#getAdapter(Class)
	 */
	public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
		if (adapter == IValidatable.class) {
			return new IValidatable() {
				public void validate() {
					AbstractRepositorySettingsPage.this.validateSettings();
				}

				public boolean needsValidation() {
					return AbstractRepositorySettingsPage.this.needsValidation();
				}

				public boolean canValidate() {
					return AbstractRepositorySettingsPage.this.canValidate();
				}
			};
		}
		return null;
	}

	/**
	 * @since 3.7
	 */
	public boolean needsValidateOnFinish() {
		return needsValidateOnFinish;
	}

	/**
	 * @since 3.7
	 */
	public void setNeedsValidateOnFinish(boolean needsValidateOnFinish) {
		this.needsValidateOnFinish = needsValidateOnFinish;
	}

	@Override
	public boolean preFinish(TaskRepository repository) {
		if (shouldValidateOnFinish() && !propertiesUnchanged()) {
			isValid = false;
			validateSettings();
		} else {
			isValid = true;
		}
		if (isValid) {
			isValid = super.preFinish(repository);
		}
		return isValid;
	}

	boolean shouldValidateOnFinish() {
		return validateOnFinishButton != null && validateOnFinishButton.getSelection();
	}

	@Override
	protected ExpandableComposite createSection(Composite parentControl, String title) {
		if (parentControl instanceof SectionComposite) {
			return ((SectionComposite) parentControl).createSection(title);
		} else {
			return super.createSection(parentControl, title);
		}
	}

	/**
	 * Returns the toolkit used to construct sections and hyperlinks.
	 *
	 * @return the toolkit
	 * @throws IllegalStateException
	 *             if the toolkit has not been initialized
	 * @since 3.9
	 */
	protected FormToolkit getToolkit() {
		if (toolkit == null) {
			throw new IllegalStateException("Toolkit is not initialized, createControl() must be invoked first"); //$NON-NLS-1$
		}
		return toolkit;
	}

	private boolean propertiesUnchanged() {
		TaskRepository newRepository = createTaskRepository();
		boolean propertiesUnchanged = false;
		if (validatedTaskRepository != null) {
			propertiesUnchanged = validatedTaskRepository.getProperties().equals(newRepository.getProperties());
			if (propertiesUnchanged) {
				for (AuthenticationType authenticationType : AuthenticationType.values()) {
					AuthenticationCredentials credentialsOld = validatedAuthenticationCredentials
							.get(authenticationType);
					AuthenticationCredentials credentialsNew = newRepository.getCredentials(authenticationType);
					if (credentialsOld != null) {
						propertiesUnchanged = credentialsOld.equals(credentialsNew);
						if (!propertiesUnchanged) {
							break;
						}
					} else if (credentialsNew != null) {
						propertiesUnchanged = false;
						break;
					}
				}
			}
		}
		return propertiesUnchanged;
	}

	private void saveToValidatedProperties(TaskRepository taskRepository) {
		validatedTaskRepository = taskRepository;
		validatedAuthenticationCredentials.clear();
		for (AuthenticationType authenticationType : AuthenticationType.values()) {
			AuthenticationCredentials ra = validatedTaskRepository.getCredentials(authenticationType);
			validatedAuthenticationCredentials.put(authenticationType, ra);
		}
	}

	/**
	 * Updates the branding of this repository settings page. This also updates the title and wizard banner for the
	 * given brand.
	 *
	 * @param brand
	 *            new connector branding ID
	 * @since 3.17
	 */
	public void setBrand(@NonNull String brand) {
		this.brand = brand;
		updateTitle(brand);
		updateBanner(brand);
	}

	private void updateBrandFromRepository() {
		if (repository != null && repository.hasProperty(ITasksCoreConstants.PROPERTY_BRAND_ID)) {
			setBrand(repository.getProperty(ITasksCoreConstants.PROPERTY_BRAND_ID));
		}
	}

	/**
	 * Called when the page's branding is set. Implementors may change the wizard's title to one with branding specific
	 * information. Sets the title to the branding's connector title by default.
	 *
	 * @param brand
	 *            The current connector branding ID
	 * @since 3.17
	 */
	protected void updateTitle(String brand) {
		IBrandManager brandManager = TasksUiPlugin.getDefault().getBrandManager();
		setTitle(brandManager.getConnectorLabel(getConnector(), brand));
	}

	/**
	 * Called when the page's branding is set. Implementors may change the wizard's banner to one with branding specific
	 * information. Does nothing by default.
	 *
	 * @param brand
	 *            The current connector branding ID
	 * @since 3.17
	 */
	protected void updateBanner(String brand) {
		// do nothing
	}

}
