</property>
</bean>
- <!-- <bean id="repositoryRegister" class="org.argeo.jcr.DefaultRepositoryRegister"
- /> -->
-
- <bean id="sessionProvider" init-method="init" destroy-method="destroy"
- class="org.argeo.jackrabbit.remote.SimpleSessionProvider" />
+ <!-- The JCR sessions, optimised per web session. -->
+ <bean id="scopedSessionProvider" init-method="init"
+ destroy-method="destroy" class="org.argeo.jackrabbit.remote.ScopedSessionProvider"
+ scope="session">
+ <aop:scoped-proxy proxy-target-class="false" />
+ </bean>
- <!-- <bean id="osivInterceptor" class="org.argeo.jcr.mvc.OpenSessionInViewJcrInterceptor"> -->
- <!-- <property name="session" ref="jcrSession" /> -->
- <!-- </bean> -->
+ <!-- The JCR sessions, one login per request. -->
+<!-- <bean id="openInViewSessionProvider" init-method="init" -->
+<!-- destroy-method="destroy" class="org.argeo.jackrabbit.remote.OpenInViewSessionProvider"> -->
+<!-- </bean> -->
<bean id="repositoryRegister" class="org.argeo.jcr.DefaultRepositoryRegister" />
<bean id="urlMapping"
class="org.argeo.jackrabbit.remote.JcrRemotingHandlerMapping">
<property name="repositoryRegister" ref="repositoryRegister" />
- <property name="sessionProvider" ref="sessionProvider" />
+ <property name="sessionProvider" ref="scopedSessionProvider" />
</bean>
</beans>
\ No newline at end of file
<display-name>Argeo Jackrabbit Webapp</display-name>
+ <!-- We don't want the session-scoped JCR sessions to wait too long before
+ being logged out. -->
+ <session-config>
+ <session-timeout>5</session-timeout>
+ </session-config>
+
<!-- General -->
<context-param>
<param-name>contextConfigLocation</param-name>
<url-pattern>/public/*</url-pattern>
</servlet-mapping>
- <!-- Security -->
+ <!-- Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<bean id="urlMapping" class="org.argeo.jackrabbit.remote.SimpleWebdavHandlerMapping">
<property name="configuration" value="/WEB-INF/webdav-config.xml" />
<property name="repositoryRegister" ref="repositoryRegister" />
- <property name="sessionProvider" ref="sessionProvider" />
+ <property name="sessionProvider" ref="scopedSessionProvider" />
</bean>
</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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 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 org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.server.SessionProvider;
+import org.argeo.jcr.JcrUtils;
+
+/**
+ * Implements an open session in view patter: a new JCR session is created for
+ * each request
+ */
+public class OpenInViewSessionProvider implements SessionProvider, Serializable {
+ private static final long serialVersionUID = 2270957712453841368L;
+
+ private final static Log log = LogFactory
+ .getLog(OpenInViewSessionProvider.class);
+
+ public Session getSession(HttpServletRequest request, Repository rep,
+ String workspace) throws LoginException, ServletException,
+ RepositoryException {
+ return login(request, rep, workspace);
+ }
+
+ protected Session login(HttpServletRequest request, Repository repository,
+ String workspace) throws RepositoryException {
+ if (log.isDebugEnabled())
+ log.debug("Login to workspace "
+ + (workspace == null ? "<default>" : workspace)
+ + " in web session " + request.getSession().getId());
+ return repository.login(workspace);
+ }
+
+ public void releaseSession(Session session) {
+ JcrUtils.logoutQuietly(session);
+ if (log.isDebugEnabled())
+ log.debug("Logged out remote JCR session " + session);
+ }
+
+ public void init() {
+ }
+
+ public void destroy() {
+ }
+
+}
--- /dev/null
+/*
+ * 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
/**
* Implements an open session in view patter: a new JCR session is created for
* each request
+ *
+ * @deprecated use {@link ScopedSessionProvider} or
+ * {@link OpenInViewSessionProvider}
*/
+@Deprecated
public class SimpleSessionProvider implements SessionProvider, Serializable {
private static final long serialVersionUID = 2270957712453841368L;
private String defaultWorkspace = "default";
+ private String webSessionId = null;
+
public Session getSession(HttpServletRequest request, Repository rep,
String workspace) throws LoginException, ServletException,
RepositoryException {
if (openSessionInView) {
- JackrabbitSession session = (JackrabbitSession) rep
- .login(workspace);
+ JackrabbitSession session = (JackrabbitSession) login(request, rep,
+ workspace);
if (session.getWorkspace().getName().equals(defaultWorkspace))
writeRemoteRoles(session);
return session;
} else {
+ if (webSessionId != null
+ && !webSessionId.equals(request.getSession().getId()))
+ throw new ArgeoException(
+ "Only session scope is supported in this mode");
+ webSessionId = request.getSession().getId();
+
// since sessions is transient it can't be restored from the session
if (sessions == null)
sessions = Collections
if (!sessions.containsKey(workspace)) {
try {
- JackrabbitSession session = (JackrabbitSession) rep.login(
- null, workspace);
+ // JackrabbitSession session = (JackrabbitSession)
+ // rep.login(
+ // null, workspace);
+ JackrabbitSession session = (JackrabbitSession) login(
+ request, rep, workspace);
if (session.getWorkspace().getName()
.equals(defaultWorkspace))
writeRemoteRoles(session);
Session session = sessions.get(workspace);
if (!session.isLive()) {
sessions.remove(workspace);
- session = rep.login(null, workspace);
+ session = login(request, rep, workspace);
sessions.put(workspace, session);
}
return session;
}
}
+ protected Session login(HttpServletRequest request, Repository repository,
+ String workspace) throws RepositoryException {
+ if (log.isDebugEnabled())
+ log.debug("Login to workspace "
+ + (workspace == null ? "<default>" : workspace)
+ + " in web session " + request.getSession().getId());
+ return repository.login(workspace);
+ }
+
protected void writeRemoteRoles(JackrabbitSession session)
throws RepositoryException {
// FIXME better deal w/ non node repo
if (log.isTraceEnabled())
log.trace("Releasing JCR session " + session);
if (openSessionInView) {
- if (session.isLive()) {
- session.logout();
- if (log.isTraceEnabled())
- log.trace("Logged out remote JCR session " + session);
- }
+ JcrUtils.logoutQuietly(session);
+ if (log.isDebugEnabled())
+ log.debug("Logged out remote JCR session " + session);
}
}
public void init() {
+ if (log.isDebugEnabled())
+ log.debug("Init session provider for web session " + webSessionId);
}
public void destroy() {
+ if (log.isDebugEnabled())
+ log.debug("Destroy session provider for web session "
+ + webSessionId);
+
if (sessions != null)
for (String workspace : sessions.keySet()) {
Session session = sessions.get(workspace);
- if (session.isLive()) {
- session.logout();
- if (log.isDebugEnabled())
- log.debug("Logged out remote JCR session " + session);
- }
+ JcrUtils.logoutQuietly(session);
}
}
acl.addAccessControlEntry(principal,
privs.toArray(new Privilege[privs.size()]));
acm.setPolicy(path, acl);
- if (log.isDebugEnabled()) {
- StringBuffer privBuf = new StringBuffer();
- for (Privilege priv : privs)
- privBuf.append(priv.getName());
- log.debug("Added privileges " + privBuf + " to " + principal
- + " on " + path);
- }
+// if (log.isTraceEnabled()) {
+// StringBuffer privBuf = new StringBuffer();
+// for (Privilege priv : privs)
+// privBuf.append(priv.getName());
+// log.trace("Added privileges " + privBuf + " to " + principal
+// + " on " + path);
+// }
session.refresh(true);
session.save();
}
private Repository repository;
private String workspace = null;
+ private String securityWorkspace = "security";
+
/**
* key := privilege1,privilege2/path/to/node<br/>
* value := group1,group2,user1
private Map<String, String> principalPrivileges = new HashMap<String, String>();
public void run() {
+ String currentWorkspace = workspace;
+ Session session = null;
+ try {
+ if (workspace != null && workspace.equals("*")) {
+ session = repository.login();
+ String[] workspaces = session.getWorkspace()
+ .getAccessibleWorkspaceNames();
+ JcrUtils.logoutQuietly(session);
+ for (String wksp : workspaces) {
+ currentWorkspace = wksp;
+ if (currentWorkspace.equals(securityWorkspace))
+ continue;
+ session = repository.login(currentWorkspace);
+ initAuthorizations(session);
+ JcrUtils.logoutQuietly(session);
+ }
+ } else {
+ session = repository.login(workspace);
+ initAuthorizations(session);
+ }
+ } catch (Exception e) {
+ JcrUtils.discardQuietly(session);
+ throw new ArgeoException(
+ "Cannot set authorizations " + principalPrivileges
+ + " on workspace " + currentWorkspace, e);
+ } finally {
+ JcrUtils.logoutQuietly(session);
+ }
+ }
+
+ protected void processWorkspace(String workspace) {
Session session = null;
try {
session = repository.login(workspace);
Principal principal = getOrCreatePrincipal(session,
principalName);
JcrUtils.addPrivileges(session, path, principal, privs);
+ if (log.isDebugEnabled()) {
+ StringBuffer privBuf = new StringBuffer();
+ for (Privilege priv : privs)
+ privBuf.append(priv.getName());
+ log.debug("Added privileges " + privBuf + " to "
+ + principal.getName() + " on " + path + " in '"
+ + session.getWorkspace().getName() + "'");
+ }
}
}
- if (log.isDebugEnabled())
- log.debug("All authorizations applied on workspace "
- + session.getWorkspace().getName());
+ // if (log.isDebugEnabled())
+ // log.debug("JCR authorizations applied on '"
+ // + session.getWorkspace().getName() + "'");
}
/**
this.workspace = workspace;
}
+ public void setSecurityWorkspace(String securityWorkspace) {
+ this.securityWorkspace = securityWorkspace;
+ }
+
}