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
.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
;
75 * Defines parameters for the fetch process and run it using a {@link RepoSync}
78 public class FetchWizard
extends Wizard
{
79 // private final static Log log = LogFactory.getLog(FetchWizard.class);
82 private Keyring keyring
;
83 private RepositoryFactory repositoryFactory
;
84 private Session currSession
;
85 private Node targetRepoNode
, sourceRepoNode
;
87 private List
<WkspObject
> selectedWorkspaces
= new ArrayList
<WkspObject
>();
90 private ChooseWkspPage chooseWkspPage
;
91 private RecapPage recapPage
;
93 // Cache the advanced pages
94 private Map
<WkspObject
, AdvancedFetchPage
> advancedPages
= new HashMap
<FetchWizard
.WkspObject
, FetchWizard
.AdvancedFetchPage
>();
96 // Controls with parameters
97 private Button filesOnlyBtn
;
98 private Button advancedBtn
;
99 private CheckboxTableViewer wkspViewer
;
101 public FetchWizard(Keyring keyring
, RepositoryFactory repositoryFactory
,
102 Repository nodeRepository
) {
104 this.keyring
= keyring
;
105 this.repositoryFactory
= repositoryFactory
;
107 currSession
= nodeRepository
.login();
108 } catch (RepositoryException e
) {
109 throw new SlcException(
110 "Unexpected error while initializing fetch wizard", e
);
115 public void dispose() {
116 JcrUtils
.logoutQuietly(currSession
);
121 public void addPages() {
123 chooseWkspPage
= new ChooseWkspPage();
124 addPage(chooseWkspPage
);
125 recapPage
= new RecapPage();
127 setWindowTitle("Define Fetch Procedure");
128 } catch (Exception e
) {
129 throw new SlcException("Cannot add page to wizard ", e
);
134 public boolean performFinish() {
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
);
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
);
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 ?";
158 boolean result
= MessageDialog
.openConfirm(DistPlugin
.getDefault()
159 .getWorkbench().getDisplay().getActiveShell(),
160 "Confirm Fetch Launch", msg
);
163 RepoSync repoSync
= new RepoSync(sourceRepo
, sourceCredentials
,
164 targetRepo
, targetCredentials
);
165 repoSync
.setTargetRepoUri(targetRepoUri
);
166 repoSync
.setSourceRepoUri(sourceRepoUri
);
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
);
174 repoSync
.setWkspMap(wksps
);
176 // Set the import files only option
177 repoSync
.setFilesOnly(filesOnlyBtn
.getSelection());
178 FetchJob job
= new FetchJob(repoSync
);
182 } catch (Exception e
) {
183 throw new SlcException(
184 "Unexpected error while launching the fetch", e
);
189 // ///////////////////////////////
192 private class ChooseWkspPage
extends WizardPage
{
194 private Map
<String
, Node
> sourceReposMap
;
195 private Combo chooseSourceRepoCmb
;
197 public ChooseWkspPage() {
199 setTitle("Choose workspaces to fetch");
200 setDescription("Check 'advanced fetch' box to "
201 + "rename workspaces and fine tune the process");
203 // Initialise with registered Repositories
204 sourceReposMap
= getSourceRepoUris();
207 public void createControl(Composite parent
) {
208 Composite composite
= new Composite(parent
, SWT
.NO_FOCUS
);
209 composite
.setLayout(new GridLayout(2, false));
211 // Choose source repository combo
212 new Label(composite
, SWT
.NONE
)
213 .setText("Choose a source repository");
214 chooseSourceRepoCmb
= new Combo(composite
, SWT
.BORDER
216 chooseSourceRepoCmb
.setItems(sourceReposMap
.keySet().toArray(
217 new String
[sourceReposMap
.size()]));
218 GridData gd
= new GridData(GridData
.FILL_HORIZONTAL
);
219 chooseSourceRepoCmb
.setLayoutData(gd
);
222 final Button selectAllBtn
= new Button(composite
, SWT
.CHECK
);
223 selectAllBtn
.setText("Select/Unselect all");
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");
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
);
239 filesOnlyBtn
= new Button(composite
, SWT
.CHECK
| SWT
.WRAP
);
241 .setText("Import only files (faster, a normalized action should be launched once done)");
242 filesOnlyBtn
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, false,
246 selectAllBtn
.addSelectionListener(new SelectionAdapter() {
247 public void widgetSelected(SelectionEvent e
) {
248 wkspViewer
.setAllChecked(selectAllBtn
.getSelection());
249 getContainer().updateButtons();
253 // advancedBtn.addSelectionListener(new SelectionAdapter() {
254 // public void widgetSelected(SelectionEvent e) {
255 // if (advancedBtn.getSelection()){
258 // wkspViewer.setAllChecked();
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
);
271 wkspViewer
.addCheckStateListener(new ICheckStateListener() {
272 public void checkStateChanged(CheckStateChangedEvent event
) {
273 getContainer().updateButtons();
277 // Initialise to first available repo
278 if (chooseSourceRepoCmb
.getItemCount() > 0)
279 chooseSourceRepoCmb
.select(0);
282 setControl(composite
);
286 public boolean isPageComplete() {
287 return wkspViewer
.getCheckedElements().length
!= 0;
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
);
303 advancedPages
.put(curr
, page
);
305 page
= advancedPages
.get(curr
);
306 if (toReturn
== null)
315 // Configure the workspace table
316 private void configureWkspTable(Table table
) {
317 table
.setLinesVisible(true);
318 table
.setHeaderVisible(true);
319 wkspViewer
= new CheckboxTableViewer(table
);
322 TableViewerColumn column
= ViewerUtils
.createTableViewerColumn(
323 wkspViewer
, "Source names", SWT
.NONE
, 250);
324 column
.setLabelProvider(new ColumnLabelProvider() {
326 public String
getText(Object element
) {
327 return ((WkspObject
) element
).srcName
;
331 // column = ViewerUtils.createTableViewerColumn(wkspViewer, "Size",
333 // column.setLabelProvider(new ColumnLabelProvider() {
335 // public String getText(Object element) {
336 // return ((WkspObject) element).getFormattedSize();
340 wkspViewer
.setContentProvider(new WkspContentProvider());
342 // TODO implement a fitting comparator
343 // wkspViewer.setComparator(new ArtifactNamesComparator());
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();
502 * Define the privileged job that will be run asynchronously to accomplish
505 private class FetchJob
extends PrivilegedJob
{
506 private RepoSync repoSync
;
508 public FetchJob(RepoSync repoSync
) {
510 this.repoSync
= repoSync
;
514 protected IStatus
doRun(IProgressMonitor progressMonitor
) {
516 ArgeoMonitor monitor
= new EclipseArgeoMonitor(progressMonitor
);
517 repoSync
.setMonitor(monitor
);
519 } catch (Exception e
) {
520 return new Status(IStatus
.ERROR
, DistPlugin
.ID
,
521 "Cannot fetch repository", e
);
523 return Status
.OK_STATUS
;
527 // ///////////////////////
529 private class WkspObject
{
530 protected final String srcName
;
531 protected String targetName
;
533 protected WkspObject(String srcName
) {
534 this.srcName
= srcName
;
535 this.targetName
= srcName
;
539 public String
toString() {
540 return "[" + srcName
+ " to " + targetName
+ "]";
544 private class WkspContentProvider
implements IStructuredContentProvider
{
545 // caches current repo
546 private Node currSourceNodeRepo
;
547 private Repository currSourceRepo
;
548 private Credentials currSourceCred
;
550 private List
<WkspObject
> workspaces
= new ArrayList
<WkspObject
>();
552 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
553 if (newInput
!= null && newInput
instanceof Node
) {
554 Session session
= null;
556 Node newRepoNode
= (Node
) newInput
;
557 if (currSourceNodeRepo
== null
558 || !newRepoNode
.getPath().equals(
559 currSourceNodeRepo
.getPath())) {
562 currSourceNodeRepo
= newRepoNode
;
563 currSourceRepo
= RepoUtils
.getRepository(
564 repositoryFactory
, keyring
, currSourceNodeRepo
);
565 currSourceCred
= RepoUtils
.getRepositoryCredentials(
566 keyring
, currSourceNodeRepo
);
568 // reset workspace list
569 wkspViewer
.setAllChecked(false);
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
577 if (name
.lastIndexOf('-') > 0) {
578 WkspObject currWksp
= new WkspObject(name
);
579 // compute wkspace size
580 // TODO implement this
581 // Session currSession = null;
583 // currSession = currSourceRepo.login(
584 // currSourceCred, name);
585 // currWksp.size = JcrUtils
586 // .getNodeApproxSize(currSession
589 // } catch (RepositoryException re) {
591 // "unable to compute size of workspace "
594 // JcrUtils.logoutQuietly(currSession);
596 workspaces
.add(currWksp
);
600 } catch (RepositoryException e
) {
601 throw new SlcException("Unexpected error while "
602 + "initializing fetch wizard", e
);
604 JcrUtils
.logoutQuietly(session
);
610 public void dispose() {
613 public Object
[] getElements(Object obj
) {
614 return workspaces
.toArray();
618 // ////////////////////////////
621 // populate available source repo list
622 private Map
<String
, Node
> getSourceRepoUris() {
624 Node repoList
= currSession
.getNode(UserJcrUtils
.getUserHome(
625 currSession
).getPath()
626 + RepoConstants
.REPOSITORIES_BASE_PATH
);
628 String targetRepoUri
= null;
629 if (targetRepoNode
!= null) {
630 targetRepoUri
= targetRepoNode
631 .getProperty(ArgeoNames
.ARGEO_URI
).getString();
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
)
643 if (targetRepoUri
== null || !targetRepoUri
.equals(currUri
)) {
644 sourceReposMap
.put(currUri
, currNode
);
645 // sourceRepoNames.add(currUri);
649 return sourceReposMap
;
650 // sourceRepoNames.toArray(new String[sourceRepoNames
652 } catch (RepositoryException e
) {
653 throw new SlcException("Error while getting repo aliases", e
);
657 public void setTargetRepoNode(Node targetRepoNode
) {
658 this.targetRepoNode
= targetRepoNode
;
661 public void setSourceRepoNode(Node sourceRepoNode
) {
662 this.sourceRepoNode
= sourceRepoNode
;