| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.team.internal.ccvs.ui.repo; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.*; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.jface.dialogs.*; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.*; |
| import org.eclipse.team.core.RepositoryProvider; |
| import org.eclipse.team.core.TeamException; |
| 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.ccvs.ui.Policy; |
| import org.eclipse.team.internal.ccvs.ui.wizards.ConfigurationWizardMainPage; |
| import org.eclipse.team.internal.ui.SWTUtils; |
| import org.eclipse.team.internal.ui.dialogs.DetailsDialogWithProjects; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.actions.WorkspaceModifyOperation; |
| import org.eclipse.ui.dialogs.PropertyPage; |
| |
| public class CVSRepositoryPropertiesPage extends PropertyPage { |
| private static final String FAKE_PASSWORD = "*********"; //$NON-NLS-1$ |
| ICVSRepositoryLocation location; |
| |
| // Widgets |
| Text userText; |
| Text passwordText; |
| Combo methodType; |
| Text hostText; |
| Text pathText; |
| // Port |
| private Text portText; |
| private Button useDefaultPort; |
| private Button useCustomPort; |
| |
| // Caching password |
| private Button allowCachingButton; |
| private boolean allowCaching = false; |
| |
| boolean passwordChanged; |
| boolean connectionInfoChanged; |
| |
| IUserInfo info; |
| |
| // Label |
| private Button useLocationAsLabel; |
| private Button useCustomLabel; |
| private Text labelText; |
| |
| @Override |
| protected Control createContents(Composite parent) { |
| initialize(); |
| |
| Composite composite = new Composite(parent, SWT.NULL); |
| composite.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = 3; |
| composite.setLayout(layout); |
| |
| // Repository Label |
| // create a composite to ensure the radio buttons come in the correct order |
| Composite labelGroup = new Composite(composite, SWT.NONE); |
| GridData data = new GridData(); |
| data.horizontalSpan = 3; |
| labelGroup.setLayoutData(data); |
| layout = new GridLayout(); |
| layout.numColumns = 3; |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| labelGroup.setLayout(layout); |
| Listener labelListener = event -> updateWidgetEnablements(); |
| useLocationAsLabel = createRadioButton(labelGroup, CVSUIMessages.CVSRepositoryPropertiesPage_useLocationAsLabel, 3); |
| useCustomLabel = createRadioButton(labelGroup, CVSUIMessages.CVSRepositoryPropertiesPage_useCustomLabel, 1); |
| useCustomLabel.addListener(SWT.Selection, labelListener); |
| labelText = createTextField(labelGroup); |
| labelText.addListener(SWT.Modify, labelListener); |
| |
| // Add some extra space |
| createLabel(composite, "", 3); //$NON-NLS-1$ |
| |
| createLabel(composite, CVSUIMessages.CVSPropertiesPage_connectionType, 1); |
| methodType = createCombo(composite); |
| |
| createLabel(composite, CVSUIMessages.CVSPropertiesPage_user, 1); |
| userText = createTextField(composite); |
| |
| createLabel(composite, CVSUIMessages.CVSPropertiesPage_password, 1); |
| passwordText = createPasswordField(composite); |
| |
| createLabel(composite, CVSUIMessages.CVSPropertiesPage_host, 1); |
| hostText = createTextField(composite); |
| |
| createLabel(composite, CVSUIMessages.CVSPropertiesPage_path, 1); |
| pathText = createTextField(composite); |
| |
| // Port number |
| // create a composite to ensure the radio buttons come in the correct order |
| Composite portGroup = new Composite(composite, SWT.NONE); |
| data = new GridData(); |
| data.horizontalSpan = 3; |
| portGroup.setLayoutData(data); |
| layout = new GridLayout(); |
| layout.numColumns = 3; |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| portGroup.setLayout(layout); |
| useDefaultPort = createRadioButton(portGroup, CVSUIMessages.ConfigurationWizardMainPage_useDefaultPort, 3); |
| useCustomPort = createRadioButton(portGroup, CVSUIMessages.ConfigurationWizardMainPage_usePort, 1); |
| portText = createTextField(portGroup); |
| |
| // Add some extra space |
| createLabel(composite, "", 3); //$NON-NLS-1$ |
| |
| allowCachingButton = new Button(composite, SWT.CHECK); |
| allowCachingButton.setText(CVSUIMessages.UserValidationDialog_6); |
| data = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); |
| data.horizontalSpan = 3; |
| allowCachingButton.setLayoutData(data); |
| allowCachingButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| allowCaching = allowCachingButton.getSelection(); |
| } |
| }); |
| |
| Link link = SWTUtils.createPreferenceLink(getShell(), composite, CVSUIMessages.ConfigurationWizardMainPage_9, CVSUIMessages.ConfigurationWizardMainPage_10); |
| link.setLayoutData(data); |
| |
| // Add some extra space |
| createLabel(composite, "", 3); //$NON-NLS-1$ |
| |
| initializeValues(); |
| updateWidgetEnablements(); |
| Listener connectionInfoChangedListener = event -> { |
| connectionInfoChanged = true; |
| updateWidgetEnablements(); |
| }; |
| passwordText.addListener(SWT.Modify, event -> passwordChanged = !passwordText.getText().equals(FAKE_PASSWORD)); |
| userText.addListener(SWT.Modify, connectionInfoChangedListener); |
| methodType.addListener(SWT.Modify, connectionInfoChangedListener); |
| hostText.addListener(SWT.Modify, connectionInfoChangedListener); |
| portText.addListener(SWT.Modify, connectionInfoChangedListener); |
| useCustomPort.addListener(SWT.Selection, connectionInfoChangedListener); |
| pathText.addListener(SWT.Modify, connectionInfoChangedListener); |
| |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IHelpContextIds.REPOSITORY_LOCATION_PROPERTY_PAGE); |
| Dialog.applyDialogFont(parent); |
| return composite; |
| } |
| |
| /** |
| * Utility method that creates a combo box |
| * |
| * @param parent the parent for the new label |
| * @return the new widget |
| */ |
| protected Combo createCombo(Composite parent) { |
| Combo combo = new Combo(parent, SWT.READ_ONLY); |
| GridData data = new GridData(GridData.FILL_HORIZONTAL); |
| data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; |
| data.horizontalSpan = 2; |
| combo.setLayoutData(data); |
| return combo; |
| } |
| /** |
| * Utility method that creates a label instance |
| * and sets the default layout data. |
| * |
| * @param parent the parent for the new label |
| * @param text the text for the new label |
| * @return the new label |
| */ |
| protected Label createLabel(Composite parent, String text, int span) { |
| Label label = new Label(parent, SWT.LEFT); |
| label.setText(text); |
| GridData data = new GridData(); |
| data.horizontalSpan = span; |
| data.horizontalAlignment = GridData.FILL; |
| label.setLayoutData(data); |
| return label; |
| } |
| /** |
| * Create a text field specific for this application |
| * |
| * @param parent the parent of the new text field |
| * @return the new text field |
| */ |
| protected Text createTextField(Composite parent) { |
| Text text = new Text(parent, SWT.SINGLE | SWT.BORDER); |
| return layoutTextField(text); |
| } |
| /** |
| * Create a password field specific for this application |
| * |
| * @param parent the parent of the new text field |
| * @return the new text field |
| */ |
| protected Text createPasswordField(Composite parent) { |
| Text text = new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.PASSWORD); |
| return layoutTextField(text); |
| } |
| /** |
| * Layout a text or password field specific for this application |
| * |
| * @param parent the parent of the new text field |
| * @return the new text field |
| */ |
| protected Text layoutTextField(Text text) { |
| GridData data = new GridData(GridData.FILL_HORIZONTAL); |
| data.verticalAlignment = GridData.CENTER; |
| data.grabExcessVerticalSpace = false; |
| data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; |
| data.horizontalSpan = 2; |
| text.setLayoutData(data); |
| return text; |
| } |
| |
| /** |
| * Utility method to create a radio button |
| * |
| * @param parent the parent of the radio button |
| * @param label the label of the radio button |
| * @param span the number of columns to span |
| * @return the created radio button |
| */ |
| protected Button createRadioButton(Composite parent, String label, int span) { |
| Button button = new Button(parent, SWT.RADIO); |
| button.setText(label); |
| GridData data = new GridData(); |
| data.horizontalSpan = span; |
| button.setLayoutData(data); |
| return button; |
| } |
| /** |
| * Initializes the page |
| */ |
| private void initialize() { |
| location = null; |
| IAdaptable element = getElement(); |
| if (element instanceof ICVSRepositoryLocation) { |
| location = (ICVSRepositoryLocation)element; |
| } else { |
| Object adapter = element.getAdapter(ICVSRepositoryLocation.class); |
| if (adapter instanceof ICVSRepositoryLocation) { |
| location = (ICVSRepositoryLocation)adapter; |
| } |
| } |
| } |
| /** |
| * Set the initial values of the widgets |
| */ |
| private void initializeValues() { |
| passwordChanged = false; |
| connectionInfoChanged = false; |
| |
| IConnectionMethod[] methods = CVSRepositoryLocation.getPluggedInConnectionMethods(); |
| for (int i = 0; i < methods.length; i++) { |
| methodType.add(methods[i].getName()); |
| } |
| String method = location.getMethod().getName(); |
| methodType.select(methodType.indexOf(method)); |
| info = location.getUserInfo(true); |
| userText.setText(info.getUsername()); |
| passwordText.setText(FAKE_PASSWORD); |
| hostText.setText(location.getHost()); |
| int port = location.getPort(); |
| if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT) { |
| useDefaultPort.setSelection(true); |
| useCustomPort.setSelection(false); |
| portText.setEnabled(false); |
| } else { |
| useDefaultPort.setSelection(false); |
| useCustomPort.setSelection(true); |
| portText.setText("" + port); //$NON-NLS-1$ |
| } |
| pathText.setText(location.getRootDirectory()); |
| allowCachingButton.setSelection(location.getUserInfoCached()); |
| allowCaching = allowCachingButton.getSelection(); |
| |
| // get the repository label |
| String label = null; |
| RepositoryRoot root = CVSUIPlugin.getPlugin().getRepositoryManager().getRepositoryRootFor(location); |
| label = root.getName(); |
| useLocationAsLabel.setSelection(label == null); |
| useCustomLabel.setSelection(!useLocationAsLabel.getSelection()); |
| if (label == null) { |
| label = location.getLocation(true); |
| } |
| labelText.setText(label); |
| } |
| |
| private boolean performConnectionInfoChanges() { |
| // Set the caching mode of the location |
| if (!connectionInfoChanged) { |
| location.setAllowCaching(allowCaching); |
| if (!passwordChanged) { |
| ((CVSRepositoryLocation)location).updateCache(); |
| } |
| } |
| // Don't do anything else if there wasn't a password or connection change |
| if (!passwordChanged && !connectionInfoChanged) return true; |
| |
| try { |
| // Check if the password was the only thing to change. |
| if (passwordChanged && !connectionInfoChanged) { |
| CVSRepositoryLocation oldLocation = (CVSRepositoryLocation)location; |
| oldLocation.setPassword(getNewPassword()); |
| if (allowCaching) { |
| oldLocation.updateCache(); |
| } |
| passwordChanged = false; |
| return true; |
| } |
| |
| // Otherwise change the connection info and the password |
| // This operation is done inside a workspace operation in case the sharing |
| // info for existing projects is changed |
| if (!(location.getHost().equals(hostText.getText()) && location.getRootDirectory().equals(pathText.getText()))) { |
| // The host or path has changed |
| if (!MessageDialog.openConfirm(getShell(), |
| CVSUIMessages.CVSRepositoryPropertiesPage_0, |
| CVSUIMessages.CVSRepositoryPropertiesPage_1)) { |
| return false; |
| } |
| } |
| final boolean[] result = new boolean[] { false }; |
| final ProgressMonitorDialog progressMonitorDialog = new ProgressMonitorDialog(getShell()); |
| progressMonitorDialog.run(false, false, new WorkspaceModifyOperation(null) { |
| @Override |
| public void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { |
| try { |
| // Create a new repository location with the new information |
| CVSRepositoryLocation newLocation = CVSRepositoryLocation.fromProperties(createProperties()); |
| newLocation.setEncoding(location.getEncoding()); |
| location.setAllowCaching(allowCaching); |
| try { |
| // For each project shared with the old location, set connection info to the new one |
| List projects = new ArrayList(); |
| IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); |
| for (int i = 0; i < allProjects.length; i++) { |
| RepositoryProvider teamProvider = RepositoryProvider.getProvider(allProjects[i], CVSProviderPlugin.getTypeId()); |
| if (teamProvider != null) { |
| CVSTeamProvider cvsProvider = (CVSTeamProvider)teamProvider; |
| if (cvsProvider.getCVSWorkspaceRoot().getRemoteLocation().equals(location)) { |
| projects.add(allProjects[i]); |
| } |
| } |
| } |
| if (projects.size() > 0) { |
| // To do: warn the user |
| DetailsDialogWithProjects dialog = new DetailsDialogWithProjects( |
| progressMonitorDialog.getShell(), |
| CVSUIMessages.CVSRepositoryPropertiesPage_Confirm_Project_Sharing_Changes_1, |
| CVSUIMessages.CVSRepositoryPropertiesPage_There_are_projects_in_the_workspace_shared_with_this_repository_2, |
| NLS.bind(CVSUIMessages.CVSRepositoryPropertiesPage_sharedProject, new String[] { location.toString() }), |
| (IProject[]) projects.toArray(new IProject[projects.size()]), |
| true, |
| Dialog.DLG_IMG_WARNING); |
| int r = dialog.open(); |
| if (r != Window.OK) { |
| result[0] = false; |
| return; |
| } |
| monitor.beginTask(null, 1000 * projects.size()); |
| try { |
| Iterator it = projects.iterator(); |
| while (it.hasNext()) { |
| IProject project = (IProject)it.next(); |
| RepositoryProvider teamProvider = RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()); |
| CVSTeamProvider cvsProvider = (CVSTeamProvider)teamProvider; |
| cvsProvider.setRemoteRoot(newLocation, Policy.subMonitorFor(monitor, 1000)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| // Dispose the old repository location |
| CVSUIPlugin.getPlugin().getRepositoryManager().replaceRepositoryLocation(location, newLocation); |
| |
| } finally { |
| // Even if we failed, ensure that the new location appears in the repo view. |
| newLocation = (CVSRepositoryLocation)KnownRepositories.getInstance().addRepository(newLocation, !KnownRepositories.getInstance().isKnownRepository(newLocation.getLocation())); |
| } |
| |
| // Set the location of the page to the new location in case Apply was chosen |
| location = newLocation; |
| connectionInfoChanged = false; |
| passwordChanged = false; |
| } catch (TeamException e) { |
| throw new InvocationTargetException(e); |
| } |
| result[0] = true; |
| } |
| }); |
| return result[0]; |
| } catch (InvocationTargetException e) { |
| handle(e); |
| } catch (InterruptedException e) { |
| } |
| return false; /* we only get here if an exception occurred */ |
| } |
| |
| private void performNonConnectionInfoChanges() { |
| recordNewLabel((CVSRepositoryLocation)location); |
| } |
| |
| @Override |
| public boolean performOk() { |
| if (performConnectionInfoChanges()) { |
| performNonConnectionInfoChanges(); |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| protected void performDefaults() { |
| super.performDefaults(); |
| initializeValues(); |
| } |
| |
| /** |
| * Shows the given errors to the user. |
| */ |
| protected void handle(Throwable e) { |
| CVSUIPlugin.openError(getShell(), null, null, e); |
| } |
| |
| /** |
| * Updates widget enablements and sets error message if appropriate. |
| */ |
| protected void updateWidgetEnablements() { |
| if (useLocationAsLabel.getSelection()) { |
| labelText.setEnabled(false); |
| } else { |
| labelText.setEnabled(true); |
| } |
| if (useDefaultPort.getSelection()) { |
| portText.setEnabled(false); |
| } else { |
| portText.setEnabled(true); |
| } |
| validateFields(); |
| } |
| |
| private void validateFields() { |
| if (labelText.isEnabled()) { |
| if (labelText.getText().length() == 0) { |
| setValid(false); |
| return; |
| } |
| } |
| String user = userText.getText(); |
| IStatus status = ConfigurationWizardMainPage.validateUserName(user); |
| if (!isStatusOK(status)) { |
| return; |
| } |
| |
| String host = hostText.getText(); |
| status = ConfigurationWizardMainPage.validateHost(host); |
| if (!isStatusOK(status)) { |
| return; |
| } |
| |
| if (portText.isEnabled()) { |
| String port = portText.getText(); |
| status = ConfigurationWizardMainPage.validatePort(port); |
| if (!isStatusOK(status)) { |
| return; |
| } |
| } |
| |
| String pathString = pathText.getText(); |
| status = ConfigurationWizardMainPage.validatePath(pathString); |
| if (!isStatusOK(status)) { |
| return; |
| } |
| |
| try { |
| CVSRepositoryLocation l = CVSRepositoryLocation.fromProperties(createProperties()); |
| if (!l.equals(location) && KnownRepositories.getInstance().isKnownRepository(l.getLocation())) { |
| setErrorMessage(CVSUIMessages.ConfigurationWizardMainPage_0); |
| setValid(false); |
| return; |
| } |
| } catch (CVSException e) { |
| CVSUIPlugin.log(e); |
| // Let it pass. Creation should fail |
| } |
| |
| setErrorMessage(null); |
| setValid(true); |
| } |
| |
| private boolean isStatusOK(IStatus status) { |
| if (!status.isOK()) { |
| setErrorMessage(status.getMessage()); |
| setValid(false); |
| return false; |
| } |
| return true; |
| } |
| |
| private void recordNewLabel(CVSRepositoryLocation location) { |
| String newLabel = getNewLabel(location); |
| if (newLabel == null) { |
| String oldLabel = getOldLabel(location); |
| if (oldLabel == null || oldLabel.equals(location.getLocation())) { |
| return; |
| } |
| } else if (newLabel.equals(getOldLabel(location))) { |
| return; |
| } |
| CVSUIPlugin.getPlugin().getRepositoryManager().setLabel(location, newLabel); |
| CVSUIPlugin.broadcastPropertyChange(new PropertyChangeEvent(this, |
| CVSUIPlugin.P_DECORATORS_CHANGED, null, null)); |
| |
| } |
| private String getOldLabel(CVSRepositoryLocation location) { |
| return CVSUIPlugin.getPlugin().getRepositoryManager().getRepositoryRootFor(location).getName(); |
| } |
| private String getNewLabel(CVSRepositoryLocation location) { |
| String label = null; |
| if (useCustomLabel.getSelection()) { |
| label = labelText.getText(); |
| if (label.equals(location.getLocation())) { |
| label = null; |
| } |
| } |
| return label; |
| } |
| /* internal use only */ String getNewPassword() { |
| return passwordText.getText(); |
| } |
| |
| private Properties createProperties() { |
| Properties result = new Properties(); |
| result.setProperty("connection", methodType.getText()); //$NON-NLS-1$ |
| result.setProperty("user", userText.getText()); //$NON-NLS-1$ |
| if (passwordChanged) { |
| result.setProperty("password", passwordText.getText()); //$NON-NLS-1$ |
| } |
| result.setProperty("host", hostText.getText()); //$NON-NLS-1$ |
| if (useCustomPort.getSelection()) { |
| result.setProperty("port", portText.getText()); //$NON-NLS-1$ |
| } |
| result.setProperty("root", pathText.getText()); //$NON-NLS-1$ |
| return result; |
| } |
| } |
| |