]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.client.ui.dist/src/org/argeo/slc/client/ui/dist/wizards/FetchWizard.java
81541d79c1664f7e80ff011a16880780e1e5291c
[gpl/argeo-slc.git] / org.argeo.slc.client.ui.dist / src / org / argeo / slc / client / ui / dist / wizards / FetchWizard.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.slc.client.ui.dist.wizards;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import javax.jcr.Credentials;
24 import javax.jcr.Node;
25 import javax.jcr.NodeIterator;
26 import javax.jcr.Repository;
27 import javax.jcr.RepositoryException;
28 import javax.jcr.RepositoryFactory;
29 import javax.jcr.Session;
30
31 import org.argeo.ArgeoMonitor;
32 import org.argeo.eclipse.ui.EclipseArgeoMonitor;
33 import org.argeo.jcr.ArgeoNames;
34 import org.argeo.jcr.ArgeoTypes;
35 import org.argeo.jcr.JcrUtils;
36 import org.argeo.jcr.UserJcrUtils;
37 import org.argeo.security.ui.PrivilegedJob;
38 import org.argeo.slc.SlcException;
39 import org.argeo.slc.client.ui.dist.DistPlugin;
40 import org.argeo.slc.client.ui.dist.utils.ViewerUtils;
41 import org.argeo.slc.repo.RepoConstants;
42 import org.argeo.slc.repo.RepoSync;
43 import org.argeo.slc.repo.RepoUtils;
44 import org.argeo.util.security.Keyring;
45 import org.eclipse.core.runtime.IProgressMonitor;
46 import org.eclipse.core.runtime.IStatus;
47 import org.eclipse.core.runtime.Status;
48 import org.eclipse.jface.dialogs.MessageDialog;
49 import org.eclipse.jface.viewers.CheckStateChangedEvent;
50 import org.eclipse.jface.viewers.CheckboxTableViewer;
51 import org.eclipse.jface.viewers.ColumnLabelProvider;
52 import org.eclipse.jface.viewers.ICheckStateListener;
53 import org.eclipse.jface.viewers.IStructuredContentProvider;
54 import org.eclipse.jface.viewers.TableViewer;
55 import org.eclipse.jface.viewers.TableViewerColumn;
56 import org.eclipse.jface.viewers.Viewer;
57 import org.eclipse.jface.viewers.ViewerComparator;
58 import org.eclipse.jface.wizard.IWizardPage;
59 import org.eclipse.jface.wizard.Wizard;
60 import org.eclipse.jface.wizard.WizardPage;
61 import org.eclipse.swt.SWT;
62 import org.eclipse.swt.events.ModifyEvent;
63 import org.eclipse.swt.events.ModifyListener;
64 import org.eclipse.swt.events.SelectionAdapter;
65 import org.eclipse.swt.events.SelectionEvent;
66 import org.eclipse.swt.layout.GridData;
67 import org.eclipse.swt.layout.GridLayout;
68 import org.eclipse.swt.widgets.Button;
69 import org.eclipse.swt.widgets.Combo;
70 import org.eclipse.swt.widgets.Composite;
71 import org.eclipse.swt.widgets.Label;
72 import org.eclipse.swt.widgets.Table;
73 import org.eclipse.swt.widgets.Text;
74
75 /**
76 * Defines parameters for the fetch process and run it using a {@link RepoSync}
77 * object.
78 */
79 public class FetchWizard extends Wizard {
80 // private final static Log log = LogFactory.getLog(FetchWizard.class);
81
82 // Business objects
83 private Keyring keyring;
84 private RepositoryFactory repositoryFactory;
85 private Session currSession;
86 private Node targetRepoNode, sourceRepoNode;
87
88 private List<WkspObject> selectedWorkspaces = new ArrayList<WkspObject>();
89
90 // The pages
91 private ChooseWkspPage chooseWkspPage;
92 private RecapPage recapPage;
93
94 // Cache the advanced pages
95 private Map<WkspObject, AdvancedFetchPage> advancedPages = new HashMap<FetchWizard.WkspObject, FetchWizard.AdvancedFetchPage>();
96
97 // Controls with parameters
98 private Button filesOnlyBtn;
99 private Button advancedBtn;
100 private CheckboxTableViewer wkspViewer;
101
102 public FetchWizard(Keyring keyring, RepositoryFactory repositoryFactory,
103 Repository nodeRepository) {
104 super();
105 this.keyring = keyring;
106 this.repositoryFactory = repositoryFactory;
107 try {
108 currSession = nodeRepository.login();
109 } catch (RepositoryException e) {
110 throw new SlcException(
111 "Unexpected error while initializing fetch wizard", e);
112 }
113 }
114
115 @Override
116 public void dispose() {
117 JcrUtils.logoutQuietly(currSession);
118 super.dispose();
119 }
120
121 @Override
122 public void addPages() {
123 try {
124 chooseWkspPage = new ChooseWkspPage();
125 addPage(chooseWkspPage);
126 recapPage = new RecapPage();
127 addPage(recapPage);
128 setWindowTitle("Define Fetch Procedure");
129 } catch (Exception e) {
130 throw new SlcException("Cannot add page to wizard ", e);
131 }
132 }
133
134 @Override
135 public boolean performFinish() {
136 if (!canFinish())
137 return false;
138 try {
139 // Target Repository
140 String targetRepoUri = targetRepoNode.getProperty(
141 ArgeoNames.ARGEO_URI).getString();
142 Repository targetRepo = RepoUtils.getRepository(repositoryFactory,
143 keyring, targetRepoNode);
144 Credentials targetCredentials = RepoUtils.getRepositoryCredentials(
145 keyring, targetRepoNode);
146
147 // Source Repository
148 String sourceRepoUri = sourceRepoNode.getProperty(
149 ArgeoNames.ARGEO_URI).getString();
150 Repository sourceRepo = RepoUtils.getRepository(repositoryFactory,
151 keyring, sourceRepoNode);
152 Credentials sourceCredentials = RepoUtils.getRepositoryCredentials(
153 keyring, sourceRepoNode);
154
155 String msg = "Your are about to fetch data from repository: \n\t"
156 + sourceRepoUri + "\ninto target repository: \n\t"
157 + targetRepoUri + "\nDo you really want to proceed ?";
158
159 boolean result = MessageDialog.openConfirm(DistPlugin.getDefault()
160 .getWorkbench().getDisplay().getActiveShell(),
161 "Confirm Fetch Launch", msg);
162
163 if (result) {
164 RepoSync repoSync = new RepoSync(sourceRepo, sourceCredentials,
165 targetRepo, targetCredentials);
166 repoSync.setTargetRepoUri(targetRepoUri);
167 repoSync.setSourceRepoUri(sourceRepoUri);
168
169 // Specify workspaces to synchronise
170 Map<String, String> wksps = new HashMap<String, String>();
171 for (Object obj : wkspViewer.getCheckedElements()) {
172 WkspObject stn = (WkspObject) obj;
173 wksps.put(stn.srcName, stn.targetName);
174 }
175 repoSync.setWkspMap(wksps);
176
177 // Set the import files only option
178 repoSync.setFilesOnly(filesOnlyBtn.getSelection());
179 FetchJob job = new FetchJob(repoSync);
180 job.setUser(true);
181 job.schedule();
182 }
183 } catch (Exception e) {
184 throw new SlcException(
185 "Unexpected error while launching the fetch", e);
186 }
187 return true;
188 }
189
190 // ///////////////////////////////
191 // ////// THE PAGES
192
193 private class ChooseWkspPage extends WizardPage {
194 private static final long serialVersionUID = 211336700788047638L;
195
196 private Map<String, Node> sourceReposMap;
197 private Combo chooseSourceRepoCmb;
198
199 public ChooseWkspPage() {
200 super("Main");
201 setTitle("Choose workspaces to fetch");
202 setDescription("Check 'advanced fetch' box to "
203 + "rename workspaces and fine tune the process");
204
205 // Initialise with registered Repositories
206 sourceReposMap = getSourceRepoUris();
207 }
208
209 public void createControl(Composite parent) {
210 Composite composite = new Composite(parent, SWT.NO_FOCUS);
211 composite.setLayout(new GridLayout(2, false));
212
213 // Choose source repository combo
214 new Label(composite, SWT.NONE)
215 .setText("Choose a source repository");
216 chooseSourceRepoCmb = new Combo(composite, SWT.BORDER
217 | SWT.V_SCROLL);
218 chooseSourceRepoCmb.setItems(sourceReposMap.keySet().toArray(
219 new String[sourceReposMap.size()]));
220 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
221 chooseSourceRepoCmb.setLayoutData(gd);
222
223 // Check boxes
224 final Button selectAllBtn = new Button(composite, SWT.CHECK);
225 selectAllBtn.setText("Select/Unselect all");
226
227 advancedBtn = new Button(composite, SWT.CHECK);
228 advancedBtn.setText("Advanced fetch");
229 advancedBtn.setToolTipText("Check this for further "
230 + "parameterization of the fetch process");
231
232 // Workspace table
233 Table table = new Table(composite, SWT.H_SCROLL | SWT.V_SCROLL
234 | SWT.BORDER | SWT.CHECK);
235 gd = new GridData(SWT.FILL, SWT.FILL, true, true);
236 gd.horizontalSpan = 2;
237 table.setLayoutData(gd);
238 configureWkspTable(table);
239
240 // Import only files
241 filesOnlyBtn = new Button(composite, SWT.CHECK | SWT.WRAP);
242 filesOnlyBtn
243 .setText("Import only files (faster, a normalized action should be launched once done)");
244 filesOnlyBtn.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
245 false, 2, 1));
246
247 // Listeners
248 selectAllBtn.addSelectionListener(new SelectionAdapter() {
249 private static final long serialVersionUID = -2071840477444152170L;
250
251 public void widgetSelected(SelectionEvent e) {
252 wkspViewer.setAllChecked(selectAllBtn.getSelection());
253 getContainer().updateButtons();
254 }
255 });
256
257 // advancedBtn.addSelectionListener(new SelectionAdapter() {
258 // public void widgetSelected(SelectionEvent e) {
259 // if (advancedBtn.getSelection()){
260 //
261 // }
262 // wkspViewer.setAllChecked();
263 // }
264 // });
265
266 chooseSourceRepoCmb.addModifyListener(new ModifyListener() {
267 private static final long serialVersionUID = 932462568382594523L;
268
269 public void modifyText(ModifyEvent e) {
270 String chosenUri = chooseSourceRepoCmb
271 .getItem(chooseSourceRepoCmb.getSelectionIndex());
272 sourceRepoNode = sourceReposMap.get(chosenUri);
273 wkspViewer.setInput(sourceRepoNode);
274 }
275 });
276
277 wkspViewer.addCheckStateListener(new ICheckStateListener() {
278 public void checkStateChanged(CheckStateChangedEvent event) {
279 getContainer().updateButtons();
280 }
281 });
282
283 // Initialise to first available repo
284 if (chooseSourceRepoCmb.getItemCount() > 0)
285 chooseSourceRepoCmb.select(0);
286
287 // Compulsory
288 setControl(composite);
289 }
290
291 @Override
292 public boolean isPageComplete() {
293 return wkspViewer.getCheckedElements().length != 0;
294 }
295
296 @Override
297 public IWizardPage getNextPage() {
298 // WARNING: page are added and never removed.
299 if (advancedBtn.getSelection()
300 && wkspViewer.getCheckedElements().length != 0) {
301 IWizardPage toReturn = null;
302 for (Object obj : wkspViewer.getCheckedElements()) {
303 WkspObject curr = (WkspObject) obj;
304 // currSelecteds.add(curr);
305 AdvancedFetchPage page;
306 if (!advancedPages.containsKey(curr)) {
307 page = new AdvancedFetchPage(curr.srcName, curr);
308 addPage(page);
309 advancedPages.put(curr, page);
310 } else
311 page = advancedPages.get(curr);
312 if (toReturn == null)
313 toReturn = page;
314 }
315 return toReturn;
316 } else {
317 return recapPage;
318 }
319 }
320
321 // Configure the workspace table
322 private void configureWkspTable(Table table) {
323 table.setLinesVisible(true);
324 table.setHeaderVisible(true);
325 wkspViewer = new CheckboxTableViewer(table);
326
327 // WORKSPACE COLUMNS
328 TableViewerColumn column = ViewerUtils.createTableViewerColumn(
329 wkspViewer, "Source names", SWT.NONE, 250);
330 column.setLabelProvider(new ColumnLabelProvider() {
331 private static final long serialVersionUID = 5906079281065061967L;
332
333 @Override
334 public String getText(Object element) {
335 return ((WkspObject) element).srcName;
336 }
337 });
338
339 // column = ViewerUtils.createTableViewerColumn(wkspViewer, "Size",
340 // SWT.NONE, 250);
341 // column.setLabelProvider(new ColumnLabelProvider() {
342 // @Override
343 // public String getText(Object element) {
344 // return ((WkspObject) element).getFormattedSize();
345 // }
346 // });
347
348 wkspViewer.setContentProvider(new WkspContentProvider());
349 // A basic comparator
350 wkspViewer.setComparator(new ViewerComparator());
351 }
352 }
353
354 private class AdvancedFetchPage extends WizardPage {
355 private static final long serialVersionUID = 1109183561920445169L;
356
357 private final WkspObject currentWorkspace;
358
359 private Text targetNameTxt;
360
361 protected AdvancedFetchPage(String pageName, WkspObject currentWorkspace) {
362 super(pageName);
363 this.currentWorkspace = currentWorkspace;
364 }
365
366 @Override
367 public void setVisible(boolean visible) {
368 super.setVisible(visible);
369 if (visible) {
370 String msg = "Define advanced parameters to fetch workspace "
371 + currentWorkspace.srcName;
372 setMessage(msg);
373 targetNameTxt.setText(currentWorkspace.targetName);
374 }
375 // else
376 // currentWorkspace.targetName = targetNameTxt.getText();
377 }
378
379 public void createControl(Composite parent) {
380 Composite body = new Composite(parent, SWT.NO_FOCUS);
381 body.setLayout(new GridLayout(2, false));
382 new Label(body, SWT.NONE).setText("Choose a new name");
383 targetNameTxt = new Text(body, SWT.BORDER);
384 targetNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER,
385 true, false));
386 setControl(body);
387 }
388
389 protected WkspObject getWorkspaceObject() {
390 currentWorkspace.targetName = targetNameTxt.getText();
391 return currentWorkspace;
392 }
393
394 @Override
395 public IWizardPage getNextPage() {
396 // WARNING: page are added and never removed.
397 // IWizardPage toReturn = null;
398 // IWizardPage[] pages = ((Wizard) getContainer()).getPages();
399 Object[] selected = wkspViewer.getCheckedElements();
400 for (int i = 0; i < selected.length - 1; i++) {
401 WkspObject curr = (WkspObject) selected[i];
402 if (curr.equals(currentWorkspace))
403 return advancedPages.get((WkspObject) selected[i + 1]);
404 }
405 return recapPage;
406 }
407 }
408
409 private class RecapPage extends WizardPage {
410 private static final long serialVersionUID = -7064862323304300989L;
411 private TableViewer recapViewer;
412
413 public RecapPage() {
414 super("Validate and launch");
415 setTitle("Validate and launch");
416 }
417
418 @Override
419 public boolean isPageComplete() {
420 return isCurrentPage();
421 }
422
423 public IWizardPage getNextPage() {
424 // always last....
425 return null;
426 }
427
428 @Override
429 public void setVisible(boolean visible) {
430 super.setVisible(visible);
431 if (visible) {
432 try {
433 String targetRepoUri = targetRepoNode.getProperty(
434 ArgeoNames.ARGEO_URI).getString();
435 String sourceRepoUri = sourceRepoNode.getProperty(
436 ArgeoNames.ARGEO_URI).getString();
437
438 String msg = "Fetch data from: " + sourceRepoUri
439 + "\ninto target repository: " + targetRepoUri;
440 // + "\nDo you really want to proceed ?";
441 setMessage(msg);
442
443 // update values that will be used for the fetch
444 selectedWorkspaces.clear();
445
446 for (Object obj : wkspViewer.getCheckedElements()) {
447 WkspObject curr = (WkspObject) obj;
448
449 if (advancedBtn.getSelection()) {
450 AdvancedFetchPage page = advancedPages.get(curr);
451 selectedWorkspaces.add(page.getWorkspaceObject());
452 } else
453 selectedWorkspaces.add(curr);
454 }
455 recapViewer.setInput(selectedWorkspaces);
456 recapViewer.refresh();
457
458 } catch (RepositoryException re) {
459 throw new SlcException("Unable to get repositories URIs",
460 re);
461 }
462 }
463 }
464
465 public void createControl(Composite parent) {
466 Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL
467 | SWT.BORDER);
468 table.setLinesVisible(true);
469 table.setHeaderVisible(true);
470 recapViewer = new TableViewer(table);
471
472 // WORKSPACE COLUMNS
473 TableViewerColumn column = ViewerUtils.createTableViewerColumn(
474 recapViewer, "Sources", SWT.NONE, 250);
475 column.setLabelProvider(new ColumnLabelProvider() {
476 private static final long serialVersionUID = 3913459002502680377L;
477
478 @Override
479 public String getText(Object element) {
480 return ((WkspObject) element).srcName;
481 }
482 });
483
484 column = ViewerUtils.createTableViewerColumn(recapViewer,
485 "targets", SWT.NONE, 250);
486 column.setLabelProvider(new ColumnLabelProvider() {
487 private static final long serialVersionUID = -517920072332563632L;
488
489 @Override
490 public String getText(Object element) {
491 return ((WkspObject) element).targetName;
492 }
493 });
494
495 recapViewer.setContentProvider(new IStructuredContentProvider() {
496 private static final long serialVersionUID = 4926999891003040865L;
497
498 public void inputChanged(Viewer viewer, Object oldInput,
499 Object newInput) {
500 // TODO Auto-generated method stub
501 }
502
503 public void dispose() {
504 }
505
506 public Object[] getElements(Object inputElement) {
507 return selectedWorkspaces.toArray();
508 }
509 });
510
511 // A basic comparator
512 recapViewer.setComparator(new ViewerComparator());
513 setControl(table);
514 }
515 }
516
517 /**
518 * Define the privileged job that will be run asynchronously to accomplish
519 * the sync
520 */
521 private class FetchJob extends PrivilegedJob {
522 private RepoSync repoSync;
523
524 public FetchJob(RepoSync repoSync) {
525 super("Fetch");
526 this.repoSync = repoSync;
527 }
528
529 @Override
530 protected IStatus doRun(IProgressMonitor progressMonitor) {
531 try {
532 ArgeoMonitor monitor = new EclipseArgeoMonitor(progressMonitor);
533 repoSync.setMonitor(monitor);
534 repoSync.run();
535 } catch (Exception e) {
536 return new Status(IStatus.ERROR, DistPlugin.PLUGIN_ID,
537 "Cannot fetch repository", e);
538 }
539 return Status.OK_STATUS;
540 }
541 }
542
543 // ///////////////////////
544 // Local classes
545 private class WkspObject {
546 protected final String srcName;
547 protected String targetName;
548
549 protected WkspObject(String srcName) {
550 this.srcName = srcName;
551 this.targetName = srcName;
552 }
553
554 @Override
555 public String toString() {
556 return "[" + srcName + " to " + targetName + "]";
557 }
558 }
559
560 // private class WkspComparator extends ViewerComparator {
561 //
562 // }
563
564 private class WkspContentProvider implements IStructuredContentProvider {
565 private static final long serialVersionUID = -925058051598536307L;
566 // caches current repo
567 private Node currSourceNodeRepo;
568 private Repository currSourceRepo;
569 private Credentials currSourceCred;
570
571 private List<WkspObject> workspaces = new ArrayList<WkspObject>();
572
573 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
574 if (newInput != null && newInput instanceof Node) {
575 Session session = null;
576 try {
577 Node newRepoNode = (Node) newInput;
578 if (currSourceNodeRepo == null
579 || !newRepoNode.getPath().equals(
580 currSourceNodeRepo.getPath())) {
581
582 // update cache
583 currSourceNodeRepo = newRepoNode;
584 currSourceRepo = RepoUtils.getRepository(
585 repositoryFactory, keyring, currSourceNodeRepo);
586 currSourceCred = RepoUtils.getRepositoryCredentials(
587 keyring, currSourceNodeRepo);
588
589 // reset workspace list
590 wkspViewer.setAllChecked(false);
591 workspaces.clear();
592 session = currSourceRepo.login(currSourceCred);
593 // remove unvalid elements
594 for (String name : session.getWorkspace()
595 .getAccessibleWorkspaceNames())
596 // TODO implement a cleaner way to filter
597 // workspaces out
598 if (name.lastIndexOf('-') > 0) {
599 WkspObject currWksp = new WkspObject(name);
600 // compute wkspace size
601 // TODO implement this
602 // Session currSession = null;
603 // try {
604 // currSession = currSourceRepo.login(
605 // currSourceCred, name);
606 // currWksp.size = JcrUtils
607 // .getNodeApproxSize(currSession
608 // .getNode("/"));
609 //
610 // } catch (RepositoryException re) {
611 // log.warn(
612 // "unable to compute size of workspace "
613 // + name, re);
614 // } finally {
615 // JcrUtils.logoutQuietly(currSession);
616 // }
617 workspaces.add(currWksp);
618 }
619 }
620
621 } catch (RepositoryException e) {
622 throw new SlcException("Unexpected error while "
623 + "initializing fetch wizard", e);
624 } finally {
625 JcrUtils.logoutQuietly(session);
626 }
627 viewer.refresh();
628 }
629 }
630
631 public void dispose() {
632 }
633
634 public Object[] getElements(Object obj) {
635 return workspaces.toArray();
636 }
637 }
638
639 // ////////////////////////////
640 // // Helpers
641
642 // populate available source repo list
643 private Map<String, Node> getSourceRepoUris() {
644 try {
645 Node repoList = currSession.getNode(UserJcrUtils.getUserHome(
646 currSession).getPath()
647 + RepoConstants.REPOSITORIES_BASE_PATH);
648
649 String targetRepoUri = null;
650 if (targetRepoNode != null) {
651 targetRepoUri = targetRepoNode
652 .getProperty(ArgeoNames.ARGEO_URI).getString();
653 }
654 NodeIterator ni = repoList.getNodes();
655 // List<String> sourceRepoNames = new ArrayList<String>();
656 // // caches a map of the source repo nodes with their URI as a key
657 // // to ease further processing
658 Map<String, Node> sourceReposMap = new HashMap<String, Node>();
659 while (ni.hasNext()) {
660 Node currNode = ni.nextNode();
661 if (currNode.isNodeType(ArgeoTypes.ARGEO_REMOTE_REPOSITORY)) {
662 String currUri = currNode.getProperty(ArgeoNames.ARGEO_URI)
663 .getString();
664 if (targetRepoUri == null || !targetRepoUri.equals(currUri)) {
665 sourceReposMap.put(currUri, currNode);
666 // sourceRepoNames.add(currUri);
667 }
668 }
669 }
670 return sourceReposMap;
671 // sourceRepoNames.toArray(new String[sourceRepoNames
672 // .size()]);
673 } catch (RepositoryException e) {
674 throw new SlcException("Error while getting repo aliases", e);
675 }
676 }
677
678 public void setTargetRepoNode(Node targetRepoNode) {
679 this.targetRepoNode = targetRepoNode;
680 }
681
682 public void setSourceRepoNode(Node sourceRepoNode) {
683 this.sourceRepoNode = sourceRepoNode;
684 }
685 }