]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/DistributionsView.java
Fixed RPMs.
[gpl/argeo-slc.git] / plugins / org.argeo.slc.client.ui.dist / src / main / java / org / argeo / slc / client / ui / dist / views / DistributionsView.java
index 8d046f5adbede3b1e258bf6c560e7c122b6424ab..218e613faa40808e7eddbaa20261ff96c9e5286e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2012 Mathieu Baudier
+ * Copyright (C) 2007-2012 Argeo GmbH
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 package org.argeo.slc.client.ui.dist.views;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import javax.jcr.Credentials;
 import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
 import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoMonitor;
+import org.argeo.eclipse.ui.EclipseArgeoMonitor;
 import org.argeo.eclipse.ui.ErrorFeedback;
 import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ArgeoJcrUtils;
 import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
 import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.UserJcrUtils;
-import org.argeo.slc.SlcException;
 import org.argeo.slc.client.ui.dist.DistPlugin;
 import org.argeo.slc.client.ui.dist.commands.CopyWorkspace;
 import org.argeo.slc.client.ui.dist.commands.CreateWorkspace;
 import org.argeo.slc.client.ui.dist.commands.DeleteWorkspace;
-import org.argeo.slc.client.ui.dist.commands.ManageWorkspaceAuth;
+import org.argeo.slc.client.ui.dist.commands.DisplayRepoInformation;
+import org.argeo.slc.client.ui.dist.commands.Fetch;
 import org.argeo.slc.client.ui.dist.commands.NormalizeDistribution;
+import org.argeo.slc.client.ui.dist.commands.PublishWorkspace;
+import org.argeo.slc.client.ui.dist.commands.RegisterRepository;
+import org.argeo.slc.client.ui.dist.commands.UnregisterRemoteRepo;
 import org.argeo.slc.client.ui.dist.editors.DistributionEditor;
 import org.argeo.slc.client.ui.dist.editors.DistributionEditorInput;
+import org.argeo.slc.client.ui.dist.model.DistParentElem;
+import org.argeo.slc.client.ui.dist.model.GroupElem;
+import org.argeo.slc.client.ui.dist.model.RepoElem;
+import org.argeo.slc.client.ui.dist.model.WorkspaceElem;
+import org.argeo.slc.client.ui.dist.providers.DistTreeContentProvider;
+import org.argeo.slc.client.ui.dist.providers.DistTreeLabelProvider;
+import org.argeo.slc.client.ui.dist.utils.ArtifactNamesComparator;
 import org.argeo.slc.client.ui.dist.utils.CommandHelpers;
 import org.argeo.slc.jcr.SlcNames;
-import org.argeo.slc.repo.RepoConstants;
-import org.argeo.util.security.Keyring;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.action.IMenuListener;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IDoubleClickListener;
 import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITreeContentProvider;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.TreeViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerDropAdapter;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.Tree;
