Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java (revision 1858869) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java (date 1557301562000) @@ -123,8 +123,7 @@ * {@code jcr:uuid} property. */ @NotNull - public NodeBuilder getOrCreateVersionHistory(@NotNull NodeBuilder versionable, @NotNull Map infoMap) - throws CommitFailedException { + public NodeBuilder getOrCreateVersionHistory(@NotNull NodeBuilder versionable, @NotNull Map infoMap) { checkNotNull(versionable); String vUUID = uuidFromNode(versionable); String relPath = getVersionHistoryPath(vUUID); @@ -161,7 +160,7 @@ vLabels.setProperty(JCR_PRIMARYTYPE, NT_VERSIONLABELS, Type.NAME); // jcr:rootVersion child node - createVersion(node, versionable); + createRootVersion(node, versionable); } else if (!versionable.hasProperty(JCR_VERSIONHISTORY)) { // connect versionable node with existing history connectHistory(node.getChildNode(JCR_ROOTVERSION), @@ -342,6 +341,34 @@ return node; } + /** + * Creates the root version in the given version history. + * + * @param vHistory the version history node. + * @param versionable the versionable node. + */ + private void createRootVersion(@NotNull NodeBuilder vHistory, + @NotNull NodeBuilder versionable) { + String versionUUID = UUIDUtils.generateUUID(); + NodeBuilder version = vHistory.child(JCR_ROOTVERSION); + version.setProperty(JCR_UUID, versionUUID, Type.STRING); + version.setProperty(JCR_PRIMARYTYPE, NT_VERSION, Type.NAME); + version.setProperty(JCR_CREATED, ISO8601.format(Calendar.getInstance()), Type.DATE); + version.setProperty(JCR_PREDECESSORS, Collections.emptyList(), Type.REFERENCES); + version.setProperty(JCR_SUCCESSORS, Collections.emptyList(), Type.REFERENCES); + + // incomplete frozen node on root-version (don't call create on versionable-state) + VersionableState.fromVersion(version, vHistory, versionable, this, getNodeTypeManager()); + + // set jcr:isCheckedOut, jcr:versionHistory, jcr:baseVersion and + // jcr:predecessors on versionable node + versionable.setProperty(JCR_ISCHECKEDOUT, true, Type.BOOLEAN); + versionable.setProperty(JCR_VERSIONHISTORY, uuidFromNode(vHistory), Type.REFERENCE); + versionable.setProperty(JCR_BASEVERSION, versionUUID, Type.REFERENCE); + // set predecessors to base version for the root version + versionable.setProperty(JCR_PREDECESSORS, Collections.singletonList(versionUUID), Type.REFERENCES); + } + /** * Creates a version in the given version history. If the given version * history does not yet have a version, then a root version is created and @@ -350,28 +377,22 @@ * * @param vHistory the version history node. * @param versionable the versionable node. - * @return the created version (nt:version) node. * @throws CommitFailedException if creating the version fails. E.g. because * the versionable node contains a OPV item with ABORT. */ - private NodeBuilder createVersion(@NotNull NodeBuilder vHistory, + private void createVersion(@NotNull NodeBuilder vHistory, @NotNull NodeBuilder versionable) throws IllegalArgumentException, CommitFailedException { - List predecessors; - NodeBuilder version; - boolean isRootVersion; if (!vHistory.hasChildNode(JCR_ROOTVERSION)) { - // create root version - isRootVersion = true; - predecessors = Collections.emptyList(); - version = vHistory.child(JCR_ROOTVERSION); - } else { - isRootVersion = false; - checkState(versionable.hasProperty(JCR_PREDECESSORS)); - PropertyState state = versionable.getProperty(JCR_PREDECESSORS); - predecessors = ImmutableList.copyOf(state.getValue(Type.REFERENCES)); - version = vHistory.child(calculateVersion(vHistory, versionable)); - } + createRootVersion(vHistory, versionable); + return; + } + + checkState(versionable.hasProperty(JCR_PREDECESSORS)); + PropertyState state = versionable.getProperty(JCR_PREDECESSORS); + List predecessors = ImmutableList.copyOf(state.getValue(Type.REFERENCES)); + NodeBuilder version = vHistory.child(calculateVersion(vHistory, versionable)); + String versionUUID = UUIDUtils.generateUUID(); version.setProperty(JCR_UUID, versionUUID, Type.STRING); version.setProperty(JCR_PRIMARYTYPE, NT_VERSION, Type.NAME); @@ -383,7 +404,7 @@ for (String id : predecessors) { String name = PathUtils.getName(getIdentifierManager().getPath(id)); NodeBuilder predecessor = vHistory.getChildNode(name); - PropertyState state = predecessor.getProperty(JCR_SUCCESSORS); + state = predecessor.getProperty(JCR_SUCCESSORS); if (state == null) { throw new IllegalStateException("Missing " + JCR_SUCCESSORS + " property on " + predecessor); @@ -394,27 +415,16 @@ } // jcr:frozenNode of created version - VersionableState versionableState = VersionableState.fromVersion( - version, vHistory, versionable, this, getNodeTypeManager()); - if (!isRootVersion) { - versionableState.create(); - } + VersionableState versionableState = VersionableState.fromVersion(version, vHistory, versionable, this, getNodeTypeManager()); + versionableState.create(); // set jcr:isCheckedOut, jcr:versionHistory, jcr:baseVersion and // jcr:predecessors on versionable node - versionable.setProperty(JCR_ISCHECKEDOUT, isRootVersion, Type.BOOLEAN); - versionable.setProperty(JCR_VERSIONHISTORY, - uuidFromNode(vHistory), Type.REFERENCE); + versionable.setProperty(JCR_ISCHECKEDOUT, false, Type.BOOLEAN); + versionable.setProperty(JCR_VERSIONHISTORY, uuidFromNode(vHistory), Type.REFERENCE); versionable.setProperty(JCR_BASEVERSION, versionUUID, Type.REFERENCE); - if (isRootVersion) { - // set predecessors to base version if this is the root version - predecessors = Collections.singletonList(versionUUID); - } else { - // otherwise clear predecessors for check-in - predecessors = Collections.emptyList(); - } - versionable.setProperty(JCR_PREDECESSORS, predecessors, Type.REFERENCES); - return version; + // clear predecessors for check-in + versionable.setProperty(JCR_PREDECESSORS, Collections.emptyList(), Type.REFERENCES); } /** Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/VersionablePathHook.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/VersionablePathHook.java (revision 1858869) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/VersionablePathHook.java (date 1557300424000) @@ -16,9 +16,6 @@ */ package org.apache.jackrabbit.oak.security.authorization.permission; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import com.google.common.collect.ImmutableSet; import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.oak.api.CommitFailedException; @@ -40,6 +37,8 @@ import org.apache.jackrabbit.oak.spi.version.VersionConstants; import org.jetbrains.annotations.NotNull; +import java.util.Collections; + import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; /** @@ -69,12 +68,7 @@ ReadWriteVersionManager vMgr = new ReadWriteVersionManager(vsRoot, rootBuilder); ReadOnlyNodeTypeManager ntMgr = ReadOnlyNodeTypeManager.getInstance(providerCtx.getRootProvider().createReadOnlyRoot(rootBuilder.getNodeState()), NamePathMapper.DEFAULT); - List exceptions = new ArrayList<>(); - after.compareAgainstBaseState(before, - new Diff(vMgr, ntMgr, new Node(rootBuilder), exceptions)); - if (!exceptions.isEmpty()) { - throw exceptions.get(0); - } + after.compareAgainstBaseState(before, new Diff(vMgr, ntMgr, new Node(rootBuilder))); return rootBuilder.getNodeState(); } @@ -88,16 +82,13 @@ private final ReadWriteVersionManager versionManager; private final ReadOnlyNodeTypeManager ntMgr; private final Node nodeAfter; - private final List exceptions; private Diff(@NotNull ReadWriteVersionManager versionManager, @NotNull ReadOnlyNodeTypeManager ntMgr, - @NotNull Node node, - @NotNull List exceptions) { + @NotNull Node node) { this.versionManager = versionManager; this.ntMgr = ntMgr; this.nodeAfter = node; - this.exceptions = exceptions; } @Override @@ -124,21 +115,12 @@ } Node node = new Node(nodeAfter, name); return after.compareAgainstBaseState( - before, new Diff(versionManager, ntMgr, node, exceptions)); + before, new Diff(versionManager, ntMgr, node)); } private boolean setVersionablePath(@NotNull PropertyState after) { if (JcrConstants.JCR_VERSIONHISTORY.equals(after.getName()) && nodeAfter.isVersionable(ntMgr)) { - NodeBuilder vhBuilder; - try { - vhBuilder = versionManager.getOrCreateVersionHistory( - nodeAfter.builder, Collections.emptyMap()); - } catch (CommitFailedException e) { - exceptions.add(e); - // stop further comparison - return false; - } - + NodeBuilder vhBuilder = versionManager.getOrCreateVersionHistory(nodeAfter.builder, Collections.emptyMap()); if (!vhBuilder.hasProperty(JcrConstants.JCR_MIXINTYPES)) { vhBuilder.setProperty( JcrConstants.JCR_MIXINTYPES,