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
;
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
;
41 * Wizard page that allows the user entering the location of a repository to be
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
;
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
;
77 private Text hostText
;
79 private Text pathText
;
81 private Text userText
;
83 private Text passText
;
87 private Text portText
;
89 private int eventDepth
;
91 private URIish uri
= new URIish();
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
);
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
) {
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());
141 portText
.setText(Integer
.toString(u
.getPort()));
143 portText
.setText("");
146 scheme
.select(S_FILE
);
148 scheme
.select(S_SSH
);
150 for (int i
= 0; i
< DEFAULT_SCHEMES
.length
; i
++) {
151 if (DEFAULT_SCHEMES
[i
].equals(u
.getScheme())) {
160 for (final URIishChangeListener l
: uriishChangeListeners
)
162 setPageComplete(isPageComplete());
163 } catch (URISyntaxException err
) {
165 setErrorMessage(err
.getMessage());
166 setPageComplete(false);
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());
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
) {
223 public void widgetSelected(final SelectionEvent e
) {
224 final int idx
= scheme
.getSelectionIndex();
226 setURI(uri
.setScheme(null));
228 setURI(uri
.setScheme(nullString(scheme
.getItem(idx
))));
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();
241 v
.substring(0, e
.start
) + e
.text
+ v
.substring(e
.end
))
245 portText
.addModifyListener(new ModifyListener() {
246 public void modifyText(final ModifyEvent e
) {
247 final String val
= nullString(portText
.getText());
249 setURI(uri
.setPort(-1));
252 setURI(uri
.setPort(Integer
.parseInt(val
)));
253 } catch (NumberFormatException err
) {
254 // Ignore it for now.
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;
268 final GridData gd
= new GridData();
269 gd
.grabExcessHorizontalSpace
= true;
270 gd
.horizontalAlignment
= SWT
.FILL
;
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());
294 public boolean isPageComplete() {
295 if (uriText
.getText().length() == 0) {
296 setErrorMessage(null);
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) {
308 setErrorMessage(NLS
.bind(UIText
.CloneSourcePage_fieldRequired
,
309 UIText
.CloneSourcePage_promptPath
, proto
));
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) {
323 setErrorMessage(NLS
.bind(
324 UIText
.CloneSourcePage_fieldNotSupported
, badField
,
329 final File d
= FS
.resolve(new File("."), uri
.getPath());
331 setErrorMessage(NLS
.bind(
332 UIText
.CloneSourcePage_fileNotFound
, d
333 .getAbsolutePath()));
336 setErrorMessage(null);
340 if (uri
.getHost() == null) {
342 setErrorMessage(NLS
.bind(UIText
.CloneSourcePage_fieldRequired
,
343 UIText
.CloneSourcePage_promptHost
, proto
));
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) {
355 setErrorMessage(NLS
.bind(
356 UIText
.CloneSourcePage_fieldNotSupported
, badField
,
362 setErrorMessage(null);
364 } catch (URISyntaxException e
) {
366 setErrorMessage(e
.getReason());
368 } catch (Exception e
) {
370 Activator
.logError("Error validating " + getClass().getName(), e
);
371 setErrorMessage(UIText
.CloneSourcePage_internalError
);
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()))
383 if (uri
.getHost() != null || uri
.getPort() > 0 || uri
.getUser() != null
384 || uri
.getPass() != null || uri
.getPath() == null)
386 if (uri
.getScheme() == null)
387 return FS
.resolve(new File("."), uri
.getPath()).isDirectory();
391 private static boolean isSSH(final URIish uri
) {
394 final String scheme
= uri
.getScheme();
395 if ("ssh".equals(scheme
))
397 if ("ssh+git".equals(scheme
))
399 if ("git+ssh".equals(scheme
))
401 if (scheme
== null && uri
.getHost() != null && uri
.getPath() != null)
406 private static String
nullString(final String value
) {
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
) {
420 if (eventDepth
== 1) {
421 for (final URIishChangeListener l
: uriishChangeListeners
)
424 uriText
.setText(uri
.toString());
425 setPageComplete(isPageComplete());
432 private void updateAuthGroup() {
433 switch (scheme
.getSelectionIndex()) {
435 hostText
.setEnabled(true);
436 portText
.setEnabled(true);
437 authGroup
.setEnabled(false);
444 hostText
.setEnabled(true);
445 portText
.setEnabled(true);
446 authGroup
.setEnabled(true);
449 hostText
.setEnabled(false);
450 portText
.setEnabled(false);
451 authGroup
.setEnabled(false);
456 private void uriInvalid() {
457 for (final URIishChangeListener l
: uriishChangeListeners
)
458 l
.uriishChanged(null);