@@ -71,25 +85,19 @@ import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.part.ViewPart;
 
 /**
- * Browse and manipulate distributions (like merge, rename, etc.). Only support
- * one single repository currently.
+ * Browse, manipulate and manage distributions accross multiple repositories
+ * (like fetch, merge, publish, etc.).
  */
 public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames {
-       // private final static Log log =
-       // LogFactory.getLog(DistributionsView.class);
+       private final static Log log = LogFactory.getLog(DistributionsView.class);
        public final static String ID = DistPlugin.ID + ".distributionsView";
 
+       /* DEPENDENCY INJECTION */
        private Repository nodeRepository;
-       private RepositoryFactory repositoryFactory;
-       private Keyring keyring;
+       private DistTreeContentProvider treeContentProvider;
 
        private TreeViewer viewer;
 
-       // private List<RepositoryElem> repositories = new
-       // ArrayList<DistributionsView.RepositoryElem>();
-
-       // private Session nodeSession = null;
-
        @Override
        public void createPartControl(Composite parent) {
                // Define the TableViewer
@@ -97,23 +105,26 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                                | SWT.FULL_SELECTION | SWT.BORDER);
 
                TreeViewerColumn col = new TreeViewerColumn(viewer, SWT.NONE);
-               col.getColumn().setWidth(200);
-               // col.getColumn().setText("Workspace");
-               col.setLabelProvider(new ColumnLabelProvider() {
-                       @Override
-                       public String getText(Object element) {
-                               if (element instanceof RepoElem)
-                                       return ((RepoElem) element).getLabel();
-                               return element.toString();
-                       }
-               });
+               col.getColumn().setWidth(400);
+               col.setLabelProvider(new DistTreeLabelProvider());
 
-               final Tree table = viewer.getTree();
-               table.setHeaderVisible(false);
-               table.setLinesVisible(false);
+               final Tree tree = viewer.getTree();
+               tree.setHeaderVisible(false);
+               tree.setLinesVisible(false);
 
-               viewer.setContentProvider(new DistributionsContentProvider());
+               // viewer.setContentProvider(new DistTreeContentProvider());
+               viewer.setContentProvider(treeContentProvider);
                viewer.addDoubleClickListener(new DistributionsDCL());
+               viewer.setComparator(new BrowserElementComparator());
+
+               // Enable selection retrieving from outside the view
+               getSite().setSelectionProvider(viewer);
+
+               // Drag'n drop
+               Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
+               int operations = DND.DROP_COPY | DND.DROP_MOVE;
+               viewer.addDragSupport(operations, tt, new ViewDragListener());
+               viewer.addDropSupport(operations, tt, new ViewDropListener(viewer));
 
                MenuManager menuManager = new MenuManager();
                Menu menu = menuManager.createContextMenu(viewer.getTree());
@@ -125,405 +136,384 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                viewer.getTree().setMenu(menu);
                getSite().registerContextMenu(menuManager, viewer);
 
-               Session nodeSession = null;
-               try {
-                       nodeSession = nodeRepository.login();
-
-                       // make sure base directory is available
-                       Node repos = JcrUtils.mkdirs(nodeSession,
-                                       UserJcrUtils.getUserHome(nodeSession).getPath()
-                                                       + RepoConstants.REPOSITORIES_BASE_PATH);
-                       nodeSession.save();
-
-                       // register default local java repository
-                       String alias = RepoConstants.DEFAULT_JAVA_REPOSITORY_ALIAS;
-                       Repository javaRepository = ArgeoJcrUtils.getRepositoryByAlias(
-                                       repositoryFactory, alias);
-                       if (javaRepository != null) {
-                               if (!repos.hasNode(alias)) {
-                                       Node repoNode = repos.addNode(alias,
-                                                       ArgeoTypes.ARGEO_REMOTE_REPOSITORY);
-                                       repoNode.setProperty(ARGEO_URI, alias);
-                                       repoNode.addMixin(NodeType.MIX_TITLE);
-                                       repoNode.setProperty(Property.JCR_TITLE, "vm://" + alias);
-                                       nodeSession.save();
-                               }
-                       }
-               } catch (RepositoryException e) {
-                       throw new SlcException("Cannot register repository", e);
-               } finally {
-                       JcrUtils.logoutQuietly(nodeSession);
-               }
-               //
-               // try {
-               // nodeSession = nodeRepository.login();
-               // NodeIterator repos = JcrUtils.mkdirs(
-               // nodeSession,
-               // UserJcrUtils.getUserHome(nodeSession).getPath()
-               // + RepoConstants.REPOSITORIES_BASE_PATH).getNodes();
-               // while (repos.hasNext()) {
-               // Node repository = repos.nextNode();
-               // String label = null;
-               // if (repository.isNodeType(NodeType.MIX_TITLE)) {
-               // label = repository.getProperty(Property.JCR_TITLE)
-               // .getString();
-               // }
-               //
-               // if (repository.isNodeType(ArgeoTypes.ARGEO_REMOTE_REPOSITORY)) {
-               // String uri = repository.getProperty(ARGEO_URI).getString();
-               // Credentials credentials = null;
-               // if (repository.hasProperty(ARGEO_USER_ID)) {
-               // String userId = repository.getProperty(ARGEO_USER_ID)
-               // .getString();
-               // credentials = new SimpleCredentials(userId,
-               // "".toCharArray());
-               // }
-               // Repository remoteRepository = ArgeoJcrUtils
-               // .getRepositoryByUri(repositoryFactory, uri);
-               // if (label == null)
-               // label = repository.getName();
-               // repositories.add(new RepositoryElem(label,
-               // remoteRepository, credentials));
-               // }
-               // }
-               // } catch (RepositoryException e) {
-               // throw new ArgeoException("Cannot read registered repositories", e);
-               // }
-
-               // Remote
-               // String uri = null;
-               // Credentials credentials = null;
-               // Repository remoteRepository = null;
-
-               // try {
-               // uri = "http://dev.argeo.org/org.argeo.jcr.webapp/pub/java";
-               // credentials = new GuestCredentials();
-               // remoteRepository =
-               // ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, uri);
-               // repositories.add(new RepositoryElem("anonymous@dev.argeo.org//java",
-               // remoteRepository, credentials));
-               // } catch (Exception e) {
-               // e.printStackTrace();
-               // }
-
-               // uri = "http://localhost:7070/org.argeo.jcr.webapp/pub/java";
-               // credentials = new GuestCredentials();
-               // remoteRepository =
-               // ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, uri);
-               // repositories.add(new RepositoryElem("anonymous@localhost//java",
-               // remoteRepository, credentials));
-
-               // uri = "http://localhost:7070/org.argeo.jcr.webapp/remoting/java";
-               // credentials = new SimpleCredentials(System.getProperty("user.name"),
-               // "".toCharArray());
-               // remoteRepository =
-               // ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, uri);
-               // repositories.add(new RepositoryElem("@localhost//java",
-               // remoteRepository, credentials));
-
-               viewer.setInput(nodeRepository);
-
-       }
-
-       @Override
-       public void setFocus() {
-               viewer.getTree().setFocus();
-       }
-
-       /**
-        * Force refresh of the whole view
-        */
-       public void refresh() {
-               viewer.setContentProvider(new DistributionsContentProvider());
-       }
-
-       public void setNodeRepository(Repository repository) {
-               this.nodeRepository = repository;
-       }
-
-       public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
-               this.repositoryFactory = repositoryFactory;
-       }
-
-       public void setKeyring(Keyring keyring) {
-               this.keyring = keyring;
+               // Initialize
+               refresh();
        }
 
        /** Programatically configure the context menu */
        protected void contextMenuAboutToShow(IMenuManager menuManager) {
                IWorkbenchWindow window = DistPlugin.getDefault().getWorkbench()
                                .getActiveWorkbenchWindow();
+               // Most of the implemented commands support only one selected
+               // element
+               boolean singleElement = ((IStructuredSelection) viewer.getSelection())
+                               .size() == 1;
                // Get Current selected item :
                Object firstElement = ((IStructuredSelection) viewer.getSelection())
                                .getFirstElement();
 
-               if (firstElement instanceof TreeParent) {
-                       TreeParent tp = (TreeParent) firstElement;
-                       String wsName = tp.getName();
+               if (firstElement instanceof TreeParent
+                               || firstElement instanceof DistParentElem) {
+                       String targetRepoPath = null;
 
-                       // Build conditions depending on element type (repo or distribution
-                       // for the time being)
-                       boolean isDistribElem = false; // , isRepoElem = false;
+                       // Build conditions depending on element type
+                       boolean isDistribElem = false, isRepoElem = false, isDistribGroupElem = false;
+                       boolean isHomeRepo = false, isReadOnly = true;
 
-                       // if (tp instanceof RepositoryElem){
-                       // isRepoElem = true;
-                       // } else
-                       if (tp instanceof DistributionElem) {
+                       if (firstElement instanceof WorkspaceElem) {
+                               WorkspaceElem de = (WorkspaceElem) firstElement;
                                isDistribElem = true;
+                               isReadOnly = de.isReadOnly();
+                       } else if (firstElement instanceof RepoElem) {
+                               RepoElem re = (RepoElem) firstElement;
+                               isRepoElem = true;
+                               targetRepoPath = re.getRepoPath();
+                               isHomeRepo = re.inHome();
+                               isReadOnly = re.isReadOnly();
+                       } else if (firstElement instanceof GroupElem) {
+                               GroupElem dge = (GroupElem) firstElement;
+                               isReadOnly = dge.isReadOnly();
+                               isDistribGroupElem = true;
                        }
 
+                       // Display repo info
+                       CommandHelpers.refreshCommand(menuManager, window,
+                                       DisplayRepoInformation.ID,
+                                       DisplayRepoInformation.DEFAULT_LABEL,
+                                       DisplayRepoInformation.DEFAULT_ICON_PATH, isRepoElem
+                                                       && singleElement);
+
                        // create workspace
                        CommandHelpers.refreshCommand(menuManager, window,
                                        CreateWorkspace.ID, CreateWorkspace.DEFAULT_LABEL,
-                                       CreateWorkspace.DEFAULT_ICON_PATH, !isDistribElem);
+                                       CreateWorkspace.DEFAULT_ICON_PATH,
+                                       (isRepoElem || isDistribGroupElem) && singleElement
+                                                       && !isReadOnly);
+                       // publish workspace
+                       CommandHelpers.refreshCommand(menuManager, window,
+                                       PublishWorkspace.ID, PublishWorkspace.DEFAULT_LABEL,
+                                       PublishWorkspace.DEFAULT_ICON_PATH, isDistribElem
+                                                       && singleElement && !isReadOnly);
 
-                       // Normalize workspace
+                       // Register a remote repository
+                       CommandHelpers.refreshCommand(menuManager, window,
+                                       RegisterRepository.ID, RegisterRepository.DEFAULT_LABEL,
+                                       RegisterRepository.DEFAULT_ICON_PATH, isRepoElem
+                                                       && singleElement);
+
+                       // Unregister a remote repository
                        Map<String, String> params = new HashMap<String, String>();
-                       params.put(NormalizeDistribution.PARAM_WORKSPACE, wsName);
+                       params.put(UnregisterRemoteRepo.PARAM_REPO_PATH, targetRepoPath);
+                       CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                                       UnregisterRemoteRepo.ID,
+                                       UnregisterRemoteRepo.DEFAULT_LABEL,
+                                       UnregisterRemoteRepo.DEFAULT_ICON_PATH, isRepoElem
+                                                       && !isHomeRepo && singleElement, params);
+
+                       // Fetch repository
+                       params = new HashMap<String, String>();
+                       params.put(Fetch.PARAM_TARGET_REPO, targetRepoPath);
                        CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                                       Fetch.ID, Fetch.DEFAULT_LABEL, Fetch.DEFAULT_ICON_PATH,
+                                       isRepoElem && singleElement && !isReadOnly, params);
+
+                       // Normalize workspace
+                       CommandHelpers.refreshCommand(menuManager, window,
                                        NormalizeDistribution.ID,
                                        NormalizeDistribution.DEFAULT_LABEL,
-                                       NormalizeDistribution.DEFAULT_ICON_PATH, isDistribElem,
-                                       params);
+                                       NormalizeDistribution.DEFAULT_ICON_PATH, isDistribElem
+                                                       && singleElement && !isReadOnly);
 
                        // Copy workspace
