2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.jackrabbit
.remote
;
18 import java
.io
.Serializable
;
20 import javax
.jcr
.LoginException
;
21 import javax
.jcr
.Repository
;
22 import javax
.jcr
.RepositoryException
;
23 import javax
.jcr
.Session
;
24 import javax
.servlet
.ServletException
;
25 import javax
.servlet
.http
.HttpServletRequest
;
26 import javax
.servlet
.http
.HttpSession
;
28 import org
.apache
.commons
.logging
.Log
;
29 import org
.apache
.commons
.logging
.LogFactory
;
30 import org
.apache
.jackrabbit
.server
.SessionProvider
;
31 import org
.argeo
.ArgeoException
;
32 import org
.argeo
.jcr
.ArgeoJcrConstants
;
33 import org
.argeo
.jcr
.JcrUtils
;
34 import org
.springframework
.security
.Authentication
;
35 import org
.springframework
.security
.context
.SecurityContextHolder
;
38 * Session provider assuming a single workspace and a short life cycle,
39 * typically a Spring bean of scope (web) 'session'.
41 public class ScopedSessionProvider
implements SessionProvider
, Serializable
{
42 private static final long serialVersionUID
= 6589775984177317058L;
43 private static final Log log
= LogFactory
44 .getLog(ScopedSessionProvider
.class);
45 private transient HttpSession httpSession
= null;
46 private transient Session jcrSession
= null;
48 private transient String currentRepositoryName
= null;
49 private transient String currentWorkspaceName
= null;
50 private transient String currentJcrUser
= null;
52 // private transient String anonymousUserId = "anonymous";
54 public Session
getSession(HttpServletRequest request
, Repository rep
,
55 String workspace
) throws LoginException
, ServletException
,
58 Authentication authentication
= SecurityContextHolder
.getContext()
60 if (authentication
== null)
61 throw new ArgeoException(
62 "Request not authenticated by Spring Security");
63 String springUser
= authentication
.getName();
66 String requestJcrRepository
= (String
) request
67 .getAttribute(ArgeoJcrConstants
.JCR_REPOSITORY_ALIAS
);
70 if (httpSession
!= null
71 && !httpSession
.getId().equals(request
.getSession().getId()))
72 throw new ArgeoException(
73 "Only session scope is supported in this mode");
74 if (httpSession
== null)
75 httpSession
= request
.getSession();
77 // Initializes current values
78 if (currentRepositoryName
== null)
79 currentRepositoryName
= requestJcrRepository
;
80 if (currentWorkspaceName
== null)
81 currentWorkspaceName
= workspace
;
82 if (currentJcrUser
== null)
83 currentJcrUser
= springUser
;
85 // logout if there was a change in session coordinates
86 if (jcrSession
!= null)
87 if (!currentRepositoryName
.equals(requestJcrRepository
)) {
88 if (log
.isDebugEnabled())
89 log
.debug(getHttpSessionId() + " Changed from repository '"
90 + currentRepositoryName
+ "' to '"
91 + requestJcrRepository
92 + "', logging out cached JCR session.");
94 } else if (!currentWorkspaceName
.equals(workspace
)) {
95 if (log
.isDebugEnabled())
96 log
.debug(getHttpSessionId() + " Changed from workspace '"
97 + currentWorkspaceName
+ "' to '" + workspace
98 + "', logging out cached JCR session.");
100 } else if (!currentJcrUser
.equals(springUser
)) {
101 if (log
.isDebugEnabled())
102 log
.debug(getHttpSessionId() + " Changed from user '"
103 + currentJcrUser
+ "' to '" + springUser
104 + "', logging out cached JCR session.");
109 if (jcrSession
== null)
111 Session session
= login(rep
, workspace
);
112 if (!session
.getUserID().equals(springUser
)) {
113 JcrUtils
.logoutQuietly(session
);
114 throw new ArgeoException("Spring Security user '"
115 + springUser
+ "' not in line with JCR user '"
116 + session
.getUserID() + "'");
118 currentRepositoryName
= requestJcrRepository
;
119 // do not use workspace variable which may be null
120 currentWorkspaceName
= session
.getWorkspace().getName();
121 currentJcrUser
= session
.getUserID();
123 jcrSession
= session
;
125 } catch (RepositoryException e
) {
126 throw new ArgeoException("Cannot open session to workspace "
130 // returns cached session
134 protected Session
login(Repository repository
, String workspace
)
135 throws RepositoryException
{
136 Session session
= repository
.login(workspace
);
137 if (log
.isDebugEnabled())
138 log
.debug(getHttpSessionId() + " User '" + session
.getUserID()
139 + "' logged in workspace '"
140 + session
.getWorkspace().getName() + "' of repository '"
141 + currentRepositoryName
+ "'");
145 public void releaseSession(Session session
) {
146 if (log
.isTraceEnabled())
147 log
.trace(getHttpSessionId() + " Releasing JCR session " + session
);
150 protected void logout() {
151 JcrUtils
.logoutQuietly(jcrSession
);
155 protected final String
getHttpSessionId() {
156 return httpSession
!= null ? httpSession
.getId() : "<null>";
162 public void destroy() {
164 if (getHttpSessionId() != null)
165 if (log
.isDebugEnabled())
166 log
.debug(getHttpSessionId()
167 + " Cleaned up provider for web session ");