You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mr...@apache.org on 2013/05/23 10:37:19 UTC
svn commit: r1485613 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/core/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/
oak-core/src/test/java/org/apache/jackrabbit/oak/core/ oak-jcr/
Author: mreutegg
Date: Thu May 23 08:37:19 2013
New Revision: 1485613
URL: http://svn.apache.org/r1485613
Log:
OAK-168: Basic JCR VersionManager support
- Restore of versionable nodes with OPV=Version
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/DateVersionSelector.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/Utils.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionExceptionCode.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionableState.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/ImmutableRootTest.java
jackrabbit/oak/trunk/oak-jcr/pom.xml
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java Thu May 23 08:37:19 2013
@@ -27,13 +27,17 @@ import org.apache.jackrabbit.oak.api.Blo
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.QueryEngine;
import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexProvider;
+import org.apache.jackrabbit.oak.query.QueryEngineImpl;
import org.apache.jackrabbit.oak.spi.state.NodeState;
/**
* Simple implementation of the Root interface that only supports simple read
- * operations (excluding query) based on the {@code NodeState} (or {@code ImmutableTree})
- * passed to the constructor.
+ * operations based on the {@code NodeState} (or {@code ImmutableTree})
+ * passed to the constructor. This root implementation provides a query engine
+ * with index support limited to the {@link PropertyIndexProvider}.
*/
public final class ImmutableRoot implements Root {
@@ -99,7 +103,17 @@ public final class ImmutableRoot impleme
@Nonnull
@Override
public QueryEngine getQueryEngine() {
- throw new UnsupportedOperationException();
+ return new QueryEngineImpl(new PropertyIndexProvider()) {
+ @Override
+ protected NodeState getRootState() {
+ return rootTree.state;
+ }
+
+ @Override
+ protected Tree getRootTree() {
+ return rootTree;
+ }
+ };
}
@Nonnull
@@ -107,10 +121,11 @@ public final class ImmutableRoot impleme
public BlobFactory getBlobFactory() {
throw new UnsupportedOperationException();
}
-
- @Override
- public ContentSession getContentSession() {
- throw new UnsupportedOperationException();
- }
-
+
+ @Nonnull
+ @Override
+ public ContentSession getContentSession() {
+ throw new UnsupportedOperationException();
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/DateVersionSelector.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/DateVersionSelector.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/DateVersionSelector.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/DateVersionSelector.java Thu May 23 08:37:19 2013
@@ -69,8 +69,9 @@ public class DateVersionSelector impleme
NodeBuilder latestVersion = null;
for (String name: history.getChildNodeNames()) {
NodeBuilder v = history.getChildNode(name);
- if (name.equals(JcrConstants.JCR_ROOTVERSION)) {
- // ignore root version
+ if (name.equals(JcrConstants.JCR_ROOTVERSION)
+ || name.equals(JcrConstants.JCR_VERSIONLABELS)) {
+ // ignore root version and labels node
continue;
}
long c = v.getProperty(JcrConstants.JCR_CREATED).getValue(Type.DATE);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java Thu May 23 08:37:19 2013
@@ -18,6 +18,7 @@
*/
package org.apache.jackrabbit.oak.plugins.version;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
@@ -36,6 +37,7 @@ import static org.apache.jackrabbit.JcrC
import static org.apache.jackrabbit.JcrConstants.NT_VERSIONLABELS;
import static org.apache.jackrabbit.oak.plugins.version.Utils.uuidFromNode;
import static org.apache.jackrabbit.oak.plugins.version.VersionConstants.REP_VERSIONSTORAGE;
+import static org.apache.jackrabbit.oak.plugins.version.VersionConstants.VERSION_STORE_PATH;
import java.util.Collections;
import java.util.Iterator;
@@ -43,6 +45,8 @@ import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
@@ -58,7 +62,6 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/**
@@ -161,18 +164,16 @@ class ReadWriteVersionManager extends Re
}
public void restore(@Nonnull NodeBuilder versionable,
- @Nonnull String versionUUID)
+ @Nonnull String versionUUID,
+ @Nullable VersionSelector selector)
throws CommitFailedException {
+ String versionPath = getIdentifierManager().getPath(versionUUID);
NodeBuilder history = getOrCreateVersionHistory(versionable);
- // FIXME: inefficient because it iterates over all versions (worst case)
NodeBuilder version = null;
- for (String name : history.getChildNodeNames()) {
- if (name.equals(JCR_VERSIONLABELS)) {
- continue;
- }
- NodeBuilder child = history.getChildNode(name);
- if (versionUUID.equals(uuidFromNode(child))) {
- version = child;
+ if (versionPath != null) {
+ String versionName = PathUtils.getName(versionPath);
+ if (history.hasChildNode(versionName)) {
+ version = history.getChildNode(versionName);
}
}
if (version == null) {
@@ -182,8 +183,40 @@ class ReadWriteVersionManager extends Re
" does not have a Version with UUID: " + versionUUID);
}
VersionableState versionableState = VersionableState.forRestore(
- version, versionable, ntMgr);
- versionableState.restore();
+ version, history, versionable, this, ntMgr);
+ versionableState.restore(selector);
+ }
+
+ /**
+ * Restores a version from the history identified by <code>historyIdentifier</code>
+ * using the given version <code>selector</code>.
+ *
+ * @param historyIdentifier identifier of the version history node.
+ * @param selector the version selector.
+ * @param versionable the versionable node where the version is restored to.
+ * @throws CommitFailedException if an error occurs while restoring.
+ */
+ void restore(@Nonnull String historyIdentifier,
+ @Nonnull VersionSelector selector,
+ @Nonnull NodeBuilder versionable)
+ throws CommitFailedException, RepositoryException {
+ String historyPath = getIdentifierManager().getPath(historyIdentifier);
+ String historyRelPath = PathUtils.relativize(VERSION_STORE_PATH, historyPath);
+ NodeBuilder history = resolve(versionStorageNode, historyRelPath);
+ checkState(history.exists(), "Version history does not exist: " + historyPath);
+ NodeBuilder version = selector.select(history);
+ if (version == null) {
+ throw new CommitFailedException(CommitFailedException.VERSION,
+ VersionExceptionCode.NO_VERSION_TO_RESTORE.ordinal(),
+ "VersionSelector did not select any version from " +
+ "history: " + historyPath);
+ }
+ // make sure versionable nodes has a jcr:uuid
+ // (required to identify its version history)
+ String versionableUUUID = history.getProperty(
+ JCR_VERSIONABLEUUID).getValue(Type.STRING);
+ versionable.setProperty(JCR_UUID, versionableUUUID, Type.STRING);
+ restore(versionable, uuidFromNode(version), selector);
}
// TODO: more methods that modify versions
@@ -191,6 +224,23 @@ class ReadWriteVersionManager extends Re
//------------------------------< internal >--------------------------------
/**
+ * Resolves the <code>relPath</code> based on the given <code>node</code>
+ * and returns the resulting node, possibly non-existing.
+ *
+ * @param node the resolved node.
+ * @param relPath a relative path.
+ * @return the resolved node.
+ */
+ @Nonnull
+ private NodeBuilder resolve(NodeBuilder node, String relPath) {
+ checkArgument(!PathUtils.isAbsolute(relPath), "Not a relative path");
+ for (String name : PathUtils.elements(relPath)) {
+ node = node.getChildNode(name);
+ }
+ return node;
+ }
+
+ /**
* 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
* the versionable node is in a checked out state. Otherwise a version is
@@ -229,27 +279,22 @@ class ReadWriteVersionManager extends Re
version.setProperty(JCR_SUCCESSORS, Collections.<String>emptyList(), Type.REFERENCES);
// update successors of versions identified by predecessors
- // FIXME: inefficient because it iterates over all versions
- for (String name : vHistory.getChildNodeNames()) {
- if (name.equals(JCR_VERSIONLABELS)) {
- continue;
- }
+ for (String id : predecessors) {
+ String name = PathUtils.getName(getIdentifierManager().getPath(id));
NodeBuilder predecessor = vHistory.getChildNode(name);
- if (predecessors.contains(uuidFromNode(predecessor))) {
- PropertyState state = predecessor.getProperty(JCR_SUCCESSORS);
- if (state == null) {
- throw new IllegalStateException("Missing " + JCR_SUCCESSORS +
- " property on " + predecessor);
- }
- Set<String> refs = Sets.newHashSet(state.getValue(Type.REFERENCES));
- refs.add(versionUUID);
- predecessor.setProperty(JCR_SUCCESSORS, refs, Type.REFERENCES);
+ PropertyState state = predecessor.getProperty(JCR_SUCCESSORS);
+ if (state == null) {
+ throw new IllegalStateException("Missing " + JCR_SUCCESSORS +
+ " property on " + predecessor);
}
+ Set<String> refs = Sets.newHashSet(state.getValue(Type.REFERENCES));
+ refs.add(versionUUID);
+ predecessor.setProperty(JCR_SUCCESSORS, refs, Type.REFERENCES);
}
// jcr:frozenNode of created version
VersionableState versionableState = VersionableState.fromVersion(
- version, versionable, ntMgr);
+ version, vHistory, versionable, this, ntMgr);
if (!isRootVersion) {
versionableState.create();
}
@@ -331,18 +376,11 @@ class ReadWriteVersionManager extends Re
throw new IllegalStateException(message);
}
- // FIXME: inefficient because it iterates over all versions!
- Set<String> uuids = ImmutableSet.copyOf(predecessors.getValue(Type.REFERENCES));
String best = null;
- for (String name : history.getChildNodeNames()) {
- if (name.equals(JCR_VERSIONLABELS)) {
- continue;
- }
- NodeBuilder child = history.getChildNode(name);
- if (uuids.contains(uuidFromNode(child))) {
- if (best == null || name.length() < best.length()) {
- best = name;
- }
+ for (String id : predecessors.getValue(Type.REFERENCES)) {
+ String name = PathUtils.getName(getIdentifierManager().getPath(id));
+ if (best == null || name.length() < best.length()) {
+ best = name;
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/Utils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/Utils.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/Utils.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/Utils.java Thu May 23 08:37:19 2013
@@ -62,7 +62,7 @@ public class Utils {
@Nonnull
static String primaryTypeOf(@Nonnull NodeBuilder node)
throws IllegalStateException {
- String primaryType = node.getName(JCR_PRIMARYTYPE);
+ String primaryType = checkNotNull(node).getName(JCR_PRIMARYTYPE);
if (primaryType == null) {
throw new IllegalStateException("Node does not have a jcr:primaryType");
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionEditor.java Thu May 23 08:37:19 2013
@@ -91,7 +91,7 @@ class VersionEditor implements Editor {
&& !this.after.hasProperty(JcrConstants.JCR_ISCHECKEDOUT)
&& !this.before.exists()) {
// sentinel node for restore
- vMgr.restore(node, after.getValue(Type.REFERENCE));
+ vMgr.restore(node, after.getValue(Type.REFERENCE), null);
return;
}
if (!wasReadOnly) {
@@ -124,7 +124,7 @@ class VersionEditor implements Editor {
vMgr.checkin(node);
}
} else if (propName.equals(VersionConstants.JCR_BASEVERSION)) {
- vMgr.restore(node, after.getValue(Type.REFERENCE));
+ vMgr.restore(node, after.getValue(Type.REFERENCE), null);
} else if (isVersionProperty(after)) {
throwProtected(after.getName());
} else if (wasReadOnly) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionExceptionCode.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionExceptionCode.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionExceptionCode.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionExceptionCode.java Thu May 23 08:37:19 2013
@@ -27,7 +27,8 @@ public enum VersionExceptionCode {
UNEXPECTED_REPOSITORY_EXCEPTION("Unexpected RepositoryException"),
NODE_CHECKED_IN("Node is checked in"),
NO_SUCH_VERSION("No such Version"),
- OPV_ABORT_ITEM_PRESENT("Item with OPV ABORT action present");
+ OPV_ABORT_ITEM_PRESENT("Item with OPV ABORT action present"),
+ NO_VERSION_TO_RESTORE("No suitable version to restore");
private final String desc;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionableState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionableState.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionableState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionableState.java Thu May 23 08:37:19 2013
@@ -20,9 +20,11 @@ package org.apache.jackrabbit.oak.plugin
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.PropertyDefinition;
@@ -64,6 +66,8 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.util.TODO;
+import com.google.common.collect.Lists;
+
/**
* <code>VersionableState</code> provides methods to create a versionable state
* for a version based on a versionable node.
@@ -84,22 +88,29 @@ class VersionableState {
BASIC_PROPERTIES.add(JCR_PRIMARYTYPE);
BASIC_PROPERTIES.add(JCR_UUID);
BASIC_PROPERTIES.add(JCR_MIXINTYPES);
+ BASIC_FROZEN_PROPERTIES.addAll(BASIC_PROPERTIES);
BASIC_FROZEN_PROPERTIES.add(JCR_FROZENPRIMARYTYPE);
BASIC_FROZEN_PROPERTIES.add(JCR_FROZENUUID);
BASIC_FROZEN_PROPERTIES.add(JCR_FROZENMIXINTYPES);
}
private final NodeBuilder version;
+ private final NodeBuilder history;
private final NodeBuilder frozenNode;
private final NodeBuilder versionable;
+ private final ReadWriteVersionManager vMgr;
private final ReadOnlyNodeTypeManager ntMgr;
private VersionableState(@Nonnull NodeBuilder version,
+ @Nonnull NodeBuilder history,
@Nonnull NodeBuilder versionable,
+ @Nonnull ReadWriteVersionManager vMgr,
@Nonnull ReadOnlyNodeTypeManager ntMgr) {
this.version = checkNotNull(version);
+ this.history = checkNotNull(history);
this.frozenNode = version.child(JCR_FROZENNODE);
this.versionable = checkNotNull(versionable);
+ this.vMgr = checkNotNull(vMgr);
this.ntMgr = checkNotNull(ntMgr);
}
@@ -109,15 +120,19 @@ class VersionableState {
* jcr:frozenUuid) from the given versionable node.
*
* @param version the parent node of the frozen node.
+ * @param history the history node of the version.
* @param versionable the versionable node.
+ * @param vMgr the version manager.
* @param ntMgr the node type manager.
* @return a versionable state
*/
@Nonnull
static VersionableState fromVersion(@Nonnull NodeBuilder version,
+ @Nonnull NodeBuilder history,
@Nonnull NodeBuilder versionable,
+ @Nonnull ReadWriteVersionManager vMgr,
@Nonnull ReadOnlyNodeTypeManager ntMgr) {
- VersionableState state = new VersionableState(version, versionable, ntMgr);
+ VersionableState state = new VersionableState(version, history, versionable, vMgr, ntMgr);
return state.initFrozen(version.child(JCR_FROZENNODE), versionable);
}
@@ -125,14 +140,18 @@ class VersionableState {
* Creates a versionable state for a restore.
*
* @param version the version to restore.
+ * @param history the history node of the version.
* @param versionable the versionable node.
+ * @param vMgr the version manager.
* @param ntMgr the node type manager.
* @return a versionable state.
*/
static VersionableState forRestore(@Nonnull NodeBuilder version,
+ @Nonnull NodeBuilder history,
@Nonnull NodeBuilder versionable,
+ @Nonnull ReadWriteVersionManager vMgr,
@Nonnull ReadOnlyNodeTypeManager ntMgr) {
- return new VersionableState(version, versionable, ntMgr);
+ return new VersionableState(version, history, versionable, vMgr, ntMgr);
}
/**
@@ -147,15 +166,19 @@ class VersionableState {
// initialize jcr:frozenNode
frozen.setProperty(JCR_UUID, IdentifierManager.generateUUID(), Type.STRING);
frozen.setProperty(JCR_PRIMARYTYPE, NT_FROZENNODE, Type.NAME);
- Iterable<String> mixinTypes;
+ List<String> mixinTypes;
if (referenceable.hasProperty(JCR_MIXINTYPES)) {
- mixinTypes = referenceable.getNames(JCR_MIXINTYPES);
+ mixinTypes = Lists.newArrayList(referenceable.getNames(JCR_MIXINTYPES));
} else {
mixinTypes = Collections.emptyList();
}
- frozen.setProperty(JCR_FROZENMIXINTYPES, mixinTypes, Type.NAMES);
- frozen.setProperty(JCR_FROZENPRIMARYTYPE, primaryTypeOf(referenceable), Type.NAME);
frozen.setProperty(JCR_FROZENUUID, uuidFromNode(referenceable), Type.STRING);
+ frozen.setProperty(JCR_FROZENPRIMARYTYPE, primaryTypeOf(referenceable), Type.NAME);
+ if (mixinTypes.isEmpty()) {
+ frozen.removeProperty(JCR_FROZENMIXINTYPES);
+ } else {
+ frozen.setProperty(JCR_FROZENMIXINTYPES, mixinTypes, Type.NAMES);
+ }
return this;
}
@@ -180,13 +203,18 @@ class VersionableState {
/**
* Restore the versionable node to the given version.
*
+ * @param selector an optional version selector. If none is passed, this
+ * method will use a date based version selector.
* @return the versionable node.
* @throws CommitFailedException if the operation fails.
*/
- public NodeBuilder restore() throws CommitFailedException {
+ public NodeBuilder restore(@Nullable VersionSelector selector)
+ throws CommitFailedException {
try {
- long created = version.getProperty(JCR_CREATED).getValue(Type.DATE);
- VersionSelector selector = new DateVersionSelector(created);
+ if (selector == null) {
+ long created = version.getProperty(JCR_CREATED).getValue(Type.DATE);
+ selector = new DateVersionSelector(created);
+ }
restoreFrozen(frozenNode, versionable, selector);
restoreVersionable(versionable, version);
return versionable;
@@ -199,37 +227,49 @@ class VersionableState {
//--------------------------< internal >------------------------------------
+ /**
+ * Restores the state from <code>src</code> to a child node of
+ * <code>destParent</code> with the same name as <code>src</code>.
+ *
+ * @param src the source node.
+ * @param destParent the parent of the destination node.
+ * @param name the name of the source node.
+ * @param selector the version selector.
+ */
private void restoreState(@Nonnull NodeBuilder src,
- @Nonnull NodeBuilder dest,
+ @Nonnull NodeBuilder destParent,
+ @Nonnull String name,
@Nonnull VersionSelector selector)
throws RepositoryException, CommitFailedException {
+ checkNotNull(name);
+ checkNotNull(destParent);
String primaryType = primaryTypeOf(src);
if (primaryType.equals(NT_FROZENNODE)) {
- restoreFrozen(src, dest, selector);
+ // replace with frozen state
+ destParent.removeChildNode(name);
+ restoreFrozen(src, destParent.child(name), selector);
} else if (primaryType.equals(NT_VERSIONEDCHILD)) {
- restoreVersionedChild(src, dest, selector);
+ // only perform chained restore if the node didn't exist
+ // before. see 15.7.5 and RestoreTest#testRestoreName
+ if (!destParent.hasChildNode(name)) {
+ restoreVersionedChild(src, destParent.child(name), selector);
+ }
} else {
- restoreNode(src, dest, selector);
+ // replace
+ destParent.removeChildNode(name);
+ restoreNode(src, destParent.child(name), selector);
}
}
/**
* Restore a nt:frozenNode.
*/
- private void restoreFrozen(NodeBuilder frozen,
- NodeBuilder dest,
- VersionSelector selector)
+ private void restoreFrozen(@Nonnull NodeBuilder frozen,
+ @Nonnull NodeBuilder dest,
+ @Nonnull VersionSelector selector)
throws RepositoryException, CommitFailedException {
// 15.7.2 Restoring Type and Identifier
- dest.setProperty(JCR_PRIMARYTYPE,
- frozen.getName(JCR_FROZENPRIMARYTYPE), Type.NAME);
- dest.setProperty(JCR_UUID,
- frozen.getProperty(JCR_FROZENUUID).getValue(Type.STRING),
- Type.STRING);
- if (frozen.hasProperty(JCR_FROZENMIXINTYPES)) {
- dest.setProperty(JCR_MIXINTYPES,
- frozen.getNames(JCR_FROZENMIXINTYPES), Type.NAMES);
- }
+ restoreFrozen(frozen, dest);
// 15.7.3 Restoring Properties
for (PropertyState p : frozen.getProperties()) {
if (BASIC_FROZEN_PROPERTIES.contains(p.getName())) {
@@ -265,13 +305,35 @@ class VersionableState {
}
/**
+ * Restores the basic frozen properties (jcr:primaryType, jcr:mixinTypes
+ * and jcr:uuid).
+ */
+ private void restoreFrozen(@Nonnull NodeBuilder frozen,
+ @Nonnull NodeBuilder dest) {
+ dest.setProperty(JCR_PRIMARYTYPE,
+ frozen.getName(JCR_FROZENPRIMARYTYPE), Type.NAME);
+ dest.setProperty(JCR_UUID,
+ frozen.getProperty(JCR_FROZENUUID).getValue(Type.STRING),
+ Type.STRING);
+ if (frozen.hasProperty(JCR_FROZENMIXINTYPES)) {
+ dest.setProperty(JCR_MIXINTYPES,
+ frozen.getNames(JCR_FROZENMIXINTYPES), Type.NAMES);
+ }
+ }
+
+ /**
* Restore a copied node.
*/
private void restoreNode(NodeBuilder src,
NodeBuilder dest,
VersionSelector selector)
throws RepositoryException, CommitFailedException {
- copyProperties(src, dest, OPVForceCopy.INSTANCE, false);
+ if (primaryTypeOf(src).equals(NT_FROZENNODE)) {
+ restoreFrozen(src, dest);
+ copyProperties(src, dest, OPVForceCopy.INSTANCE, true);
+ } else {
+ copyProperties(src, dest, OPVForceCopy.INSTANCE, false);
+ }
restoreChildren(src, dest, selector);
}
@@ -281,11 +343,14 @@ class VersionableState {
private void restoreVersionedChild(NodeBuilder versionedChild,
NodeBuilder dest,
VersionSelector selector)
- throws RepositoryException {
+ throws RepositoryException, CommitFailedException {
// 15.7.5 Chained Versions on Restore
- TODO.unimplemented().doNothing();
- // ...
- // restoreVersionable(dest, selector.select(history));
+ PropertyState id = versionedChild.getProperty(JCR_CHILDVERSIONHISTORY);
+ if (id == null) {
+ throw new RepositoryException("Mandatory property " +
+ JCR_CHILDVERSIONHISTORY + " is missing.");
+ }
+ vMgr.restore(id.getValue(Type.REFERENCE), selector, dest);
}
/**
@@ -299,10 +364,12 @@ class VersionableState {
for (String name : src.getChildNodeNames()) {
NodeBuilder srcChild = src.getChildNode(name);
int action = getOPV(dest, srcChild, name);
- if (action == COPY || action == VERSION) {
+ if (action == COPY) {
// replace on destination
dest.removeChildNode(name);
- restoreState(srcChild, dest.child(name), selector);
+ restoreNode(srcChild, dest.child(name), selector);
+ } else if (action == VERSION) {
+ restoreState(srcChild, dest, name, selector);
}
}
for (String name : dest.getChildNodeNames()) {
@@ -331,6 +398,7 @@ class VersionableState {
@Nonnull NodeBuilder version) {
checkNotNull(versionable).setProperty(JCR_ISCHECKEDOUT,
false, Type.BOOLEAN);
+ versionable.setProperty(JCR_VERSIONHISTORY, uuidFromNode(history));
versionable.setProperty(JCR_BASEVERSION,
uuidFromNode(version), Type.REFERENCE);
versionable.setProperty(JCR_PREDECESSORS,
@@ -380,18 +448,12 @@ class VersionableState {
if (ntMgr.isNodeType(new ReadOnlyTree(child.getNodeState()), MIX_VERSIONABLE)) {
// create frozen versionable child
versionedChild(child, dest.child(name));
- } else if (isReferenceable(child)) {
- createFrozen(child, dest.child(name));
} else {
// else copy
copy(child, dest.child(name));
}
} else if (opv == COPY) {
- if (isReferenceable(child)) {
- createFrozen(child, dest.child(name));
- } else {
- copy(child, dest.child(name));
- }
+ copy(child, dest.child(name));
}
}
}
@@ -405,14 +467,15 @@ class VersionableState {
private void copy(NodeBuilder src,
NodeBuilder dest)
throws RepositoryException, CommitFailedException {
- copyProperties(src, dest, OPVForceCopy.INSTANCE, false);
+ if (isReferenceable(src)) {
+ initFrozen(dest, src);
+ copyProperties(src, dest, OPVForceCopy.INSTANCE, true);
+ } else {
+ copyProperties(src, dest, OPVForceCopy.INSTANCE, false);
+ }
for (String name : src.getChildNodeNames()) {
NodeBuilder child = src.getChildNode(name);
- if (isReferenceable(child)) {
- createFrozen(child, dest.child(name));
- } else {
- copy(child, dest.child(name));
- }
+ copy(child, dest.child(name));
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/ImmutableRootTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/ImmutableRootTest.java?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/ImmutableRootTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/ImmutableRootTest.java Thu May 23 08:37:19 2013
@@ -86,13 +86,6 @@ public class ImmutableRootTest extends O
}
try {
- root.getQueryEngine();
- fail();
- } catch (UnsupportedOperationException e) {
- // success
- }
-
- try {
root.move("/x", "/b");
fail();
} catch (UnsupportedOperationException e) {
Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1485613&r1=1485612&r2=1485613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Thu May 23 08:37:19 2013
@@ -267,21 +267,8 @@
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrderJcr2_2
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrderJcr2_3
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrderJcr2_4
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreChild1
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreChild1Jcr2
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreChild1Jcr2_2
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreChild1Jcr2_3
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreChild1Jcr2_4
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreLabel
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreLabelJcr2
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreNameJcr2
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2Jcr2
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2Jcr2_2
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2Jcr2_3
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2Jcr2_4
org.apache.jackrabbit.test.api.version.WorkspaceRestoreTest
org.apache.jackrabbit.test.api.version.OnParentVersionComputeTest
org.apache.jackrabbit.test.api.version.OnParentVersionCopyTest