X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms.jcr%2Fsrc%2Forg%2Fargeo%2Fcms%2Fjcr%2Facr%2FJcrSessionAdapter.java;h=e1ded7d1f8aab9141e05ef9e21cf409ad2a533a0;hb=311d6e47ad278fd00d1ad15fe9d59be47e23e385;hp=ae8ae80f29867636005d0c8428da88f3c769986d;hpb=f0cbf84181c2dbef459150e75d403aa66c12de1d;p=gpl%2Fargeo-jcr.git diff --git a/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionAdapter.java b/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionAdapter.java index ae8ae80..e1ded7d 100644 --- a/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionAdapter.java +++ b/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrSessionAdapter.java @@ -4,14 +4,20 @@ import java.security.PrivilegedAction; 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; @@ -28,6 +34,14 @@ class JcrSessionAdapter { private Thread lastRetrievingThread = null; +// private Thread writeThread; + private Map writeSessions = new HashMap<>(); + /** + * Path of versionable nodes which have been modified during an edition cycle. + */ + private Map> checkedInModified = new HashMap<>(); + private Map> checkedOutModified = new HashMap<>(); + public JcrSessionAdapter(Repository repository, ProvidedSession contentSession, Subject subject) { this.repository = repository; this.contentSession = contentSession; @@ -61,19 +75,7 @@ class JcrSessionAdapter { Session session = threadSession.get(workspace); if (session == null) { - session = Subject.doAs(subject, (PrivilegedAction) () -> { - 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); } @@ -88,4 +90,84 @@ class JcrSessionAdapter { 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 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) () -> { + 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); + } + }); + } + }