Make CMS sesison management more robust.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / auth / CmsSessionImpl.java
index ce38cf0ee94514ed445661707bb9d27e180e6563..c18348385587e4ac956160779a3235f36b0626e9 100644 (file)
@@ -3,13 +3,13 @@ package org.argeo.cms.internal.auth;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.time.ZonedDateTime;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
-import java.util.LinkedHashSet;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
@@ -23,14 +23,14 @@ import javax.naming.ldap.LdapName;
 import javax.security.auth.Subject;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
+import javax.security.auth.x500.X500Principal;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.CmsException;
+import org.argeo.api.NodeConstants;
+import org.argeo.api.security.NodeSecurityUtils;
 import org.argeo.cms.auth.CmsSession;
 import org.argeo.jcr.JcrUtils;
-import org.argeo.node.NodeConstants;
-import org.argeo.node.security.NodeSecurityUtils;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
@@ -38,6 +38,7 @@ import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.useradmin.Authorization;
 
+/** Default CMS session implementation. */
 public class CmsSessionImpl implements CmsSession {
        private final static BundleContext bc = FrameworkUtil.getBundle(CmsSessionImpl.class).getBundleContext();
        private final static Log log = LogFactory.getLog(CmsSessionImpl.class);
@@ -58,7 +59,9 @@ public class CmsSessionImpl implements CmsSession {
 
        private Map<String, Session> dataSessions = new HashMap<>();
        private Set<String> dataSessionsInUse = new HashSet<>();
-       private LinkedHashSet<Session> additionalDataSessions = new LinkedHashSet<>();
+       private Set<Session> additionalDataSessions = new HashSet<>();
+
+       private Map<String, Object> views = new HashMap<>();
 
        public CmsSessionImpl(Subject initialSubject, Authorization authorization, Locale locale, String localSessionId) {
                this.creationTime = ZonedDateTime.now();
@@ -79,7 +82,7 @@ public class CmsSessionImpl implements CmsSession {
                                this.userDn = new LdapName(authorization.getName());
                                this.anonymous = false;
                        } catch (InvalidNameException e) {
-                               throw new CmsException("Invalid user name " + authorization.getName(), e);
+                               throw new IllegalArgumentException("Invalid user name " + authorization.getName(), e);
                        }
                else {
                        this.userDn = NodeSecurityUtils.ROLE_ANONYMOUS_NAME;
@@ -125,17 +128,20 @@ public class CmsSessionImpl implements CmsSession {
        }
 
        public Set<SecretKey> getSecretKeys() {
+               checkValid();
                return getSubject().getPrivateCredentials(SecretKey.class);
        }
 
        public Session newDataSession(String cn, String workspace, Repository repository) {
+               checkValid();
                return login(repository, workspace);
        }
 
        public synchronized Session getDataSession(String cn, String workspace, Repository repository) {
+               checkValid();
                // FIXME make it more robust
                if (workspace == null)
-                       workspace = "main";
+                       workspace = NodeConstants.SYS_WORKSPACE;
                String path = cn + '/' + workspace;
                if (dataSessionsInUse.contains(path)) {
                        try {
@@ -173,8 +179,8 @@ public class CmsSessionImpl implements CmsSession {
                                        return repository.login(workspace);
                                }
                        });
-               } catch (Exception e) {
-                       throw new CmsException("Cannot log in " + userDn + " to JCR", e);
+               } catch (PrivilegedActionException e) {
+                       throw new IllegalStateException("Cannot log in " + userDn + " to JCR", e);
                }
        }
 
@@ -203,12 +209,18 @@ public class CmsSessionImpl implements CmsSession {
                return !isClosed();
        }
 
-       protected boolean isClosed() {
+       private void checkValid() {
+               if (!isValid())
+                       throw new IllegalStateException("CMS session " + uuid + " is not valid since " + end);
+       }
+
+       final protected boolean isClosed() {
                return getEnd() != null;
        }
 
        @Override
        public Authorization getAuthorization() {
+               checkValid();
                return authorization;
        }
 
@@ -222,6 +234,11 @@ public class CmsSessionImpl implements CmsSession {
                return userDn;
        }
 
+       @Override
+       public String getUserRole() {
+               return new X500Principal(authorization.getName()).getName();
+       }
+
        @Override
        public String getLocalId() {
                return localSessionId;
@@ -247,6 +264,14 @@ public class CmsSessionImpl implements CmsSession {
                return end;
        }
 
+       @Override
+       public void registerView(String uid, Object view) {
+               checkValid();
+               if (views.containsKey(uid))
+                       throw new IllegalArgumentException("View " + uid + " is already registered.");
+               views.put(uid, view);
+       }
+
        public String toString() {
                return "CMS Session " + userDn + " local=" + localSessionId + ", uuid=" + uuid;
        }
@@ -256,7 +281,7 @@ public class CmsSessionImpl implements CmsSession {
                try {
                        sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_LOCAL_ID + "=" + localId + ")");
                } catch (InvalidSyntaxException e) {
-                       throw new CmsException("Cannot get CMS session for id " + localId, e);
+                       throw new IllegalArgumentException("Cannot get CMS session for id " + localId, e);
                }
                ServiceReference<CmsSession> cmsSessionRef;
                if (sr.size() == 1) {
@@ -265,7 +290,7 @@ public class CmsSessionImpl implements CmsSession {
                } else if (sr.size() == 0) {
                        return null;
                } else
-                       throw new CmsException(sr.size() + " CMS sessions registered for " + localId);
+                       throw new IllegalStateException(sr.size() + " CMS sessions registered for " + localId);
 
        }
 
@@ -274,7 +299,7 @@ public class CmsSessionImpl implements CmsSession {
                try {
                        sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")");
                } catch (InvalidSyntaxException e) {
-                       throw new CmsException("Cannot get CMS session for uuid " + uuid, e);
+                       throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e);
                }
                ServiceReference<CmsSession> cmsSessionRef;
                if (sr.size() == 1) {
@@ -283,7 +308,7 @@ public class CmsSessionImpl implements CmsSession {
                } else if (sr.size() == 0) {
                        return null;
                } else
-                       throw new CmsException(sr.size() + " CMS sessions registered for " + uuid);
+                       throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid);
 
        }
 
@@ -300,7 +325,7 @@ public class CmsSessionImpl implements CmsSession {
                                }
                        }
                } catch (InvalidSyntaxException e) {
-                       throw new CmsException("Cannot get CMS sessions", e);
+                       throw new IllegalArgumentException("Cannot get CMS sessions", e);
                }
        }
 }