-                       params = new HashMap<String, String>();
-                       params.put(CopyWorkspace.PARAM_WORKSPACE_NAME, wsName);
-                       CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                       CommandHelpers.refreshCommand(menuManager, window,
                                        CopyWorkspace.ID, CopyWorkspace.DEFAULT_LABEL,
-                                       CopyWorkspace.DEFAULT_ICON_PATH, isDistribElem, params);
+                                       CopyWorkspace.DEFAULT_ICON_PATH, isDistribElem
+                                                       && singleElement);
 
-                       // Delete Workspace
-                       params = new HashMap<String, String>();
-                       params.put(DeleteWorkspace.PARAM_WORKSPACE_NAME, wsName);
-                       CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                       // Clear Workspace
+                       CommandHelpers.refreshCommand(menuManager, window,
                                        DeleteWorkspace.ID, DeleteWorkspace.DEFAULT_LABEL,
-                                       DeleteWorkspace.DEFAULT_ICON_PATH, isDistribElem, params);
-
-                       // Manage workspace authorizations
-                       params = new HashMap<String, String>();
-                       params.put(ManageWorkspaceAuth.PARAM_WORKSPACE_NAME, wsName);
-                       CommandHelpers.refreshParameterizedCommand(menuManager, window,
-                                       ManageWorkspaceAuth.ID, ManageWorkspaceAuth.DEFAULT_LABEL,
-                                       ManageWorkspaceAuth.DEFAULT_ICON_PATH, isDistribElem,
-                                       params);
+                                       DeleteWorkspace.DEFAULT_ICON_PATH, isDistribElem
+                                                       && singleElement && !isReadOnly);
+
+                       // // Manage workspace authorizations
+                       // params = new HashMap<String, String>();
+                       // params.put(ManageWorkspaceAuth.PARAM_WORKSPACE_NAME, wsName);
+                       // CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                       // ManageWorkspaceAuth.ID, ManageWorkspaceAuth.DEFAULT_LABEL,
+                       // ManageWorkspaceAuth.DEFAULT_ICON_PATH, isDistribElem
+                       // && singleElement && !isReadOnly, params);
                }
