X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fauth%2FCmsSessionImpl.java;h=a3670c0cb4b8cbf4313a7a8eea3aa82a26b77b57;hb=eb4cc3db3bf141c229f0f7ff929daff108bee6d2;hp=f40c6fffd561d6315239c96109863fa2d9c35495;hpb=043d226a5504a212eb5673c3ed4441c1167724d7;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java index f40c6fffd..a3670c0cb 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java @@ -4,21 +4,20 @@ import java.io.Serializable; 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.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Hashtable; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.function.Consumer; import javax.crypto.SecretKey; -import javax.jcr.Repository; -import javax.jcr.Session; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import javax.security.auth.Subject; @@ -26,12 +25,11 @@ 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.api.NodeConstants; -import org.argeo.api.security.NodeSecurityUtils; -import org.argeo.cms.auth.CmsSession; -import org.argeo.jcr.JcrUtils; +import org.argeo.api.cms.CmsAuth; +import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.CmsSession; +import org.argeo.cms.internal.runtime.CmsContextImpl; +import org.argeo.cms.security.NodeSecurityUtils; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; @@ -42,8 +40,8 @@ import org.osgi.service.useradmin.Authorization; /** Default CMS session implementation. */ public class CmsSessionImpl implements CmsSession, Serializable { private static final long serialVersionUID = 1867719354246307225L; - private final static BundleContext bc = FrameworkUtil.getBundle(CmsSessionImpl.class).getBundleContext(); - private final static Log log = LogFactory.getLog(CmsSessionImpl.class); +// private final static BundleContext bc = FrameworkUtil.getBundle(CmsSessionImpl.class).getBundleContext(); + private final static CmsLog log = CmsLog.getLog(CmsSessionImpl.class); // private final Subject initialSubject; private transient AccessControlContext accessControlContext; @@ -59,12 +57,10 @@ public class CmsSessionImpl implements CmsSession, Serializable { private ServiceRegistration serviceRegistration; - private Map dataSessions = new HashMap<>(); - private Set dataSessionsInUse = new HashSet<>(); - private Set additionalDataSessions = new HashSet<>(); - private Map views = new HashMap<>(); + private List> onCloseCallbacks = Collections.synchronizedList(new ArrayList<>()); + public CmsSessionImpl(Subject initialSubject, Authorization authorization, Locale locale, String localSessionId) { this.creationTime = ZonedDateTime.now(); this.locale = locale; @@ -90,33 +86,31 @@ public class CmsSessionImpl implements CmsSession, Serializable { this.userDn = NodeSecurityUtils.ROLE_ANONYMOUS_NAME; this.anonymous = true; } + // TODO use time-based UUID? this.uuid = UUID.randomUUID(); // register as service - Hashtable props = new Hashtable<>(); - props.put(CmsSession.USER_DN, userDn.toString()); - props.put(CmsSession.SESSION_UUID, uuid.toString()); - props.put(CmsSession.SESSION_LOCAL_ID, localSessionId); - serviceRegistration = bc.registerService(CmsSession.class, this, props); +// Hashtable props = new Hashtable<>(); +// props.put(CmsSession.USER_DN, userDn.toString()); +// props.put(CmsSession.SESSION_UUID, uuid.toString()); +// props.put(CmsSession.SESSION_LOCAL_ID, localSessionId); +// serviceRegistration = bc.registerService(CmsSession.class, this, props); } public void close() { end = ZonedDateTime.now(); - serviceRegistration.unregister(); - - synchronized (this) { - // TODO check data session in use ? - for (String path : dataSessions.keySet()) - JcrUtils.logoutQuietly(dataSessions.get(path)); - for (Session session : additionalDataSessions) - JcrUtils.logoutQuietly(session); + CmsContextImpl.getCmsContext().unregisterCmsSession(this); +// serviceRegistration.unregister(); + + for (Consumer onClose : onCloseCallbacks) { + onClose.accept(this); } try { LoginContext lc; if (isAnonymous()) { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS, getSubject()); + lc = new LoginContext(CmsAuth.LOGIN_CONTEXT_ANONYMOUS, getSubject()); } else { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, getSubject()); + lc = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, getSubject()); } lc.logout(); } catch (LoginException e) { @@ -127,7 +121,12 @@ public class CmsSessionImpl implements CmsSession, Serializable { log.debug("Closed " + this); } - private Subject getSubject() { + @Override + public void addOnCloseCallback(Consumer onClose) { + onCloseCallbacks.add(onClose); + } + + public Subject getSubject() { return Subject.getSubject(accessControlContext); } @@ -136,78 +135,6 @@ public class CmsSessionImpl implements CmsSession, Serializable { 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 = NodeConstants.SYS_WORKSPACE; - String path = cn + '/' + workspace; - if (dataSessionsInUse.contains(path)) { - try { - wait(1000); - if (dataSessionsInUse.contains(path)) { - Session session = login(repository, workspace); - additionalDataSessions.add(session); - if (log.isTraceEnabled()) - log.trace("Additional data session " + path + " for " + userDn); - return session; - } - } catch (InterruptedException e) { - // silent - } - } - - Session session = null; - if (dataSessions.containsKey(path)) { - session = dataSessions.get(path); - } else { - session = login(repository, workspace); - dataSessions.put(path, session); - if (log.isTraceEnabled()) - log.trace("New data session " + path + " for " + userDn); - } - dataSessionsInUse.add(path); - return session; - } - - private Session login(Repository repository, String workspace) { - try { - return Subject.doAs(getSubject(), new PrivilegedExceptionAction() { - @Override - public Session run() throws Exception { - return repository.login(workspace); - } - }); - } catch (PrivilegedActionException e) { - throw new IllegalStateException("Cannot log in " + userDn + " to JCR", e); - } - } - - public synchronized void releaseDataSession(String cn, Session session) { - if (additionalDataSessions.contains(session)) { - JcrUtils.logoutQuietly(session); - additionalDataSessions.remove(session); - if (log.isTraceEnabled()) - log.trace("Remove additional data session " + session); - return; - } - String path = cn + '/' + session.getWorkspace().getName(); - if (!dataSessionsInUse.contains(path)) - log.warn("Data session " + path + " was not in use for " + userDn); - dataSessionsInUse.remove(path); - Session registeredSession = dataSessions.get(path); - if (session != registeredSession) - log.warn("Data session " + path + " not consistent for " + userDn); - if (log.isTraceEnabled()) - log.trace("Released data session " + session + " for " + path); - notifyAll(); - } - @Override public boolean isValid() { return !isClosed(); @@ -222,12 +149,16 @@ public class CmsSessionImpl implements CmsSession, Serializable { return getEnd() != null; } - @Override public Authorization getAuthorization() { checkValid(); return authorization; } + @Override + public String getDisplayName() { + return authorization.toString(); + } + @Override public UUID getUuid() { return uuid; @@ -277,59 +208,59 @@ public class CmsSessionImpl implements CmsSession, Serializable { } public String toString() { - return "CMS Session " + userDn + " local=" + localSessionId + ", uuid=" + uuid; + return "CMS Session " + userDn + " localId=" + localSessionId + ", uuid=" + uuid; } - public static CmsSessionImpl getByLocalId(String localId) { - Collection> sr; - try { - sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_LOCAL_ID + "=" + localId + ")"); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS session for id " + localId, e); - } - ServiceReference cmsSessionRef; - if (sr.size() == 1) { - cmsSessionRef = sr.iterator().next(); - return (CmsSessionImpl) bc.getService(cmsSessionRef); - } else if (sr.size() == 0) { - return null; - } else - throw new IllegalStateException(sr.size() + " CMS sessions registered for " + localId); - - } - - public static CmsSessionImpl getByUuid(Object uuid) { - Collection> sr; - try { - sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")"); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e); - } - ServiceReference cmsSessionRef; - if (sr.size() == 1) { - cmsSessionRef = sr.iterator().next(); - return (CmsSessionImpl) bc.getService(cmsSessionRef); - } else if (sr.size() == 0) { - return null; - } else - throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid); - - } - - public static void closeInvalidSessions() { - Collection> srs; - try { - srs = bc.getServiceReferences(CmsSession.class, null); - for (ServiceReference sr : srs) { - CmsSession cmsSession = bc.getService(sr); - if (!cmsSession.isValid()) { - ((CmsSessionImpl) cmsSession).close(); - if (log.isDebugEnabled()) - log.debug("Closed expired CMS session " + cmsSession); - } - } - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException("Cannot get CMS sessions", e); - } - } +// public static CmsSessionImpl getByLocalId(String localId) { +// Collection> sr; +// try { +// sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_LOCAL_ID + "=" + localId + ")"); +// } catch (InvalidSyntaxException e) { +// throw new IllegalArgumentException("Cannot get CMS session for id " + localId, e); +// } +// ServiceReference cmsSessionRef; +// if (sr.size() == 1) { +// cmsSessionRef = sr.iterator().next(); +// return (CmsSessionImpl) bc.getService(cmsSessionRef); +// } else if (sr.size() == 0) { +// return null; +// } else +// throw new IllegalStateException(sr.size() + " CMS sessions registered for " + localId); +// +// } +// +// public static CmsSessionImpl getByUuid(Object uuid) { +// Collection> sr; +// try { +// sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_UUID + "=" + uuid + ")"); +// } catch (InvalidSyntaxException e) { +// throw new IllegalArgumentException("Cannot get CMS session for uuid " + uuid, e); +// } +// ServiceReference cmsSessionRef; +// if (sr.size() == 1) { +// cmsSessionRef = sr.iterator().next(); +// return (CmsSessionImpl) bc.getService(cmsSessionRef); +// } else if (sr.size() == 0) { +// return null; +// } else +// throw new IllegalStateException(sr.size() + " CMS sessions registered for " + uuid); +// +// } +// +// public static void closeInvalidSessions() { +// Collection> srs; +// try { +// srs = bc.getServiceReferences(CmsSession.class, null); +// for (ServiceReference sr : srs) { +// CmsSession cmsSession = bc.getService(sr); +// if (!cmsSession.isValid()) { +// ((CmsSessionImpl) cmsSession).close(); +// if (log.isDebugEnabled()) +// log.debug("Closed expired CMS session " + cmsSession); +// } +// } +// } catch (InvalidSyntaxException e) { +// throw new IllegalArgumentException("Cannot get CMS sessions", e); +// } +// } }