Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Brock Janiczak <brockj@tpg.com.au> - Bug 185708 Provide link to open SSH/SSH2/proxy preferences from Connection wizard * Brock Janiczak <brockj@tpg.com.au> - Bug 107025 [Wizards] expose the 'paste cvs connection' easter egg * Remy Chi Jian Suen <remy.suen@gmail.com> - Bug 274284 - 'Add CVS Repository' dialog is clipped at the bottom *******************************************************************************/ package org.eclipse.team.internal.ccvs.ui.wizards; import java.util.*; import java.util.List; import org.eclipse.core.runtime.*; import org.eclipse.jface.dialogs.*; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.fieldassist.*; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.eclipse.team.internal.ccvs.core.*; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.util.KnownRepositories; import org.eclipse.team.internal.ccvs.ui.*; import org.eclipse.team.internal.ui.SWTUtils; import org.eclipse.ui.PlatformUI; /** * Wizard page for entering information about a CVS repository location. */ public class ConfigurationWizardMainPage extends CVSWizardPage { private static final String ANONYMOUS_USER = "anonymous"; //$NON-NLS-1$ private boolean showValidate; private boolean validate; // Widgets // Connection Method private Combo connectionMethodCombo; // User private Combo userCombo; // Password private Text passwordText; // Port private Text portText; private Button useDefaultPort; private Button useCustomPort; // Host private Combo hostCombo; // Repository Path private Combo repositoryPathCombo; // Validation private Button validateButton; // Caching password private Button allowCachingButton; private boolean allowCaching = false; private static final int COMBO_HISTORY_LENGTH = 5; private Properties properties = null; // The previously created repository. // It is recorded when asked for and // nulled when the page is changed. private ICVSRepositoryLocation location; // The previously created repository. // It is recorded when fields are changed private ICVSRepositoryLocation oldLocation; // Dialog store id constants private static final String STORE_USERNAME_ID = "ConfigurationWizardMainPage.STORE_USERNAME_ID";//$NON-NLS-1$ private static final String STORE_HOSTNAME_ID = "ConfigurationWizardMainPage.STORE_HOSTNAME_ID";//$NON-NLS-1$ private static final String STORE_PATH_ID = "ConfigurationWizardMainPage.STORE_PATH_ID";//$NON-NLS-1$ private static final String STORE_DONT_VALIDATE_ID = "ConfigurationWizardMainPage.STORE_DONT_VALIDATE_ID";//$NON-NLS-1$ // In case the page was launched from a different wizard private IDialogSettings settings; /** * ConfigurationWizardMainPage constructor. * * @param pageName the name of the page * @param title the title of the page * @param titleImage the image for the page */ public ConfigurationWizardMainPage(String pageName, String title, ImageDescriptor titleImage) { super(pageName, title, titleImage); } /** * Adds an entry to a history, while taking care of duplicate history items * and excessively long histories. The assumption is made that all histories * should be of length <code>ConfigurationWizardMainPage.COMBO_HISTORY_LENGTH</code>. * * @param history the current history * @param newEntry the entry to add to the history * @return the history with the new entry appended */ private String[] addToHistory(String[] history, String newEntry) { ArrayList l = new ArrayList(Arrays.asList(history)); addToHistory(l, newEntry); String[] r = new String[l.size()]; l.toArray(r); return r; } protected IDialogSettings getDialogSettings() { return settings; } protected void setDialogSettings(IDialogSettings settings) { this.settings = settings; } /** * Adds an entry to a history, while taking care of duplicate history items * and excessively long histories. The assumption is made that all histories * should be of length <code>ConfigurationWizardMainPage.COMBO_HISTORY_LENGTH</code>. * * @param history the current history * @param newEntry the entry to add to the history */ private void addToHistory(List history, String newEntry) { history.remove(newEntry); history.add(0, newEntry); // since only one new item was added, we can be over the limit // by at most one item if (history.size() > COMBO_HISTORY_LENGTH) history.remove(COMBO_HISTORY_LENGTH); } /** * Creates the UI part of the page. * * @param parent the parent of the created widgets */ public void createControl(Composite parent) { Composite composite = createComposite(parent, 2, false); // set F1 help PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.SHARING_NEW_REPOSITORY_PAGE); Listener listener = new Listener() { public void handleEvent(Event event) { if (location != null) { oldLocation = location; location = null; } if (event.widget == hostCombo) { String hostText = hostCombo.getText(); if (hostText.length() > 0 && hostText.charAt(0) == ':') { try { CVSRepositoryLocation newLocation = CVSRepositoryLocation.fromString(hostText); connectionMethodCombo.setText(newLocation.getMethod().getName()); repositoryPathCombo.setText(newLocation.getRootDirectory()); int port = newLocation.getPort(); if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT) { useDefaultPort.setSelection(true); useCustomPort.setSelection(false); } else { useCustomPort.setSelection(true); useDefaultPort.setSelection(false); portText.setText(String.valueOf(port)); } userCombo.setText(newLocation.getUsername()); //passwordText.setText(newLocation.xxx); hostCombo.setText(newLocation.getHost()); } catch (CVSException e) { CVSUIPlugin.log(e); } } } updateWidgetEnablements(); } }; Group g = createGroup(composite, CVSUIMessages.ConfigurationWizardMainPage_Location_1); // Host name createLabel(g, CVSUIMessages.ConfigurationWizardMainPage_host); hostCombo = createEditableCombo(g); ControlDecoration decoration = new ControlDecoration(hostCombo, SWT.TOP | SWT.LEFT); FieldDecoration infoDecoration = FieldDecorationRegistry.getDefault() .getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION); decoration.setImage(infoDecoration.getImage()); decoration.setDescriptionText(CVSUIMessages.ConfigurationWizardMainPage_8); decoration.setShowOnlyOnFocus(true); ((GridLayout) g.getLayout()).horizontalSpacing = decoration.getMarginWidth() + infoDecoration.getImage().getBounds().width; hostCombo.addListener(SWT.Selection, listener); hostCombo.addListener(SWT.Modify, listener); // Repository Path createLabel(g, CVSUIMessages.ConfigurationWizardMainPage_repositoryPath); repositoryPathCombo = createEditableCombo(g); repositoryPathCombo.addListener(SWT.Selection, listener); repositoryPathCombo.addListener(SWT.Modify, listener); g = createGroup(composite, CVSUIMessages.ConfigurationWizardMainPage_Authentication_2); // User name createLabel(g, CVSUIMessages.ConfigurationWizardMainPage_userName); userCombo = createEditableCombo(g); userCombo.addListener(SWT.Selection, listener); userCombo.addListener(SWT.Modify, listener); // Password createLabel(g, CVSUIMessages.ConfigurationWizardMainPage_password); passwordText = createPasswordField(g); passwordText.addListener(SWT.Modify, listener); g = createGroup(composite, CVSUIMessages.ConfigurationWizardMainPage_Connection_3); // Connection type createLabel(g, CVSUIMessages.ConfigurationWizardMainPage_connection); connectionMethodCombo = createCombo(g); connectionMethodCombo.addListener(SWT.Selection, listener); // Port number // create a composite to ensure the radio buttons come in the correct order Composite portGroup = new Composite(g, SWT.NONE); GridData data = new GridData(); data.horizontalSpan = 2; portGroup.setLayoutData(data); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; portGroup.setLayout(layout); useDefaultPort = createRadioButton(portGroup, CVSUIMessages.ConfigurationWizardMainPage_useDefaultPort, 2); useCustomPort = createRadioButton(portGroup, CVSUIMessages.ConfigurationWizardMainPage_usePort, 1); useCustomPort.addListener(SWT.Selection, listener); portText = createTextField(portGroup); portText.addListener(SWT.Modify, listener); // create a composite to ensure the validate button is in its own tab group if (showValidate) { Composite validateButtonTabGroup = new Composite(composite, SWT.NONE); data = new GridData(); data.horizontalSpan = 2; validateButtonTabGroup.setLayoutData(data); validateButtonTabGroup.setLayout(new FillLayout()); validateButton = new Button(validateButtonTabGroup, SWT.CHECK); validateButton.setText(CVSUIMessages.ConfigurationWizardAutoconnectPage_validate); validateButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { validate = validateButton.getSelection(); } }); } allowCachingButton = new Button(composite, SWT.CHECK); allowCachingButton.setText(CVSUIMessages.UserValidationDialog_6); data = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); data.horizontalSpan = 2; allowCachingButton.setLayoutData(data); allowCachingButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { allowCaching = allowCachingButton.getSelection(); } }); Link link = SWTUtils.createPreferenceLink(getShell(), composite, CVSUIMessages.ConfigurationWizardMainPage_9, CVSUIMessages.ConfigurationWizardMainPage_10); data = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); data.horizontalSpan = 2; link.setLayoutData(data); SWTUtils.createPreferenceLink(getShell(), composite, "org.eclipse.team.cvs.ui.ExtMethodPreferencePage", //$NON-NLS-1$ new String[] { "org.eclipse.team.cvs.ui.cvs", //$NON-NLS-1$ "org.eclipse.team.cvs.ui.ExtMethodPreferencePage", //$NON-NLS-1$ "org.eclipse.jsch.ui.SSHPreferences", //$NON-NLS-1$ "org.eclipse.ui.net.NetPreferences" }, //$NON-NLS-1$ CVSUIMessages.ConfigurationWizardMainPage_7); initializeValues(); updateWidgetEnablements(); hostCombo.setFocus(); setControl(composite); Dialog.applyDialogFont(parent); } /** * Utility method to create an editable combo box * * @param parent the parent of the combo box * @return the created combo */ protected Combo createEditableCombo(Composite parent) { Combo combo = new Combo(parent, SWT.NULL); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; combo.setLayoutData(data); return combo; } protected Group createGroup(Composite parent, String text) { Group group = new Group(parent, SWT.NULL); group.setText(text); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; //data.widthHint = GROUP_WIDTH; group.setLayoutData(data); GridLayout layout = new GridLayout(); layout.numColumns = 2; group.setLayout(layout); return group; } /* * Create a Properties node that contains everything needed to create a repository location */ private Properties createProperties() { Properties result = new Properties(); result.setProperty("connection", connectionMethodCombo.getText()); //$NON-NLS-1$ result.setProperty("user", userCombo.getText()); //$NON-NLS-1$ result.setProperty("password", passwordText.getText()); //$NON-NLS-1$ result.setProperty("host", hostCombo.getText()); //$NON-NLS-1$ if (useCustomPort.getSelection()) { result.setProperty("port", portText.getText()); //$NON-NLS-1$ } result.setProperty("root", repositoryPathCombo.getText()); //$NON-NLS-1$ return result; } /** * Create a new location with the information entered on the page. * The location will exists and can be set for connecting but is not * registered for persistence. This method must be called from the UI * thread. * @return a location or <code>null</code> * @throws CVSException */ public ICVSRepositoryLocation getLocation() throws CVSException { if (location == null) { if (!isPageComplete()) return null; location = CVSRepositoryLocation.fromProperties(createProperties()); if (location.equals(oldLocation)) { location = oldLocation; } location.setAllowCaching(allowCaching); oldLocation = null; saveWidgetValues(); } return location; } /** * Initializes states of the controls. */ private void initializeValues() { // Set remembered values IDialogSettings settings = getDialogSettings(); if (settings != null) { String[] hostNames = settings.getArray(STORE_HOSTNAME_ID); if (hostNames != null) { for (int i = 0; i < hostNames.length; i++) { hostCombo.add(hostNames[i]); } } String[] paths = settings.getArray(STORE_PATH_ID); if (paths != null) { for (int i = 0; i < paths.length; i++) { repositoryPathCombo.add(paths[i]); } } String[] userNames = settings.getArray(STORE_USERNAME_ID); if (userNames != null) { for (int i = 0; i < userNames.length; i++) { userCombo.add(userNames[i]); } } userCombo.add(ANONYMOUS_USER); if (showValidate) { validate = !settings.getBoolean(STORE_DONT_VALIDATE_ID); validateButton.setSelection(validate); } } // Initialize other values and widget states IConnectionMethod[] methods = CVSRepositoryLocation.getPluggedInConnectionMethods(); for (int i = 0; i < methods.length; i++) { connectionMethodCombo.add(methods[i].getName()); } // pserver is a default connection method int defaultIndex = connectionMethodCombo.indexOf("pserver") != -1 ? connectionMethodCombo.indexOf("pserver") //$NON-NLS-1$//$NON-NLS-2$ : 0; connectionMethodCombo.select(defaultIndex); useDefaultPort.setSelection(true); if (properties != null) { String method = properties.getProperty("connection"); //$NON-NLS-1$ if (method == null) { connectionMethodCombo.select(defaultIndex); } else { connectionMethodCombo.select(connectionMethodCombo.indexOf(method)); } String user = properties.getProperty("user"); //$NON-NLS-1$ if (user != null) { userCombo.setText(user); } String password = properties.getProperty("password"); //$NON-NLS-1$ if (password != null) { passwordText.setText(password); } String host = properties.getProperty("host"); //$NON-NLS-1$ if (host != null) { hostCombo.setText(host); } String port = properties.getProperty("port"); //$NON-NLS-1$ if (port != null) { useCustomPort.setSelection(true); portText.setText(port); } String repositoryPath = properties.getProperty("root"); //$NON-NLS-1$ if (repositoryPath != null) { repositoryPathCombo.setText(repositoryPath); } } } /** * Saves the widget values */ private void saveWidgetValues() { // Update history IDialogSettings settings = getDialogSettings(); if (settings != null) { String userName = userCombo.getText(); if (!userName.equals(ANONYMOUS_USER)) { String[] userNames = settings.getArray(STORE_USERNAME_ID); if (userNames == null) userNames = new String[0]; userNames = addToHistory(userNames, userName); settings.put(STORE_USERNAME_ID, userNames); } String[] hostNames = settings.getArray(STORE_HOSTNAME_ID); if (hostNames == null) hostNames = new String[0]; hostNames = addToHistory(hostNames, hostCombo.getText()); settings.put(STORE_HOSTNAME_ID, hostNames); String[] paths = settings.getArray(STORE_PATH_ID); if (paths == null) paths = new String[0]; paths = addToHistory(paths, repositoryPathCombo.getText()); settings.put(STORE_PATH_ID, paths); if (showValidate) { settings.put(STORE_DONT_VALIDATE_ID, !validate); } } } public void setShowValidate(boolean showValidate) { this.showValidate = showValidate; } /** * Sets the properties for the repository connection * * @param properties the properties or null */ public void setProperties(Properties properties) { this.properties = properties; } /** * Updates widget enablements and sets error message if appropriate. */ protected void updateWidgetEnablements() { if (useDefaultPort.getSelection()) { portText.setEnabled(false); } else { portText.setEnabled(true); } validateFields(); } /** * Validates the contents of the editable fields and set page completion * and error messages appropriately. */ protected void validateFields() { String user = userCombo.getText(); IStatus status = validateUserName(user); if (!isStatusOK(status)) { return; } String host = hostCombo.getText(); status = validateHost(host); if (!isStatusOK(status)) { return; } if (portText.isEnabled()) { String port = portText.getText(); status = validatePort(port); if (!isStatusOK(status)) { return; } } String pathString = repositoryPathCombo.getText(); status = validatePath(pathString); if (!isStatusOK(status)) { return; } try { CVSRepositoryLocation l = CVSRepositoryLocation.fromProperties(createProperties()); if (!l.equals(oldLocation) && KnownRepositories.getInstance().isKnownRepository(l.getLocation())) { setErrorMessage(CVSUIMessages.ConfigurationWizardMainPage_0); setPageComplete(false); return; } } catch (CVSException e) { CVSUIPlugin.log(e); // Let it pass. Creation should fail } // Everything passed so we're good to go setErrorMessage(null); setPageComplete(true); } private boolean isStatusOK(IStatus status) { if (!status.isOK()) { if (status.getCode() == REQUIRED_FIELD) { // Don't set the message for an empty field setErrorMessage(null); } else { setErrorMessage(status.getMessage()); } setPageComplete(false); return false; } return true; } public boolean getValidate() { return validate; } public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { hostCombo.setFocus(); } } public static final int REQUIRED_FIELD = 1; public static final int INVALID_FIELD_CONTENTS = 2; public static final IStatus validateUserName(String user) { if (user.length() == 0) { return new Status(IStatus.ERROR, CVSUIPlugin.ID, REQUIRED_FIELD, CVSUIMessages.ConfigurationWizardMainPage_1, null); } // removed the @ sign check since, so the UI can allow full kerberos names if (user.indexOf(':') != -1) { return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_invalidUserName, null); } if (user.startsWith(" ") || user.endsWith(" ")) { //$NON-NLS-1$ //$NON-NLS-2$ return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_6, null); } return Status.OK_STATUS; } public static final IStatus validateHost(String host) { if (host.length() == 0) { return new Status(IStatus.ERROR, CVSUIPlugin.ID, REQUIRED_FIELD, CVSUIMessages.ConfigurationWizardMainPage_2, null); } if (host.indexOf(':') != -1) { return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_invalidHostName, null); } if (host.startsWith(" ") || host.endsWith(" ")) { //$NON-NLS-1$ //$NON-NLS-2$ return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_5, null); } return Status.OK_STATUS; } public static final IStatus validatePort(String port) { if (port.length() == 0) { return new Status(IStatus.ERROR, CVSUIPlugin.ID, REQUIRED_FIELD, CVSUIMessages.ConfigurationWizardMainPage_3, null); } try { Integer.parseInt(port); } catch (NumberFormatException e) { return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_invalidPort, null); } return Status.OK_STATUS; } public static final IStatus validatePath(String pathString) { if (pathString.length() == 0) { return new Status(IStatus.ERROR, CVSUIPlugin.ID, REQUIRED_FIELD, CVSUIMessages.ConfigurationWizardMainPage_4, null); } IPath path = new Path(null, pathString); String[] segments = path.segments(); for (int i = 0; i < segments.length; i++) { String string = segments[i]; if (string.charAt(0) == ' ' || string.charAt(string.length() - 1) == ' ') { return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_invalidPathWithSpaces, null); } } // look for // and inform the user that we support use of C:\cvs\root instead of /c//cvs/root if (pathString.indexOf("//") != -1) { //$NON-NLS-1$ if (pathString.indexOf("//") == 2) { //$NON-NLS-1$ // The user is probably trying to specify a CVSNT path return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_useNTFormat, null); } else { return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_invalidPathWithSlashes, null); } } if (pathString.endsWith("/")) { //$NON-NLS-1$ return new Status(IStatus.ERROR, CVSUIPlugin.ID, INVALID_FIELD_CONTENTS, CVSUIMessages.ConfigurationWizardMainPage_invalidPathWithTrailingSlash, null); } return Status.OK_STATUS; } }