import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.version.VersionManager;
import javax.security.auth.Subject;
import org.apache.jackrabbit.core.SessionImpl;
import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.jcr.Jcr;
import org.argeo.jcr.JcrException;
import org.argeo.jcr.JcrUtils;
private Thread lastRetrievingThread = null;
+// private Thread writeThread;
+ private Map<String, Session> writeSessions = new HashMap<>();
+ /**
+ * Path of versionable nodes which have been modified during an edition cycle.
+ */
+ private Map<String, Set<String>> checkedInModified = new HashMap<>();
+ private Map<String, Set<String>> checkedOutModified = new HashMap<>();
+
public JcrSessionAdapter(Repository repository, ProvidedSession contentSession, Subject subject) {
this.repository = repository;
this.contentSession = contentSession;
Session session = threadSession.get(workspace);
if (session == null) {
- session = Subject.doAs(subject, (PrivilegedAction<Session>) () -> {
- try {
-// String username = CurrentUser.getUsername(subject);
-// SimpleCredentials credentials = new SimpleCredentials(username, new char[0]);
-// credentials.setAttribute(ProvidedSession.class.getName(), contentSession);
- Session sess = repository.login(workspace);
- // Jackrabbit specific:
- ((SessionImpl)sess).setAttribute(ProvidedSession.class.getName(), contentSession);
- return sess;
- } catch (RepositoryException e) {
- throw new IllegalStateException("Cannot log in to " + workspace, e);
- }
- });
+ session = login(workspace);
threadSession.put(workspace, session);
}
return session;
}
+ protected synchronized Session getWriteSession(String workspace) throws RepositoryException {
+ Session session = writeSessions.get(workspace);
+ if (session == null) {
+ session = login(workspace);
+ writeSessions.put(workspace, session);
+ } else {
+// if ((writeThread != Thread.currentThread()) && session.hasPendingChanges()) {
+// throw new IllegalStateException("Session " + contentSession + " is currently being written to");
+// }
+// writeThread = Thread.currentThread();
+ }
+ return session;
+ }
+
+ public synchronized Node openForEdit(String workspace, String jcrPath) throws RepositoryException {
+ Session session = getWriteSession(workspace);
+ Node node = session.getNode(jcrPath);
+ if (node.isNodeType(NodeType.MIX_SIMPLE_VERSIONABLE)) {
+ VersionManager versionManager = session.getWorkspace().getVersionManager();
+ if (versionManager.isCheckedOut(jcrPath)) {
+ if (!checkedOutModified.containsKey(workspace))
+ checkedOutModified.put(workspace, new TreeSet<>());
+ checkedOutModified.get(workspace).add(jcrPath);
+ } else {
+ if (!checkedInModified.containsKey(workspace))
+ checkedInModified.put(workspace, new TreeSet<>());
+ checkedInModified.get(workspace).add(jcrPath);
+ versionManager.checkout(jcrPath);
+ }
+ }
+ return node;
+ }
+
+ public synchronized void persist() throws RepositoryException {
+ for (String workspace : writeSessions.keySet()) {
+ Session session = writeSessions.get(workspace);
+ if (session == null) {
+// assert writeThread == null;
+ assert !checkedOutModified.containsKey(workspace);
+ assert !checkedInModified.containsKey(workspace);
+ return; // nothing to do
+ }
+ session.save();
+ VersionManager versionManager = session.getWorkspace().getVersionManager();
+ if (checkedOutModified.containsKey(workspace))
+ for (String jcrPath : checkedOutModified.get(workspace)) {
+ versionManager.checkpoint(jcrPath);
+ }
+ if (checkedInModified.containsKey(workspace))
+ for (String jcrPath : checkedInModified.get(workspace)) {
+ versionManager.checkin(jcrPath);
+ }
+ Jcr.logout(session);
+ }
+
+ for (Map<String, Session> m : threadSessions.values())
+ for (Session session : m.values())
+ session.refresh(true);
+// writeThread = null;
+ writeSessions.clear();
+ checkedOutModified.clear();
+ checkedInModified.clear();
+ }
+
+ protected Session login(String workspace) {
+ return Subject.doAs(subject, (PrivilegedAction<Session>) () -> {
+ try {
+// String username = CurrentUser.getUsername(subject);
+// SimpleCredentials credentials = new SimpleCredentials(username, new char[0]);
+// credentials.setAttribute(ProvidedSession.class.getName(), contentSession);
+ Session sess = repository.login(workspace);
+ // Jackrabbit specific:
+ ((SessionImpl) sess).setAttribute(ProvidedSession.class.getName(), contentSession);
+ return sess;
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot log in to " + workspace, e);
+ }
+ });
+ }
+
}