Java tutorial
/******************************************************************************* * Copyright (C) 2011, Mathias Kinzler <mathias.kinzler@sap.com> * * 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 *******************************************************************************/ package org.eclipse.egit.ui.internal.fetch; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.internal.UIText; import org.eclipse.egit.ui.internal.push.RefSpecDialog; import org.eclipse.egit.ui.internal.push.RefSpecWizard; import org.eclipse.egit.ui.internal.repository.SelectUriWizard; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.URIish; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; 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.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; /** * A simplified wizard for configuring fetch */ public class SimpleConfigureFetchDialog extends TitleAreaDialog { private static final int DRY_RUN = 98; private static final int SAVE_ONLY = 97; private static final int REVERT = 96; private static final String ADVANCED_MODE_PREFERENCE = SimpleConfigureFetchDialog.class.getName() + "_ADVANCED_MODE"; //$NON-NLS-1$ private final Repository repository; private RemoteConfig config; private final boolean showBranchInfo; private Text commonUriText; private TableViewer specViewer; private Button changeCommonUri; private Button addRefSpec; private Button changeRefSpec; private Button addRefSpecAdvanced; /** * @param shell * @param repository * @return the dialog to open, or null */ public static Dialog getDialog(Shell shell, Repository repository) { RemoteConfig configToUse = getConfiguredRemote(repository); return new SimpleConfigureFetchDialog(shell, repository, configToUse, true); } /** * @param shell * @param repository * @param remoteName * the remote name to use * @return the dialog to open, or null */ public static Dialog getDialog(Shell shell, Repository repository, String remoteName) { RemoteConfig configToUse; try { configToUse = new RemoteConfig(repository.getConfig(), remoteName); } catch (URISyntaxException e) { Activator.handleError(e.getMessage(), e, true); return null; } return new SimpleConfigureFetchDialog(shell, repository, configToUse, false); } /** * @param repository * @return the configured remote for the current branch, or the default * remote; <code>null</code> if a local branch is checked out that * points to "." as remote */ public static RemoteConfig getConfiguredRemote(Repository repository) { String branch; try { branch = repository.getBranch(); } catch (IOException e) { Activator.handleError(e.getMessage(), e, true); return null; } if (branch == null) return null; String remoteName; if (ObjectId.isId(branch)) remoteName = Constants.DEFAULT_REMOTE_NAME; else remoteName = repository.getConfig().getString(ConfigConstants.CONFIG_BRANCH_SECTION, branch, ConfigConstants.CONFIG_REMOTE_SECTION); // check if we find the configured and default Remotes List<RemoteConfig> allRemotes; try { allRemotes = RemoteConfig.getAllRemoteConfigs(repository.getConfig()); } catch (URISyntaxException e) { allRemotes = new ArrayList<RemoteConfig>(); } RemoteConfig defaultConfig = null; RemoteConfig configuredConfig = null; for (RemoteConfig config : allRemotes) { if (config.getName().equals(Constants.DEFAULT_REMOTE_NAME)) defaultConfig = config; if (remoteName != null && config.getName().equals(remoteName)) configuredConfig = config; } RemoteConfig configToUse = configuredConfig != null ? configuredConfig : defaultConfig; return configToUse; } /** * @param shell * @param repository * @param config * @param showBranchInfo * should be true if this is used for upstream configuration; if * false, branch information will be hidden in the dialog */ private SimpleConfigureFetchDialog(Shell shell, Repository repository, RemoteConfig config, boolean showBranchInfo) { super(shell); setHelpAvailable(false); setShellStyle(getShellStyle() | SWT.SHELL_TRIM); this.repository = repository; this.config = config; this.showBranchInfo = showBranchInfo; // Add default fetch ref spec if this is a new remote config if (config.getFetchRefSpecs().isEmpty() && !repository.getConfig() .getSubsections(ConfigConstants.CONFIG_REMOTE_SECTION).contains(config.getName())) { StringBuilder defaultRefSpec = new StringBuilder(); defaultRefSpec.append('+'); defaultRefSpec.append(Constants.R_HEADS); defaultRefSpec.append('*').append(':'); defaultRefSpec.append(Constants.R_REMOTES); defaultRefSpec.append(config.getName()); defaultRefSpec.append(RefSpec.WILDCARD_SUFFIX); config.addFetchRefSpec(new RefSpec(defaultRefSpec.toString())); } } @Override protected Control createDialogArea(Composite parent) { boolean advancedMode = Activator.getDefault().getPreferenceStore().getBoolean(ADVANCED_MODE_PREFERENCE); final Composite main = new Composite(parent, SWT.NONE); main.setLayout(new GridLayout(1, false)); GridDataFactory.fillDefaults().grab(true, true).applyTo(main); if (showBranchInfo) { Composite branchArea = new Composite(main, SWT.NONE); GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(false).applyTo(branchArea); GridDataFactory.fillDefaults().grab(true, false).applyTo(branchArea); Label branchLabel = new Label(branchArea, SWT.NONE); branchLabel.setText(UIText.SimpleConfigureFetchDialog_BranchLabel); String branch; try { branch = repository.getBranch(); } catch (IOException e2) { branch = null; } if (branch == null || ObjectId.isId(branch)) branch = UIText.SimpleConfigureFetchDialog_DetachedHeadMessage; Text branchText = new Text(branchArea, SWT.BORDER | SWT.READ_ONLY); GridDataFactory.fillDefaults().grab(true, false).applyTo(branchText); branchText.setText(branch); } addDefaultOriginWarningIfNeeded(main); final Composite sameUriDetails = new Composite(main, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(4).equalWidth(false).applyTo(sameUriDetails); GridDataFactory.fillDefaults().grab(true, false).applyTo(sameUriDetails); Label commonUriLabel = new Label(sameUriDetails, SWT.NONE); commonUriLabel.setText(UIText.SimpleConfigureFetchDialog_UriLabel); commonUriText = new Text(sameUriDetails, SWT.BORDER | SWT.READ_ONLY); GridDataFactory.fillDefaults().grab(true, false).applyTo(commonUriText); changeCommonUri = new Button(sameUriDetails, SWT.PUSH); changeCommonUri.setText(UIText.SimpleConfigureFetchDialog_ChangeUriButton); changeCommonUri.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { SelectUriWizard wiz; if (commonUriText.getText().length() > 0) wiz = new SelectUriWizard(true, commonUriText.getText()); else wiz = new SelectUriWizard(true); if (new WizardDialog(getShell(), wiz).open() == Window.OK) { if (commonUriText.getText().length() > 0) try { config.removeURI(new URIish(commonUriText.getText())); } catch (URISyntaxException ex) { Activator.handleError(ex.getMessage(), ex, true); } config.addURI(wiz.getUri()); updateControls(); } } }); final Button deleteCommonUri = new Button(sameUriDetails, SWT.PUSH); deleteCommonUri.setText(UIText.SimpleConfigureFetchDialog_DeleteUriButton); deleteCommonUri.setEnabled(false); deleteCommonUri.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { config.removeURI(config.getURIs().get(0)); updateControls(); } }); commonUriText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { deleteCommonUri.setEnabled(commonUriText.getText().length() > 0); } }); final Group refSpecGroup = new Group(main, SWT.SHADOW_ETCHED_IN); GridDataFactory.fillDefaults().grab(true, true).applyTo(refSpecGroup); refSpecGroup.setText(UIText.SimpleConfigureFetchDialog_RefMappingGroup); refSpecGroup.setLayout(new GridLayout(2, false)); specViewer = new TableViewer(refSpecGroup, SWT.BORDER | SWT.MULTI); specViewer.setContentProvider(ArrayContentProvider.getInstance()); GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 150).minSize(SWT.DEFAULT, 30).grab(true, true) .applyTo(specViewer.getTable()); specViewer.getTable().addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.stateMask == SWT.MOD1 && e.keyCode == 'v') doPaste(); } }); Composite buttonArea = new Composite(refSpecGroup, SWT.NONE); GridLayoutFactory.fillDefaults().applyTo(buttonArea); GridDataFactory.fillDefaults().grab(false, true).applyTo(buttonArea); addRefSpec = new Button(buttonArea, SWT.PUSH); addRefSpec.setText(UIText.SimpleConfigureFetchDialog_AddRefSpecButton); GridDataFactory.fillDefaults().applyTo(addRefSpec); addRefSpec.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { SimpleFetchRefSpecWizard wiz = new SimpleFetchRefSpecWizard(repository, config); WizardDialog dlg = new WizardDialog(getShell(), wiz); if (dlg.open() == Window.OK) config.addFetchRefSpec(wiz.getSpec()); updateControls(); } }); changeRefSpec = new Button(buttonArea, SWT.PUSH); changeRefSpec.setText(UIText.SimpleConfigureFetchDialog_ChangeRefSpecButton); changeRefSpec.setEnabled(false); GridDataFactory.fillDefaults().exclude(!advancedMode).applyTo(changeRefSpec); changeRefSpec.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { RefSpec oldSpec = (RefSpec) ((IStructuredSelection) specViewer.getSelection()).getFirstElement(); RefSpecDialog dlg = new RefSpecDialog(getShell(), repository, config, oldSpec, false); if (dlg.open() == Window.OK) { config.removeFetchRefSpec(oldSpec); config.addFetchRefSpec(dlg.getSpec()); } updateControls(); } }); final Button deleteRefSpec = new Button(buttonArea, SWT.PUSH); deleteRefSpec.setText(UIText.SimpleConfigureFetchDialog_DeleteRefSpecButton); GridDataFactory.fillDefaults().applyTo(deleteRefSpec); deleteRefSpec.setEnabled(false); deleteRefSpec.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { for (Object spec : ((IStructuredSelection) specViewer.getSelection()).toArray()) config.removeFetchRefSpec((RefSpec) spec); updateControls(); } }); final Button copySpec = new Button(buttonArea, SWT.PUSH); copySpec.setText(UIText.SimpleConfigureFetchDialog_CopyRefSpecButton); GridDataFactory.fillDefaults().applyTo(copySpec); copySpec.setEnabled(false); copySpec.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { String toCopy = ((IStructuredSelection) specViewer.getSelection()).getFirstElement().toString(); Clipboard clipboard = new Clipboard(getShell().getDisplay()); try { clipboard.setContents(new String[] { toCopy }, new TextTransfer[] { TextTransfer.getInstance() }); } finally { clipboard.dispose(); } } }); final Button pasteSpec = new Button(buttonArea, SWT.PUSH); pasteSpec.setText(UIText.SimpleConfigureFetchDialog_PateRefSpecButton); GridDataFactory.fillDefaults().applyTo(pasteSpec); pasteSpec.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { doPaste(); } }); addRefSpecAdvanced = new Button(buttonArea, SWT.PUSH); GridDataFactory.fillDefaults().applyTo(addRefSpecAdvanced); addRefSpecAdvanced.setText(UIText.SimpleConfigureFetchDialog_EditAdvancedButton); addRefSpecAdvanced.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (new WizardDialog(getShell(), new RefSpecWizard(repository, config, false)).open() == Window.OK) updateControls(); } }); specViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection sel = (IStructuredSelection) specViewer.getSelection(); copySpec.setEnabled(sel.size() == 1); changeRefSpec.setEnabled(sel.size() == 1); deleteRefSpec.setEnabled(!sel.isEmpty()); } }); applyDialogFont(main); return main; } @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, UIText.SimpleConfigureFetchDialog_SaveAndFetchButton, true); createButton(parent, SAVE_ONLY, UIText.SimpleConfigureFetchDialog_SaveButton, false); createButton(parent, DRY_RUN, UIText.SimpleConfigureFetchDialog_DryRunButton, false); createButton(parent, REVERT, UIText.SimpleConfigureFetchDialog_RevertButton, false); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(UIText.SimpleConfigureFetchDialog_WindowTitle); } @Override public void create() { super.create(); setTitle(NLS.bind(UIText.SimpleConfigureFetchDialog_DialogTitle, config.getName())); setMessage(UIText.SimpleConfigureFetchDialog_DialogMessage); updateControls(); } private void updateControls() { setErrorMessage(null); boolean anyUri = false; if (!config.getURIs().isEmpty()) { commonUriText.setText(config.getURIs().get(0).toPrivateString()); anyUri = true; } else commonUriText.setText(""); //$NON-NLS-1$ specViewer.setInput(config.getFetchRefSpecs()); specViewer.getTable().setEnabled(true); addRefSpec.setEnabled(anyUri); addRefSpecAdvanced.setEnabled(anyUri); if (config.getURIs().isEmpty()) setErrorMessage(UIText.SimpleConfigureFetchDialog_MissingUriMessage); else if (config.getFetchRefSpecs().isEmpty()) setErrorMessage(UIText.SimpleConfigureFetchDialog_MissingMappingMessage); boolean anySpec = !config.getFetchRefSpecs().isEmpty(); getButton(OK).setEnabled(anyUri && anySpec); getButton(SAVE_ONLY).setEnabled(anyUri && anySpec); } @Override protected void buttonPressed(int buttonId) { if (buttonId == DRY_RUN) { try { new ProgressMonitorDialog(getShell()).run(false, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { int timeout = Activator.getDefault().getPreferenceStore() .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT); FetchOperationUI op = new FetchOperationUI(repository, config, timeout, true); try { FetchResultDialog dlg; dlg = new FetchResultDialog(getShell(), repository, op.execute(monitor), op.getSourceString()); dlg.showConfigureButton(false); dlg.open(); } catch (CoreException e) { Activator.handleError(e.getMessage(), e, true); } } }); } catch (InvocationTargetException e1) { Activator.handleError(e1.getMessage(), e1, true); } catch (InterruptedException e1) { // ignore here } return; } if (buttonId == REVERT) { try { config = new RemoteConfig(repository.getConfig(), config.getName()); updateControls(); } catch (URISyntaxException e) { Activator.handleError(e.getMessage(), e, true); } return; } if (buttonId == OK || buttonId == SAVE_ONLY) { config.update(repository.getConfig()); try { repository.getConfig().save(); } catch (IOException e) { Activator.handleError(e.getMessage(), e, true); } if (buttonId == OK) try { new ProgressMonitorDialog(getShell()).run(false, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { int timeout = Activator.getDefault().getPreferenceStore() .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT); FetchOperationUI op = new FetchOperationUI(repository, config, timeout, false); op.start(); } }); } catch (InvocationTargetException e) { Activator.handleError(e.getMessage(), e, true); } catch (InterruptedException e) { Activator.handleError(e.getMessage(), e, true); } okPressed(); return; } super.buttonPressed(buttonId); } private void doPaste() { Clipboard clipboard = new Clipboard(getShell().getDisplay()); try { String content = (String) clipboard.getContents(TextTransfer.getInstance()); if (content == null) MessageDialog.openConfirm(getShell(), UIText.SimpleConfigureFetchDialog_NothingToPasteMessage, UIText.SimpleConfigureFetchDialog_EmptyClipboardMessage); try { RefSpec spec = new RefSpec(content); Ref source; try { // TODO better checks for wild-cards and such source = repository.getRef(spec.getDestination()); } catch (IOException e1) { source = null; } if (source != null || MessageDialog.openQuestion(getShell(), UIText.SimpleConfigureFetchDialog_InvalidRefDialogTitle, NLS.bind(UIText.SimpleConfigureFetchDialog_InvalidRefDialogMessage, spec.toString()))) config.addFetchRefSpec(spec); updateControls(); } catch (IllegalArgumentException ex) { MessageDialog.openError(getShell(), UIText.SimpleConfigureFetchDialog_NotRefSpecDialogTitle, UIText.SimpleConfigureFetchDialog_NotRefSpecDialogMessage); } } finally { clipboard.dispose(); } } /** * Add a warning about this remote being used by other branches * * @param parent */ private void addDefaultOriginWarningIfNeeded(Composite parent) { if (!showBranchInfo) return; List<String> otherBranches = new ArrayList<String>(); String currentBranch; try { currentBranch = repository.getBranch(); } catch (IOException e) { // just don't show this warning return; } String currentRemote = config.getName(); Config repositoryConfig = repository.getConfig(); Set<String> branches = repositoryConfig.getSubsections(ConfigConstants.CONFIG_BRANCH_SECTION); for (String branch : branches) { if (branch.equals(currentBranch)) continue; String remote = repositoryConfig.getString(ConfigConstants.CONFIG_BRANCH_SECTION, branch, ConfigConstants.CONFIG_KEY_REMOTE); if ((remote == null && currentRemote.equals(Constants.DEFAULT_REMOTE_NAME)) || (remote != null && remote.equals(currentRemote))) otherBranches.add(branch); } if (otherBranches.isEmpty()) return; Composite warningAboutOrigin = new Composite(parent, SWT.NONE); warningAboutOrigin.setLayout(new GridLayout(2, false)); Label warningLabel = new Label(warningAboutOrigin, SWT.NONE); warningLabel .setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK)); Text warningText = new Text(warningAboutOrigin, SWT.READ_ONLY); warningText.setText(NLS.bind(UIText.SimpleConfigureFetchDialog_ReusedRemoteWarning, config.getName(), Integer.valueOf(otherBranches.size()))); warningText.setToolTipText(otherBranches.toString()); GridDataFactory.fillDefaults().grab(true, false).applyTo(warningLabel); } }