blob: e1ec233d35cece2cbc29c5f64307a5849d75ce65 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.repo;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
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.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.CVSTeamProvider;
import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.core.IConnectionMethod;
import org.eclipse.team.internal.ccvs.core.IUserInfo;
import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.IHelpContextIds;
import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.team.internal.ui.dialogs.DetailsDialogWithProjects;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.ui.help.WorkbenchHelp;
public class CVSRepositoryPropertiesPage extends PropertyPage {
ICVSRepositoryLocation location;
// Widgets
Text userText;
Text passwordText;
Combo methodType;
Label hostLabel;
Label pathLabel;
Label portLabel;
boolean passwordChanged;
boolean connectionInfoChanged;
IUserInfo info;
// Label
private Button useLocationAsLabel;
private Button useCustomLabel;
private Text labelText;
// Read/write access
private Button useDefaultReadWriteLocations;
private Button useCustomReadWriteLocations;
private Combo readLocation;
private Combo writeLocation;
/*
* @see PreferencesPage#createContents
*/
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 = new Listener() {
public void handleEvent(Event event) {
updateWidgetEnablements();
}
};
useLocationAsLabel = createRadioButton(labelGroup, Policy.bind("CVSRepositoryPropertiesPage.useLocationAsLabel"), 3); //$NON-NLS-1$
useCustomLabel = createRadioButton(labelGroup, Policy.bind("CVSRepositoryPropertiesPage.useCustomLabel"), 1); //$NON-NLS-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, Policy.bind("CVSPropertiesPage.connectionType"), 1); //$NON-NLS-1$
methodType = createCombo(composite);
createLabel(composite, Policy.bind("CVSPropertiesPage.user"), 1); //$NON-NLS-1$
userText = createTextField(composite);
createLabel(composite, Policy.bind("CVSPropertiesPage.password"), 1); //$NON-NLS-1$
passwordText = createPasswordField(composite);
createLabel(composite, Policy.bind("CVSPropertiesPage.host"), 1); //$NON-NLS-1$
hostLabel = createLabel(composite, "", 2); //$NON-NLS-1$
createLabel(composite, Policy.bind("CVSPropertiesPage.port"), 1); //$NON-NLS-1$
portLabel = createLabel(composite, "", 2); //$NON-NLS-1$
createLabel(composite, Policy.bind("CVSPropertiesPage.path"), 1); //$NON-NLS-1$
pathLabel = createLabel(composite, "", 2); //$NON-NLS-1$
// Add some extra space
createLabel(composite, "", 3); //$NON-NLS-1$
// Add some extra space
createLabel(composite, "", 3); //$NON-NLS-1$
createReadWriteAccessComposite(composite);
initializeValues();
updateWidgetEnablements();
passwordText.addListener(SWT.Modify, new Listener() {
public void handleEvent(Event event) {
passwordChanged = true;
}
});
userText.addListener(SWT.Modify, new Listener() {
public void handleEvent(Event event) {
connectionInfoChanged = true;
}
});
methodType.addListener(SWT.Modify, new Listener() {
public void handleEvent(Event event) {
connectionInfoChanged = true;
}
});
useDefaultReadWriteLocations.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
updateWidgetEnablements();
}
});
useCustomReadWriteLocations.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
updateWidgetEnablements();
}
});
WorkbenchHelp.setHelp(getControl(), IHelpContextIds.REPOSITORY_LOCATION_PROPERTY_PAGE);
return composite;
}
/**
* @param composite
*/
private void createReadWriteAccessComposite(Composite composite) {
Composite radioGroup = createRadioGroupComposite(composite);
useDefaultReadWriteLocations = createRadioButton(radioGroup, "Use this location's connection information for all connections", 3);
useCustomReadWriteLocations = createRadioButton(radioGroup, "Use the following locations for read and write access", 3);
createLabel(composite, "Read:", 1);
readLocation = createCombo(composite);
createLabel(composite, "Write:", 1);
writeLocation = createCombo(composite);
}
/**
* @param composite
*/
private Composite createRadioGroupComposite(Composite composite) {
Composite radioGroup = new Composite(composite, SWT.NONE);
GridData data = new GridData();
data.horizontalSpan = 3;
radioGroup.setLayoutData(data);
GridLayout layout = new GridLayout();
layout.numColumns = 3;
layout.marginHeight = 0;
layout.marginWidth = 0;
radioGroup.setLayout(layout);
return radioGroup;
}
/**
* 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;
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("*********"); //$NON-NLS-1$
hostLabel.setText(location.getHost());
int port = location.getPort();
if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT) {
portLabel.setText(Policy.bind("CVSPropertiesPage.defaultPort")); //$NON-NLS-1$
} else {
portLabel.setText("" + port); //$NON-NLS-1$
}
pathLabel.setText(location.getRootDirectory());
// 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();
}
labelText.setText(label);
// Fill in read/write repo locations
String currentReadLocation = ((CVSRepositoryLocation)root.getRoot()).getReadLocation();
String currentWriteLocation = ((CVSRepositoryLocation)root.getRoot()).getWriteLocation();
try {
// Ensure the read and write locations are listed
if (currentReadLocation != null) {
CVSProviderPlugin.getPlugin().getRepository(currentReadLocation);
}
if (currentWriteLocation != null) {
CVSProviderPlugin.getPlugin().getRepository(currentWriteLocation);
}
} catch (CVSException e) {
CVSProviderPlugin.log(e);
}
ICVSRepositoryLocation[] locations = CVSProviderPlugin.getPlugin().getKnownRepositories();
for (int i = 0; i < locations.length; i++) {
ICVSRepositoryLocation location = locations[i];
readLocation.add(location.getLocation());
writeLocation.add(location.getLocation());
}
readLocation.setText(currentReadLocation == null ? root.getRoot().getLocation() : currentReadLocation);
writeLocation.setText(currentWriteLocation == null ? root.getRoot().getLocation() : currentWriteLocation);
if (currentReadLocation == null && currentWriteLocation == null) {
useDefaultReadWriteLocations.setSelection(true);
useCustomReadWriteLocations.setSelection(false);
} else {
useDefaultReadWriteLocations.setSelection(false);
useCustomReadWriteLocations.setSelection(true);
}
}
private boolean performConnectionInfoChanges() {
// Don't do anything 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());
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
final boolean[] result = new boolean[] { false };
new ProgressMonitorDialog(getShell()).run(false, false, new WorkspaceModifyOperation() {
public void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
// Create a new repository location with the new information
CVSRepositoryLocation newLocation = CVSRepositoryLocation.fromString(location.getLocation());
newLocation.setMethod(methodType.getText());
info.setUsername(userText.getText());
if (passwordChanged) {
info.setPassword(getNewPassword());
}
newLocation.setUserInfo(info);
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(
getShell(),
Policy.bind("CVSRepositoryPropertiesPage.Confirm_Project_Sharing_Changes_1"), //$NON-NLS-1$
Policy.bind("CVSRepositoryPropertiesPage.There_are_projects_in_the_workspace_shared_with_this_repository_2"), //$NON-NLS-1$
Policy.bind("CVSRepositoryPropertiesPage.sharedProject", location.toString()), //$NON-NLS-1$
(IProject[]) projects.toArray(new IProject[projects.size()]),
true,
DetailsDialogWithProjects.DLG_IMG_WARNING);
int r = dialog.open();
if (r != DetailsDialogWithProjects.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)CVSProviderPlugin.getPlugin().getRepository(newLocation.getLocation());
newLocation.updateCache();
}
// 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) {
} catch (CVSException e) {
handle(e);
}
return false; /* we only get here if an exception occurred */
}
private void performNonConnectionInfoChanges() {
recordNewLabel((CVSRepositoryLocation)location);
recordReadWriteLocations((CVSRepositoryLocation)location);
}
/*
* @see PreferencesPage#performOk
*/
public boolean performOk() {
if (performConnectionInfoChanges()) {
performNonConnectionInfoChanges();
return true;
}
return false;
}
/**
* 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 (useDefaultReadWriteLocations.getSelection()) {
readLocation.setEnabled(false);
writeLocation.setEnabled(false);
} else {
readLocation.setEnabled(true);
writeLocation.setEnabled(true);
}
validateFields();
}
private void validateFields() {
if (labelText.isEnabled()) {
if (labelText.getText().length() == 0) {
setValid(false);
return;
}
}
setValid(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;
}
try {
CVSUIPlugin.getPlugin().getRepositoryManager().setLabel(location, newLabel);
} catch (CVSException e) {
CVSUIPlugin.log(e);
}
}
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 void recordReadWriteLocations(CVSRepositoryLocation location) {
location.setReadLocation(useDefaultReadWriteLocations.getSelection() ? null : readLocation.getText());
location.setWriteLocation(useDefaultReadWriteLocations.getSelection() ? null : writeLocation.getText());
// TODO: These will be lost if a crash occurres before shutdown
}
}