+/*
+ * Copyright (C) 2007-2012 Mathieu Baudier
+ *
+ * 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 java.util.List;
+
+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.JcrUtils;
+
+/**
+ * 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 final static 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;
+
+ public Session getSession(HttpServletRequest request, Repository rep,
+ String workspace) throws LoginException, ServletException,
+ RepositoryException {
+
+ // 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();
+
+ if (currentWorkspaceName == null)
+ currentWorkspaceName = workspace;
+
+ // TODO optimize
+ String pathInfo = request.getPathInfo();
+ List<String> tokens = JcrUtils.tokenize(pathInfo);
+ if (currentRepositoryName == null)
+ currentRepositoryName = tokens.get(0);
+ else if (!currentRepositoryName.equals(tokens.get(0))
+ || !currentWorkspaceName.equals(workspace)) {
+ JcrUtils.logoutQuietly(jcrSession);
+ jcrSession = null;
+ if (log.isDebugEnabled())
+ log.debug(getHttpSessionId()
+ + " Changed repository or workspace, logging out of "
+ + currentWorkspaceName);
+ }
+
+ // JCR session
+ if (jcrSession == null)
+ try {
+ jcrSession = login(rep, workspace);
+ currentRepositoryName = tokens.get(0);
+ // do not use workspace variable which may be null
+ currentWorkspaceName = jcrSession.getWorkspace().getName();
+ return jcrSession;
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot open session to workspace "
+ + workspace, e);
+ }
+ else
+ 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 final String getHttpSessionId() {
+ return httpSession != null ? httpSession.getId() : "<null>";
+ }
+
+ public void init() {
+ }
+
+ public void destroy() {
+ JcrUtils.logoutQuietly(jcrSession);
+ jcrSession = null;
+ if (log.isDebugEnabled())
+ log.debug(getHttpSessionId()
+ + " Cleaned up provider for web session ");
+ httpSession = null;
+ }
+}
\ No newline at end of file