You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2011/09/24 01:05:00 UTC

svn commit: r1175066 - in /jackrabbit/sandbox/jackrabbit-mk: jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/s...

Author: mduerig
Date: Fri Sep 23 23:04:59 2011
New Revision: 1175066

URL: http://svn.apache.org/viewvc?rev=1175066&view=rev
Log:
Microkernel based Jackrabbit prototype (WIP)
MVCC: operate on fixed revision until save or refresh

Modified:
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/SessionRemoveItemTest.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionInfoImpl.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/SessionInfoLogger.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SessionInfoImpl.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/SessionRemoveItemTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/SessionRemoveItemTest.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/SessionRemoveItemTest.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/SessionRemoveItemTest.java Fri Sep 23 23:04:59 2011
@@ -16,6 +16,10 @@
  */
 package org.apache.jackrabbit.test.api;
 
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.apache.jackrabbit.test.RepositoryStub;
+
 import javax.jcr.AccessDeniedException;
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.Node;
@@ -26,10 +30,6 @@ import javax.jcr.Value;
 import javax.jcr.lock.LockException;
 import javax.jcr.version.VersionException;
 
-import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.test.NotExecutableException;
-import org.apache.jackrabbit.test.RepositoryStub;
-
 /** <code>SessionRemoveItemTest</code>... */
 public class SessionRemoveItemTest extends AbstractJCRTest {
 
@@ -77,6 +77,7 @@ public class SessionRemoveItemTest exten
         adminSession.removeItem(nPath);
 
         // node must still exist for another session.
+        readOnlySession.refresh(true);
         assertTrue(readOnlySession.nodeExists(nPath));
     }
 

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java Fri Sep 23 23:04:59 2011
@@ -304,6 +304,7 @@ public class SessionImpl extends Abstrac
             getSessionItemStateManager().undo();
         }
         getHierarchyManager().getRootEntry().invalidate(true);
+        sessionInfo.refresh();
     }
 
     @Override

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionInfoImpl.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionInfoImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SessionInfoImpl.java Fri Sep 23 23:04:59 2011
@@ -102,6 +102,13 @@ public class SessionInfoImpl implements 
     }
 
     /**
+     * Empty implementation
+     */
+    @Override
+    public void refresh() {
+    }
+
+    /**
      * Return the user data set via {@link #setUserData(String)}
      * 
      * @return  userData

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/SessionInfoLogger.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/SessionInfoLogger.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/SessionInfoLogger.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/SessionInfoLogger.java Fri Sep 23 23:04:59 2011
@@ -109,5 +109,16 @@ public class SessionInfoLogger extends A
         }, "setUserData(String)", new Object[]{userData});
     }
 
+    @Override
+    public void refresh() {
+        execute(new SafeCallable<String>() {
+            @Override
+            public String call() {
+                sessionInfo.refresh();
+                return null;
+            }
+        }, "refresh()", new Object[]{});
+    }
+
 
 }

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/SessionInfo.java Fri Sep 23 23:04:59 2011
@@ -71,7 +71,8 @@ public interface SessionInfo {
      * @throws LockException If the token cannot be added.
      * @throws RepositoryException If another error occurs.
      */
-    void addLockToken(String lockToken) throws UnsupportedRepositoryOperationException, LockException, RepositoryException;
+    void addLockToken(String lockToken) throws UnsupportedRepositoryOperationException, LockException,
+            RepositoryException;
 
     /**
      * Removes the given lock token from this {@code SessionInfo}.
@@ -86,7 +87,8 @@ public interface SessionInfo {
      * @throws LockException If the token cannot be removed.
      * @throws RepositoryException If another error occurs.
      */
-    void removeLockToken(String lockToken) throws UnsupportedRepositoryOperationException, LockException, RepositoryException;
+    void removeLockToken(String lockToken) throws UnsupportedRepositoryOperationException, LockException,
+            RepositoryException;
 
     /**
      * Sets the user data used for {@link org.apache.jackrabbit.spi.Event#getUserData()}.
@@ -96,4 +98,12 @@ public interface SessionInfo {
      * @see javax.jcr.observation.ObservationManager#setUserData(String)
      */
     void setUserData(String userData) throws RepositoryException;
