Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2004, 2008 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
10 |
* Red Hat, Inc - extensive changes to allow importing of Archive Files |
11 |
* Philippe Ombredanne (pombredanne@nexb.com) |
12 |
* - Bug 101180 [Import/Export] Import Existing Project into Workspace default widget is back button , should be text field |
13 |
* Martin Oberhuber (martin.oberhuber@windriver.com) |
14 |
* - Bug 187318[Wizards] "Import Existing Project" loops forever with cyclic symbolic links |
15 |
* Remy Chi Jian Suen (remy.suen@gmail.com) |
16 |
* - Bug 210568 [Import/Export] [Import/Export] - Refresh button does not update list of projects |
17 |
*******************************************************************************/ |
18 |
package org.eclipse.ui.internal.wizards.projectmigration; |
19 |
|
20 |
import java.io.*; |
21 |
import java.lang.reflect.InvocationTargetException; |
22 |
import java.util.ArrayList; |
23 |
import java.util.Collection; |
24 |
import java.util.HashSet; |
25 |
import java.util.Iterator; |
26 |
import java.util.List; |
27 |
import java.util.Set; |
28 |
|
29 |
import org.eclipse.core.resources.IProject; |
30 |
import org.eclipse.core.resources.IProjectDescription; |
31 |
import org.eclipse.core.runtime.CoreException; |
32 |
import org.eclipse.core.runtime.IPath; |
33 |
import org.eclipse.core.runtime.IProgressMonitor; |
34 |
import org.eclipse.core.runtime.IStatus; |
35 |
import org.eclipse.core.runtime.OperationCanceledException; |
36 |
import org.eclipse.core.runtime.Path; |
37 |
import org.eclipse.core.runtime.Platform; |
38 |
import org.eclipse.core.runtime.Status; |
39 |
import org.eclipse.core.runtime.SubProgressMonitor; |
40 |
import org.eclipse.jface.dialogs.Dialog; |
41 |
import org.eclipse.jface.dialogs.ErrorDialog; |
42 |
import org.eclipse.jface.dialogs.IDialogConstants; |
43 |
import org.eclipse.jface.dialogs.IDialogSettings; |
44 |
import org.eclipse.jface.dialogs.MessageDialog; |
45 |
import org.eclipse.jface.operation.IRunnableWithProgress; |
46 |
import org.eclipse.jface.viewers.CheckStateChangedEvent; |
47 |
import org.eclipse.jface.viewers.CheckboxTreeViewer; |
48 |
import org.eclipse.jface.viewers.ICheckStateListener; |
49 |
import org.eclipse.jface.viewers.ITreeContentProvider; |
50 |
import org.eclipse.jface.viewers.LabelProvider; |
51 |
import org.eclipse.jface.viewers.Viewer; |
52 |
import org.eclipse.jface.viewers.ViewerComparator; |
53 |
import org.eclipse.jface.wizard.WizardPage; |
54 |
import org.eclipse.osgi.util.NLS; |
55 |
import org.eclipse.swt.SWT; |
56 |
import org.eclipse.swt.events.FocusAdapter; |
57 |
import org.eclipse.swt.events.SelectionAdapter; |
58 |
import org.eclipse.swt.events.SelectionEvent; |
59 |
import org.eclipse.swt.events.TraverseEvent; |
60 |
import org.eclipse.swt.events.TraverseListener; |
61 |
import org.eclipse.swt.layout.GridData; |
62 |
import org.eclipse.swt.layout.GridLayout; |
63 |
import org.eclipse.swt.widgets.Button; |
64 |
import org.eclipse.swt.widgets.Composite; |
65 |
import org.eclipse.swt.widgets.DirectoryDialog; |
66 |
import org.eclipse.swt.widgets.Label; |
67 |
import org.eclipse.swt.widgets.Text; |
68 |
|
69 |
//import org.eclipse.cdt.core.CCorePlugin; |
70 |
//import org.eclipse.cdt.ui.CUIPlugin; |
71 |
|
72 |
import org.eclipse.ui.actions.WorkspaceModifyOperation; |
73 |
|
74 |
import org.eclipse.ui.dialogs.IOverwriteQuery; |
75 |
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; |
76 |
import org.eclipse.ui.statushandlers.StatusManager; |
77 |
|
78 |
/** |
79 |
* The ProjectMigrationWizardPage is the page that allows the user to import |
80 |
* projects from a particular location. |
81 |
*/ |
82 |
public class ProjectMigrationWizardPage extends WizardPage implements |
83 |
IOverwriteQuery { |
84 |
|
85 |
/** |
86 |
* The name of the folder containing metadata information for the workspace. |
87 |
*/ |
88 |
public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$ |
89 |
|
90 |
/** |
91 |
* Class declared public only for test suite. |
92 |
* |
93 |
*/ |
94 |
public class ProjectRecord { |
95 |
File projectSystemFile; |
96 |
|
97 |
String projectName; |
98 |
|
99 |
Object parent; |
100 |
|
101 |
int level; |
102 |
|
103 |
IProjectDescription description; |
104 |
|
105 |
/** |
106 |
* Create a record for a project based on the info in the file. |
107 |
* |
108 |
* @param file |
109 |
*/ |
110 |
ProjectRecord(File file) { |
111 |
projectSystemFile = file; |
112 |
setProjectName(); |
113 |
} |
114 |
|
115 |
/** |
116 |
* Set the name of the project based on the projectFile. |
117 |
*/ |
118 |
private void setProjectName() { |
119 |
try { |
120 |
|
121 |
// If we don't have the project name try again |
122 |
if (projectName == null) { |
123 |
IPath path = new Path(projectSystemFile.getPath()); |
124 |
// if the file is in the default location, use the directory |
125 |
// name as the project name |
126 |
if (isDefaultLocation(path)) { |
127 |
projectName = path.segment(path.segmentCount() - 2); |
128 |
description = IDEWorkbenchPlugin.getPluginWorkspace() |
129 |
.newProjectDescription(projectName); |
130 |
} else { |
131 |
description = IDEWorkbenchPlugin.getPluginWorkspace() |
132 |
.loadProjectDescription(path); |
133 |
projectName = description.getName(); |
134 |
} |
135 |
|
136 |
} |
137 |
} catch (CoreException e) { |
138 |
// no good couldn't get the name |
139 |
} |
140 |
} |
141 |
|
142 |
/** |
143 |
* Returns whether the given project description file path is in the |
144 |
* default location for a project |
145 |
* |
146 |
* @param path |
147 |
* The path to examine |
148 |
* @return Whether the given path is the default location for a project |
149 |
*/ |
150 |
private boolean isDefaultLocation(IPath path) { |
151 |
// The project description file must at least be within the project, |
152 |
// which is within the workspace location |
153 |
if (path.segmentCount() < 2) |
154 |
return false; |
155 |
return path.removeLastSegments(2).toFile().equals( |
156 |
Platform.getLocation().toFile()); |
157 |
} |
158 |
|
159 |
/** |
160 |
* Get the name of the project |
161 |
* |
162 |
* @return String |
163 |
*/ |
164 |
public String getProjectName() { |
165 |
return projectName; |
166 |
} |
167 |
|
168 |
/** |
169 |
* Gets the label to be used when rendering this project record in the |
170 |
* UI. |
171 |
* |
172 |
* @return String the label |
173 |
* @since 3.4 |
174 |
*/ |
175 |
public String getProjectLabel() { |
176 |
if (description == null) |
177 |
return projectName; |
178 |
|
179 |
String path = projectSystemFile.getParent(); |
180 |
|
181 |
return NLS |
182 |
.bind( |
183 |
Messages.getString("ProjectMigrationWizardPage.0"), //$NON-NLS-1$ |
184 |
projectName, path); |
185 |
} |
186 |
} |
187 |
|
188 |
// dialog store id constants |
189 |
//private final static String STORE_IGNORE_EXPORTED_INDEX_ID = "ProjectMigrationWizardPage.STORE_IGNORE_EXPORTED_INDEX_ID"; //$NON-NLS-1$ |
190 |
|
191 |
//private final static String STORE_IGNORE_EXPORTED_PROJECT_ID = "ProjectMigrationWizardPage.STORE_IGNORE_EXPORTED_PROJECT_ID"; //$NON-NLS-1$ |
192 |
|
193 |
//private final static String STORE_SHOW_TIMING_PROJECT_ID = "ProjectMigrationWizardPage.STORE_SHOW_TIMING_PROJECT_ID"; //$NON-NLS-1$ |
194 |
|
195 |
private Text directoryPathField; |
196 |
|
197 |
private Text directoryDestinationPathField; |
198 |
|
199 |
private Text newProjectNameField; |
200 |
|
201 |
private Text oldLinkedPathPrefixField; |
202 |
|
203 |
private Text newLinkedPathPrefixField; |
204 |
|
205 |
private CheckboxTreeViewer projectsList; |
206 |
|
207 |
//private Button ignoreExportedIndexCheckbox; |
208 |
|
209 |
//private Button ignoreExportedProjectRefreshCheckBox; |
210 |
|
211 |
//private Button showTimingCheckBox; |
212 |
|
213 |
//private boolean ignoreExportedIndex = false; |
214 |
|
215 |
//private boolean ignoreExportedProjectRefresh = false; |
216 |
|
217 |
//private boolean showTiming = false; |
218 |
|
219 |
private ProjectRecord[] selectedProjects = new ProjectRecord[0]; |
220 |
|
221 |
// Keep track of the directory that we browsed to last time |
222 |
// the wizard was invoked. |
223 |
private static String previouslyBrowsedDirectory = ""; //$NON-NLS-1$ |
224 |
|
225 |
private static String previouslyBrowsedDestinationDirectory = ""; //$NON-NLS-1$ |
226 |
|
227 |
private Button browseDirectoriesButton; |
228 |
|
229 |
private Button browseDestinationDirectoryButton; |
230 |
|
231 |
private IProject[] wsProjects; |
232 |
|
233 |
// The last selected path to minimize searches |
234 |
private String lastPath; |
235 |
|
236 |
// The last time that the file or folder at the selected path was modified |
237 |
// to mimize searches |
238 |
private long lastModified; |
239 |
|
240 |
/** |
241 |
* Creates a new project creation wizard page. |
242 |
* |
243 |
*/ |
244 |
public ProjectMigrationWizardPage() { |
245 |
this("wizardExternalProjectsPage"); //$NON-NLS-1$ |
246 |
} |
247 |
|
248 |
/** |
249 |
* Create a new instance of the receiver. |
250 |
* |
251 |
* @param pageName |
252 |
*/ |
253 |
public ProjectMigrationWizardPage(String pageName) { |
254 |
super(pageName); |
255 |
setPageComplete(false); |
256 |
setTitle(Messages.getString("ProjectMigrationWizardPage.1")); //$NON-NLS-1$ |
257 |
setDescription(Messages.getString("ProjectMigrationWizardPage.2")); //$NON-NLS-1$ |
258 |
} |
259 |
|
260 |
/* |
261 |
* (non-Javadoc) |
262 |
* |
263 |
* @see |
264 |
* org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets |
265 |
* .Composite) |
266 |
*/ |
267 |
public void createControl(Composite parent) { |
268 |
|
269 |
initializeDialogUnits(parent); |
270 |
|
271 |
Composite workArea = new Composite(parent, SWT.NONE); |
272 |
setControl(workArea); |
273 |
|
274 |
workArea.setLayout(new GridLayout()); |
275 |
workArea.setLayoutData(new GridData(GridData.FILL_BOTH |
276 |
| GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL)); |
277 |
|
278 |
createProjectsRoot(workArea); |
279 |
createProjectsList(workArea); |
280 |
createLinkedPathPrefixArea(workArea); |
281 |
createDestinationArea(workArea); |
282 |
createOptionsArea(workArea); |
283 |
restoreWidgetValues(); |
284 |
Dialog.applyDialogFont(workArea); |
285 |
|
286 |
} |
287 |
|
288 |
/** |
289 |
* Create the area with the extra options. |
290 |
* |
291 |
* @param workArea |
292 |
*/ |
293 |
private void createOptionsArea(Composite workArea) { |
294 |
Composite optionsGroup = new Composite(workArea, SWT.NONE); |
295 |
optionsGroup.setLayout(new GridLayout()); |
296 |
optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
297 |
|
298 |
} |
299 |
|
300 |
private void checkForComplete() { |
301 |
if (projectsList.getCheckedElements().length == 1) { |
302 |
String path = directoryDestinationPathField.getText().trim(); |
303 |
if (path.length() > 0) { |
304 |
File dirpath = new File(path); |
305 |
if (dirpath.exists()) { |
306 |
setPageComplete(true); |
307 |
return; |
308 |
} |
309 |
} |
310 |
} |
311 |
|
312 |
setPageComplete(false); |
313 |
} |
314 |
|
315 |
/** |
316 |
* Create the checkbox list for the found projects. |
317 |
* |
318 |
* @param workArea |
319 |
*/ |
320 |
private void createProjectsList(Composite workArea) { |
321 |
|
322 |
Label title = new Label(workArea, SWT.NONE); |
323 |
title |
324 |
.setText(Messages.getString("ProjectMigrationWizardPage.3")); //$NON-NLS-1$ |
325 |
|
326 |
Composite listComposite = new Composite(workArea, SWT.NONE); |
327 |
GridLayout layout = new GridLayout(); |
328 |
layout.numColumns = 2; |
329 |
layout.marginWidth = 0; |
330 |
layout.makeColumnsEqualWidth = false; |
331 |
listComposite.setLayout(layout); |
332 |
|
333 |
listComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL |
334 |
| GridData.GRAB_VERTICAL | GridData.FILL_BOTH)); |
335 |
|
336 |
projectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER); |
337 |
GridData listData = new GridData(GridData.GRAB_HORIZONTAL |
338 |
| GridData.GRAB_VERTICAL | GridData.FILL_BOTH); |
339 |
listData.heightHint = 100; |
340 |
projectsList.getControl().setLayoutData(listData); |
341 |
|
342 |
projectsList.setContentProvider(new ITreeContentProvider() { |
343 |
|
344 |
/* |
345 |
* (non-Javadoc) |
346 |
* |
347 |
* @see |
348 |
* org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java |
349 |
* .lang.Object) |
350 |
*/ |
351 |
public Object[] getChildren(Object parentElement) { |
352 |
return null; |
353 |
} |
354 |
|
355 |
/* |
356 |
* (non-Javadoc) |
357 |
* |
358 |
* @see |
359 |
* org.eclipse.jface.viewers.IStructuredContentProvider#getElements |
360 |
* (java.lang.Object) |
361 |
*/ |
362 |
public Object[] getElements(Object inputElement) { |
363 |
return getValidProjects(); |
364 |
} |
365 |
|
366 |
/* |
367 |
* (non-Javadoc) |
368 |
* |
369 |
* @see |
370 |
* org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java |
371 |
* .lang.Object) |
372 |
*/ |
373 |
public boolean hasChildren(Object element) { |
374 |
return false; |
375 |
} |
376 |
|
377 |
/* |
378 |
* (non-Javadoc) |
379 |
* |
380 |
* @see |
381 |
* org.eclipse.jface.viewers.ITreeContentProvider#getParent(java |
382 |
* .lang.Object) |
383 |
*/ |
384 |
public Object getParent(Object element) { |
385 |
return null; |
386 |
} |
387 |
|
388 |
/* |
389 |
* (non-Javadoc) |
390 |
* |
391 |
* @see org.eclipse.jface.viewers.IContentProvider#dispose() |
392 |
*/ |
393 |
public void dispose() { |
394 |
|
395 |
} |
396 |
|
397 |
/* |
398 |
* (non-Javadoc) |
399 |
* |
400 |
* @see |
401 |
* org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse |
402 |
* .jface.viewers.Viewer, java.lang.Object, java.lang.Object) |
403 |
*/ |
404 |
public void inputChanged(Viewer viewer, Object oldInput, |
405 |
Object newInput) { |
406 |
} |
407 |
|
408 |
}); |
409 |
|
410 |
projectsList.setLabelProvider(new LabelProvider() { |
411 |
/* |
412 |
* (non-Javadoc) |
413 |
* |
414 |
* @see |
415 |
* org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) |
416 |
*/ |
417 |
public String getText(Object element) { |
418 |
return ((ProjectRecord) element).getProjectLabel(); |
419 |
} |
420 |
}); |
421 |
|
422 |
projectsList.addCheckStateListener(new ICheckStateListener() { |
423 |
/* |
424 |
* (non-Javadoc) |
425 |
* |
426 |
* @see |
427 |
* org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged |
428 |
* (org.eclipse.jface.viewers.CheckStateChangedEvent) |
429 |
*/ |
430 |
public void checkStateChanged(CheckStateChangedEvent event) { |
431 |
checkForComplete(); |
432 |
} |
433 |
}); |
434 |
|
435 |
projectsList.setInput(this); |
436 |
projectsList.setComparator(new ViewerComparator()); |
437 |
} |
438 |
|
439 |
/** |
440 |
* Create the checkbox list for the found projects. |
441 |
* |
442 |
* @param workArea |
443 |
*/ |
444 |
private void createLinkedPathPrefixArea(Composite workArea) { |
445 |
|
446 |
// project specification group |
447 |
Composite projectGroup = new Composite(workArea, SWT.NONE); |
448 |
GridLayout layout = new GridLayout(); |
449 |
layout.numColumns = 2; |
450 |
layout.makeColumnsEqualWidth = false; |
451 |
layout.marginWidth = 0; |
452 |
projectGroup.setLayout(layout); |
453 |
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
454 |
|
455 |
// old linked directory path |
456 |
Label oldLinkedPathLabel = new Label(projectGroup, SWT.NONE); |
457 |
oldLinkedPathLabel |
458 |
.setText(Messages.getString("ProjectMigrationWizardPage.4")); //$NON-NLS-1$ |
459 |
|
460 |
this.oldLinkedPathPrefixField = new Text(projectGroup, SWT.BORDER); |
461 |
|
462 |
this.oldLinkedPathPrefixField.setLayoutData(new GridData( |
463 |
GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); |
464 |
|
465 |
// new linked directory path |
466 |
Label newLinkedPathLabel = new Label(projectGroup, SWT.NONE); |
467 |
newLinkedPathLabel |
468 |
.setText(Messages.getString("ProjectMigrationWizardPage.5")); //$NON-NLS-1$ |
469 |
|
470 |
this.newLinkedPathPrefixField = new Text(projectGroup, SWT.BORDER); |
471 |
|
472 |
this.newLinkedPathPrefixField.setLayoutData(new GridData( |
473 |
GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); |
474 |
|
475 |
} |
476 |
|
477 |
/** |
478 |
* Create the checkbox list for the found projects. |
479 |
* |
480 |
* @param workArea |
481 |
*/ |
482 |
private void createDestinationArea(Composite workArea) { |
483 |
|
484 |
// project specification group |
485 |
Composite projectGroup = new Composite(workArea, SWT.NONE); |
486 |
GridLayout layout = new GridLayout(); |
487 |
layout.numColumns = 3; |
488 |
layout.makeColumnsEqualWidth = false; |
489 |
layout.marginWidth = 0; |
490 |
projectGroup.setLayout(layout); |
491 |
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
492 |
|
493 |
Label title = new Label(projectGroup, SWT.NONE); |
494 |
title |
495 |
.setText(Messages.getString("ProjectMigrationWizardPage.6")); //$NON-NLS-1$ |
496 |
|
497 |
// project destination directory location entry field |
498 |
this.directoryDestinationPathField = new Text(projectGroup, SWT.BORDER); |
499 |
|
500 |
this.directoryDestinationPathField.setLayoutData(new GridData( |
501 |
GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); |
502 |
|
503 |
// browse button |
504 |
browseDestinationDirectoryButton = new Button(projectGroup, SWT.PUSH); |
505 |
browseDestinationDirectoryButton |
506 |
.setText(Messages.getString("ProjectMigrationWizardPage.7")); //$NON-NLS-1$ |
507 |
setButtonLayoutData(browseDestinationDirectoryButton); |
508 |
|
509 |
browseDestinationDirectoryButton |
510 |
.addSelectionListener(new SelectionAdapter() { |
511 |
/* |
512 |
* (non-Javadoc) |
513 |
* |
514 |
* @see org.eclipse.swt.events.SelectionAdapter#widgetS |
515 |
* elected(org.eclipse.swt.events.SelectionEvent) |
516 |
*/ |
517 |
public void widgetSelected(SelectionEvent e) { |
518 |
handleLocationDestinationDirectoryButtonPressed(); |
519 |
} |
520 |
}); |
521 |
|
522 |
directoryDestinationPathField |
523 |
.addTraverseListener(new TraverseListener() { |
524 |
|
525 |
/* |
526 |
* (non-Javadoc) |
527 |
* |
528 |
* @see |
529 |
* org.eclipse.swt.events.TraverseListener#keyTraversed( |
530 |
* org.eclipse.swt.events.TraverseEvent) |
531 |
*/ |
532 |
public void keyTraversed(TraverseEvent e) { |
533 |
if (e.detail == SWT.TRAVERSE_RETURN) { |
534 |
e.doit = false; |
535 |
checkForComplete(); |
536 |
} |
537 |
} |
538 |
|
539 |
}); |
540 |
|
541 |
directoryDestinationPathField.addFocusListener(new FocusAdapter() { |
542 |
|
543 |
/* |
544 |
* (non-Javadoc) |
545 |
* |
546 |
* @see |
547 |
* org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt |
548 |
* .events.FocusEvent) |
549 |
*/ |
550 |
public void focusLost(org.eclipse.swt.events.FocusEvent e) { |
551 |
checkForComplete(); |
552 |
} |
553 |
|
554 |
}); |
555 |
|
556 |
Label projectTitle = new Label(projectGroup, SWT.NONE); |
557 |
projectTitle |
558 |
.setText(Messages.getString("ProjectMigrationWizardPage.8")); //$NON-NLS-1$ |
559 |
|
560 |
// project name location entry field |
561 |
this.newProjectNameField = new Text(projectGroup, SWT.BORDER); |
562 |
|
563 |
this.newProjectNameField.setLayoutData(new GridData( |
564 |
GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); |
565 |
} |
566 |
|
567 |
/** |
568 |
* Create the area where you select the root directory for the projects. |
569 |
* |
570 |
* @param workArea |
571 |
* Composite |
572 |
*/ |
573 |
private void createProjectsRoot(Composite workArea) { |
574 |
|
575 |
// project specification group |
576 |
Composite projectGroup = new Composite(workArea, SWT.NONE); |
577 |
GridLayout layout = new GridLayout(); |
578 |
layout.numColumns = 3; |
579 |
layout.makeColumnsEqualWidth = false; |
580 |
layout.marginWidth = 0; |
581 |
projectGroup.setLayout(layout); |
582 |
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
583 |
|
584 |
Label dirTitle = new Label(projectGroup, SWT.NONE); |
585 |
dirTitle |
586 |
.setText(Messages.getString("ProjectMigrationWizardPage.9")); //$NON-NLS-1$ |
587 |
|
588 |
// project location entry field |
589 |
this.directoryPathField = new Text(projectGroup, SWT.BORDER); |
590 |
|
591 |
this.directoryPathField.setLayoutData(new GridData( |
592 |
GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); |
593 |
|
594 |
// browse button |
595 |
browseDirectoriesButton = new Button(projectGroup, SWT.PUSH); |
596 |
browseDirectoriesButton |
597 |
.setText(Messages.getString("ProjectMigrationWizardPage.10")); //$NON-NLS-1$ |
598 |
setButtonLayoutData(browseDirectoriesButton); |
599 |
|
600 |
browseDirectoriesButton.addSelectionListener(new SelectionAdapter() { |
601 |
/* |
602 |
* (non-Javadoc) |
603 |
* |
604 |
* @see org.eclipse.swt.events.SelectionAdapter#widgetS |
605 |
* elected(org.eclipse.swt.events.SelectionEvent) |
606 |
*/ |
607 |
public void widgetSelected(SelectionEvent e) { |
608 |
handleLocationDirectoryButtonPressed(); |
609 |
} |
610 |
|
611 |
}); |
612 |
|
613 |
directoryPathField.addTraverseListener(new TraverseListener() { |
614 |
|
615 |
/* |
616 |
* (non-Javadoc) |
617 |
* |
618 |
* @see |
619 |
* org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse |
620 |
* .swt.events.TraverseEvent) |
621 |
*/ |
622 |
public void keyTraversed(TraverseEvent e) { |
623 |
if (e.detail == SWT.TRAVERSE_RETURN) { |
624 |
e.doit = false; |
625 |
updateProjectsList(directoryPathField.getText().trim()); |
626 |
} |
627 |
} |
628 |
|
629 |
}); |
630 |
|
631 |
directoryPathField.addFocusListener(new FocusAdapter() { |
632 |
|
633 |
/* |
634 |
* (non-Javadoc) |
635 |
* |
636 |
* @see |
637 |
* org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt |
638 |
* .events.FocusEvent) |
639 |
*/ |
640 |
public void focusLost(org.eclipse.swt.events.FocusEvent e) { |
641 |
updateProjectsList(directoryPathField.getText().trim()); |
642 |
} |
643 |
|
644 |
}); |
645 |
} |
646 |
|
647 |
/* |
648 |
* (non-Javadoc) Method declared on IDialogPage. Set the focus on path |
649 |
* fields when page becomes visible. |
650 |
*/ |
651 |
public void setVisible(boolean visible) { |
652 |
super.setVisible(visible); |
653 |
if (visible) { |
654 |
this.directoryPathField.setFocus(); |
655 |
} |
656 |
} |
657 |
|
658 |
/** |
659 |
* Update the list of projects based on path. Method declared public only |
660 |
* for test suite. |
661 |
* |
662 |
* @param path |
663 |
*/ |
664 |
public void updateProjectsList(final String path) { |
665 |
// on an empty path empty selectedProjects |
666 |
if (path == null || path.length() == 0) { |
667 |
setMessage(Messages.getString("ProjectMigrationWizardPage.11")); //$NON-NLS-1$ |
668 |
selectedProjects = new ProjectRecord[0]; |
669 |
projectsList.refresh(true); |
670 |
projectsList.setCheckedElements(selectedProjects); |
671 |
checkForComplete(); |
672 |
lastPath = path; |
673 |
return; |
674 |
} |
675 |
|
676 |
final File directory = new File(path); |
677 |
long modified = directory.lastModified(); |
678 |
if (path.equals(lastPath) && lastModified == modified) { |
679 |
// since the file/folder was not modified and the path did not |
680 |
// change, no refreshing is required |
681 |
return; |
682 |
} |
683 |
|
684 |
lastPath = path; |
685 |
lastModified = modified; |
686 |
|
687 |
try { |
688 |
getContainer().run(true, true, new IRunnableWithProgress() { |
689 |
|
690 |
/* |
691 |
* (non-Javadoc) |
692 |
* |
693 |
* @see |
694 |
* org.eclipse.jface.operation.IRunnableWithProgress#run(org |
695 |
* .eclipse.core.runtime.IProgressMonitor) |
696 |
*/ |
697 |
public void run(IProgressMonitor monitor) { |
698 |
|
699 |
boolean dirSelected = true; |
700 |
|
701 |
monitor |
702 |
.beginTask( |
703 |
Messages.getString("ProjectMigrationWizardPage.12"), //$NON-NLS-1$ |
704 |
100); |
705 |
selectedProjects = new ProjectRecord[0]; |
706 |
Collection files = new ArrayList(); |
707 |
monitor.worked(10); |
708 |
|
709 |
File dirpath = new File(path); |
710 |
if (dirpath.exists()) { |
711 |
dirSelected = true; |
712 |
} |
713 |
|
714 |
if (dirSelected && directory.isDirectory()) { |
715 |
|
716 |
if (!collectProjectFilesFromDirectory(files, directory, |
717 |
null, monitor)) { |
718 |
return; |
719 |
} |
720 |
Iterator filesIterator = files.iterator(); |
721 |
selectedProjects = new ProjectRecord[files.size()]; |
722 |
int index = 0; |
723 |
monitor.worked(50); |
724 |
monitor |
725 |
.subTask(Messages.getString("ProjectMigrationWizardPage.13")); //$NON-NLS-1$ |
726 |
while (filesIterator.hasNext()) { |
727 |
File file = (File) filesIterator.next(); |
728 |
selectedProjects[index] = new ProjectRecord(file); |
729 |
index++; |
730 |
} |
731 |
} else { |
732 |
monitor.worked(60); |
733 |
} |
734 |
monitor.done(); |
735 |
} |
736 |
|
737 |
}); |
738 |
} catch (InvocationTargetException e) { |
739 |
IDEWorkbenchPlugin.log(e.getMessage(), e); |
740 |
} catch (InterruptedException e) { |
741 |
// Nothing to do if the user interrupts. |
742 |
} |
743 |
|
744 |
projectsList.refresh(true); |
745 |
projectsList.setCheckedElements(getValidProjects()); |
746 |
if (getValidProjects().length < selectedProjects.length) { |
747 |
setMessage( |
748 |
Messages.getString("ProjectMigrationWizardPage.14"), //$NON-NLS-1$ |
749 |
WARNING); |
750 |
} else { |
751 |
setMessage(Messages.getString("ProjectMigrationWizardPage.15")); //$NON-NLS-1$ |
752 |
} |
753 |
checkForComplete(); |
754 |
} |
755 |
|
756 |
/** |
757 |
* Display an error dialog with the specified message. |
758 |
* |
759 |
* @param message |
760 |
* the error message |
761 |
*/ |
762 |
protected void displayErrorDialog(String message) { |
763 |
MessageDialog.openError(getContainer().getShell(), |
764 |
getErrorDialogTitle(), message); |
765 |
} |
766 |
|
767 |
/** |
768 |
* Get the title for an error dialog. Subclasses should override. |
769 |
*/ |
770 |
protected String getErrorDialogTitle() { |
771 |
return Messages.getString("ProjectMigrationWizardPage.16"); //$NON-NLS-1$ |
772 |
} |
773 |
|
774 |
/** |
775 |
* Get the title for an error dialog. Subclasses should override. |
776 |
*/ |
777 |
protected String getInformationDialogTitle() { |
778 |
return Messages.getString("ProjectMigrationWizardPage.17"); //$NON-NLS-1$ |
779 |
} |
780 |
|
781 |
/** |
782 |
* Collect the list of .project files that are under directory into files. |
783 |
* |
784 |
* @param files |
785 |
* @param directory |
786 |
* @param directoriesVisited |
787 |
* Set of canonical paths of directories, used as recursion guard |
788 |
* @param monitor |
789 |
* The monitor to report to |
790 |
* @return boolean <code>true</code> if the operation was completed. |
791 |
*/ |
792 |
private boolean collectProjectFilesFromDirectory(Collection files, |
793 |
File directory, Set directoriesVisited, IProgressMonitor monitor) { |
794 |
|
795 |
if (monitor.isCanceled()) { |
796 |
return false; |
797 |
} |
798 |
monitor |
799 |
.subTask(NLS |
800 |
.bind( |
801 |
Messages.getString("ProjectMigrationWizardPage.18"), //$NON-NLS-1$ |
802 |
directory.getPath())); |
803 |
File[] contents = directory.listFiles(); |
804 |
if (contents == null) |
805 |
return false; |
806 |
|
807 |
// Initialize recursion guard for recursive symbolic links |
808 |
if (directoriesVisited == null) { |
809 |
directoriesVisited = new HashSet(); |
810 |
try { |
811 |
directoriesVisited.add(directory.getCanonicalPath()); |
812 |
} catch (IOException exception) { |
813 |
StatusManager.getManager().handle( |
814 |
new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, |
815 |
exception.getLocalizedMessage())); |
816 |
} |
817 |
} |
818 |
|
819 |
// first look for project description files |
820 |
final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME; |
821 |
for (int i = 0; i < contents.length; i++) { |
822 |
File file = contents[i]; |
823 |
if (file.isFile() && file.getName().equals(dotProject)) { |
824 |
files.add(file); |
825 |
// don't search sub-directories since we can't have nested |
826 |
// projects |
827 |
return true; |
828 |
} |
829 |
} |
830 |
return true; |
831 |
|
832 |
} |
833 |
|
834 |
/** |
835 |
* The browse button has been selected. Select the location. |
836 |
*/ |
837 |
protected void handleLocationDirectoryButtonPressed() { |
838 |
|
839 |
DirectoryDialog dialog = new DirectoryDialog(directoryPathField |
840 |
.getShell()); |
841 |
dialog |
842 |
.setMessage(Messages.getString("ProjectMigrationWizardPage.19")); //$NON-NLS-1$ |
843 |
|
844 |
String dirName = directoryPathField.getText().trim(); |
845 |
if (dirName.length() == 0) { |
846 |
dirName = previouslyBrowsedDirectory; |
847 |
} |
848 |
|
849 |
if (dirName.length() == 0) { |
850 |
dialog.setFilterPath(IDEWorkbenchPlugin.getPluginWorkspace().getRoot() |
851 |
.getLocation().toOSString()); |
852 |
} else { |
853 |
File path = new File(dirName); |
854 |
if (path.exists()) { |
855 |
dialog.setFilterPath(new Path(dirName).toOSString()); |
856 |
} |
857 |
} |
858 |
|
859 |
String selectedDirectory = dialog.open(); |
860 |
if (selectedDirectory != null) { |
861 |
previouslyBrowsedDirectory = selectedDirectory; |
862 |
directoryPathField.setText(previouslyBrowsedDirectory); |
863 |
updateProjectsList(selectedDirectory); |
864 |
} |
865 |
|
866 |
} |
867 |
|
868 |
/** |
869 |
* The browse button has been selected. Select the location. |
870 |
*/ |
871 |
protected void handleLocationDestinationDirectoryButtonPressed() { |
872 |
|
873 |
DirectoryDialog dialog = new DirectoryDialog( |
874 |
directoryDestinationPathField.getShell()); |
875 |
dialog |
876 |
.setMessage(Messages.getString("ProjectMigrationWizardPage.20")); //$NON-NLS-1$ |
877 |
|
878 |
String dirName = directoryDestinationPathField.getText().trim(); |
879 |
if (dirName.length() == 0) { |
880 |
dirName = previouslyBrowsedDestinationDirectory; |
881 |
} |
882 |
|
883 |
if (dirName.length() == 0) { |
884 |
dialog.setFilterPath(IDEWorkbenchPlugin.getPluginWorkspace().getRoot() |
885 |
.getLocation().toOSString()); |
886 |
} else { |
887 |
File path = new File(dirName); |
888 |
if (path.exists()) { |
889 |
dialog.setFilterPath(new Path(dirName).toOSString()); |
890 |
} |
891 |
} |
892 |
|
893 |
String selectedDirectory = dialog.open(); |
894 |
if (selectedDirectory != null) { |
895 |
previouslyBrowsedDestinationDirectory = selectedDirectory; |
896 |
directoryDestinationPathField |
897 |
.setText(previouslyBrowsedDestinationDirectory); |
898 |
checkForComplete(); |
899 |
} |
900 |
|
901 |
} |
902 |
|
903 |
/** |
904 |
* Create the selected projects |
905 |
* |
906 |
* @return boolean <code>true</code> if all project creations were |
907 |
* successful. |
908 |
*/ |
909 |
public boolean createProjects() { |
910 |
//long startTime = 0; |
911 |
//long estimatedTime; |
912 |
|
913 |
saveWidgetValues(); |
914 |
final String newProjectName = newProjectNameField.getText().trim(); |
915 |
final String oldLinkedPath = oldLinkedPathPrefixField.getText().trim(); |
916 |
final String newLinkedPath = newLinkedPathPrefixField.getText().trim(); |
917 |
|
918 |
//if (showTiming) |
919 |
//startTime = System.nanoTime(); |
920 |
|
921 |
final IPath sourcePath = new Path(directoryPathField.getText().trim()); |
922 |
final IPath destinationPath = new Path(directoryDestinationPathField |
923 |
.getText().trim()); |
924 |
|
925 |
WorkspaceModifyOperation op = new WorkspaceModifyOperation() { |
926 |
protected void execute(IProgressMonitor monitor) |
927 |
throws InvocationTargetException, InterruptedException { |
928 |
try { |
929 |
ProjectMigrationOperation op = new ProjectMigrationOperation( sourcePath, |
930 |
newProjectName, destinationPath, |
931 |
oldLinkedPath, newLinkedPath); |
932 |
|
933 |
|
934 |
monitor.beginTask("", 1); //$NON-NLS-1$ |
935 |
if (monitor.isCanceled()) { |
936 |
throw new OperationCanceledException(); |
937 |
} |
938 |
op.run(new SubProgressMonitor(monitor, 1)); |
939 |
|
940 |
|
941 |
} finally { |
942 |
monitor.done(); |
943 |
} |
944 |
} |
945 |
}; |
946 |
// run the new project creation operation |
947 |
try { |
948 |
getContainer().run(true, true, op); |
949 |
} catch (InterruptedException e) { |
950 |
return false; |
951 |
} catch (InvocationTargetException e) { |
952 |
// one of the steps resulted in a core exception |
953 |
Throwable t = e.getTargetException(); |
954 |
String message = Messages.getString("ProjectMigrationWizardPage.21"); //$NON-NLS-1$ |
955 |
IStatus status; |
956 |
if (t instanceof CoreException) { |
957 |
status = ((CoreException) t).getStatus(); |
958 |
} else { |
959 |
status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, 1, |
960 |
message, t); |
961 |
} |
962 |
ErrorDialog.openError(getShell(), message, null, status); |
963 |
return false; |
964 |
} |
965 |
return true; |
966 |
} |
967 |
|
968 |
/** |
969 |
* Performs clean-up if the user cancels the wizard without doing anything |
970 |
*/ |
971 |
public void performCancel() { |
972 |
} |
973 |
|
974 |
/** |
975 |
* The <code>WizardDataTransfer</code> implementation of this |
976 |
* <code>IOverwriteQuery</code> method asks the user whether the existing |
977 |
* resource at the given path should be overwritten. |
978 |
* |
979 |
* @param pathString |
980 |
* @return the user's reply: one of <code>"YES"</code>, <code>"NO"</code>, |
981 |
* <code>"ALL"</code>, or <code>"CANCEL"</code> |
982 |
*/ |
983 |
public String queryOverwrite(String pathString) { |
984 |
|
985 |
Path path = new Path(pathString); |
986 |
|
987 |
String messageString; |
988 |
// Break the message up if there is a file name and a directory |
989 |
// and there are at least 2 segments. |
990 |
if (path.getFileExtension() == null || path.segmentCount() < 2) { |
991 |
messageString = NLS.bind( |
992 |
Messages.getString("ProjectMigrationWizardPage.22"), //$NON-NLS-1$ |
993 |
pathString); |
994 |
} else { |
995 |
messageString = NLS |
996 |
.bind( |
997 |
Messages.getString("ProjectMigrationWizardPage.23"), //$NON-NLS-1$ |
998 |
path.lastSegment(), path.removeLastSegments(1) |
999 |
.toOSString()); |
1000 |
} |
1001 |
|
1002 |
final MessageDialog dialog = new MessageDialog(getContainer() |
1003 |
.getShell(), Messages.getString("ProjectMigrationWizardPage.24"), null, //$NON-NLS-1$ |
1004 |
messageString, MessageDialog.QUESTION, new String[] { |
1005 |
IDialogConstants.YES_LABEL, |
1006 |
IDialogConstants.YES_TO_ALL_LABEL, |
1007 |
IDialogConstants.NO_LABEL, |
1008 |
IDialogConstants.NO_TO_ALL_LABEL, |
1009 |
IDialogConstants.CANCEL_LABEL }, 0); |
1010 |
String[] response = new String[] { YES, ALL, NO, NO_ALL, CANCEL }; |
1011 |
// run in syncExec because callback is from an operation, |
1012 |
// which is probably not running in the UI thread. |
1013 |
getControl().getDisplay().syncExec(new Runnable() { |
1014 |
public void run() { |
1015 |
dialog.open(); |
1016 |
} |
1017 |
}); |
1018 |
return dialog.getReturnCode() < 0 ? CANCEL : response[dialog |
1019 |
.getReturnCode()]; |
1020 |
} |
1021 |
|
1022 |
/** |
1023 |
* Method used for test suite. |
1024 |
* |
1025 |
* @return CheckboxTreeViewer the viewer containing all the projects found |
1026 |
*/ |
1027 |
public CheckboxTreeViewer getProjectsList() { |
1028 |
return projectsList; |
1029 |
} |
1030 |
|
1031 |
/** |
1032 |
* Retrieve all the projects in the current workspace. |
1033 |
* |
1034 |
* @return IProject[] array of IProject in the current workspace |
1035 |
*/ |
1036 |
private IProject[] getProjectsInWorkspace() { |
1037 |
if (wsProjects == null) { |
1038 |
wsProjects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot().getProjects(); |
1039 |
} |
1040 |
return wsProjects; |
1041 |
} |
1042 |
|
1043 |
/** |
1044 |
* Get the array of valid project records that can be imported from the |
1045 |
* source workspace or archive, selected by the user. If a project with the |
1046 |
* same name exists in both the source workspace and the current workspace, |
1047 |
* it will not appear in the list of projects to import and thus cannot be |
1048 |
* selected for import. |
1049 |
* |
1050 |
* Method declared public for test suite. |
1051 |
* |
1052 |
* @return ProjectRecord[] array of projects that can be imported into the |
1053 |
* workspace |
1054 |
*/ |
1055 |
public ProjectRecord[] getValidProjects() { |
1056 |
List validProjects = new ArrayList(); |
1057 |
for (int i = 0; i < selectedProjects.length; i++) { |
1058 |
if (!isProjectInWorkspace(selectedProjects[i].getProjectName())) { |
1059 |
validProjects.add(selectedProjects[i]); |
1060 |
} |
1061 |
} |
1062 |
return (ProjectRecord[]) validProjects |
1063 |
.toArray(new ProjectRecord[validProjects.size()]); |
1064 |
} |
1065 |
|
1066 |
/** |
1067 |
* Determine if the project with the given name is in the current workspace. |
1068 |
* |
1069 |
* @param projectName |
1070 |
* String the project name to check |
1071 |
* @return boolean true if the project with the given name is in this |
1072 |
* workspace |
1073 |
*/ |
1074 |
private boolean isProjectInWorkspace(String projectName) { |
1075 |
if (projectName == null) { |
1076 |
return false; |
1077 |
} |
1078 |
IProject[] workspaceProjects = getProjectsInWorkspace(); |
1079 |
for (int i = 0; i < workspaceProjects.length; i++) { |
1080 |
if (projectName.equals(workspaceProjects[i].getName())) { |
1081 |
return true; |
1082 |
} |
1083 |
} |
1084 |
return false; |
1085 |
} |
1086 |
|
1087 |
/** |
1088 |
* Use the dialog store to restore widget values to the values that they |
1089 |
* held last time this wizard was used to completion. |
1090 |
* |
1091 |
* Method declared public only for use of tests. |
1092 |
*/ |
1093 |
public void restoreWidgetValues() { |
1094 |
IDialogSettings settings = getDialogSettings(); |
1095 |
if (settings != null) { |
1096 |
// checkbox |
1097 |
/*ignoreExportedIndex = settings |
1098 |
.getBoolean(STORE_IGNORE_EXPORTED_INDEX_ID); |
1099 |
ignoreExportedIndexCheckbox.setSelection(ignoreExportedIndex); |
1100 |
|
1101 |
ignoreExportedProjectRefresh = settings |
1102 |
.getBoolean(STORE_IGNORE_EXPORTED_PROJECT_ID); |
1103 |
ignoreExportedProjectRefreshCheckBox |
1104 |
.setSelection(ignoreExportedIndex); |
1105 |
|
1106 |
showTiming = settings.getBoolean(STORE_SHOW_TIMING_PROJECT_ID); |
1107 |
showTimingCheckBox.setSelection(showTiming); |
1108 |
*/ |
1109 |
} |
1110 |
} |
1111 |
|
1112 |
/** |
1113 |
* Since Finish was pressed, write widget values to the dialog store so that |
1114 |
* they will persist into the next invocation of this wizard page. |
1115 |
* |
1116 |
* Method declared public only for use of tests. |
1117 |
*/ |
1118 |
public void saveWidgetValues() { |
1119 |
IDialogSettings settings = getDialogSettings(); |
1120 |
if (settings != null) { |
1121 |
/*settings.put(STORE_IGNORE_EXPORTED_INDEX_ID, |
1122 |
ignoreExportedIndexCheckbox.getSelection()); |
1123 |
|
1124 |
settings.put(STORE_IGNORE_EXPORTED_PROJECT_ID, |
1125 |
ignoreExportedProjectRefreshCheckBox.getSelection()); |
1126 |
|
1127 |
settings.put(STORE_SHOW_TIMING_PROJECT_ID, showTimingCheckBox |
1128 |
.getSelection()); |
1129 |
*/ |
1130 |
} |
1131 |
} |
1132 |
|
1133 |
/** |
1134 |
* Method used for test suite. |
1135 |
* |
1136 |
* @return Button copy checkbox |
1137 |
*/ |
1138 |
// public Button getIgnoreExportedIndexCheckbox() { |
1139 |
// return ignoreExportedIndexCheckbox; |
1140 |
// } |
1141 |
// |
1142 |
/** |
1143 |
* Method used for test suite. |
1144 |
* |
1145 |
* @return Button copy checkbox |
1146 |
*/ |
1147 |
// public Button getIgnoreExportedProjectRefreshCheckbox() { |
1148 |
// return ignoreExportedProjectRefreshCheckBox; |
1149 |
// } |
1150 |
//// |
1151 |
} |