]> 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/model/RepoElem.java
+ clean repo model
[gpl/argeo-slc.git] / plugins / org.argeo.slc.client.ui.dist / src / main / java / org / argeo / slc / client / ui / dist / model / RepoElem.java
index 7d584f7875d311927e90b2566e8e3eb4cab3a263..28841c8695aaf51195a6fe881e7af9756ba3dfd6 100644 (file)
@@ -1,20 +1,14 @@
 package org.argeo.slc.client.ui.dist.model;
 
 import java.security.AccessControlException;
-import java.util.HashMap;
-import java.util.Map;
 
 import javax.jcr.Credentials;
 import javax.jcr.Node;
-import javax.jcr.Property;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.RepositoryFactory;
 import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.argeo.jcr.ArgeoJcrUtils;
 import org.argeo.jcr.ArgeoNames;
 import org.argeo.jcr.JcrUtils;
@@ -24,152 +18,217 @@ import org.argeo.slc.repo.RepoUtils;
 import org.argeo.util.security.Keyring;
 
 /**
- * Abstract a repository. Might be persisted by a node in the current user home
- * Node or just an URI and a label if user is anonymous
+ * Abstract a repository. It might be persisted by a node in the current user
+ * home Node or just an URI and a label if user is anonymous
  */
 public class RepoElem extends DistParentElem {
-       private final static Log log = LogFactory.getLog(RepoElem.class);
+       // private final static Log log = LogFactory.getLog(RepoElem.class);
 
-       private Repository repository;
-       private Credentials credentials;
        private RepositoryFactory repositoryFactory;
        private Keyring keyring;
+       private Credentials credentials;
+       private Session defaultSession = null;
 
        // Defines current repo
        private Node repoNode = null;
        private String label;
        private String uri;
 
+       private Repository repository;
+
        /**
-        * Creates a RepoElement for an authenticated user. repofactory and keyring
-        * are used to enable lazy init
+        * Creates a RepoElement for anonymous user. The {@code RepositoryFactory}
+        * is used to enable lazy initialisation
+        */
+       public RepoElem(RepositoryFactory repoFactory, String uri, String label) {
+               super(label);
+               this.repositoryFactory = repoFactory;
+               this.uri = uri;
+               this.label = label;
+       }
+
+       /**
+        * Creates a RepoElement for an authenticated user. The
+        * {@code RepositoryFactory} and {@code Keyring} are used to enable lazy
+        * initialisation
         * 
         */
-       public RepoElem(Node repoNode, RepositoryFactory repoFactory,
-                       Keyring keyring) {
+       public RepoElem(RepositoryFactory repoFactory, Keyring keyring,
+                       Node repoNode, String alias) {
+               super(alias);
+               this.label = alias;
+               // label = repoNode.isNodeType(NodeType.MIX_TITLE) ? repoNode
+               // .getProperty(Property.JCR_TITLE).getString() : repoNode
+               // .getName();
                this.repoNode = repoNode;
                this.repositoryFactory = repoFactory;
                this.keyring = keyring;
                try {
-                       // initialize this repo informations
+                       // Initialize this repo information
                        setInHome(RepoConstants.DEFAULT_JAVA_REPOSITORY_ALIAS
                                        .equals(repoNode.getName()));
-                       if (!inHome())
+                       if (inHome())
+                               // Directly log and retrieve children for local repository
+                               login();
+                       else
                                setReadOnly(!repoNode.hasNode(ArgeoNames.ARGEO_PASSWORD));
                        uri = JcrUtils.get(repoNode, ArgeoNames.ARGEO_URI);
-                       label = repoNode.isNodeType(NodeType.MIX_TITLE) ? repoNode
-                                       .getProperty(Property.JCR_TITLE).getString() : repoNode
-                                       .getName();
                } catch (RepositoryException e) {
                        throw new SlcException("Unable to " + "initialize repo element", e);
                }
        }
 
-       /**
-        * Creates a RepoElement for anonymous user. repofactory is used to enable
-        * lazy init
-        * 
-        */
-       public RepoElem(RepositoryFactory repoFactory, String uri, String label) {
-               this.repositoryFactory = repoFactory;
-               this.uri = uri;
-               this.label = label;
+       /** Effective login. Does nothing if the session is already there. */
+       public void login() {
+               if (isConnected())
+                       return;
+
+               if (repository == null)
+                       if (repoNode == null)
+                               // Anonymous
+                               repository = ArgeoJcrUtils.getRepositoryByUri(
+                                               repositoryFactory, uri);
+                       else {
+                               repository = RepoUtils.getRepository(repositoryFactory,
+                                               keyring, repoNode);
+                               credentials = RepoUtils.getRepositoryCredentials(keyring,
+                                               repoNode);
+                       }
+
+               try {
+                       defaultSession = repository.login(credentials);
+                       refreshChildren();
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot login repository " + label
+                                       + " with credential " + credentials, e);
+               }
        }
 
-       /** Lazily connects to repository */
-       protected void connect() {
-               if (repository != null)
-                       return;
-               if (repoNode == null)
-                       // Anonymous
-                       repository = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory,
-                                       uri);
-               else {
-                       repository = RepoUtils.getRepository(repositoryFactory, keyring,
-                                       repoNode);
-                       credentials = RepoUtils.getRepositoryCredentials(keyring, repoNode);
+       protected void refreshChildren() {
+               try {
+                       // TODO also remove deleted children (only adds for the time being
+                       String[] workspaceNames = defaultSession.getWorkspace()
+                                       .getAccessibleWorkspaceNames();
+                       buildWksp: for (String workspaceName : workspaceNames) {
+                               if (!isWorkspaceVisible(workspaceName))
+                                       continue buildWksp;
+
+                               String prefix = getPrefix(workspaceName);
+                               if (getChildByName(prefix) == null) {
+                                       WkspGroupElem wkspGpElem = new WkspGroupElem(RepoElem.this,
+                                                       prefix);
+                                       addChild(wkspGpElem);
+                               }
+                       }
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot list workspaces for " + repoNode, e);
                }
        }
 
-       public String getLabel() {
-               return label;
+       @Override
+       public synchronized void dispose() {
+               JcrUtils.logoutQuietly(defaultSession);
+               super.dispose();
        }
 
-       public String getUri() {
-               return uri;
+       private String getPrefix(String workspaceName) {
+               // Here is the tricks - we rely on a "hard coded" convention
+               // Workspace name should be like: name-major.minor
+               if (workspaceName.lastIndexOf(VERSION_SEP) > 0)
+                       return workspaceName.substring(0,
+                                       workspaceName.lastIndexOf(VERSION_SEP));
+               else
+                       return workspaceName;
        }
 
-       public String toString() {
-               return repoNode != null ? repoNode.toString() : label;
+       /* Exposes this to the children workspace group */
+       protected boolean isWorkspaceVisible(String wkspName) {
+               Boolean result = true;
+               if (ARGEO_SYSTEM_WKSP.contains(wkspName))
+                       return false;
+               // Add a supplementary check to hide workspace that are not
+               // public to anonymous user
+               if (repoNode == null) {
+                       Session tmpSession = null;
+                       try {
+                               tmpSession = repository.login(wkspName);
+                               try {
+                                       tmpSession.checkPermission("/", "read");
+                               } catch (AccessControlException e) {
+                                       result = false;
+                               }
+                       } catch (RepositoryException e) {
+                               throw new SlcException(
+                                               "Cannot list workspaces for anonymous user", e);
+                       } finally {
+                               JcrUtils.logoutQuietly(tmpSession);
+                       }
+               }
+               return result;
        }
 
-       public Object[] getChildren() {
+       /**
+        * Actual call to the
+        * {@link Repository#login(javax.jcr.Credentials, String)} method. To be
+        * overridden.
+        * 
+        * Creates a new session with correct credentials using the information
+        * contained in the corresponding repo node. It provides all UI children
+        * elements an unique entry point to retrieve a new Session. Caller must
+        * close the session when it is not in use anymore.
+        * 
+        */
+       protected Session repositoryLogin(String workspaceName) {
                try {
-                       connect();
-               } catch (Exception e) {
-                       log.error("Cannot connect to " + uri + " return no children.", e);
-                       return new Object[0];
+                       return repository.login(credentials, workspaceName);
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot login repository " + label
+                                       + " with credential " + credentials, e);
                }
+       }
 
-               Session session = null;
-               try {
-                       session = repository.login(credentials);
-                       String[] workspaceNames = session.getWorkspace()
-                                       .getAccessibleWorkspaceNames();
-                       Map<String, GroupElem> children = new HashMap<String, GroupElem>();
+       public Boolean isConnected() {
+               if (defaultSession != null && defaultSession.isLive())
+                       return true;
+               else
+                       return false;
+       }
 
-                       buildWksp: for (String workspaceName : workspaceNames) {
-                               // Add a supplementary check to hide workspace that are not
-                               // public to anonymous user
-
-                               if (repoNode == null) {
-                                       Session tmpSession = null;
-                                       try {
-                                               tmpSession = repository.login(workspaceName);
-                                               Boolean res = true;
-                                               try {
-                                                       tmpSession.checkPermission("/", "read");
-                                               } catch (AccessControlException e) {
-                                                       res = false;
-                                               }
-                                               if (!res)
-                                                       continue buildWksp;
-                                       } catch (RepositoryException e) {
-                                               throw new SlcException(
-                                                               "Cannot list workspaces for anonymous user", e);
-                                       } finally {
-                                               JcrUtils.logoutQuietly(tmpSession);
-                                       }
-                               }
+       /** Exposes URI to the current repository */
+       public String getUri() {
+               return uri;
+       }
 
-                               // filter technical workspaces
-                               // FIXME: rely on a more robust rule than just wksp name
-                               if (workspaceName.lastIndexOf(VERSION_SEP) > 0) {
-                                       String prefix = workspaceName.substring(0,
-                                                       workspaceName.lastIndexOf(VERSION_SEP));
-                                       if (!children.containsKey(prefix)) {
-                                               children.put(prefix, new GroupElem(RepoElem.this,
-                                                               prefix));
-                                       }
-                               }
+       public String getRepoNodePath() {
+               if (repoNode == null)
+                       return null;
+               else
+                       try {
+                               return repoNode.getPath();
+                       } catch (RepositoryException e) {
+                               throw new SlcException("Cannot get node path for repository "
+                                               + label, e);
                        }
-                       return children.values().toArray();
-               } catch (RepositoryException e) {
-                       throw new SlcException("Cannot list workspaces for " + repoNode, e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
        }
 
-       public Repository getRepository() {
-               connect();
+       /**
+        * Exposes the local repoNode that completely define a connection to a
+        * repository (including a set of credentials). Might return null in case of
+        * an anonymous user
+        */
+       protected Node getRepoNode() {
+               return repoNode;
+       }
+
+       protected Repository getRepository() {
                return repository;
        }
 
-       public Credentials getCredentials() {
+       protected Credentials getCredentials() {
                return credentials;
        }
 
+       // META INFO
        public String getDescription() {
                String desc = label;
                if (repoNode != null)
@@ -177,8 +236,11 @@ public class RepoElem extends DistParentElem {
                return desc;
        }
 
-       /** Might return null in case of an anonymous user */
-       public Node getRepoNode() {
-               return repoNode;
+       public String getLabel() {
+               return label;
+       }
+
+       public String toString() {
+               return repoNode != null ? repoNode.toString() : label;
        }
 }
\ No newline at end of file