+               // } catch (RepositoryException e) {
+               // throw new SlcException("unexpected errror while "
+               // + "building context menu", e);
+               // }
        }
 
-       private class DistributionsContentProvider implements ITreeContentProvider {
-               Session nodeSession;
-               List<RepoElem> repositories = new ArrayList<RepoElem>();
-
-               public Object[] getElements(Object input) {
-                       Repository nodeRepository = (Repository) input;
-                       try {
-                               if (nodeSession != null)
-                                       dispose();
-                               nodeSession = nodeRepository.login();
-
-                               String reposPath = UserJcrUtils.getUserHome(nodeSession)
-                                               .getPath() + RepoConstants.REPOSITORIES_BASE_PATH;
-                               NodeIterator repos = nodeSession.getNode(reposPath).getNodes();
-                               while (repos.hasNext()) {
-                                       Node repoNode = repos.nextNode();
-                                       if (repoNode.isNodeType(ArgeoTypes.ARGEO_REMOTE_REPOSITORY)) {
-                                               repositories.add(new RepoElem(repoNode));
-                                       }
-                               }
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot get base elements", e);
-                       }
-                       return repositories.toArray();
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-
-               }
+       /**
+        * Exposes some Repository and workspace information about the selected
+        * element without exposing the UI model
+        */
+       public class DistributionViewSelectedElement {
+               public boolean isRepository = false;
+               public boolean isWorkspaceGroup = false;
+               public boolean isWorkspace = false;
+               public boolean isReadOnly = false;
+               public String repositoryDescription;
+               public Node repoNode;
+               public String wkspName;
+               public String wkspPrefix;
+               public Repository repository;
+               public Credentials credentials;
+       }
 
-               public Object[] getChildren(Object parentElement) {
-                       if (parentElement instanceof RepoElem) {
-                               return ((RepoElem) parentElement).getChildren();
-                       } else if (parentElement instanceof DistributionElem) {
-                               return ((DistributionElem) parentElement).getChildren();
-                       }
-                       return null;
-               }
+       /**
+        * Returns a {@see DistributionViewSelectedElement} if one and only one
+        * valid element is currently selected.
+        * 
+        */
+       public DistributionViewSelectedElement getSelectedElement() {
 
-               public Object getParent(Object element) {
-                       // TODO register repo elem in distirbution elem?
+               IStructuredSelection iss = (IStructuredSelection) viewer.getSelection();
+               if (iss.isEmpty() || iss.size() > 1)
                        return null;
-               }
 
-               public boolean hasChildren(Object element) {
-                       if (element instanceof RepoElem) {
-                               return true;
-                       } else if (element instanceof DistributionElem) {
-                               return false;
-                       }
-                       return false;
-               }
-
-               public void dispose() {
-                       for (RepoElem repoElem : repositories)
-                               repoElem.dispose();
-                       repositories = new ArrayList<RepoElem>();
-                       JcrUtils.logoutQuietly(nodeSession);
+               DistributionViewSelectedElement dvse = new DistributionViewSelectedElement();
+               Object obj = iss.getFirstElement();
+               if (obj instanceof RepoElem) {
+                       RepoElem re = (RepoElem) obj;
+                       dvse.isRepository = true;
+                       dvse.isReadOnly = re.isReadOnly();
+                       dvse.repository = re.getRepository();
+                       dvse.repoNode = re.getRepoNode();
+                       dvse.credentials = re.getCredentials();
+                       dvse.repositoryDescription = getRepositoryDescription(re);
+               } else if (obj instanceof GroupElem) {
+                       GroupElem dge = (GroupElem) obj;
+                       dvse.isWorkspaceGroup = true;
+                       dvse.isReadOnly = dge.isReadOnly();
+                       dvse.repository = dge.getRepoElem().getRepository();
+                       dvse.repoNode = dge.getRepoElem().getRepoNode();
+                       dvse.credentials = dge.getRepoElem().getCredentials();
+                       dvse.wkspPrefix = dge.getLabel();
+                       dvse.repositoryDescription = getRepositoryDescription(dge
+                                       .getRepoElem());
+               } else if (obj instanceof WorkspaceElem) {
+                       WorkspaceElem de = (WorkspaceElem) obj;
+                       dvse.isWorkspace = true;
+                       dvse.isReadOnly = de.isReadOnly();
+                       dvse.repository = de.getRepoElem().getRepository();
+                       dvse.repoNode = de.getRepoElem().getRepoNode();
+                       dvse.credentials = de.getRepoElem().getCredentials();
+                       dvse.wkspName = de.getWorkspaceName();
+                       dvse.repositoryDescription = getRepositoryDescription(de
+                                       .getRepoElem());
                }
+               return dvse;
+       }
 
+       private String getRepositoryDescription(RepoElem repo) {
+               StringBuffer repoDesc = new StringBuffer();
+               repoDesc.append(repo.getLabel());
+               repoDesc.append(" (");
+               repoDesc.append(JcrUtils.get(repo.getRepoNode(), ARGEO_URI));
+               repoDesc.append(")");
+               return repoDesc.toString();
        }
 
-       // private class DistributionsContentProvider extends
-       // AbstractTreeContentProvider {
-       //
-       // public Object[] getElements(Object arg0) {
-       // return repositories.toArray();
-       // }
-       //
-       // }
+       @Override
+       public void setFocus() {
+               viewer.getTree().setFocus();
+       }
 
-       private class RepoElem {
-               private Node repoNode;
+       /**
+        * Force refresh of the whole view
+        */
+       public void refresh() {
+               viewer.setInput(nodeRepository);
+               viewer.expandToLevel(2);
+       }
 
-               private Repository repository;
-               private Credentials credentials;
-               private Session defaultSession = null;
+       /** Add some view specific behaviours to the comparator */
+       private class BrowserElementComparator extends ArtifactNamesComparator {
+               @Override
+               public int category(Object element) {
+                       // Home repository always first
+                       if (element instanceof RepoElem && ((RepoElem) element).inHome())
+                               return 2;
+                       else
+                               return super.category(element);
+               }
 
-               public RepoElem(Node repoNode) {
-                       this.repoNode = repoNode;
+               @Override
+               public int compare(Viewer viewer, Object e1, Object e2) {
+                       // reverse order for versions
+                       if (e1 instanceof WorkspaceElem)
+                               return -super.compare(viewer, e1, e2);
+                       else
+                               return super.compare(viewer, e1, e2);
                }
+       }
 
-               /** Lazily connects to repository */
-               protected void connect() {
-                       if (defaultSession != null)
-                               return;
+       /** Abstract class to simplify UI conditions build */
 
-                       try {
-                               if (repoNode.isNodeType(ArgeoTypes.ARGEO_REMOTE_REPOSITORY)) {
-                                       String uri = repoNode.getProperty(ARGEO_URI).getString();
-                                       if (uri.startsWith("http")) {// http, https
-                                               if (repoNode.hasProperty(ARGEO_USER_ID)) {
-                                                       String userId = repoNode.getProperty(ARGEO_USER_ID)
-                                                                       .getString();
-                                                       char[] password = keyring.getAsChars(repoNode
-                                                                       .getPath() + '/' + ARGEO_PASSWORD);
-                                                       credentials = new SimpleCredentials(userId,
-                                                                       password);
-                                               }
-                                               repository = ArgeoJcrUtils.getRepositoryByUri(
-                                                               repositoryFactory, uri);
-                                       } else {// alias
-                                               String alias = uri;
-                                               repository = ArgeoJcrUtils.getRepositoryByAlias(
-                                                               repositoryFactory, alias);
-                                               credentials = null;
-                                       }
-                                       defaultSession = repository.login(credentials);
-                               }
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot connect to repository "
-                                               + repoNode, e);
-                       }
-               }
+       /** A software repository */
 
-               public String getLabel() {
-                       try {
-                               if (repoNode.isNodeType(NodeType.MIX_TITLE)) {
-                                       return repoNode.getProperty(Property.JCR_TITLE).getString();
-                               } else {
-                                       return repoNode.getName();
+       /** Listens to drag */
+       class ViewDragListener extends DragSourceAdapter {
+               public void dragSetData(DragSourceEvent event) {
+                       IStructuredSelection selection = (IStructuredSelection) viewer
+                                       .getSelection();
+                       if (selection.getFirstElement() instanceof WorkspaceElem) {
+                               WorkspaceElem de = (WorkspaceElem) selection.getFirstElement();
+                               if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
+                                       event.data = de.getWorkspacePath();
                                }
-                       } catch (RepositoryException e) {
-                               throw new SlcException("Cannot read label of " + repoNode, e);
                        }
                }
+       }
 
-               public String toString() {
-                       return repoNode.toString();
-               }
+       /** Listens to drop */
+       class ViewDropListener extends ViewerDropAdapter {
 
-               public Object[] getChildren() {
-                       connect();
-                       try {
-                               String[] workspaceNames = defaultSession.getWorkspace()
-                                               .getAccessibleWorkspaceNames();
-                               List<DistributionElem> distributionElems = new ArrayList<DistributionElem>();
-                               for (String workspace : workspaceNames)
-                                       distributionElems.add(new DistributionElem(repository,
-                                                       workspace, credentials));
-                               return distributionElems.toArray();
-                       } catch (RepositoryException e) {
-                               throw new SlcException(
-                                               "Cannot list workspaces for " + repoNode, e);
-                       }
+               public ViewDropListener(Viewer viewer) {
+                       super(viewer);
                }
 
-               public void dispose() {
-                       JcrUtils.logoutQuietly(defaultSession);
-               }
-       }
+               @Override
+               public boolean performDrop(Object data) {
+                       WorkspaceElem sourceDist = (WorkspaceElem) getSelectedObject();
+                       RepoElem targetRepo = (RepoElem) getCurrentTarget();
+
+                       Boolean ok = MessageDialog.openConfirm(getSite().getShell(),
+                                       "FIXME: BROKEN BY REFACTORING--Confirm distribution merge",
+                                       "Do you want to merge " + sourceDist.getWorkspaceName()
+                                                       + " (from repo "
+                                                       + sourceDist.getRepoElem().getLabel()
+                                                       + ") to repo " + targetRepo.getLabel() + "?");
+                       if (!ok)
+                               return false;
 
-       /** Wraps a repository **/
-       // private static class RepositoryElem extends TreeParent {
-       // // private final Repository repository;
-       // private Session defaultSession;
-       //
-       // public RepositoryElem(String name, Repository repository,
-       // Credentials credentials) {
-       // super(name);
-       // try {
-       // defaultSession = repository.login(credentials);
-       // String[] workspaceNames = defaultSession.getWorkspace()
-       // .getAccessibleWorkspaceNames();
-       // for (String workspace : workspaceNames)
-       // addChild(new DistributionElem(repository, workspace,
-       // credentials));
-       // } catch (RepositoryException e) {
-       // ErrorFeedback.show("Cannot log to repository", e);
-       // }
-       // }
-       //
-       // @Override
-       // public synchronized void dispose() {
-       // if (log.isTraceEnabled())
-       // log.trace("Disposing RepositoryElement");
-       // JcrUtils.logoutQuietly(defaultSession);
-       // super.dispose();
-       // }
-       // }
-
-       private static class DistributionElem extends TreeParent {
-               private final String workspaceName;
-               private final Repository repository;
-               private final Credentials credentials;
-
-               public DistributionElem(Repository repository, String workspaceName,
-                               Credentials credentials) {
-                       super(workspaceName);
-                       this.workspaceName = workspaceName;
-                       this.repository = repository;
-                       this.credentials = credentials;
+                       // TODO uncomment that
+                       return true;
+                       // try {
+                       // String sourceWorkspace = sourceDist.getWorkspaceName();
+                       // Repository sourceRepository = RepoUtils.getRepository(
+                       // repositoryFactory, keyring, sourceDist
+                       // .getWorkspaceNode().getParent());
+                       // Credentials sourceCredentials = RepoUtils
+                       // .getRepositoryCredentials(keyring, sourceDist
+                       // .getWorkspaceNode().getParent());
+                       //
+                       // String targetWorkspace = sourceWorkspace;
+                       // Repository targetRepository = RepoUtils.getRepository(
+                       // repositoryFactory, keyring, targetRepo.getRepoNode());
+                       // Credentials targetCredentials = RepoUtils
+                       // .getRepositoryCredentials(keyring,
+                       // targetRepo.getRepoNode());
+                       //
+                       // // Open sessions here since the background thread
+                       // // won't necessarily be authenticated.
+                       // // Job should close the sessions.
+                       // Session sourceSession = sourceRepository.login(
+                       // sourceCredentials, sourceWorkspace);
+                       // Session targetSession;
+                       // try {
+                       // targetSession = targetRepository.login(targetCredentials,
+                       // targetWorkspace);
+                       // } catch (NoSuchWorkspaceException e) {
+                       // Session defaultSession = targetRepository
+                       // .login(targetCredentials);
+                       // try {
+                       // defaultSession.getWorkspace().createWorkspace(
+                       // targetWorkspace);
+                       // } catch (Exception e1) {
+                       // throw new SlcException("Cannot create new workspace "
+                       // + targetWorkspace, e);
+                       // } finally {
+                       // JcrUtils.logoutQuietly(defaultSession);
+                       // }
+                       // targetSession = targetRepository.login(targetCredentials,
+                       // targetWorkspace);
+                       // }
+                       //
+                       // Job workspaceMergeJob = new WorkspaceMergeJob(sourceSession,
+                       // targetSession);
+                       // workspaceMergeJob.setUser(true);
+                       // workspaceMergeJob.schedule();
+                       // return true;
+                       // } catch (RepositoryException e) {
+                       // throw new SlcException("Cannot process drop from " + sourceDist
+                       // + " to " + targetRepo, e);
+                       // }
                }
 
-               public String getWorkspaceName() {
-                       return workspaceName;
+               @Override
+               public boolean validateDrop(Object target, int operation,
+                               TransferData transferType) {
+                       if (target instanceof RepoElem) {
+                               if (getSelectedObject() instanceof WorkspaceElem) {
+                                       // check if not same repository
+                                       String srcRepoPath = ((WorkspaceElem) getSelectedObject())
+                                                       .getRepoPath();
+                                       String targetRepoPath = ((RepoElem) target).getRepoPath();
+                                       return !targetRepoPath.equals(srcRepoPath);
+                               }
+                       }
+                       return false;
                }
+       }
 
-               public Repository getRepository() {
-                       return repository;
-               }
+       private static class WorkspaceMergeJob extends Job {
+               private Session sourceSession;
+               private Session targetSession;
 
-               public Credentials getCredentials() {
-                       return credentials;
+               public WorkspaceMergeJob(Session sourceSession, Session targetSession) {
+                       super("Workspace merge");
+                       this.sourceSession = sourceSession;
+                       this.targetSession = targetSession;
                }
-       }
 
-       @Override
-       public void dispose() {
-               // for (RepositoryElem re : repositories)
-               // re.dispose();
-               super.dispose();
+               @Override
+               protected IStatus run(IProgressMonitor eclipseMonitor) {
+                       long begin = System.currentTimeMillis();
+                       try {
+                               Query countQuery = sourceSession
+                                               .getWorkspace()
+                                               .getQueryManager()
+                                               .createQuery("select file from [nt:file] as file",
+                                                               Query.JCR_SQL2);
+                               QueryResult result = countQuery.execute();
+                               Long expectedCount = result.getNodes().getSize();
+                               if (log.isDebugEnabled())
+                                       log.debug("Will copy " + expectedCount + " files...");
+
+                               ArgeoMonitor monitor = new EclipseArgeoMonitor(eclipseMonitor);
+                               eclipseMonitor
+                                               .beginTask("Copy files", expectedCount.intValue());
+
+                               Long count = JcrUtils.copyFiles(sourceSession.getRootNode(),
+                                               targetSession.getRootNode(), true, monitor);
+
+                               monitor.done();
+                               long duration = (System.currentTimeMillis() - begin) / 1000;// in
+                                                                                                                                                       // s
+                               if (log.isDebugEnabled())
+                                       log.debug("Copied " + count + " files in "
+                                                       + (duration / 60) + "min " + (duration % 60) + "s");
+
+                               return Status.OK_STATUS;
+                       } catch (RepositoryException e) {
+                               return new Status(IStatus.ERROR, DistPlugin.ID, "Cannot merge",
+                                               e);
+                       } finally {
+                               JcrUtils.logoutQuietly(sourceSession);
+                               JcrUtils.logoutQuietly(targetSession);
+                       }
+               }
        }
 
+       /** Listen to double-clicks */
        private class DistributionsDCL implements IDoubleClickListener {
 
                public void doubleClick(DoubleClickEvent event) {
@@ -531,13 +521,14 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                                return;
                        Object obj = ((IStructuredSelection) event.getSelection())
                                        .getFirstElement();
-                       if (obj instanceof DistributionElem) {
-                               DistributionElem distributionElem = (DistributionElem) obj;
+                       if (obj instanceof WorkspaceElem) {
+                               WorkspaceElem distributionElem = (WorkspaceElem) obj;
                                DistributionEditorInput dei = new DistributionEditorInput(
                                                distributionElem.getName(),
-                                               distributionElem.getRepository(),
-                                               distributionElem.getWorkspaceName(),
-                                               distributionElem.getCredentials());
+                                               getRepositoryDescription(distributionElem.getRepoElem()),
+                                               distributionElem.getRepoElem().getRepository(),
+                                               distributionElem.getWorkspaceName(), distributionElem
+                                                               .getCredentials());
                                try {
                                        DistPlugin.getDefault().getWorkbench()
                                                        .getActiveWorkbenchWindow().getActivePage()
@@ -549,4 +540,16 @@ public class DistributionsView extends ViewPart implements SlcNames, ArgeoNames
                        }
                }
        }
+
+       /*
+        * DEPENDENCY INJECTION
+        */
+       public void setNodeRepository(Repository repository) {
+               this.nodeRepository = repository;
+       }
+
+       public void setTreeContentProvider(
+                       DistTreeContentProvider treeContentProvider) {
+               this.treeContentProvider = treeContentProvider;
+       }
 }
\ No newline at end of file