X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.server.jcr.mvc%2Fsrc%2Forg%2Fargeo%2Fjackrabbit%2Fremote%2FScopedSessionProvider.java;fp=org.argeo.server.jcr.mvc%2Fsrc%2Forg%2Fargeo%2Fjackrabbit%2Fremote%2FScopedSessionProvider.java;h=931f697865afaa654932c153117c3e0ed7de9e60;hb=c95ab41f84b0cf5394e1041b6ff52fd6019aa2e6;hp=0000000000000000000000000000000000000000;hpb=f3c695378b1f845acddb70ffb4ae905dc0d429f9;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.server.jcr.mvc/src/org/argeo/jackrabbit/remote/ScopedSessionProvider.java b/org.argeo.server.jcr.mvc/src/org/argeo/jackrabbit/remote/ScopedSessionProvider.java new file mode 100644 index 000000000..931f69786 --- /dev/null +++ b/org.argeo.server.jcr.mvc/src/org/argeo/jackrabbit/remote/ScopedSessionProvider.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.jackrabbit.remote; + +import java.io.Serializable; + +import javax.jcr.LoginException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.server.SessionProvider; +import org.argeo.ArgeoException; +import org.argeo.jcr.ArgeoJcrConstants; +import org.argeo.jcr.JcrUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * Session provider assuming a single workspace and a short life cycle, + * typically a Spring bean of scope (web) 'session'. + */ +public class ScopedSessionProvider implements SessionProvider, Serializable { + private static final long serialVersionUID = 6589775984177317058L; + private static final Log log = LogFactory + .getLog(ScopedSessionProvider.class); + private transient HttpSession httpSession = null; + private transient Session jcrSession = null; + + private transient String currentRepositoryName = null; + private transient String currentWorkspaceName = null; + private transient String currentJcrUser = null; + + // private transient String anonymousUserId = "anonymous"; + + public Session getSession(HttpServletRequest request, Repository rep, + String workspace) throws LoginException, ServletException, + RepositoryException { + + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + if (authentication == null) + throw new ArgeoException( + "Request not authenticated by Spring Security"); + String springUser = authentication.getName(); + + // HTTP + String requestJcrRepository = (String) request + .getAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS); + + // HTTP session + if (httpSession != null + && !httpSession.getId().equals(request.getSession().getId())) + throw new ArgeoException( + "Only session scope is supported in this mode"); + if (httpSession == null) + httpSession = request.getSession(); + + // Initializes current values + if (currentRepositoryName == null) + currentRepositoryName = requestJcrRepository; + if (currentWorkspaceName == null) + currentWorkspaceName = workspace; + if (currentJcrUser == null) + currentJcrUser = springUser; + + // logout if there was a change in session coordinates + if (jcrSession != null) + if (!currentRepositoryName.equals(requestJcrRepository)) { + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " Changed from repository '" + + currentRepositoryName + "' to '" + + requestJcrRepository + + "', logging out cached JCR session."); + logout(); + } else if (!currentWorkspaceName.equals(workspace)) { + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " Changed from workspace '" + + currentWorkspaceName + "' to '" + workspace + + "', logging out cached JCR session."); + logout(); + } else if (!currentJcrUser.equals(springUser)) { + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " Changed from user '" + + currentJcrUser + "' to '" + springUser + + "', logging out cached JCR session."); + logout(); + } + + // login if needed + if (jcrSession == null) + try { + Session session = login(rep, workspace); + if (!session.getUserID().equals(springUser)) { + JcrUtils.logoutQuietly(session); + throw new ArgeoException("Spring Security user '" + + springUser + "' not in line with JCR user '" + + session.getUserID() + "'"); + } + currentRepositoryName = requestJcrRepository; + // do not use workspace variable which may be null + currentWorkspaceName = session.getWorkspace().getName(); + currentJcrUser = session.getUserID(); + + jcrSession = session; + return jcrSession; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot open session to workspace " + + workspace, e); + } + + // returns cached session + return jcrSession; + } + + protected Session login(Repository repository, String workspace) + throws RepositoryException { + Session session = repository.login(workspace); + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + " User '" + session.getUserID() + + "' logged in workspace '" + + session.getWorkspace().getName() + "' of repository '" + + currentRepositoryName + "'"); + return session; + } + + public void releaseSession(Session session) { + if (log.isTraceEnabled()) + log.trace(getHttpSessionId() + " Releasing JCR session " + session); + } + + protected void logout() { + JcrUtils.logoutQuietly(jcrSession); + jcrSession = null; + } + + protected final String getHttpSessionId() { + return httpSession != null ? httpSession.getId() : ""; + } + + public void init() { + } + + public void destroy() { + logout(); + if (getHttpSessionId() != null) + if (log.isDebugEnabled()) + log.debug(getHttpSessionId() + + " Cleaned up provider for web session "); + httpSession = null; + } + +}