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
.JcrUtils
;
34 import org
.argeo
.node
.ArgeoNames
;
35 import org
.argeo
.node
.ArgeoTypes
;
36 import org
.argeo
.node
.NodeUtils
;
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
;
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
{
194 private static final long serialVersionUID
= 211336700788047638L;
196 private Map
<String
, Node
> sourceReposMap
;
197 private Combo chooseSourceRepoCmb
;
199 public ChooseWkspPage() {
201 setTitle("Choose workspaces to fetch");
202 setDescription("Check 'advanced fetch' box to "
203 + "rename workspaces and fine tune the process");
205 // Initialise with registered Repositories
206 sourceReposMap
= getSourceRepoUris();
209 public void createControl(Composite parent
) {
210 Composite composite
= new Composite(parent
, SWT
.NO_FOCUS
);
211 composite
.setLayout(new GridLayout(2, false));
213 // Choose source repository combo
214 new Label(composite
, SWT
.NONE
)
215 .setText("Choose a source repository");
216 chooseSourceRepoCmb
= new Combo(composite
, SWT
.BORDER
218 chooseSourceRepoCmb
.setItems(sourceReposMap
.keySet().toArray(
219 new String
[sourceReposMap
.size()]));
220 GridData gd
= new GridData(GridData
.FILL_HORIZONTAL
);
221 chooseSourceRepoCmb
.setLayoutData(gd
);
224 final Button selectAllBtn
= new Button(composite
, SWT
.CHECK
);
225 selectAllBtn
.setText("Select/Unselect all");
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");
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
);
241 filesOnlyBtn
= new Button(composite
, SWT
.CHECK
| SWT
.WRAP
);
243 .setText("Import only files (faster, a normalized action should be launched once done)");
244 filesOnlyBtn
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, false,
248 selectAllBtn
.addSelectionListener(new SelectionAdapter() {
249 private static final long serialVersionUID
= -2071840477444152170L;
251 public void widgetSelected(SelectionEvent e
) {
252 wkspViewer
.setAllChecked(selectAllBtn
.getSelection());
253 getContainer().updateButtons();
257 // advancedBtn.addSelectionListener(new SelectionAdapter() {
258 // public void widgetSelected(SelectionEvent e) {
259 // if (advancedBtn.getSelection()){
262 // wkspViewer.setAllChecked();
266 chooseSourceRepoCmb
.addModifyListener(new ModifyListener() {
267 private static final long serialVersionUID
= 932462568382594523L;
269 public void modifyText(ModifyEvent e
) {
270 String chosenUri
= chooseSourceRepoCmb
271 .getItem(chooseSourceRepoCmb
.getSelectionIndex());
272 sourceRepoNode
= sourceReposMap
.get(chosenUri
);
273 wkspViewer
.setInput(sourceRepoNode
);
277 wkspViewer
.addCheckStateListener(new ICheckStateListener() {
278 public void checkStateChanged(CheckStateChangedEvent event
) {
279 getContainer().updateButtons();
283 // Initialise to first available repo
284 if (chooseSourceRepoCmb
.getItemCount() > 0)
285 chooseSourceRepoCmb
.select(0);
288 setControl(composite
);
292 public boolean isPageComplete() {
293 return wkspViewer
.getCheckedElements().length
!= 0;
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
);
309 advancedPages
.put(curr
, page
);
311 page
= advancedPages
.get(curr
);
312 if (toReturn
== null)
321 // Configure the workspace table
322 private void configureWkspTable(Table table
) {
323 table
.setLinesVisible(true);
324 table
.setHeaderVisible(true);
325 wkspViewer
= new CheckboxTableViewer(table
);
328 TableViewerColumn column
= ViewerUtils
.createTableViewerColumn(
329 wkspViewer
, "Source names", SWT
.NONE
, 250);
330 column
.setLabelProvider(new ColumnLabelProvider() {
331 private static final long serialVersionUID
= 5906079281065061967L;
334 public String
getText(Object element
) {
335 return ((WkspObject
) element
).srcName
;
339 // column = ViewerUtils.createTableViewerColumn(wkspViewer, "Size",
341 // column.setLabelProvider(new ColumnLabelProvider() {
343 // public String getText(Object element) {
344 // return ((WkspObject) element).getFormattedSize();
348 wkspViewer
.setContentProvider(new WkspContentProvider());
349 // A basic comparator
350 wkspViewer
.setComparator(new ViewerComparator());
354 private class AdvancedFetchPage
extends WizardPage
{
355 private static final long serialVersionUID
= 1109183561920445169L;
357 private final WkspObject currentWorkspace
;
359 private Text targetNameTxt
;
361 protected AdvancedFetchPage(String pageName
, WkspObject currentWorkspace
) {
363 this.currentWorkspace
= currentWorkspace
;
367 public void setVisible(boolean visible
) {
368 super.setVisible(visible
);
370 String msg
= "Define advanced parameters to fetch workspace "
371 + currentWorkspace
.srcName
;
373 targetNameTxt
.setText(currentWorkspace
.targetName
);
376 // currentWorkspace.targetName = targetNameTxt.getText();
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
,
389 protected WkspObject
getWorkspaceObject() {
390 currentWorkspace
.targetName
= targetNameTxt
.getText();
391 return currentWorkspace
;
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]);
409 private class RecapPage
extends WizardPage
{
410 private static final long serialVersionUID
= -7064862323304300989L;
411 private TableViewer recapViewer
;
414 super("Validate and launch");
415 setTitle("Validate and launch");
419 public boolean isPageComplete() {
420 return isCurrentPage();
423 public IWizardPage
getNextPage() {
429 public void setVisible(boolean visible
) {
430 super.setVisible(visible
);
433 String targetRepoUri
= targetRepoNode
.getProperty(
434 ArgeoNames
.ARGEO_URI
).getString();
435 String sourceRepoUri
= sourceRepoNode
.getProperty(
436 ArgeoNames
.ARGEO_URI
).getString();
438 String msg
= "Fetch data from: " + sourceRepoUri
439 + "\ninto target repository: " + targetRepoUri
;
440 // + "\nDo you really want to proceed ?";
443 // update values that will be used for the fetch
444 selectedWorkspaces
.clear();
446 for (Object obj
: wkspViewer
.getCheckedElements()) {
447 WkspObject curr
= (WkspObject
) obj
;
449 if (advancedBtn
.getSelection()) {
450 AdvancedFetchPage page
= advancedPages
.get(curr
);
451 selectedWorkspaces
.add(page
.getWorkspaceObject());
453 selectedWorkspaces
.add(curr
);
455 recapViewer
.setInput(selectedWorkspaces
);
456 recapViewer
.refresh();
458 } catch (RepositoryException re
) {
459 throw new SlcException("Unable to get repositories URIs",
465 public void createControl(Composite parent
) {
466 Table table
= new Table(parent
, SWT
.H_SCROLL
| SWT
.V_SCROLL
468 table
.setLinesVisible(true);
469 table
.setHeaderVisible(true);
470 recapViewer
= new TableViewer(table
);
473 TableViewerColumn column
= ViewerUtils
.createTableViewerColumn(
474 recapViewer
, "Sources", SWT
.NONE
, 250);
475 column
.setLabelProvider(new ColumnLabelProvider() {
476 private static final long serialVersionUID
= 3913459002502680377L;
479 public String
getText(Object element
) {
480 return ((WkspObject
) element
).srcName
;
484 column
= ViewerUtils
.createTableViewerColumn(recapViewer
,
485 "targets", SWT
.NONE
, 250);
486 column
.setLabelProvider(new ColumnLabelProvider() {
487 private static final long serialVersionUID
= -517920072332563632L;
490 public String
getText(Object element
) {
491 return ((WkspObject
) element
).targetName
;
495 recapViewer
.setContentProvider(new IStructuredContentProvider() {
496 private static final long serialVersionUID
= 4926999891003040865L;
498 public void inputChanged(Viewer viewer
, Object oldInput
,
500 // TODO Auto-generated method stub
503 public void dispose() {
506 public Object
[] getElements(Object inputElement
) {
507 return selectedWorkspaces
.toArray();
511 // A basic comparator
512 recapViewer
.setComparator(new ViewerComparator());
518 * Define the privileged job that will be run asynchronously to accomplish
521 private class FetchJob
extends PrivilegedJob
{
522 private RepoSync repoSync
;
524 public FetchJob(RepoSync repoSync
) {
526 this.repoSync
= repoSync
;
530 protected IStatus
doRun(IProgressMonitor progressMonitor
) {
532 ArgeoMonitor monitor
= new EclipseArgeoMonitor(progressMonitor
);
533 repoSync
.setMonitor(monitor
);
535 } catch (Exception e
) {
536 return new Status(IStatus
.ERROR
, DistPlugin
.PLUGIN_ID
,
537 "Cannot fetch repository", e
);
539 return Status
.OK_STATUS
;
543 // ///////////////////////
545 private class WkspObject
{
546 protected final String srcName
;
547 protected String targetName
;
549 protected WkspObject(String srcName
) {
550 this.srcName
= srcName
;
551 this.targetName
= srcName
;
555 public String
toString() {
556 return "[" + srcName
+ " to " + targetName
+ "]";
560 // private class WkspComparator extends ViewerComparator {
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
;
571 private List
<WkspObject
> workspaces
= new ArrayList
<WkspObject
>();
573 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
574 if (newInput
!= null && newInput
instanceof Node
) {
575 Session session
= null;
577 Node newRepoNode
= (Node
) newInput
;
578 if (currSourceNodeRepo
== null
579 || !newRepoNode
.getPath().equals(
580 currSourceNodeRepo
.getPath())) {
583 currSourceNodeRepo
= newRepoNode
;
584 currSourceRepo
= RepoUtils
.getRepository(
585 repositoryFactory
, keyring
, currSourceNodeRepo
);
586 currSourceCred
= RepoUtils
.getRepositoryCredentials(
587 keyring
, currSourceNodeRepo
);
589 // reset workspace list
590 wkspViewer
.setAllChecked(false);
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
598 if (name
.lastIndexOf('-') > 0) {
599 WkspObject currWksp
= new WkspObject(name
);
600 // compute wkspace size
601 // TODO implement this
602 // Session currSession = null;
604 // currSession = currSourceRepo.login(
605 // currSourceCred, name);
606 // currWksp.size = JcrUtils
607 // .getNodeApproxSize(currSession
610 // } catch (RepositoryException re) {
612 // "unable to compute size of workspace "
615 // JcrUtils.logoutQuietly(currSession);
617 workspaces
.add(currWksp
);
621 } catch (RepositoryException e
) {
622 throw new SlcException("Unexpected error while "
623 + "initializing fetch wizard", e
);
625 JcrUtils
.logoutQuietly(session
);
631 public void dispose() {
634 public Object
[] getElements(Object obj
) {
635 return workspaces
.toArray();
639 // ////////////////////////////
642 // populate available source repo list
643 private Map
<String
, Node
> getSourceRepoUris() {
645 Node repoList
= currSession
.getNode(NodeUtils
.getUserHome(
646 currSession
).getPath()
647 + RepoConstants
.REPOSITORIES_BASE_PATH
);
649 String targetRepoUri
= null;
650 if (targetRepoNode
!= null) {
651 targetRepoUri
= targetRepoNode
652 .getProperty(ArgeoNames
.ARGEO_URI
).getString();
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
)
664 if (targetRepoUri
== null || !targetRepoUri
.equals(currUri
)) {
665 sourceReposMap
.put(currUri
, currNode
);
666 // sourceRepoNames.add(currUri);
670 return sourceReposMap
;
671 // sourceRepoNames.toArray(new String[sourceRepoNames
673 } catch (RepositoryException e
) {
674 throw new SlcException("Error while getting repo aliases", e
);
678 public void setTargetRepoNode(Node targetRepoNode
) {
679 this.targetRepoNode
= targetRepoNode
;
682 public void setSourceRepoNode(Node sourceRepoNode
) {
683 this.sourceRepoNode
= sourceRepoNode
;