2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.slc
.client
.ui
.dist
.wizards
;
18 import java
.util
.ArrayList
;
19 import java
.util
.HashMap
;
20 import java
.util
.List
;
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
;
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
.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
;
76 * Defines parameters for the fetch process and run it using a {@link RepoSync}
79 public class FetchWizard
extends Wizard
{
80 // private final static Log log = LogFactory.getLog(FetchWizard.class);
83 private Keyring keyring
;
84 private RepositoryFactory repositoryFactory
;
85 private Session currSession
;
86 private Node targetRepoNode
, sourceRepoNode
;
88 private List
<WkspObject
> selectedWorkspaces
= new ArrayList
<WkspObject
>();
91 private ChooseWkspPage chooseWkspPage
;
92 private RecapPage recapPage
;
94 // Cache the advanced pages
95 private Map
<WkspObject
, AdvancedFetchPage
> advancedPages
= new HashMap
<FetchWizard
.WkspObject
, FetchWizard
.AdvancedFetchPage
>();
97 // Controls with parameters
98 private Button filesOnlyBtn
;
99 private Button advancedBtn
;
100 private CheckboxTableViewer wkspViewer
;
102 public FetchWizard(Keyring keyring
, RepositoryFactory repositoryFactory
,
103 Repository nodeRepository
) {
105 this.keyring
= keyring
;
106 this.repositoryFactory
= repositoryFactory
;
108 currSession
= nodeRepository
.login();
109 } catch (RepositoryException e
) {
110 throw new SlcException(
111 "Unexpected error while initializing fetch wizard", e
);
116 public void dispose() {
117 JcrUtils
.logoutQuietly(currSession
);
122 public void addPages() {
124 chooseWkspPage
= new ChooseWkspPage();
125 addPage(chooseWkspPage
);
126 recapPage
= new RecapPage();
128 setWindowTitle("Define Fetch Procedure");
129 } catch (Exception e
) {
130 throw new SlcException("Cannot add page to wizard ", e
);
135 public boolean performFinish() {
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
);
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
);
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 ?";
159 boolean result
= MessageDialog
.openConfirm(DistPlugin
.getDefault()
160 .getWorkbench().getDisplay().getActiveShell(),
161 "Confirm Fetch Launch", msg
);
164 RepoSync repoSync
= new RepoSync(sourceRepo
, sourceCredentials
,
165 targetRepo
, targetCredentials
);
166 repoSync
.setTargetRepoUri(targetRepoUri
);
167 repoSync
.setSourceRepoUri(sourceRepoUri
);
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
);
175 repoSync
.setWkspMap(wksps
);
177 // Set the import files only option
178 repoSync
.setFilesOnly(filesOnlyBtn
.getSelection());
179 FetchJob job
= new FetchJob(repoSync
);
183 } catch (Exception e
) {
184 throw new SlcException(
185 "Unexpected error while launching the fetch", e
);
190 // ///////////////////////////////
193 private class ChooseWkspPage
extends WizardPage
{
195 private Map
<String
, Node
> sourceReposMap
;
196 private Combo chooseSourceRepoCmb
;
198 public ChooseWkspPage() {
200 setTitle("Choose workspaces to fetch");
201 setDescription("Check 'advanced fetch' box to "
202 + "rename workspaces and fine tune the process");
204 // Initialise with registered Repositories
205 sourceReposMap
= getSourceRepoUris();
208 public void createControl(Composite parent
) {
209 Composite composite
= new Composite(parent
, SWT
.NO_FOCUS
);
210 composite
.setLayout(new GridLayout(2, false));
212 // Choose source repository combo
213 new Label(composite
, SWT
.NONE
)
214 .setText("Choose a source repository");
215 chooseSourceRepoCmb
= new Combo(composite
, SWT
.BORDER
217 chooseSourceRepoCmb
.setItems(sourceReposMap
.keySet().toArray(
218 new String
[sourceReposMap
.size()]));
219 GridData gd
= new GridData(GridData
.FILL_HORIZONTAL
);
220 chooseSourceRepoCmb
.setLayoutData(gd
);
223 final Button selectAllBtn
= new Button(composite
, SWT
.CHECK
);
224 selectAllBtn
.setText("Select/Unselect all");
226 advancedBtn
= new Button(composite
, SWT
.CHECK
);
227 advancedBtn
.setText("Advanced fetch");
228 advancedBtn
.setToolTipText("Check this for further "
229 + "parameterization of the fetch process");
232 Table table
= new Table(composite
, SWT
.H_SCROLL
| SWT
.V_SCROLL
233 | SWT
.BORDER
| SWT
.CHECK
);
234 gd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
235 gd
.horizontalSpan
= 2;
236 table
.setLayoutData(gd
);
237 configureWkspTable(table
);
240 filesOnlyBtn
= new Button(composite
, SWT
.CHECK
| SWT
.WRAP
);
242 .setText("Import only files (faster, a normalized action should be launched once done)");
243 filesOnlyBtn
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, false,
247 selectAllBtn
.addSelectionListener(new SelectionAdapter() {
248 public void widgetSelected(SelectionEvent e
) {
249 wkspViewer
.setAllChecked(selectAllBtn
.getSelection());
250 getContainer().updateButtons();
254 // advancedBtn.addSelectionListener(new SelectionAdapter() {
255 // public void widgetSelected(SelectionEvent e) {
256 // if (advancedBtn.getSelection()){
259 // wkspViewer.setAllChecked();
263 chooseSourceRepoCmb
.addModifyListener(new ModifyListener() {
264 public void modifyText(ModifyEvent e
) {
265 String chosenUri
= chooseSourceRepoCmb
266 .getItem(chooseSourceRepoCmb
.getSelectionIndex());
267 sourceRepoNode
= sourceReposMap
.get(chosenUri
);
268 wkspViewer
.setInput(sourceRepoNode
);
272 wkspViewer
.addCheckStateListener(new ICheckStateListener() {
273 public void checkStateChanged(CheckStateChangedEvent event
) {
274 getContainer().updateButtons();
278 // Initialise to first available repo
279 if (chooseSourceRepoCmb
.getItemCount() > 0)
280 chooseSourceRepoCmb
.select(0);
283 setControl(composite
);
287 public boolean isPageComplete() {
288 return wkspViewer
.getCheckedElements().length
!= 0;
292 public IWizardPage
getNextPage() {
293 // WARNING: page are added and never removed.
294 if (advancedBtn
.getSelection()
295 && wkspViewer
.getCheckedElements().length
!= 0) {
296 IWizardPage toReturn
= null;
297 for (Object obj
: wkspViewer
.getCheckedElements()) {
298 WkspObject curr
= (WkspObject
) obj
;
299 // currSelecteds.add(curr);
300 AdvancedFetchPage page
;
301 if (!advancedPages
.containsKey(curr
)) {
302 page
= new AdvancedFetchPage(curr
.srcName
, curr
);
304 advancedPages
.put(curr
, page
);
306 page
= advancedPages
.get(curr
);
307 if (toReturn
== null)
316 // Configure the workspace table
317 private void configureWkspTable(Table table
) {
318 table
.setLinesVisible(true);
319 table
.setHeaderVisible(true);
320 wkspViewer
= new CheckboxTableViewer(table
);
323 TableViewerColumn column
= ViewerUtils
.createTableViewerColumn(
324 wkspViewer
, "Source names", SWT
.NONE
, 250);
325 column
.setLabelProvider(new ColumnLabelProvider() {
327 public String
getText(Object element
) {
328 return ((WkspObject
) element
).srcName
;
332 // column = ViewerUtils.createTableViewerColumn(wkspViewer, "Size",
334 // column.setLabelProvider(new ColumnLabelProvider() {
336 // public String getText(Object element) {
337 // return ((WkspObject) element).getFormattedSize();
341 wkspViewer
.setContentProvider(new WkspContentProvider());
342 // A basic comparator
343 wkspViewer
.setComparator(new WkspComparator());
347 private class AdvancedFetchPage
extends WizardPage
{
349 private final WkspObject currentWorkspace
;
351 private Text targetNameTxt
;
353 protected AdvancedFetchPage(String pageName
, WkspObject currentWorkspace
) {
355 this.currentWorkspace
= currentWorkspace
;
359 public void setVisible(boolean visible
) {
360 super.setVisible(visible
);
362 String msg
= "Define advanced parameters to fetch workspace "
363 + currentWorkspace
.srcName
;
365 targetNameTxt
.setText(currentWorkspace
.targetName
);
368 // currentWorkspace.targetName = targetNameTxt.getText();
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
,
381 protected WkspObject
getWorkspaceObject() {
382 currentWorkspace
.targetName
= targetNameTxt
.getText();
383 return currentWorkspace
;
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]);
401 private class RecapPage
extends WizardPage
{
403 private TableViewer recapViewer
;
406 super("Validate and launch");
407 setTitle("Validate and launch");
411 public boolean isPageComplete() {
412 return isCurrentPage();
415 public IWizardPage
getNextPage() {
421 public void setVisible(boolean visible
) {
422 super.setVisible(visible
);
425 String targetRepoUri
= targetRepoNode
.getProperty(
426 ArgeoNames
.ARGEO_URI
).getString();
427 String sourceRepoUri
= sourceRepoNode
.getProperty(
428 ArgeoNames
.ARGEO_URI
).getString();
430 String msg
= "Fetch data from: " + sourceRepoUri
431 + "\ninto target repository: " + targetRepoUri
;
432 // + "\nDo you really want to proceed ?";
435 // update values that will be used for the fetch
436 selectedWorkspaces
.clear();
438 for (Object obj
: wkspViewer
.getCheckedElements()) {
439 WkspObject curr
= (WkspObject
) obj
;
441 if (advancedBtn
.getSelection()) {
442 AdvancedFetchPage page
= advancedPages
.get(curr
);
443 selectedWorkspaces
.add(page
.getWorkspaceObject());
445 selectedWorkspaces
.add(curr
);
447 recapViewer
.setInput(selectedWorkspaces
);
448 recapViewer
.refresh();
450 } catch (RepositoryException re
) {
451 throw new SlcException("Unable to get repositories URIs",
457 public void createControl(Composite parent
) {
458 Table table
= new Table(parent
, SWT
.H_SCROLL
| SWT
.V_SCROLL
460 table
.setLinesVisible(true);
461 table
.setHeaderVisible(true);
462 recapViewer
= new TableViewer(table
);
465 TableViewerColumn column
= ViewerUtils
.createTableViewerColumn(
466 recapViewer
, "Sources", SWT
.NONE
, 250);
467 column
.setLabelProvider(new ColumnLabelProvider() {
469 public String
getText(Object element
) {
470 return ((WkspObject
) element
).srcName
;
474 column
= ViewerUtils
.createTableViewerColumn(recapViewer
,
475 "targets", SWT
.NONE
, 250);
476 column
.setLabelProvider(new ColumnLabelProvider() {
478 public String
getText(Object element
) {
479 return ((WkspObject
) element
).targetName
;
483 recapViewer
.setContentProvider(new IStructuredContentProvider() {
485 public void inputChanged(Viewer viewer
, Object oldInput
,
487 // TODO Auto-generated method stub
490 public void dispose() {
493 public Object
[] getElements(Object inputElement
) {
494 return selectedWorkspaces
.toArray();
498 // A basic comparator
499 recapViewer
.setComparator(new WkspComparator());
505 * Define the privileged job that will be run asynchronously to accomplish
508 private class FetchJob
extends PrivilegedJob
{
509 private RepoSync repoSync
;
511 public FetchJob(RepoSync repoSync
) {
513 this.repoSync
= repoSync
;
517 protected IStatus
doRun(IProgressMonitor progressMonitor
) {
519 ArgeoMonitor monitor
= new EclipseArgeoMonitor(progressMonitor
);
520 repoSync
.setMonitor(monitor
);
522 } catch (Exception e
) {
523 return new Status(IStatus
.ERROR
, DistPlugin
.ID
,
524 "Cannot fetch repository", e
);
526 return Status
.OK_STATUS
;
530 // ///////////////////////
532 private class WkspObject
{
533 protected final String srcName
;
534 protected String targetName
;
536 protected WkspObject(String srcName
) {
537 this.srcName
= srcName
;
538 this.targetName
= srcName
;
542 public String
toString() {
543 return "[" + srcName
+ " to " + targetName
+ "]";
547 private class WkspComparator
extends ViewerComparator
{
551 private class WkspContentProvider
implements IStructuredContentProvider
{
552 // caches current repo
553 private Node currSourceNodeRepo
;
554 private Repository currSourceRepo
;
555 private Credentials currSourceCred
;
557 private List
<WkspObject
> workspaces
= new ArrayList
<WkspObject
>();
559 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
560 if (newInput
!= null && newInput
instanceof Node
) {
561 Session session
= null;
563 Node newRepoNode
= (Node
) newInput
;
564 if (currSourceNodeRepo
== null
565 || !newRepoNode
.getPath().equals(
566 currSourceNodeRepo
.getPath())) {
569 currSourceNodeRepo
= newRepoNode
;
570 currSourceRepo
= RepoUtils
.getRepository(
571 repositoryFactory
, keyring
, currSourceNodeRepo
);
572 currSourceCred
= RepoUtils
.getRepositoryCredentials(
573 keyring
, currSourceNodeRepo
);
575 // reset workspace list
576 wkspViewer
.setAllChecked(false);
578 session
= currSourceRepo
.login(currSourceCred
);
579 // remove unvalid elements
580 for (String name
: session
.getWorkspace()
581 .getAccessibleWorkspaceNames())
582 // TODO implement a cleaner way to filter
584 if (name
.lastIndexOf('-') > 0) {
585 WkspObject currWksp
= new WkspObject(name
);
586 // compute wkspace size
587 // TODO implement this
588 // Session currSession = null;
590 // currSession = currSourceRepo.login(
591 // currSourceCred, name);
592 // currWksp.size = JcrUtils
593 // .getNodeApproxSize(currSession
596 // } catch (RepositoryException re) {
598 // "unable to compute size of workspace "
601 // JcrUtils.logoutQuietly(currSession);
603 workspaces
.add(currWksp
);
607 } catch (RepositoryException e
) {
608 throw new SlcException("Unexpected error while "
609 + "initializing fetch wizard", e
);
611 JcrUtils
.logoutQuietly(session
);
617 public void dispose() {
620 public Object
[] getElements(Object obj
) {
621 return workspaces
.toArray();
625 // ////////////////////////////
628 // populate available source repo list
629 private Map
<String
, Node
> getSourceRepoUris() {
631 Node repoList
= currSession
.getNode(UserJcrUtils
.getUserHome(
632 currSession
).getPath()
633 + RepoConstants
.REPOSITORIES_BASE_PATH
);
635 String targetRepoUri
= null;
636 if (targetRepoNode
!= null) {
637 targetRepoUri
= targetRepoNode
638 .getProperty(ArgeoNames
.ARGEO_URI
).getString();
640 NodeIterator ni
= repoList
.getNodes();
641 // List<String> sourceRepoNames = new ArrayList<String>();
642 // // caches a map of the source repo nodes with their URI as a key
643 // // to ease further processing
644 Map
<String
, Node
> sourceReposMap
= new HashMap
<String
, Node
>();
645 while (ni
.hasNext()) {
646 Node currNode
= ni
.nextNode();
647 if (currNode
.isNodeType(ArgeoTypes
.ARGEO_REMOTE_REPOSITORY
)) {
648 String currUri
= currNode
.getProperty(ArgeoNames
.ARGEO_URI
)
650 if (targetRepoUri
== null || !targetRepoUri
.equals(currUri
)) {
651 sourceReposMap
.put(currUri
, currNode
);
652 // sourceRepoNames.add(currUri);
656 return sourceReposMap
;
657 // sourceRepoNames.toArray(new String[sourceRepoNames
659 } catch (RepositoryException e
) {
660 throw new SlcException("Error while getting repo aliases", e
);
664 public void setTargetRepoNode(Node targetRepoNode
) {
665 this.targetRepoNode
= targetRepoNode
;
668 public void setSourceRepoNode(Node sourceRepoNode
) {
669 this.sourceRepoNode
= sourceRepoNode
;