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