1 package org
.argeo
.cms
.jcr
.internal
.servlet
;
3 import java
.io
.Serializable
;
4 import java
.security
.PrivilegedActionException
;
5 import java
.security
.PrivilegedExceptionAction
;
6 import java
.util
.HashMap
;
7 import java
.util
.HashSet
;
8 import java
.util
.LinkedHashMap
;
12 import javax
.jcr
.Repository
;
13 import javax
.jcr
.RepositoryException
;
14 import javax
.jcr
.Session
;
15 import javax
.security
.auth
.Subject
;
16 import javax
.servlet
.ServletException
;
17 import javax
.servlet
.http
.HttpServletRequest
;
19 import org
.apache
.jackrabbit
.server
.SessionProvider
;
20 import org
.argeo
.api
.cms
.CmsSession
;
21 import org
.argeo
.api
.cms
.CmsLog
;
22 import org
.argeo
.api
.cms
.CmsConstants
;
23 import org
.argeo
.jcr
.JcrUtils
;
26 * Implements an open session in view patter: a new JCR session is created for
29 public class CmsSessionProvider
implements SessionProvider
, Serializable
{
30 private static final long serialVersionUID
= -1358136599534938466L;
32 private final static CmsLog log
= CmsLog
.getLog(CmsSessionProvider
.class);
34 private final String alias
;
36 private LinkedHashMap
<Session
, CmsDataSession
> cmsSessions
= new LinkedHashMap
<>();
38 public CmsSessionProvider(String alias
) {
42 public Session
getSession(HttpServletRequest request
, Repository rep
, String workspace
)
43 throws javax
.jcr
.LoginException
, ServletException
, RepositoryException
{
45 // a client is scanning parent URLs.
46 // if (workspace == null)
49 // CmsSessionImpl cmsSession = WebCmsSessionImpl.getCmsSession(request);
50 // FIXME retrieve CMS session
51 CmsSession cmsSession
= null;
52 if (log
.isTraceEnabled()) {
53 log
.trace("Get JCR session from " + cmsSession
);
55 if (cmsSession
== null)
56 throw new IllegalStateException("Cannot find a session for request " + request
.getRequestURI());
57 CmsDataSession cmsDataSession
= new CmsDataSession(cmsSession
);
58 Session session
= cmsDataSession
.getDataSession(alias
, workspace
, rep
);
59 cmsSessions
.put(session
, cmsDataSession
);
63 public void releaseSession(Session session
) {
64 // JcrUtils.logoutQuietly(session);
65 if (cmsSessions
.containsKey(session
)) {
66 CmsDataSession cmsDataSession
= cmsSessions
.get(session
);
67 cmsDataSession
.releaseDataSession(alias
, session
);
69 log
.warn("JCR session " + session
+ " not found in CMS session list. Logging it out...");
70 JcrUtils
.logoutQuietly(session
);
74 static class CmsDataSession
{
75 private CmsSession cmsSession
;
77 private Map
<String
, Session
> dataSessions
= new HashMap
<>();
78 private Set
<String
> dataSessionsInUse
= new HashSet
<>();
79 private Set
<Session
> additionalDataSessions
= new HashSet
<>();
81 private CmsDataSession(CmsSession cmsSession
) {
82 this.cmsSession
= cmsSession
;
85 public Session
newDataSession(String cn
, String workspace
, Repository repository
) {
87 return login(repository
, workspace
);
90 public synchronized Session
getDataSession(String cn
, String workspace
, Repository repository
) {
92 // FIXME make it more robust
93 if (workspace
== null)
94 workspace
= CmsConstants
.SYS_WORKSPACE
;
95 String path
= cn
+ '/' + workspace
;
96 if (dataSessionsInUse
.contains(path
)) {
99 if (dataSessionsInUse
.contains(path
)) {
100 Session session
= login(repository
, workspace
);
101 additionalDataSessions
.add(session
);
102 if (log
.isTraceEnabled())
103 log
.trace("Additional data session " + path
+ " for " + cmsSession
.getUserDn());
106 } catch (InterruptedException e
) {
111 Session session
= null;
112 if (dataSessions
.containsKey(path
)) {
113 session
= dataSessions
.get(path
);
115 session
= login(repository
, workspace
);
116 dataSessions
.put(path
, session
);
117 if (log
.isTraceEnabled())
118 log
.trace("New data session " + path
+ " for " + cmsSession
.getUserDn());
120 dataSessionsInUse
.add(path
);
124 private Session
login(Repository repository
, String workspace
) {
126 return Subject
.doAs(cmsSession
.getSubject(), new PrivilegedExceptionAction
<Session
>() {
128 public Session
run() throws Exception
{
129 return repository
.login(workspace
);
132 } catch (PrivilegedActionException e
) {
133 throw new IllegalStateException("Cannot log in " + cmsSession
.getUserDn() + " to JCR", e
);
137 public synchronized void releaseDataSession(String cn
, Session session
) {
138 if (additionalDataSessions
.contains(session
)) {
139 JcrUtils
.logoutQuietly(session
);
140 additionalDataSessions
.remove(session
);
141 if (log
.isTraceEnabled())
142 log
.trace("Remove additional data session " + session
);
145 String path
= cn
+ '/' + session
.getWorkspace().getName();
146 if (!dataSessionsInUse
.contains(path
))
147 log
.warn("Data session " + path
+ " was not in use for " + cmsSession
.getUserDn());
148 dataSessionsInUse
.remove(path
);
149 Session registeredSession
= dataSessions
.get(path
);
150 if (session
!= registeredSession
)
151 log
.warn("Data session " + path
+ " not consistent for " + cmsSession
.getUserDn());
152 if (log
.isTraceEnabled())
153 log
.trace("Released data session " + session
+ " for " + path
);
157 private void checkValid() {
158 if (!cmsSession
.isValid())
159 throw new IllegalStateException(
160 "CMS session " + cmsSession
.getUuid() + " is not valid since " + cmsSession
.getEnd());
163 private void close() {
164 // FIXME class this when CMS session is closed
165 synchronized (this) {
166 // TODO check data session in use ?
167 for (String path
: dataSessions
.keySet())
168 JcrUtils
.logoutQuietly(dataSessions
.get(path
));
169 for (Session session
: additionalDataSessions
)
170 JcrUtils
.logoutQuietly(session
);