[573863] Fix UnsupportedOperationExceptions from LockingManager.DurableView

https://bugs.eclipse.org/bugs/show_bug.cgi?id=573863
diff --git a/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters b/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters
index 4ba3666..2c80be8 100644
--- a/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters
+++ b/plugins/org.eclipse.emf.cdo.common/.settings/.api_filters
@@ -336,6 +336,13 @@
                 <message_argument value="37"/>
             </message_arguments>
         </filter>
+        <filter id="388194388">
+            <message_arguments>
+                <message_argument value="org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants"/>
+                <message_argument value="PROTOCOL_VERSION"/>
+                <message_argument value="38"/>
+            </message_arguments>
+        </filter>
     </resource>
     <resource path="src/org/eclipse/emf/cdo/common/revision/CDORevisionData.java" type="org.eclipse.emf.cdo.common.revision.CDORevisionData">
         <filter id="1209008130">
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockOwner.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockOwner.java
index befc999..ce17b73 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockOwner.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockOwner.java
@@ -33,5 +33,9 @@
 
   public String getDurableLockingID();
 
+  /**
+   * Returns <code>true</code> if this view is <b>purely</b> durable,
+   * i.e., currently not open and active on the client-side, <code>false</code> otherwise.
+   */
   public boolean isDurableView();
 }
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java
index 1709b21..623ff68 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java
@@ -10,7 +10,6 @@
  */
 package org.eclipse.emf.cdo.common.lock;
 
-import org.eclipse.emf.cdo.common.CDOCommonSession;
 import org.eclipse.emf.cdo.common.CDOCommonView;
 import org.eclipse.emf.cdo.common.branch.CDOBranch;
 import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
