Fix typo in uitext.properties message
[egit/zawir.git] / org.spearce.egit.ui / src / org / spearce / egit / ui / internal / clone / CloneSourcePage.java
blob4bdd6afbae6bb9e76565d1800d26ae39e336f25a
1 /*******************************************************************************
2 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
4 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * See LICENSE for the full license text, also available.
9 *******************************************************************************/
10 package org.spearce.egit.ui.internal.clone;
12 import java.io.File;
13 import java.net.URISyntaxException;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.regex.Pattern;
18 import org.eclipse.jface.wizard.WizardPage;
19 import org.eclipse.osgi.util.NLS;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.ModifyEvent;
22 import org.eclipse.swt.events.ModifyListener;
23 import org.eclipse.swt.events.SelectionEvent;
24 import org.eclipse.swt.events.SelectionListener;
25 import org.eclipse.swt.events.VerifyEvent;
26 import org.eclipse.swt.events.VerifyListener;
27 import org.eclipse.swt.layout.GridData;
28 import org.eclipse.swt.layout.GridLayout;
29 import org.eclipse.swt.widgets.Combo;
30 import org.eclipse.swt.widgets.Composite;
31 import org.eclipse.swt.widgets.Group;
32 import org.eclipse.swt.widgets.Label;
33 import org.eclipse.swt.widgets.Text;
34 import org.spearce.egit.ui.Activator;
35 import org.spearce.egit.ui.UIIcons;
36 import org.spearce.egit.ui.UIText;
37 import org.spearce.jgit.transport.URIish;
38 import org.spearce.jgit.util.FS;
40 /**
41 * Wizard page that allows the user entering the location of a repository to be
42 * cloned.
44 class CloneSourcePage extends WizardPage {
45 private static final int S_GIT = 0;
47 private static final int S_SSH = 1;
49 private static final int S_SFTP = 2;
51 private static final int S_HTTP = 3;
53 private static final int S_HTTPS = 4;
55 private static final int S_FTP = 5;
57 private static final int S_FILE = 6;
59 private static final String[] DEFAULT_SCHEMES;
60 static {
61 DEFAULT_SCHEMES = new String[7];
62 DEFAULT_SCHEMES[S_GIT] = "git";
63 DEFAULT_SCHEMES[S_SSH] = "git+ssh";
64 DEFAULT_SCHEMES[S_SFTP] = "sftp";
65 DEFAULT_SCHEMES[S_HTTP] = "http";
66 DEFAULT_SCHEMES[S_HTTPS] = "https";
67 DEFAULT_SCHEMES[S_FTP] = "ftp";
68 DEFAULT_SCHEMES[S_FILE] = "file";
71 private final List<URIishChangeListener> uriishChangeListeners;
73 private Group authGroup;
75 private Text uriText;
77 private Text hostText;
79 private Text pathText;
81 private Text userText;
83 private Text passText;
85 private Combo scheme;
87 private Text portText;
89 private int eventDepth;
91 private URIish uri = new URIish();
93 CloneSourcePage() {
94 super(CloneSourcePage.class.getName());
95 setTitle(UIText.CloneSourcePage_title);
96 setDescription(UIText.CloneSourcePage_description);
97 setImageDescriptor(UIIcons.WIZBAN_IMPORT_REPO);
98 uriishChangeListeners = new ArrayList<URIishChangeListener>(4);
101 void addURIishChangeListener(final URIishChangeListener l) {
102 uriishChangeListeners.add(l);
105 public void createControl(final Composite parent) {
106 final Composite panel = new Composite(parent, SWT.NULL);
107 final GridLayout layout = new GridLayout();
108 layout.numColumns = 1;
109 panel.setLayout(layout);
111 createLocationGroup(panel);
112 createConnectionGroup(panel);
113 authGroup = createAuthenticationGroup(panel);
115 updateAuthGroup();
116 setControl(panel);
117 setPageComplete(false);
120 private void createLocationGroup(final Composite parent) {
121 final Group g = createGroup(parent,
122 UIText.CloneSourcePage_groupLocation);
124 newLabel(g, UIText.CloneSourcePage_promptURI + ":");
125 uriText = new Text(g, SWT.BORDER);
126 uriText.setLayoutData(createFieldGridData());
127 uriText.addModifyListener(new ModifyListener() {
128 public void modifyText(final ModifyEvent e) {
129 try {
130 eventDepth++;
131 if (eventDepth != 1)
132 return;
134 final URIish u = new URIish(uriText.getText());
135 safeSet(hostText, u.getHost());
136 safeSet(pathText, u.getPath());
137 safeSet(userText, u.getUser());
138 safeSet(passText, u.getPass());
140 if (u.getPort() > 0)
141 portText.setText(Integer.toString(u.getPort()));
142 else
143 portText.setText("");
145 if (isFile(u))
146 scheme.select(S_FILE);
147 else if (isSSH(u))
148 scheme.select(S_SSH);
149 else {
150 for (int i = 0; i < DEFAULT_SCHEMES.length; i++) {
151 if (DEFAULT_SCHEMES[i].equals(u.getScheme())) {
152 scheme.select(i);
153 break;
158 updateAuthGroup();
159 uri = u;
160 for (final URIishChangeListener l : uriishChangeListeners)
161 l.uriishChanged(u);
162 setPageComplete(isPageComplete());
163 } catch (URISyntaxException err) {
164 uriInvalid();
165 setErrorMessage(err.getMessage());
166 setPageComplete(false);
167 } finally {
168 eventDepth--;
173 newLabel(g, UIText.CloneSourcePage_promptHost + ":");
174 hostText = new Text(g, SWT.BORDER);
175 hostText.setLayoutData(createFieldGridData());
176 hostText.addModifyListener(new ModifyListener() {
177 public void modifyText(final ModifyEvent e) {
178 setURI(uri.setHost(nullString(hostText.getText())));
182 newLabel(g, UIText.CloneSourcePage_promptPath + ":");
183 pathText = new Text(g, SWT.BORDER);
184 pathText.setLayoutData(createFieldGridData());
185 pathText.addModifyListener(new ModifyListener() {
186 public void modifyText(final ModifyEvent e) {
187 setURI(uri.setPath(nullString(pathText.getText())));
192 private Group createAuthenticationGroup(final Composite parent) {
193 final Group g = createGroup(parent,
194 UIText.CloneSourcePage_groupAuthentication);
196 newLabel(g, UIText.CloneSourcePage_promptUser + ":");
197 userText = new Text(g, SWT.BORDER);
198 userText.setLayoutData(createFieldGridData());
199 userText.addModifyListener(new ModifyListener() {
200 public void modifyText(final ModifyEvent e) {
201 setURI(uri.setUser(nullString(userText.getText())));
205 newLabel(g, UIText.CloneSourcePage_promptPassword + ":");
206 passText = new Text(g, SWT.BORDER | SWT.PASSWORD);
207 passText.setLayoutData(createFieldGridData());
208 return g;
211 private void createConnectionGroup(final Composite parent) {
212 final Group g = createGroup(parent,
213 UIText.CloneSourcePage_groupConnection);
215 newLabel(g, UIText.CloneSourcePage_promptScheme + ":");
216 scheme = new Combo(g, SWT.DROP_DOWN | SWT.READ_ONLY);
217 scheme.setItems(DEFAULT_SCHEMES);
218 scheme.addSelectionListener(new SelectionListener() {
219 public void widgetDefaultSelected(final SelectionEvent e) {
220 // Nothing
223 public void widgetSelected(final SelectionEvent e) {
224 final int idx = scheme.getSelectionIndex();
225 if (idx < 0)
226 setURI(uri.setScheme(null));
227 else
228 setURI(uri.setScheme(nullString(scheme.getItem(idx))));
229 updateAuthGroup();
233 newLabel(g, UIText.CloneSourcePage_promptPort + ":");
234 portText = new Text(g, SWT.BORDER);
235 portText.addVerifyListener(new VerifyListener() {
236 final Pattern p = Pattern.compile("^(?:[1-9][0-9]*)?$");
238 public void verifyText(final VerifyEvent e) {
239 final String v = portText.getText();
240 e.doit = p.matcher(
241 v.substring(0, e.start) + e.text + v.substring(e.end))
242 .matches();
245 portText.addModifyListener(new ModifyListener() {
246 public void modifyText(final ModifyEvent e) {
247 final String val = nullString(portText.getText());
248 if (val == null)
249 setURI(uri.setPort(-1));
250 else {
251 try {
252 setURI(uri.setPort(Integer.parseInt(val)));
253 } catch (NumberFormatException err) {
254 // Ignore it for now.
255 uriInvalid();
262 private static Group createGroup(final Composite parent, final String text) {
263 final Group g = new Group(parent, SWT.NONE);
264 final GridLayout layout = new GridLayout();
265 layout.numColumns = 2;
266 g.setLayout(layout);
267 g.setText(text);
268 final GridData gd = new GridData();
269 gd.grabExcessHorizontalSpace = true;
270 gd.horizontalAlignment = SWT.FILL;
271 g.setLayoutData(gd);
272 return g;
275 private static void newLabel(final Group g, final String text) {
276 new Label(g, SWT.NULL).setText(text);
279 private static GridData createFieldGridData() {
280 return new GridData(SWT.FILL, SWT.DEFAULT, true, false);
284 * Returns the URI entered in the Wizard page.
286 * @return the URI entered in the Wizard page.
287 * @throws URISyntaxException
289 public URIish getURI() throws URISyntaxException {
290 return new URIish(uriText.getText());
293 @Override
294 public boolean isPageComplete() {
295 if (uriText.getText().length() == 0) {
296 setErrorMessage(null);
297 return false;
300 try {
301 final URIish finalURI = getURI();
302 String proto = finalURI.getScheme();
303 if (proto == null && scheme.getSelectionIndex() >= 0)
304 proto = scheme.getItem(scheme.getSelectionIndex());
306 if (uri.getPath() == null) {
307 uriInvalid();
308 setErrorMessage(NLS.bind(UIText.CloneSourcePage_fieldRequired,
309 UIText.CloneSourcePage_promptPath, proto));
310 return false;
313 if (isFile(finalURI)) {
314 String badField = null;
315 if (uri.getHost() != null)
316 badField = UIText.CloneSourcePage_promptHost;
317 else if (uri.getUser() != null)
318 badField = UIText.CloneSourcePage_promptUser;
319 else if (uri.getPass() != null)
320 badField = UIText.CloneSourcePage_promptPassword;
321 if (badField != null) {
322 uriInvalid();
323 setErrorMessage(NLS.bind(
324 UIText.CloneSourcePage_fieldNotSupported, badField,
325 proto));
326 return false;
329 final File d = FS.resolve(new File("."), uri.getPath());
330 if (!d.exists()) {
331 setErrorMessage(NLS.bind(
332 UIText.CloneSourcePage_fileNotFound, d
333 .getAbsolutePath()));
334 return false;
336 setErrorMessage(null);
337 return true;
340 if (uri.getHost() == null) {
341 uriInvalid();
342 setErrorMessage(NLS.bind(UIText.CloneSourcePage_fieldRequired,
343 UIText.CloneSourcePage_promptHost, proto));
344 return false;
347 if (isGIT(finalURI)) {
348 String badField = null;
349 if (uri.getUser() != null)
350 badField = UIText.CloneSourcePage_promptUser;
351 else if (uri.getPass() != null)
352 badField = UIText.CloneSourcePage_promptPassword;
353 if (badField != null) {
354 uriInvalid();
355 setErrorMessage(NLS.bind(
356 UIText.CloneSourcePage_fieldNotSupported, badField,
357 proto));
358 return false;
362 setErrorMessage(null);
363 return true;
364 } catch (URISyntaxException e) {
365 uriInvalid();
366 setErrorMessage(e.getReason());
367 return false;
368 } catch (Exception e) {
369 uriInvalid();
370 Activator.logError("Error validating " + getClass().getName(), e);
371 setErrorMessage(UIText.CloneSourcePage_internalError);
372 return false;
376 private static boolean isGIT(final URIish uri) {
377 return "git".equals(uri.getScheme());
380 private static boolean isFile(final URIish uri) {
381 if ("file".equals(uri.getScheme()))
382 return true;
383 if (uri.getHost() != null || uri.getPort() > 0 || uri.getUser() != null
384 || uri.getPass() != null || uri.getPath() == null)
385 return false;
386 if (uri.getScheme() == null)
387 return FS.resolve(new File("."), uri.getPath()).isDirectory();
388 return false;
391 private static boolean isSSH(final URIish uri) {
392 if (!uri.isRemote())
393 return false;
394 final String scheme = uri.getScheme();
395 if ("ssh".equals(scheme))
396 return true;
397 if ("ssh+git".equals(scheme))
398 return true;
399 if ("git+ssh".equals(scheme))
400 return true;
401 if (scheme == null && uri.getHost() != null && uri.getPath() != null)
402 return true;
403 return false;
406 private static String nullString(final String value) {
407 if (value == null)
408 return null;
409 final String v = value.trim();
410 return v.length() == 0 ? null : v;
413 private static void safeSet(final Text text, final String value) {
414 text.setText(value != null ? value : "");
417 private void setURI(final URIish u) {
418 try {
419 eventDepth++;
420 if (eventDepth == 1) {
421 for (final URIishChangeListener l : uriishChangeListeners)
422 l.uriishChanged(u);
423 uri = u;
424 uriText.setText(uri.toString());
425 setPageComplete(isPageComplete());
427 } finally {
428 eventDepth--;
432 private void updateAuthGroup() {
433 switch (scheme.getSelectionIndex()) {
434 case S_GIT:
435 hostText.setEnabled(true);
436 portText.setEnabled(true);
437 authGroup.setEnabled(false);
438 break;
439 case S_SSH:
440 case S_SFTP:
441 case S_HTTP:
442 case S_HTTPS:
443 case S_FTP:
444 hostText.setEnabled(true);
445 portText.setEnabled(true);
446 authGroup.setEnabled(true);
447 break;
448 case S_FILE:
449 hostText.setEnabled(false);
450 portText.setEnabled(false);
451 authGroup.setEnabled(false);
452 break;
456 private void uriInvalid() {
457 for (final URIishChangeListener l : uriishChangeListeners)
458 l.uriishChanged(null);