1 package org
.argeo
.cms
.internal
.auth
;
3 import java
.security
.PrivilegedExceptionAction
;
4 import java
.util
.Collection
;
5 import java
.util
.HashMap
;
6 import java
.util
.HashSet
;
7 import java
.util
.Hashtable
;
8 import java
.util
.LinkedHashSet
;
11 import java
.util
.UUID
;
13 import javax
.jcr
.Repository
;
14 import javax
.jcr
.Session
;
15 import javax
.naming
.InvalidNameException
;
16 import javax
.naming
.ldap
.LdapName
;
17 import javax
.security
.auth
.Subject
;
19 import org
.apache
.commons
.logging
.Log
;
20 import org
.apache
.commons
.logging
.LogFactory
;
21 import org
.argeo
.cms
.CmsException
;
22 import org
.argeo
.cms
.auth
.CmsSession
;
23 import org
.argeo
.jcr
.JcrUtils
;
24 import org
.osgi
.framework
.BundleContext
;
25 import org
.osgi
.framework
.FrameworkUtil
;
26 import org
.osgi
.framework
.InvalidSyntaxException
;
27 import org
.osgi
.framework
.ServiceReference
;
28 import org
.osgi
.framework
.ServiceRegistration
;
29 import org
.osgi
.service
.useradmin
.Authorization
;
31 public class CmsSessionImpl
implements CmsSession
{
32 private final static BundleContext bc
= FrameworkUtil
.getBundle(CmsSessionImpl
.class).getBundleContext();
33 private final static Log log
= LogFactory
.getLog(CmsSessionImpl
.class);
35 private final Subject initialSubject
;
36 private final UUID uuid
;
37 private final String localSessionId
;
38 private final Authorization authorization
;
39 private final LdapName userDn
;
41 private ServiceRegistration
<CmsSession
> serviceRegistration
;
43 private Map
<String
, Session
> dataSessions
= new HashMap
<>();
44 private Set
<String
> dataSessionsInUse
= new HashSet
<>();
45 private LinkedHashSet
<Session
> additionalDataSessions
= new LinkedHashSet
<>();
47 public CmsSessionImpl(Subject initialSubject
, Authorization authorization
, String localSessionId
) {
48 this.initialSubject
= initialSubject
;
49 this.localSessionId
= localSessionId
;
50 this.authorization
= authorization
;
52 this.userDn
= new LdapName(authorization
.getName());
53 } catch (InvalidNameException e
) {
54 throw new CmsException("Invalid user name " + authorization
.getName(), e
);
56 this.uuid
= UUID
.randomUUID();
57 // register as service
58 Hashtable
<String
, String
> props
= new Hashtable
<>();
59 props
.put(CmsSession
.USER_DN
, authorization
.getName());
60 props
.put(CmsSession
.SESSION_UUID
, uuid
.toString());
61 props
.put(CmsSession
.SESSION_LOCAL_ID
, localSessionId
);
62 serviceRegistration
= bc
.registerService(CmsSession
.class, this, props
);
65 public synchronized void cleanUp() {
66 serviceRegistration
.unregister();
68 // TODO check data session in use ?
69 for (String path
: dataSessions
.keySet())
70 JcrUtils
.logoutQuietly(dataSessions
.get(path
));
71 for (Session session
: additionalDataSessions
)
72 JcrUtils
.logoutQuietly(session
);
77 public synchronized Session
getDataSession(String cn
, String workspace
, Repository repository
) {
78 String path
= cn
+ '/' + workspace
;
79 if (dataSessionsInUse
.contains(path
)) {
82 if (dataSessionsInUse
.contains(path
)) {
83 Session session
= login(repository
, workspace
);
84 additionalDataSessions
.add(session
);
85 if (log
.isTraceEnabled())
86 log
.trace("Additional data session " + path
+ " for " + userDn
);
89 } catch (InterruptedException e
) {
94 Session session
= null;
95 if (dataSessions
.containsKey(path
)) {
96 session
= dataSessions
.get(path
);
98 session
= login(repository
, workspace
);
99 dataSessions
.put(path
, session
);
100 if (log
.isTraceEnabled())
101 log
.trace("New data session " + path
+ " for " + userDn
);
103 dataSessionsInUse
.add(path
);
107 private Session
login(Repository repository
, String workspace
) {
109 return Subject
.doAs(initialSubject
, new PrivilegedExceptionAction
<Session
>() {
111 public Session
run() throws Exception
{
112 return repository
.login(workspace
);
115 } catch (Exception e
) {
116 throw new CmsException("Cannot log in " + userDn
+ " to JCR", e
);
121 public synchronized void releaseDataSession(String cn
, Session session
) {
122 if (additionalDataSessions
.contains(session
)) {
123 JcrUtils
.logoutQuietly(session
);
124 additionalDataSessions
.remove(session
);
127 String path
= cn
+ '/' + session
.getWorkspace().getName();
128 if (!dataSessionsInUse
.contains(path
))
129 log
.warn("Data session " + path
+ " was not in use for " + userDn
);
130 dataSessionsInUse
.remove(path
);
131 Session registeredSession
= dataSessions
.get(path
);
132 if (session
!= registeredSession
)
133 log
.warn("Data session " + path
+ " not consistent for " + userDn
);
138 public Authorization
getAuthorization() {
139 return authorization
;
143 public UUID
getUuid() {
147 public Subject
getInitialSubject() {
148 return initialSubject
;
151 public String
getLocalSessionId() {
152 return localSessionId
;
155 public ServiceRegistration
<CmsSession
> getServiceRegistration() {
156 return serviceRegistration
;
160 public LdapName
getUserDn() {
165 public String
getLocalId() {
166 return localSessionId
;
169 public String
toString() {
170 return "CMS Session #" + localSessionId
;
173 public static CmsSession
getByLocalId(String localId
) {
174 Collection
<ServiceReference
<CmsSession
>> sr
;
176 sr
= bc
.getServiceReferences(CmsSession
.class, "(" + CmsSession
.SESSION_LOCAL_ID
+ "=" + localId
+ ")");
177 } catch (InvalidSyntaxException e
) {
178 throw new CmsException("Cannot get CMS session for id " + localId
, e
);
180 ServiceReference
<CmsSession
> cmsSessionRef
;
181 if (sr
.size() == 1) {
182 cmsSessionRef
= sr
.iterator().next();
183 return bc
.getService(cmsSessionRef
);
184 } else if (sr
.size() == 0) {
187 throw new CmsException(sr
.size() + " CMS sessions registered for " + localId
);
191 public static CmsSession
getByUuid(String uuid
) {
192 Collection
<ServiceReference
<CmsSession
>> sr
;
194 sr
= bc
.getServiceReferences(CmsSession
.class, "(" + CmsSession
.SESSION_UUID
+ "=" + uuid
+ ")");
195 } catch (InvalidSyntaxException e
) {
196 throw new CmsException("Cannot get CMS session for uuid " + uuid
, e
);
198 ServiceReference
<CmsSession
> cmsSessionRef
;
199 if (sr
.size() == 1) {
200 cmsSessionRef
= sr
.iterator().next();
201 return bc
.getService(cmsSessionRef
);
202 } else if (sr
.size() == 0) {
205 throw new CmsException(sr
.size() + " CMS sessions registered for " + uuid
);