@@ -41,9 +40,15 @@
  */
 public final class CDOLockUtil
 {
-  private static final int DURABLE_SESSION_ID = 0;
+  /**
+   * @since 4.14
+   */
+  public static final int DURABLE_SESSION_ID = 0;
 
-  private static final int DURABLE_VIEW_ID = 0;
+  /**
+   * @since 4.14
+   */
+  public static final int DURABLE_VIEW_ID = 0;
 
   private CDOLockUtil()
   {
@@ -106,37 +111,19 @@
 
     for (CDOCommonView view : lockState.getReadLockOwners())
     {
-      String durableLockingID = view.getDurableLockingID();
-      int sessionID, viewID;
-      CDOCommonSession session = view.getSession();
-      boolean isDurableView = session == null;
-      if (isDurableView)
-      {
-        sessionID = DURABLE_SESSION_ID;
-        viewID = DURABLE_VIEW_ID;
-      }
-      else
-      {
-        sessionID = session.getSessionID();
-        viewID = view.getViewID();
-      }
-
-      CDOLockOwner owner = new CDOLockOwnerImpl(sessionID, viewID, durableLockingID, isDurableView);
-      cdoLockState.addReadLockOwner(owner);
+      cdoLockState.addReadLockOwner(createLockOwner(view));
     }
 
     CDOCommonView writeLockOwner = lockState.getWriteLockOwner();
     if (writeLockOwner != null)
     {
-      CDOLockOwner owner = createLockOwner(writeLockOwner);
-      cdoLockState.setWriteLockOwner(owner);
+      cdoLockState.setWriteLockOwner(createLockOwner(writeLockOwner));
     }
 
     CDOCommonView writeOptionOwner = lockState.getWriteOptionOwner();
     if (writeOptionOwner != null)
     {
-      CDOLockOwner owner = createLockOwner(writeOptionOwner);
-      cdoLockState.setWriteOptionOwner(owner);
+      cdoLockState.setWriteOptionOwner(createLockOwner(writeOptionOwner));
     }
 
     return cdoLockState;
@@ -144,18 +131,18 @@
 
   public static CDOLockOwner createLockOwner(CDOCommonView view)
   {
+    int sessionID = view.getSessionID();
+    int viewID = view.getViewID();
     String durableLockingID = view.getDurableLockingID();
+    return createLockOwner(sessionID, viewID, durableLockingID);
+  }
 
-    CDOCommonSession session = view.getSession();
-    if (session != null)
-    {
-      int sessionID = session.getSessionID();
-      int viewID = view.getViewID();
-      return new CDOLockOwnerImpl(sessionID, viewID, durableLockingID, false);
-    }
-
-    CheckUtil.checkNull(durableLockingID, "durableLockingID");
-    return new CDOLockOwnerImpl(DURABLE_SESSION_ID, DURABLE_VIEW_ID, durableLockingID, true);
+  /**
+   * @since 4.14
+   */
+  public static CDOLockOwner createLockOwner(int sessionID, int viewID, String durableLockingID)
+  {
+    return new CDOLockOwnerImpl(sessionID, viewID, durableLockingID);
   }
 
   public static CDOLockChangeInfo createLockChangeInfo(long timestamp, CDOLockOwner lockOwner, CDOBranch branch, Operation op, LockType lockType,
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
index b6b3416..bf42a51 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java
@@ -32,8 +32,9 @@
    * @since 4.2
    * @noreference This field is not intended to be referenced by clients.
    */
-  public static final int PROTOCOL_VERSION = 38; // CDOBranchTag support
+  public static final int PROTOCOL_VERSION = 39; // CDOLockOwner.isDurableView becomes derived
 
+  // public static final int PROTOCOL_VERSION = 38; // CDOBranchTag support
   // public static final int PROTOCOL_VERSION = 37; // SIGNAL_ACKNOWLEDGE_COMPRESSED_STRINGS
   // public static final int PROTOCOL_VERSION = 36; // CDOID.NIL
   // public static final int PROTOCOL_VERSION = 35; // DiffieHellman.Server.Challenge.getSecretAlgorithmKeyLen()
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockOwnerImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockOwnerImpl.java
index e6b7b14..c2a8f0c 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockOwnerImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockOwnerImpl.java
@@ -11,9 +11,12 @@
 package org.eclipse.emf.cdo.internal.common.lock;
 
 import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
 
 import org.eclipse.net4j.util.ObjectUtil;
 
+import java.util.Objects;
+
 /**
  * @author Caspar De Groot
  */
@@ -25,14 +28,11 @@
 
   private final String durableLockingID;
 
-  private final boolean isDurableView;
-
-  public CDOLockOwnerImpl(int sessionID, int viewID, String durableLockingID, boolean isDurableView)
+  public CDOLockOwnerImpl(int sessionID, int viewID, String durableLockingID)
   {
     this.sessionID = sessionID;
     this.viewID = viewID;
     this.durableLockingID = durableLockingID;
-    this.isDurableView = isDurableView;
   }
 
   @Override
@@ -56,12 +56,17 @@
   @Override
   public boolean isDurableView()
   {
-    return isDurableView;
+    return sessionID == CDOLockUtil.DURABLE_SESSION_ID;
   }
 
   @Override
   public int hashCode()
   {
+    if (isDurableView())
+    {
+      return ObjectUtil.hashCode(durableLockingID);
+    }
+
     return ObjectUtil.hashCode(sessionID, viewID);
   }
 
@@ -76,7 +81,13 @@
     if (obj instanceof CDOLockOwner)
     {
       CDOLockOwner that = (CDOLockOwner)obj;
-      return sessionID == that.getSessionID() && viewID == that.getViewID();
+
+      if (isDurableView())
+      {
+        return that.isDurableView() && Objects.equals(durableLockingID, that.getDurableLockingID());
+      }
+
+      return !that.isDurableView() && sessionID == that.getSessionID() && viewID == that.getViewID();
     }
 
     return false;
@@ -86,9 +97,19 @@
   public String toString()
   {
     StringBuilder builder = new StringBuilder("CDOLockOwner[");
-    builder.append(sessionID);
-    builder.append(':');
-    builder.append(viewID);
+
+    if (isDurableView())
+    {
+      builder.append("durable:");
+      builder.append(durableLockingID);
+    }
+    else
+    {
+      builder.append(sessionID);
+      builder.append(':');
+      builder.append(viewID);
+    }
+
     builder.append(']');
     return builder.toString();
   }
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/CDOBranchUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/CDOBranchUtil.java
index 3c102df..d3915b5 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/CDOBranchUtil.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/branch/CDOBranchUtil.java
@@ -142,15 +142,28 @@
   }
 
   /**
+   * @since 4.14
+   */
+  public static CDOBranch adjustBranch(CDOBranch branch, CDOBranchManager branchManager)
+  {
+    if (branch.getBranchManager() != branchManager)
+    {
+      branch = branchManager.getBranch(branch.getID());
+    }
+
+    return branch;
+  }
+
+  /**
    * @since 4.4
    */
   public static CDOBranchPoint adjustBranchPoint(CDOBranchPoint branchPoint, CDOBranchManager branchManager)
   {
     CDOBranch branch = branchPoint.getBranch();
-    if (branch.getBranchManager() != branchManager)
+    CDOBranch adjustedBranch = adjustBranch(branch, branchManager);
+    if (adjustedBranch != branch)
     {
-      branch = branchManager.getBranch(branch.getID());
-      branchPoint = branch.getPoint(branchPoint.getTimeStamp());
+      branchPoint = adjustedBranch.getPoint(branchPoint.getTimeStamp());
     }
 
     return branchPoint;
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java
index b46bfc9..8730e41 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataInputImpl.java
@@ -56,7 +56,6 @@
 import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo;
 import org.eclipse.emf.cdo.internal.common.lock.CDOLockAreaImpl;
 import org.eclipse.emf.cdo.internal.common.lock.CDOLockChangeInfoImpl;
-import org.eclipse.emf.cdo.internal.common.lock.CDOLockOwnerImpl;
 import org.eclipse.emf.cdo.internal.common.lock.CDOLockStateImpl;
 import org.eclipse.emf.cdo.internal.common.messages.Messages;
 import org.eclipse.emf.cdo.internal.common.revision.CDOIDAndBranchImpl;
@@ -380,8 +379,7 @@
     int session = readXInt();
     int view = readXInt();
     String lockAreaID = readString();
-    boolean isDurableView = readBoolean();
-    return new CDOLockOwnerImpl(session, view, lockAreaID, isDurableView);
+    return CDOLockUtil.createLockOwner(session, view, lockAreaID);
   }
 
   @Override
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java
index b5188aa..0ad9e84 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/protocol/CDODataOutputImpl.java
@@ -364,7 +364,6 @@
     writeXInt(lockOwner.getSessionID());
     writeXInt(lockOwner.getViewID());
     writeString(lockOwner.getDurableLockingID());
-    writeBoolean(lockOwner.isDurableView());
   }
 
   @Override
diff --git a/plugins/org.eclipse.emf.cdo.examples/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.examples/META-INF/MANIFEST.MF
index c6880e8..d6d99ca 100644
--- a/plugins/org.eclipse.emf.cdo.examples/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.cdo.examples/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-SymbolicName: org.eclipse.emf.cdo.examples;singleton:=true
-Bundle-Version: 4.1.3.qualifier
+Bundle-Version: 4.1.4.qualifier
 Bundle-Name: %pluginName
 Bundle-Vendor: %providerName
 Bundle-Activator: org.eclipse.emf.cdo.internal.examples.bundle.OM$Activator
@@ -23,9 +23,9 @@
  org.eclipse.emf.cdo.security;bundle-version="[4.0.0,5.0.0)",
  org.eclipse.emf.cdo.server.security;bundle-version="[4.0.0,5.0.0)"
 Import-Package: org.h2.jdbcx;version="[1.0.0,2.0.0)"
-Export-Package: org.eclipse.emf.cdo.examples;version="4.1.3";x-internal:=true,
- org.eclipse.emf.cdo.examples.embedded;version="4.1.3",
- org.eclipse.emf.cdo.examples.server;version="4.1.3";x-internal:=true,
- org.eclipse.emf.cdo.examples.server.offline;version="4.1.3";x-internal:=true,
- org.eclipse.emf.cdo.internal.examples.bundle;version="4.1.3";x-internal:=true
+Export-Package: org.eclipse.emf.cdo.examples;version="4.1.4";x-internal:=true,
+ org.eclipse.emf.cdo.examples.embedded;version="4.1.4",
+ org.eclipse.emf.cdo.examples.server;version="4.1.4";x-internal:=true,
+ org.eclipse.emf.cdo.examples.server.offline;version="4.1.4";x-internal:=true,
+ org.eclipse.emf.cdo.internal.examples.bundle;version="4.1.4";x-internal:=true
 Automatic-Module-Name: org.eclipse.emf.cdo.examples
diff --git a/plugins/org.eclipse.emf.cdo.examples/pom.xml b/plugins/org.eclipse.emf.cdo.examples/pom.xml
index 7c6ba8a..6c6cd5c 100644
--- a/plugins/org.eclipse.emf.cdo.examples/pom.xml
+++ b/plugins/org.eclipse.emf.cdo.examples/pom.xml
@@ -25,7 +25,7 @@
 
   <groupId>org.eclipse.emf.cdo</groupId>
   <artifactId>org.eclipse.emf.cdo.examples</artifactId>
-  <version>4.1.3-SNAPSHOT</version>
+  <version>4.1.4-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
 </project>
diff --git a/plugins/org.eclipse.emf.cdo.examples/src/org/eclipse/emf/cdo/examples/server/UserRolesQueryHandlerFactory.java b/plugins/org.eclipse.emf.cdo.examples/src/org/eclipse/emf/cdo/examples/server/UserRolesQueryHandlerFactory.java
index 9da2fdd..0dc2ce0 100644
--- a/plugins/org.eclipse.emf.cdo.examples/src/org/eclipse/emf/cdo/examples/server/UserRolesQueryHandlerFactory.java
+++ b/plugins/org.eclipse.emf.cdo.examples/src/org/eclipse/emf/cdo/examples/server/UserRolesQueryHandlerFactory.java
@@ -46,7 +46,7 @@
       public void executeQuery(CDOQueryInfo info, final IQueryContext context)
       {
         ISession session = context.getView().getSession();
-        IRepository repository = session.getManager().getRepository();
+        IRepository repository = session.getRepository();
         ISecurityManager securityManager = SecurityManagerUtil.getSecurityManager(repository);
 
         if (securityManager != null)
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
index 02c50d8..d07a3f8 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
@@ -1112,8 +1112,7 @@
     IDBPreparedStatement stmt = connection.prepareStatement(CDODBSchema.SQL_LOAD_BRANCHES, ReuseProbability.HIGH);
     ResultSet resultSet = null;
 
-    InternalRepository repository = getSession().getManager().getRepository();
-    InternalCDOBranchManager branchManager = repository.getBranchManager();
+    InternalCDOBranchManager branchManager = getSession().getRepository().getBranchManager();
 
     try
     {
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java
index a653af4..c731f72 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndication.java
@@ -61,7 +61,7 @@
 
   protected InternalRepository getRepository()
   {
-    InternalRepository repository = getSession().getManager().getRepository();
+    InternalRepository repository = getSession().getRepository();
     if (!LifecycleUtil.isActive(repository))
     {
       throw new IllegalStateException("CDORepositoryInfo has been deactivated"); //$NON-NLS-1$
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndicationWithMonitoring.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndicationWithMonitoring.java
index cb8caeb..1db1001 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndicationWithMonitoring.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerIndicationWithMonitoring.java
@@ -82,7 +82,7 @@
 
   protected InternalRepository getRepository()
   {
-    InternalRepository repository = getSession().getManager().getRepository();
+    InternalRepository repository = getSession().getRepository();
     if (!LifecycleUtil.isActive(repository))
     {
       throw new IllegalStateException("CDORepositoryInfo has been deactivated"); //$NON-NLS-1$
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerRequest.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerRequest.java
index 82136c6..de5bc54 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerRequest.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerRequest.java
@@ -67,13 +67,13 @@
       @Override
       public CDOPackageRegistry getPackageRegistry()
       {
-        return getSession().getManager().getRepository().getPackageRegistry();
+        return getSession().getRepository().getPackageRegistry();
       }
 
       @Override
       public CDORevisionUnchunker getRevisionUnchunker()
       {
-        return getSession().getManager().getRepository();
+        return getSession().getRepository();
       }
 
       @Override
diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/GetRemoteSessionsIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/GetRemoteSessionsIndication.java
index 4655ce9..aa2062f 100644
--- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/GetRemoteSessionsIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/GetRemoteSessionsIndication.java
@@ -48,7 +48,8 @@
   protected void responding(CDODataOutput out) throws IOException
   {
     InternalSession localSession = getSession();
-    InternalSession[] sessions = getSession().getManager().getSessions();
+    InternalSession[] sessions = localSession.getManager().getSessions();
+
     for (InternalSession session : sessions)
     {
       if (session != localSession)
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java
index c4dc5a8..c7bd27d 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockingManager.java
@@ -47,6 +47,7 @@
 import org.eclipse.net4j.util.concurrent.RWOLockManager;
 import org.eclipse.net4j.util.container.ContainerEventAdapter;
 import org.eclipse.net4j.util.container.IContainer;
+import org.eclipse.net4j.util.event.EventUtil;
 import org.eclipse.net4j.util.event.IListener;
 import org.eclipse.net4j.util.lifecycle.ILifecycle;
 import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
@@ -103,7 +104,7 @@
       }
       else
       {
-        DurableView durableView = new DurableView(durableLockingID);
+        DurableView durableView = new DurableView(durableLockingID, view, view.isReadOnly());
         changeContext(view, durableView);
         unregisterOpenDurableView(durableLockingID);
         durableViews.put(durableLockingID, durableView);
@@ -270,7 +271,7 @@
     CDOBranch branch = view.getBranch();
     boolean branching = repository.isSupportingBranches();
 
-    CDORevisionManager revisionManager = view.getSession().getManager().getRepository().getRevisionManager();
+    CDORevisionManager revisionManager = view.getSession().getRepository().getRevisionManager();
     CDORevisionProvider revisionProvider = new ManagedRevisionProvider(revisionManager, branch.getHead());
 
     Set<Object> contents = new HashSet<>();
@@ -637,13 +638,19 @@
    */
   private final class DurableView extends PlatformObject implements IView, CDOCommonView.Options
   {
-    private String durableLockingID;
+    private final String durableLockingID;
+
+    private final CDOBranchPoint branchPoint;
+
+    private final boolean readOnly;
 
     private IRegistry<String, Object> properties;
 
-    public DurableView(String durableLockingID)
+    public DurableView(String durableLockingID, CDOBranchPoint branchPoint, boolean readOnly)
     {
       this.durableLockingID = durableLockingID;
+      this.readOnly = readOnly;
+      this.branchPoint = CDOBranchUtil.copyBranchPoint(branchPoint);
     }
 
     @Override
@@ -661,43 +668,44 @@
     @Override
     public int getSessionID()
     {
-      throw new UnsupportedOperationException();
+      return CDOLockUtil.DURABLE_SESSION_ID;
     }
 
     @Override
     public int getViewID()
     {
-      throw new UnsupportedOperationException();
+      return CDOLockUtil.DURABLE_VIEW_ID;
     }
 
     @Override
     public boolean isReadOnly()
     {
-      throw new UnsupportedOperationException();
+      return readOnly;
     }
 
     @Override
     public boolean isHistorical()
     {
-      throw new UnsupportedOperationException();
+      return branchPoint.getTimeStamp() != CDOBranchPoint.UNSPECIFIED_DATE;
     }
 
     @Override
     public CDOBranch getBranch()
     {
-      throw new UnsupportedOperationException();
+      return branchPoint.getBranch();
     }
 
     @Override
     public long getTimeStamp()
     {
-      throw new UnsupportedOperationException();
+      return branchPoint.getTimeStamp();
     }
 
     @Override
     public CDORevision getRevision(CDOID id)
     {
-      throw new UnsupportedOperationException();
+      CDORevisionManager revisionManager = getRepository().getRevisionManager();
+      return revisionManager.getRevision(id, branchPoint, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true);
     }
 
     @Override
@@ -709,13 +717,13 @@
     @Override
     public boolean isClosed()
     {
-      throw new UnsupportedOperationException();
+      return false;
     }
 
     @Override
     public IRepository getRepository()
     {
-      throw new UnsupportedOperationException();
+      return LockingManager.this.getRepository();
     }
 
     @Override
@@ -756,7 +764,7 @@
     @Override
     public IOptionsContainer getContainer()
     {
-      return null;
+      return this;
     }
 
     @Override
@@ -778,7 +786,7 @@
     @Override
     public IListener[] getListeners()
     {
-      return null;
+      return EventUtil.NO_LISTENERS;
     }
 
     @Override
@@ -792,14 +800,7 @@
     {
       if (properties == null)
       {
-        properties = new HashMapRegistry<String, Object>()
-        {
-          @Override
-          public void setAutoCommit(boolean autoCommit)
-          {
-            throw new UnsupportedOperationException();
-          }
-        };
+        properties = new HashMapRegistry.AutoCommit<>();
       }
 
       return properties;
@@ -841,15 +842,15 @@
     public boolean handleLockArea(LockArea area)
     {
       String durableLockingID = area.getDurableLockingID();
+
       IView view = getView(durableLockingID);
       if (view != null)
       {
         unlock2(view);
       }
-
-      if (view == null)
+      else
       {
-        view = new DurableView(durableLockingID);
+        view = new DurableView(durableLockingID, area, area.isReadOnly());
         durableViews.put(durableLockingID, (DurableView)view);
       }
 
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
index a90588e..9940a91 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
@@ -2474,7 +2474,7 @@
       @Override
       protected long[] createTimeStamp(OMMonitor monitor)
       {
-        InternalRepository repository = getTransaction().getSession().getManager().getRepository();
+        InternalRepository repository = getTransaction().getSession().getRepository();
         return repository.forceCommitTimeStamp(store.getCreationTime(), monitor);
       }
 
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
index 3579f9a..4a3c01f 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
@@ -624,7 +624,7 @@
     public ServerCDOSession(InternalSession internalSession)
     {
       this.internalSession = internalSession;
-      repository = internalSession.getManager().getRepository();
+      repository = internalSession.getRepository();
       openingTime = repository.getTimeStamp();
     }
 
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
index 69d8d46..0fba853 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
@@ -171,6 +171,12 @@
   }
 
   @Override
+  public InternalRepository getRepository()
+  {
+    return manager.getRepository();
+  }
+
+  @Override
   public ExecutorService getExecutorService()
   {
     return manager.getExecutorService();
@@ -178,7 +184,7 @@
 
   public CDOBranchManager getBranchManager()
   {
-    return manager.getRepository().getBranchManager();
+    return getRepository().getBranchManager();
   }
 
   @Override
@@ -450,7 +456,7 @@
   public void collectContainedRevisions(InternalCDORevision revision, CDOBranchPoint branchPoint, int referenceChunk, Set<CDOID> revisions,
       List<CDORevision> additionalRevisions)
   {
-    InternalCDORevisionManager revisionManager = manager.getRepository().getRevisionManager();
+    InternalCDORevisionManager revisionManager = getRepository().getRevisionManager();
     for (EStructuralFeature feature : revision.getClassInfo().getAllPersistentFeatures())
     {
       // TODO Clarify feature maps
@@ -670,7 +676,7 @@
     }
 
     Set<CDOID> lockedIDs = new HashSet<>();
-    InternalLockManager lockingManager = getManager().getRepository().getLockingManager();
+    InternalLockManager lockingManager = getRepository().getLockingManager();
 
     for (InternalView view : getViews())
     {
@@ -703,7 +709,7 @@
 
   private boolean isDeltaNeeded(CDOID id, InternalView[] views)
   {
-    boolean supportingUnits = manager.getRepository().isSupportingUnits();
+    boolean supportingUnits = getRepository().isSupportingUnits();
 
     for (InternalView view : views)
     {
@@ -762,7 +768,7 @@
     String name = "unknown";
     if (manager != null)
     {
-      InternalRepository repository = manager.getRepository();
+      InternalRepository repository = getRepository();
       if (repository != null)
       {
         name = repository.getName();
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
index b1b82c3..5dd90f6 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
@@ -87,7 +87,7 @@
     this.viewID = viewID;
     sessionID = session.getSessionID();
 
-    repository = session.getManager().getRepository();
+    repository = session.getRepository();
     setBranchPoint(branchPoint);
   }
 
@@ -206,7 +206,7 @@
     checkOpen();
     validateTimeStamp(branchPoint.getTimeStamp());
 
-    InternalCDOBranchManager branchManager = getSession().getManager().getRepository().getBranchManager();
+    InternalCDOBranchManager branchManager = getSession().getRepository().getBranchManager();
     this.branchPoint = CDOBranchUtil.adjustBranchPoint(branchPoint, branchManager);
     normalizedBranchPoint = CDOBranchUtil.normalizeBranchPoint(this.branchPoint);
   }
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/ReplicatorCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/ReplicatorCommitContext.java
index f16131d..4ace8b1 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/ReplicatorCommitContext.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/ReplicatorCommitContext.java
@@ -66,7 +66,7 @@
   @Override
   protected long[] createTimeStamp(OMMonitor monitor)
   {
-    InternalRepository repository = getTransaction().getSession().getManager().getRepository();
+    InternalRepository repository = getTransaction().getSession().getRepository();
 
     long commitTimeStamp = commitInfo.getTimeStamp();
     if (commitTimeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
index 4c21245..0bd9c09 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
@@ -1190,7 +1190,7 @@
       long previousTimeStamp = result.getPreviousTimeStamp();
       result = null;
 
-      InternalRepository repository = getTransaction().getSession().getManager().getRepository();
+      InternalRepository repository = getTransaction().getSession().getRepository();
       repository.forceCommitTimeStamp(timeStamp, monitor);
 
       return new long[] { timeStamp, previousTimeStamp };
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerUtil.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerUtil.java
index 700bb04..305844f 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerUtil.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerUtil.java
@@ -83,7 +83,7 @@
    */
   public static CDOView openView(ISession session, CDOBranchPoint branchPoint)
   {
-    CDORevisionManager revisionManager = session.getManager().getRepository().getRevisionManager();
+    CDORevisionManager revisionManager = session.getRepository().getRevisionManager();
     CDORevisionProvider revisionProvider = new ManagedRevisionProvider(revisionManager, branchPoint);
     return openView(session, branchPoint, revisionProvider);
   }
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISession.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISession.java
index 9c3fb17..65874d0 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISession.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISession.java
@@ -33,6 +33,11 @@
   public ISessionManager getManager();
 
   /**
+   * @since 4.13
+   */
+  public IRepository getRepository();
+
+  /**
    * @since 3.0
    */
   public ISessionProtocol getProtocol();
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/StoreThreadLocal.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/StoreThreadLocal.java
index 40cf3ce..91f6938 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/StoreThreadLocal.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/StoreThreadLocal.java
@@ -144,7 +144,7 @@
     if (accessor == null)
     {
       ISession session = getSession();
-      IStore store = session.getManager().getRepository().getStore();
+      IStore store = session.getRepository().getStore();
       accessor = store.getReader(session);
       ACCESSOR.set(accessor);
     }
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
index fa73248..b7a7f69 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
@@ -47,6 +47,12 @@
   public InternalSessionManager getManager();
 
   /**
+   * @since 4.13
+   */
+  @Override
+  public InternalRepository getRepository();
+
+  /**
    * @since 4.2
    */
   public void setUserID(String userID);
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java
index 2bc1e87..a1155a0 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java
@@ -163,7 +163,7 @@
     Object serverLockTarget = serverLockTarget(lockState.getLockedObject());
 
     InternalSession serverSession = serverSession(session);
-    InternalLockManager lockingManager = serverSession.getManager().getRepository().getLockingManager();
+    InternalLockManager lockingManager = serverSession.getRepository().getLockingManager();
     return lockingManager.getLockState(serverLockTarget);
   }
 
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerRestartTransactionTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerRestartTransactionTest.java
index e96aeed..b662c5b 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerRestartTransactionTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerRestartTransactionTest.java
@@ -10,17 +10,36 @@
  */
 package org.eclipse.emf.cdo.tests;
 
+import static org.junit.Assume.assumeNotNull;
+
+import org.eclipse.emf.cdo.CDOObject;
 import org.eclipse.emf.cdo.common.CDOCommonSession;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
 import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
 import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;
 import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.server.CDOServerUtil;
 import org.eclipse.emf.cdo.server.ILockingManager;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IView;
 import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
 import org.eclipse.emf.cdo.tests.model1.Company;
 import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.view.CDOView;
 
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
 import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
 
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import java.util.Set;
+
 /**
  * @author Eike Stepper
  */
@@ -405,4 +424,118 @@
 
     assertEquals(true, gotCalled[0]);
   }
+
+  public void _testClearLocksOnServer() throws Exception
+  {
+    ISession serverSession = CDOServerUtil.getServerSession(session);
+    InternalLockManager lm = (InternalLockManager)serverSession.getRepository().getLockingManager();
+
+    transaction.commit();
+    transaction.options().setLockNotificationEnabled(true);
+    // EventUtil.addListener(transaction, CDOViewLocksChangedEvent.class, System.out::println);
+
+    CDOView localView = session.openView();
+    localView.options().setLockNotificationEnabled(true);
+    // EventUtil.addListener(localView, CDOViewLocksChangedEvent.class, System.out::println);
+    CDOResource localResource = localView.getResource(resource.getPath());
+
+    CDOSession remoteSession = openSession();
+    CDOView remoteView = remoteSession.openView();
+    remoteView.options().setLockNotificationEnabled(true);
+    // EventUtil.addListener(remoteView, CDOViewLocksChangedEvent.class, System.out::println);
+    CDOResource remoteResource = remoteView.getResource(resource.getPath());
+
+    writeLock(resource);
+    assertWriteLock(true, resource);
+    assertServerLockState(resource);
+    assertServerLockState(localResource);
+    assertServerLockState(remoteResource);
+
+    System.out.println("Normal:  " + ((InternalCDOView)transaction).getLockOwner());
+    String durableLockingID = transaction.enableDurableLocking();
+    System.out.println("Durable: " + ((InternalCDOView)transaction).getLockOwner());
+
+    assertWriteLock(true, resource);
+    assertServerLockState(resource);
+    assertServerLockState(localResource);
+    assertServerLockState(remoteResource);
+
+    sleep(100);
+    assertEquals(true, localResource.cdoWriteLock().isLockedByOthers());
+    // System.out.println(localResource.cdoLockState());
+
+    transaction.close();
+    sleep(100);
+    // System.out.println(localResource.cdoLockState());
+
+    CDOServerUtil.execute(serverSession, () -> {
+      // LockArea lockArea = lm.getLockArea(durableLockingID);
+      // System.out.println(lockArea);
+      lm.deleteLockArea(durableLockingID);
+    });
+
+    sleep(1000);
+    // assertWriteLock(false, resource);
+    // assertServerLockState(resource);
+    assertServerLockState(localResource);
+    assertServerLockState(remoteResource);
+  }
+
+  private static void assertServerLockState(CDOObject object)
+  {
+    CDOView view = object.cdoView();
+    assumeNotNull(view);
+
+    CDOLockState clientLockState = object.cdoLockState();
+    assumeNotNull(clientLockState);
+
+    IRepository repository = CDOServerUtil.getRepository(view.getSession());
+    InternalLockManager lm = (InternalLockManager)repository.getLockingManager();
+
+    CDOBranch serverBranch = CDOBranchUtil.adjustBranch(view.getBranch(), repository.getBranchManager());
+    Object lockKey = lm.getLockKey(object.cdoID(), serverBranch);
+    LockState<Object, IView> serverLockState = lm.getLockState(lockKey);
+    assumeNotNull(serverLockState);
+
+    assertLockOwners(clientLockState.getReadLockOwners(), //
+        serverLockState.getReadLockOwners());
+
+    assertLockOwner(clientLockState.getWriteLockOwner(), //
+        serverLockState.getWriteLockOwner());
+
+    assertLockOwner(clientLockState.getWriteOptionOwner(), //
+        serverLockState.getWriteOptionOwner());
+  }
+
+  private static void assertLockOwners(Set<CDOLockOwner> clientLockOwners, Set<IView> serverViews)
+  {
+    assertEquals(clientLockOwners.size(), serverViews.size());
+
+    for (IView serverView : serverViews)
+    {
+      CDOLockOwner serverLockOwner = CDOLockUtil.createLockOwner(serverView);
+      assertTrue("Missing on client: " + serverLockOwner, clientLockOwners.contains(serverLockOwner));
+    }
+  }
+
+  private static void assertLockOwner(CDOLockOwner clientLockOwner, IView serverView)
+  {
+    if (clientLockOwner == null)
+    {
+      assertEquals(null, serverView);
+    }
+    else
+    {
+      CDOLockOwner serverLockOwner = CDOLockUtil.createLockOwner(serverView);
+      assertEquals(clientLockOwner, serverLockOwner);
+
+      // assumeNotNull(serverLockOwner);
+      //
+      // assertEquals(clientLockOwner.getSessionID(), //
+      // serverLockOwner.getSessionID());
+      //
+      // assertEquals(clientLockOwner.getViewID(), //
+      // serverLockOwner.getViewID());
+    }
+  }
 }
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
index dc069e2..0be7800 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
@@ -826,9 +826,9 @@
 
         try
         {
-          CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
           if (durableLockingID == null)
           {
+            CDOSessionProtocol sessionProtocol = session.getSessionProtocol();
             durableLockingID = sessionProtocol.changeLockArea(this, true);
           }
 
@@ -1821,7 +1821,7 @@
 
         try
         {
-          if (session.isActive() && !lockStates.isEmpty())
+          if (session.isActive() && !lockStates.isEmpty() && !isDurableView())
           {
             List<CDOLockState> result = new ArrayList<>();
             for (CDOLockState lockState : lockStates.values())