+
+    /**
+     * Notification about a {@link javax.jcr.Session#refresh(boolean)} call. Implementations need to ensure
+     * that after this call all infos returned by {@link RepositoryService#getItemInfos(SessionInfo, ItemId)}
+     * reflect the state of the persistence layer not later than from the time of this method call. That is,
+     * implementations need to evict their caches and/or advance to the head revision when MVCC based.
+     */
+    void refresh();
 }

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java Fri Sep 23 23:04:59 2011
@@ -207,7 +207,7 @@ public class QueryProcessor {
             if (index != null && index.propertyIndex != null) {
                 String v = propertyValue.length() == 0 ? null : propertyValue;
                 Iterator<String> paths = index.propertyIndex.getPaths(v, microKernel
-                        .getHeadRevision());
+                        .getHeadRevision());  // todo is head revision correct here?
                 while (paths.hasNext()) {
                     String path = paths.next();
                     path = path.substring(path.indexOf('/', 1));

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java Fri Sep 23 23:04:59 2011
@@ -82,7 +82,6 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.UUID;
-import java.util.concurrent.Callable;
 
 import static javax.jcr.Repository.IDENTIFIER_STABILITY;
 import static javax.jcr.Repository.IDENTIFIER_STABILITY_METHOD_DURATION;
@@ -280,13 +279,11 @@ public class RepositoryServiceImpl exten
 
     @Override
     public String[] getWorkspaceNames(SessionInfo sessionInfo) throws RepositoryException {
-        String rev = microKernel.getHeadRevision();
-
         // Names of first level nodes correspond to workspace names
         final List<String> workspaces = new ArrayList<String>();
 
         try {
-            String json = microKernel.getNodes("/", rev, 0, 0, -1);
+            String json = microKernel.getNodes("/", getRevision(sessionInfo), 0, 0, -1);
             new JSONParser().parse(json, new JsonHandlerBase() {
 
                 private String key;
@@ -334,8 +331,7 @@ public class RepositoryServiceImpl exten
             throw new NoSuchWorkspaceException(workspaceName);
         }
 
-        String head = microKernel.getHeadRevision();
-        if (!microKernel.nodeExists('/' + workspaceName, head)) {
+        if (!microKernel.nodeExists('/' + workspaceName, microKernel.getHeadRevision())) {
             throw new NoSuchWorkspaceException(workspaceName);
         }
     }
@@ -353,13 +349,13 @@ public class RepositoryServiceImpl exten
     public Iterator<? extends ItemInfo> getItemInfos(SessionInfo sessionInfo, ItemId itemId) throws RepositoryException {
         try {
             String wspName = sessionInfo.getWorkspaceName();
-            Path itemPath = getPath(itemId, wspName);
+            String rev = getRevision(sessionInfo);
+            Path itemPath = getPath(itemId, wspName, rev);
             if (!itemPath.isAbsolute()) {
                 throw new ItemNotFoundException(itemId.toString());
             }
 
             Path nodePath = itemId.denotesNode() ? itemPath : itemPath.getAncestor(1);
-            String rev = microKernel.getHeadRevision();
             String mkPath = Paths.pathToString(wspName, nodePath);
 
             if (!microKernel.nodeExists(mkPath, rev)) {
@@ -379,9 +375,9 @@ public class RepositoryServiceImpl exten
     public Iterator<ChildInfo> getChildInfos(SessionInfo sessionInfo, NodeId parentId) throws RepositoryException {
         try {
             String wspName = sessionInfo.getWorkspaceName();
-            Path path = getPath(parentId, wspName);
+            String rev = getRevision(sessionInfo);
+            Path path = getPath(parentId, wspName, rev);
             String mkPath = Paths.pathToString(wspName, path);
-            String rev = microKernel.getHeadRevision();
 
             if (!microKernel.nodeExists(mkPath, rev)) {
                 throw new PathNotFoundException(path.toString());
@@ -409,7 +405,7 @@ public class RepositoryServiceImpl exten
 
         String prefix = Values.typePrefix(weakReferences ? PropertyType.WEAKREFERENCE : PropertyType.REFERENCE);
         PrefixIndex index = weakReferences ? weakReferenceIndex : referenceIndex;
-        Iterator<String> paths = index.getPaths(prefix + id, microKernel.getHeadRevision());
+        Iterator<String> paths = index.getPaths(prefix + id, getRevision(sessionInfo));
         final IdFactory idFactory = getIdFactory();
         final String wspName = sessionInfo.getWorkspaceName();
 
@@ -462,7 +458,7 @@ public class RepositoryServiceImpl exten
 
     @Override
     public void createWorkspace(SessionInfo sessionInfo, String name, String srcWorkspaceName) throws RepositoryException {
-        String rev = microKernel.getHeadRevision();
+        String rev = getRevision(sessionInfo);
         if (srcWorkspaceName == null) {
             createWorkspace(rev, name, false);
         }
@@ -473,8 +469,7 @@ public class RepositoryServiceImpl exten
 
     @Override
     public void deleteWorkspace(SessionInfo sessionInfo, String name) throws RepositoryException {
-        String rev = microKernel.getHeadRevision();
-        deleteWorkspace(rev, name);
+        deleteWorkspace(getRevision(sessionInfo), name);
     }
 
     //------------------------------------------< Node type management >---
@@ -818,7 +813,7 @@ public class RepositoryServiceImpl exten
 
     //------------------------------------------< private >---
 
-    private Path getPath(ItemId itemId, String wspName) throws RepositoryException {
+    private Path getPath(ItemId itemId, String wspName, String revision) throws RepositoryException {
         String uid = itemId.getUniqueID();
         Path path = itemId.getPath();
 
@@ -826,7 +821,7 @@ public class RepositoryServiceImpl exten
             return path;
         }
 
-        Path basePath = resolveId(uid, wspName);
+        Path basePath = resolveId(uid, wspName, revision);
         if (path == null) {
             return basePath;
         }
@@ -835,8 +830,8 @@ public class RepositoryServiceImpl exten
         }
     }
 
-    private Path resolveId(String id, String wspName) throws ItemNotFoundException {
-        String path = jcrUuidIndex.getPath(id, microKernel.getHeadRevision());
+    private Path resolveId(String id, String wspName, String revision) throws ItemNotFoundException {
+        String path = jcrUuidIndex.getPath(id, revision);
         if (path == null) {
             throw new ItemNotFoundException(id);
         }
@@ -845,15 +840,14 @@ public class RepositoryServiceImpl exten
         return Paths.stringToPath(path);
     }
 
-    private String createId(NodeId nodeId, Name childName) {
+    private String createId(NodeId nodeId, Name childName, String revision) {
         int nodeHash = nodeId.hashCode();
         int childHash = childName == null ? 0 : childName.hashCode();
         // this will result in a very short id, which is good,
         // but it might not be unique
         String id = Integer.toHexString(nodeHash + childHash);
 
-        String rev = microKernel.getHeadRevision();
-        while (jcrUuidIndex.getPath(id, rev) != null) {
+        while (jcrUuidIndex.getPath(id, revision) != null) {
             // generate a 'real' random id while not unique
             id = UUID.randomUUID().toString();
         }
@@ -894,6 +888,10 @@ public class RepositoryServiceImpl exten
         }
     }
 
+    private static String getRevision(SessionInfo sessionInfo) throws RepositoryException {
+        return sessionInfoImpl(sessionInfo).getRevision();
+    }
+
     private void createWorkspace(String revisionId, String name, boolean ignoreExisting) throws RepositoryException {
         try {
             if (microKernel.nodeExists('/' + name, revisionId)) {
@@ -983,7 +981,7 @@ public class RepositoryServiceImpl exten
                 DefaultValueProvider defaultProvider = Values.getDefaultProvider(nodetypeName, nodeTypeDefs);
                 for (Name propertyName : defaultProvider.getDefaultProperties()) {
                     if (uuid == null) {
-                        uuid = createId(parentId, nodeName);
+                        uuid = createId(parentId, nodeName, getRevision(sessionInfo));
                     }
                     QValue value = defaultProvider.getValue(propertyName, sessionInfo, uuid);
                     setProperty(target(parentId, nodeName, propertyName), Values.valueToString(value, saveToDataStore));
@@ -1019,7 +1017,7 @@ public class RepositoryServiceImpl exten
         public void remove(ItemId itemId) throws RepositoryException {
             if (itemId.denotesNode()) {
                 NodeId nodeId = (NodeId) itemId;
-                if (getPath(nodeId, sessionInfo.getWorkspaceName()).denotesRoot()) {
+                if (getPath(nodeId, sessionInfo.getWorkspaceName(), getRevision(sessionInfo)).denotesRoot()) {
                     throw new RepositoryException("Cannot remove root node");
                 }
 
@@ -1052,7 +1050,7 @@ public class RepositoryServiceImpl exten
             for (Name mixin: mixinNodeTypeNames) {
                 DefaultValueProvider defaultProvider = Values.getDefaultProvider(mixin, nodeTypeDefs);
                 for (Name propertyName : defaultProvider.getDefaultProperties()) {
-                    String uuid = createId(nodeId, null);
+                    String uuid = createId(nodeId, null, getRevision(sessionInfo));
                     QValue value = defaultProvider.getValue(propertyName, sessionInfo, uuid);
                     setProperty(nodeId, propertyName, Values.valueToString(value, saveToDataStore));
                 }
@@ -1074,10 +1072,10 @@ public class RepositoryServiceImpl exten
             // todo: check value constraints
             // todo: throw InvalidItemStateException when item no longer exists
             // todo: throw ReferentialIntegrityException when saving removed node which is target of a reference
-            sessionInfoImpl(sessionInfo).commitWithLock(new Callable<String>() {
+            sessionInfoImpl(sessionInfo).commitWithLock(new Function1<MicroKernel, String>() {
                 @Override
-                public String call() {
-                    String rev = microKernel.getHeadRevision();
+                public String apply(MicroKernel microKernel) throws RepositoryException {
+                    String rev = getRevision(sessionInfo);
                     String userId = sessionInfo.getUserID();
                     String userData = sessionInfo.getUserData();
                     CommitMessage commitMessage = new CommitMessage(userId, userData == null ? "" : userData);
@@ -1088,7 +1086,7 @@ public class RepositoryServiceImpl exten
 
         private String target(NodeId nodeId) throws RepositoryException {
             String wspName = sessionInfo.getWorkspaceName();
-            Path path = getPath(nodeId, wspName);
+            Path path = getPath(nodeId, wspName, getRevision(sessionInfo));
 
             return JsonBuilder.quote(JsonBuilder.escape(
                     PathUtils.relativize("/", Paths.pathToString(wspName, path))));
@@ -1096,7 +1094,7 @@ public class RepositoryServiceImpl exten
 
         private String target(NodeId parentId, Name... itemNames) throws RepositoryException {
             String wspName = sessionInfo.getWorkspaceName();
-            String path = Paths.pathToString(wspName, getPath(parentId, wspName));
+            String path = Paths.pathToString(wspName, getPath(parentId, wspName, getRevision(sessionInfo)));
             String relPath = PathUtils.relativize("/", path);
 
             for (Name itemName : itemNames) {

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SessionInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SessionInfoImpl.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SessionInfoImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SessionInfoImpl.java Fri Sep 23 23:04:59 2011
@@ -20,13 +20,13 @@
 package org.apache.jackrabbit.spi2microkernel;
 
 import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.spi.commons.util.Function1;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.jcr.RepositoryException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.Callable;
 
 public class SessionInfoImpl extends org.apache.jackrabbit.spi.commons.SessionInfoImpl {
     private static final Logger log = LoggerFactory.getLogger(SessionInfoImpl.class);
@@ -34,17 +34,25 @@ public class SessionInfoImpl extends org
     private final MicroKernel microKernel;
     private final List<String> commitLog = new ArrayList<String>();
 
+    private String revision;
+
     public SessionInfoImpl(MicroKernel microKernel, String userId, String workspaceName) {
         this.microKernel = microKernel;
         setUserID(userId);
         setWorkspacename(workspaceName);
-        commitLog.add(microKernel.getHeadRevision());
+        revision = microKernel.getHeadRevision();
+        commitLog.add(revision);
+    }
+
+    public String getRevision() {
+        return revision;
     }
 
-    public void commitWithLock(Callable<String> commit) throws RepositoryException {
+    public void commitWithLock(Function1<MicroKernel, String> commit) throws RepositoryException {
         try {
             synchronized (commitLog) {
-                commitLog.add(commit.call());
+                revision = commit.apply(microKernel);
+                commitLog.add(revision);
             }
         }
         catch (Exception e) {
@@ -85,4 +93,17 @@ public class SessionInfoImpl extends org
         return getCommitLog().contains(revisionId);
     }
 
+    //------------------------------------------< SessionInfo >---
+
+    @Override
+    public void refresh() {
+        revision = microKernel.getHeadRevision();
+    }
+
+    //------------------------------------------< Object >---
+
+    @Override
+    public String toString() {
+        return "SessionInfoImpl(revision = " + revision + ')';
+    }
 }

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java?rev=1175066&r1=1175065&r2=1175066&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java Fri Sep 23 23:04:59 2011
@@ -1075,6 +1075,27 @@ public class RepositoryTest {
     }
 
     @Test
+    public void itemRefresh() throws RepositoryException {
+        Session session2 = getRepository().login();
+        try {
+            Node testNode = getNode(testPath);
+            assertFalse(session2.nodeExists(testNode.getPath() + "/newNode"));
+
+            testNode.addNode("newNode");
+            assertFalse(session2.nodeExists(testNode.getPath() + "/newNode"));
+
+            testNode.getSession().save();
+            assertFalse(session2.nodeExists(testNode.getPath() + "/newNode"));
+
+            session2.refresh(true);
+            assertTrue(session2.nodeExists(testNode.getPath() + "/newNode"));
+        }
+        finally {
+            session2.logout();
+        }
+    }
+
+    @Test
     @Ignore  // todo fix microkernel
     public void reorderTest() throws RepositoryException {
         Node testNode = getNode(testPath);