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 ba...@apache.org on 2015/07/27 17:25:56 UTC
svn commit: r1692897 - in /jackrabbit/oak/branches/1.2: ./
oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/
oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/
oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/s...
Author: baedke
Date: Mon Jul 27 15:25:55 2015
New Revision: 1692897
URL: http://svn.apache.org/r1692897
Log:
OAK-2619: Repeated upgrades
Merged c1691280.
Added:
jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/
- copied from r1691280, jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/
jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java (contents, props changed)
- copied, changed from r1691280, jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java
jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/
- copied from r1691280, jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/
jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/
- copied from r1691280, jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/
Modified:
jackrabbit/oak/branches/1.2/ (props changed)
jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopier.java (contents, props changed)
jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/GroupEditor.java
jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java
jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopierTest.java (contents, props changed)
jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/NodeStateTestUtils.java (contents, props changed)
Propchange: jackrabbit/oak/branches/1.2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Jul 27 15:25:55 2015
@@ -1,3 +1,3 @@
/jackrabbit/oak/branches/1.0:1665962
-/jackrabbit/oak/trunk:1672350,1672468,1672537,1672603,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678023,1678095-1678096,1678124,1678171,1678173,1678211,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680170,1680172,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1682042,1682218,1682235,1682437,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376,1684442,1684561,1684570,1684601,1684618,1684820,1684868,1685023
,1685075,1685370,1685552,1685589-1685590,1685840,1685964,1685977,1685989,1685999,1686023,1686032,1686097,1686162,1686229,1686234,1686253,1686414,1686780,1686854,1686857,1686971,1687053-1687055,1687175,1687196,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688179,1688349,1688421,1688436,1688453,1688616,1688622,1688634,1688636,1688817,1689003-1689004,1689008,1689577,1689581,1689623,1689810,1689828,1689831,1689833,1689903,1690017,1690043,1690047,1690057,1690247,1690249,1690634-1690637,1690650,1690669,1690674,1690885,1690941,1691139,1691151,1691159,1691167,1691183,1691188,1691210,1691307,1691331-1691333,1691345,1691384-1691385,1691401,1691509,1692133-1692134,1692274,1692363,1692478
+/jackrabbit/oak/trunk:1672350,1672468,1672537,1672603,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678023,1678095-1678096,1678124,1678171,1678173,1678211,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680170,1680172,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1682042,1682218,1682235,1682437,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376,1684442,1684561,1684570,1684601,1684618,1684820,1684868,1685023
,1685075,1685370,1685552,1685589-1685590,1685840,1685964,1685977,1685989,1685999,1686023,1686032,1686097,1686162,1686229,1686234,1686253,1686414,1686780,1686854,1686857,1686971,1687053-1687055,1687175,1687196,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688179,1688349,1688421,1688436,1688453,1688616,1688622,1688634,1688636,1688817,1689003-1689004,1689008,1689577,1689581,1689623,1689810,1689828,1689831,1689833,1689903,1690017,1690043,1690047,1690057,1690247,1690249,1690634-1690637,1690650,1690669,1690674,1690885,1690941,1691139,1691151,1691159,1691167,1691183,1691188,1691210,1691280,1691307,1691331-1691333,1691345,1691384-1691385,1691401,1691509,1692133-1692134,1692274,1692363,1692478
/jackrabbit/trunk:1345480
Modified: jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java?rev=1692897&r1=1692896&r2=1692897&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java (original)
+++ jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java Mon Jul 27 15:25:55 2015
@@ -17,11 +17,11 @@
package org.apache.jackrabbit.oak.upgrade;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableSet.of;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static com.google.common.collect.Maps.newHashMap;
import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
-import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONSTORAGE;
import static org.apache.jackrabbit.core.RepositoryImpl.ACTIVITIES_NODE_ID;
import static org.apache.jackrabbit.core.RepositoryImpl.ROOT_NODE_ID;
import static org.apache.jackrabbit.core.RepositoryImpl.VERSION_STORAGE_NODE_ID;
@@ -33,6 +33,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -73,6 +74,7 @@ import org.apache.jackrabbit.oak.api.Com
import org.apache.jackrabbit.oak.api.PropertyState;
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.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.index.CompositeIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
@@ -85,7 +87,6 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
import org.apache.jackrabbit.oak.plugins.nodetype.write.ReadWriteNodeTypeManager;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeBuilder;
import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
@@ -107,6 +108,7 @@ import org.apache.jackrabbit.oak.spi.sta
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.upgrade.nodestate.NodeStateCopier;
import org.apache.jackrabbit.oak.upgrade.security.GroupEditorProvider;
import org.apache.jackrabbit.oak.upgrade.security.RestrictionEditorProvider;
import org.apache.jackrabbit.spi.Name;
@@ -506,6 +508,12 @@ public class RepositoryUpgrade {
logger.debug("Registering custom non-aggregated privileges");
for (Privilege privilege : registry.getRegisteredPrivileges()) {
String privilegeName = privilege.getName();
+
+ if (hasPrivilege(pMgr, privilegeName)) {
+ logger.debug("Privilege {} already exists", privilegeName);
+ continue;
+ }
+
if (PrivilegeBits.BUILT_IN.containsKey(privilegeName) || JCR_ALL.equals(privilegeName)) {
// Ignore built in privileges as those have been installed by the PrivilegesInitializer already
logger.debug("Built-in privilege -> ignore.");
@@ -557,6 +565,16 @@ public class RepositoryUpgrade {
}
}
+ private boolean hasPrivilege(PrivilegeManager pMgr, String privilegeName) throws RepositoryException {
+ final Privilege[] registeredPrivileges = pMgr.getRegisteredPrivileges();
+ for (Privilege registeredPrivilege : registeredPrivileges) {
+ if (registeredPrivilege.getName().equals(privilegeName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static boolean allAggregatesRegistered(PrivilegeManager privilegeManager, List<String> aggrNames) {
for (String name : aggrNames) {
try {
@@ -694,16 +712,18 @@ public class RepositoryUpgrade {
NodeBuilder system = builder.child(JCR_SYSTEM);
logger.info("Copying version histories");
- copyState(system, JCR_VERSIONSTORAGE, new JackrabbitNodeState(
+ copyState(system, "/jcr:system/jcr:versionStorage", new JackrabbitNodeState(
pm, root, uriToPrefix, VERSION_STORAGE_NODE_ID,
"/jcr:system/jcr:versionStorage",
- workspaceName, versionablePaths, copyBinariesByReference, skipOnError));
+ workspaceName, versionablePaths, copyBinariesByReference, skipOnError),
+ true);
logger.info("Copying activities");
- copyState(system, "jcr:activities", new JackrabbitNodeState(
+ copyState(system, "/jcr:system/jcr:activities", new JackrabbitNodeState(
pm, root, uriToPrefix, ACTIVITIES_NODE_ID,
"/jcr:system/jcr:activities",
- workspaceName, versionablePaths, copyBinariesByReference, skipOnError));
+ workspaceName, versionablePaths, copyBinariesByReference, skipOnError),
+ true);
}
private String copyWorkspace(
@@ -725,40 +745,30 @@ public class RepositoryUpgrade {
for (ChildNodeEntry child : state.getChildNodeEntries()) {
String childName = child.getName();
if (!JCR_SYSTEM.equals(childName)) {
- logger.info("Copying subtree /{}", childName);
- copyState(builder, childName, child.getNodeState());
+ final String path = PathUtils.concat("/", childName);
+ logger.info("Copying subtree {}", path);
+ copyState(builder, path, child.getNodeState(), false);
}
}
return workspaceName;
}
- private void copyState(NodeBuilder parent, String name, NodeState state) {
- if (parent instanceof SegmentNodeBuilder) {
- parent.setChildNode(name, state);
- } else {
- setChildNode(parent, name, state);
- }
- }
-
- /**
- * NodeState are copied by value by recursing down the complete tree
- * This is a temporary approach for OAK-1760 for 1.0 branch.
- */
- private void setChildNode(NodeBuilder parent, String name, NodeState state) {
+ private void copyState(NodeBuilder targetParent, String path, NodeState source, boolean merge) {
+ final String name = PathUtils.getName(path);
// OAK-1589: maximum supported length of name for DocumentNodeStore
// is 150 bytes. Skip the sub tree if the the name is too long
if (name.length() > 37 && name.getBytes(Charsets.UTF_8).length > 150) {
- logger.warn("Node name too long. Skipping {}", state);
+ logger.warn("Node name too long. Skipping {}", source);
return;
}
- NodeBuilder builder = parent.setChildNode(name);
- for (PropertyState property : state.getProperties()) {
- builder.setProperty(property);
- }
- for (ChildNodeEntry child : state.getChildNodeEntries()) {
- setChildNode(builder, child.getName(), child.getNodeState());
- }
+ NodeBuilder target = targetParent.child(name);
+ NodeStateCopier.copyNodeState(
+ source,
+ target,
+ path,
+ merge ? of(path) : Collections.<String>emptySet()
+ );
}
private static class LoggingCompositeHook implements CommitHook {
Modified: jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopier.java?rev=1692897&r1=1691280&r2=1692897&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopier.java (original)
+++ jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopier.java Mon Jul 27 15:25:55 2015
@@ -1,173 +1,173 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.oak.upgrade.nodestate;
-
-import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
-import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.annotation.Nonnull;
-import java.util.Collections;
-import java.util.Set;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * The NodeStateCopier and NodeStateCopier.Builder classes allow
- * recursively copying a NodeState to a NodeBuilder.
- * <br>
- * The copy algorithm is optimized for copying nodes between two
- * different NodeStore instances, i.e. where comparing NodeStates
- * is imprecise and/or expensive.
- * <br>
- * The algorithm does a post-order traversal. I.e. it copies
- * changed leaf-nodes first.
- * <br>
- * The work for a traversal without any differences between
- * {@code source} and {@code target} is equivalent to the single
- * execution of a naive equals implementation.
- */
-public class NodeStateCopier {
-
- private static final Logger LOG = LoggerFactory.getLogger(NodeStateCopier.class);
-
-
- private NodeStateCopier() {
- // no instances
- }
-
- /**
- * Shorthand method to copy one NodeStore to another. The changes in the
- * target NodeStore are automatically persisted.
- *
- * @param source NodeStore to copy from.
- * @param target NodeStore to copy to.
- * @throws CommitFailedException
- */
- public static boolean copyNodeStore(@Nonnull final NodeStore source, @Nonnull final NodeStore target)
- throws CommitFailedException {
- final NodeBuilder builder = checkNotNull(target).getRoot().builder();
- final boolean hasChanges = copyNodeState(checkNotNull(source).getRoot(), builder, "/", Collections.<String>emptySet());
- if (hasChanges) {
- source.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
- }
- return hasChanges;
- }
-
- /**
- * Copies all changed properties from the source NodeState to the target
- * NodeBuilder instance.
- *
- * @param source The NodeState to copy from.
- * @param target The NodeBuilder to copy to.
- * @return Whether changes were made or not.
- */
- public static boolean copyProperties(NodeState source, NodeBuilder target) {
- boolean hasChanges = false;
-
- // remove removed properties
- for (final PropertyState property : target.getProperties()) {
- final String name = property.getName();
- if (!source.hasProperty(name)) {
- target.removeProperty(name);
- hasChanges = true;
- }
- }
-
- // add new properties and change changed properties
- for (PropertyState property : source.getProperties()) {
- if (!property.equals(target.getProperty(property.getName()))) {
- target.setProperty(property);
- hasChanges = true;
- }
- }
- return hasChanges;
- }
-
- /**
- * Recursively copies the source NodeState to the target NodeBuilder.
- * <br>
- * Nodes that exist in the {@code target} but not in the {@code source}
- * are removed, unless they are descendants of one of the {@code mergePaths}.
- * This is determined by checking if the {@code currentPath} is a descendant
- * of any of the {@code mergePaths}.
- * <br>
- * <b>Note:</b> changes are not persisted.
- *
- * @param source NodeState to copy from
- * @param target NodeBuilder to copy to
- * @param currentPath The path of both the source and target arguments.
- * @param mergePaths A Set of paths under which existing nodes should be
- * preserved, even if the do not exist in the source.
- * @return An indication of whether there were changes or not.
- */
- public static boolean copyNodeState(@Nonnull final NodeState source, @Nonnull final NodeBuilder target,
- @Nonnull final String currentPath, @Nonnull final Set<String> mergePaths) {
-
-
- boolean hasChanges = false;
-
- // delete deleted children
- for (final String childName : target.getChildNodeNames()) {
- if (!source.hasChildNode(childName) && !isMerge(PathUtils.concat(currentPath, childName), mergePaths)) {
- target.setChildNode(childName, EmptyNodeState.MISSING_NODE);
- hasChanges = true;
- }
- }
-
- for (ChildNodeEntry child : source.getChildNodeEntries()) {
- final String childName = child.getName();
- final NodeState childSource = child.getNodeState();
- if (!target.hasChildNode(childName)) {
- // add new children
- target.setChildNode(childName, childSource);
- hasChanges = true;
- } else {
- // recurse into existing children
- final NodeBuilder childTarget = target.getChildNode(childName);
- final String childPath = PathUtils.concat(currentPath, childName);
- hasChanges = copyNodeState(childSource, childTarget, childPath, mergePaths) || hasChanges;
- }
- }
-
- hasChanges = copyProperties(source, target) || hasChanges;
-
- if (hasChanges) {
- LOG.trace("Node {} has changes", target);
- }
-
- return hasChanges;
- }
-
- private static boolean isMerge(String path, Set<String> mergePaths) {
- for (String mergePath : mergePaths) {
- if (PathUtils.isAncestor(mergePath, path) || mergePath.equals(path)) {
- return true;
- }
- }
- return false;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.upgrade.nodestate;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.Collections;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * The NodeStateCopier and NodeStateCopier.Builder classes allow
+ * recursively copying a NodeState to a NodeBuilder.
+ * <br>
+ * The copy algorithm is optimized for copying nodes between two
+ * different NodeStore instances, i.e. where comparing NodeStates
+ * is imprecise and/or expensive.
+ * <br>
+ * The algorithm does a post-order traversal. I.e. it copies
+ * changed leaf-nodes first.
+ * <br>
+ * The work for a traversal without any differences between
+ * {@code source} and {@code target} is equivalent to the single
+ * execution of a naive equals implementation.
+ */
+public class NodeStateCopier {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodeStateCopier.class);
+
+
+ private NodeStateCopier() {
+ // no instances
+ }
+
+ /**
+ * Shorthand method to copy one NodeStore to another. The changes in the
+ * target NodeStore are automatically persisted.
+ *
+ * @param source NodeStore to copy from.
+ * @param target NodeStore to copy to.
+ * @throws CommitFailedException
+ */
+ public static boolean copyNodeStore(@Nonnull final NodeStore source, @Nonnull final NodeStore target)
+ throws CommitFailedException {
+ final NodeBuilder builder = checkNotNull(target).getRoot().builder();
+ final boolean hasChanges = copyNodeState(checkNotNull(source).getRoot(), builder, "/", Collections.<String>emptySet());
+ if (hasChanges) {
+ source.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ }
+ return hasChanges;
+ }
+
+ /**
+ * Copies all changed properties from the source NodeState to the target
+ * NodeBuilder instance.
+ *
+ * @param source The NodeState to copy from.
+ * @param target The NodeBuilder to copy to.
+ * @return Whether changes were made or not.
+ */
+ public static boolean copyProperties(NodeState source, NodeBuilder target) {
+ boolean hasChanges = false;
+
+ // remove removed properties
+ for (final PropertyState property : target.getProperties()) {
+ final String name = property.getName();
+ if (!source.hasProperty(name)) {
+ target.removeProperty(name);
+ hasChanges = true;
+ }
+ }
+
+ // add new properties and change changed properties
+ for (PropertyState property : source.getProperties()) {
+ if (!property.equals(target.getProperty(property.getName()))) {
+ target.setProperty(property);
+ hasChanges = true;
+ }
+ }
+ return hasChanges;
+ }
+
+ /**
+ * Recursively copies the source NodeState to the target NodeBuilder.
+ * <br>
+ * Nodes that exist in the {@code target} but not in the {@code source}
+ * are removed, unless they are descendants of one of the {@code mergePaths}.
+ * This is determined by checking if the {@code currentPath} is a descendant
+ * of any of the {@code mergePaths}.
+ * <br>
+ * <b>Note:</b> changes are not persisted.
+ *
+ * @param source NodeState to copy from
+ * @param target NodeBuilder to copy to
+ * @param currentPath The path of both the source and target arguments.
+ * @param mergePaths A Set of paths under which existing nodes should be
+ * preserved, even if the do not exist in the source.
+ * @return An indication of whether there were changes or not.
+ */
+ public static boolean copyNodeState(@Nonnull final NodeState source, @Nonnull final NodeBuilder target,
+ @Nonnull final String currentPath, @Nonnull final Set<String> mergePaths) {
+
+
+ boolean hasChanges = false;
+
+ // delete deleted children
+ for (final String childName : target.getChildNodeNames()) {
+ if (!source.hasChildNode(childName) && !isMerge(PathUtils.concat(currentPath, childName), mergePaths)) {
+ target.setChildNode(childName, EmptyNodeState.MISSING_NODE);
+ hasChanges = true;
+ }
+ }
+
+ for (ChildNodeEntry child : source.getChildNodeEntries()) {
+ final String childName = child.getName();
+ final NodeState childSource = child.getNodeState();
+ if (!target.hasChildNode(childName)) {
+ // add new children
+ target.setChildNode(childName, childSource);
+ hasChanges = true;
+ } else {
+ // recurse into existing children
+ final NodeBuilder childTarget = target.getChildNode(childName);
+ final String childPath = PathUtils.concat(currentPath, childName);
+ hasChanges = copyNodeState(childSource, childTarget, childPath, mergePaths) || hasChanges;
+ }
+ }
+
+ hasChanges = copyProperties(source, target) || hasChanges;
+
+ if (hasChanges) {
+ LOG.trace("Node {} has changes", target);
+ }
+
+ return hasChanges;
+ }
+
+ private static boolean isMerge(String path, Set<String> mergePaths) {
+ for (String mergePath : mergePaths) {
+ if (PathUtils.isAncestor(mergePath, path) || mergePath.equals(path)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Propchange: jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopier.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/GroupEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/GroupEditor.java?rev=1692897&r1=1692896&r2=1692897&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/GroupEditor.java (original)
+++ jackrabbit/oak/branches/1.2/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/GroupEditor.java Mon Jul 27 15:25:55 2015
@@ -108,7 +108,7 @@ class GroupEditor extends DefaultEditor
@Override
public Editor childNodeChanged(String name, NodeState before, NodeState after) {
- throw new IllegalStateException("changed node during upgrade copy not expected: " + state.path + "/" + name);
+ return null;
}
@Override
Modified: jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java?rev=1692897&r1=1692896&r2=1692897&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java (original)
+++ jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java Mon Jul 27 15:25:55 2015
@@ -19,12 +19,14 @@
package org.apache.jackrabbit.oak.upgrade;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.jcr.Credentials;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
+import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.apache.commons.io.FileUtils;
@@ -40,63 +42,118 @@ import org.apache.jackrabbit.oak.stats.C
import org.junit.Before;
import org.junit.BeforeClass;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
public abstract class AbstractRepositoryUpgradeTest {
protected static final Credentials CREDENTIALS = new SimpleCredentials("admin", "admin".toCharArray());
- private static Repository targetRepository;
+ private static NodeStore targetNodeStore;
+
+ private static File testDirectory;
@BeforeClass
- public static void init() {
+ public static void init() throws InterruptedException {
// ensure that we create a new repository for the next test
- targetRepository = null;
+ targetNodeStore = null;
+ testDirectory = createTestDirectory();
+ }
+
+ protected static File createTestDirectory() throws InterruptedException {
+ final File dir = new File("target", "upgrade-" + Clock.SIMPLE.getTimeIncreasing());
+ FileUtils.deleteQuietly(dir);
+ return dir;
+ }
+
+ protected NodeStore createTargetNodeStore() {
+ return new SegmentNodeStore();
}
@Before
public synchronized void upgradeRepository() throws Exception {
- if (targetRepository == null) {
- File directory = new File(
- "target", "upgrade-" + Clock.SIMPLE.getTimeIncreasing());
- FileUtils.deleteQuietly(directory);
-
+ if (targetNodeStore == null) {
+ File directory = getTestDirectory();
File source = new File(directory, "source");
source.mkdirs();
-
- InputStream repoConfig = getRepositoryConfig();
- RepositoryConfig config;
- if (repoConfig == null) {
- config = RepositoryConfig.install(source);
- } else {
- OutputStream out = FileUtils.openOutputStream(new File(source, "repository.xml"));
- IOUtils.copy(repoConfig, out);
- out.close();
- repoConfig.close();
- config = RepositoryConfig.create(source);
- }
- RepositoryImpl repository = RepositoryImpl.create(config);
+ RepositoryImpl repository = createSourceRepository(source);
try {
createSourceContent(repository);
} finally {
repository.shutdown();
}
- NodeStore target = new SegmentNodeStore();
- RepositoryUpgrade.copy(source, target);
- targetRepository = new Jcr(new Oak(target)).createRepository();
+ final NodeStore target = getTargetNodeStore();
+ doUpgradeRepository(source, target);
+ targetNodeStore = target;
}
}
- public InputStream getRepositoryConfig() {
+ protected synchronized NodeStore getTargetNodeStore() {
+ if (targetNodeStore == null) {
+ targetNodeStore = createTargetNodeStore();
+ }
+ return targetNodeStore;
+ }
+
+ protected static File getTestDirectory() {
+ return testDirectory;
+ }
+
+ protected RepositoryImpl createSourceRepository(File repositoryHome) throws IOException, RepositoryException {
+ InputStream repoConfig = getRepositoryConfig();
+ RepositoryConfig config;
+ if (repoConfig == null) {
+ config = RepositoryConfig.install(repositoryHome);
+ } else {
+ OutputStream out = FileUtils.openOutputStream(new File(repositoryHome, "repository.xml"));
+ IOUtils.copy(repoConfig, out);
+ out.close();
+ repoConfig.close();
+ config = RepositoryConfig.create(repositoryHome);
+ }
+ return RepositoryImpl.create(config);
+ }
+
+
+ protected void doUpgradeRepository(File source, NodeStore target)throws RepositoryException{
+ RepositoryUpgrade.copy(source, target);
+ }
+
+ public InputStream getRepositoryConfig(){
return null;
}
- public Repository getTargetRepository() {
- return targetRepository;
+ public Repository getTargetRepository(){
+ return new Jcr(new Oak(targetNodeStore)).createRepository();
}
- public JackrabbitSession createAdminSession() throws RepositoryException {
- return (JackrabbitSession) getTargetRepository().login(CREDENTIALS);
+ public JackrabbitSession createAdminSession()throws RepositoryException{
+ return(JackrabbitSession)getTargetRepository().login(CREDENTIALS);
}
protected abstract void createSourceContent(Repository repository) throws Exception;
+ protected void assertExisting(final String... paths) throws RepositoryException {
+ final Session session = createAdminSession();
+ try {
+ for (final String path : paths) {
+ final String relPath = path.substring(1);
+ assertTrue("node " + path + " should exist", session.getRootNode().hasNode(relPath));
+ }
+ } finally {
+ session.logout();
+ }
+ }
+
+ protected void assertMissing(final String... paths) throws RepositoryException {
+ final Session session = createAdminSession();
+ try {
+ for (final String path : paths) {
+ final String relPath = path.substring(1);
+ assertFalse("node " + path + " should not exist", session.getRootNode().hasNode(relPath));
+ }
+ } finally {
+ session.logout();
+ }
+ }
}
Copied: jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java (from r1691280, jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java?p2=jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java&p1=jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java&r1=1691280&r2=1692897&rev=1692897&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java (original)
+++ jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java Mon Jul 27 15:25:55 2015
@@ -1,221 +1,221 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.jackrabbit.oak.upgrade;
-
-import org.apache.jackrabbit.api.JackrabbitWorkspace;
-import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
-import org.apache.jackrabbit.commons.JcrUtils;
-import org.apache.jackrabbit.core.RepositoryContext;
-import org.apache.jackrabbit.core.RepositoryImpl;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
-import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
-import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeStore;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import javax.annotation.Nonnull;
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Test case to simulate an incremental upgrade, where a source repository is
- * copied to target initially. Then some modifications are made in the source
- * repository and these are (incrementally) copied to the target repository.
- * <br>
- * The expectation is that in the end the state in the target repository is
- * identical to the state in the source repository, with the exception of any
- * initial content that the upgrade tool created.
- */
-public class RepeatedRepositoryUpgradeTest extends AbstractRepositoryUpgradeTest {
-
- private static boolean upgradeComplete;
- private static FileStore fileStore;
-
- @Override
- protected NodeStore createTargetNodeStore() {
- return new SegmentNodeStore(fileStore);
- }
-
- @BeforeClass
- public static void initialize() {
- final File dir = new File(getTestDirectory(), "segments");
- dir.mkdirs();
- try {
- fileStore = FileStore.newFileStore(dir).withMaxFileSize(128).create();
- upgradeComplete = false;
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- @AfterClass
- public static void cleanup() {
- fileStore.close();
- fileStore = null;
- }
-
- @Before
- public synchronized void upgradeRepository() throws Exception {
- if (!upgradeComplete) {
- final File sourceDir = new File(getTestDirectory(), "jackrabbit2");
-
- sourceDir.mkdirs();
-
- RepositoryImpl source = createSourceRepository(sourceDir);
-
- try {
- createSourceContent(source);
- } finally {
- source.shutdown();
- }
-
- final NodeStore target = getTargetNodeStore();
- doUpgradeRepository(sourceDir, target);
- fileStore.flush();
-
- // re-create source repo
- source = createSourceRepository(sourceDir);
- try {
- modifySourceContent(source);
- } finally {
- source.shutdown();
- }
-
- doUpgradeRepository(sourceDir, target);
- fileStore.flush();
-
- upgradeComplete = true;
- }
- }
-
- @Override
- protected void doUpgradeRepository(File source, NodeStore target) throws RepositoryException {
- final RepositoryConfig config = RepositoryConfig.create(source);
- final RepositoryContext context = RepositoryContext.create(config);
- try {
- final RepositoryUpgrade repositoryUpgrade = new RepositoryUpgrade(context, target);
- repositoryUpgrade.copy(new RepositoryInitializer() {
- @Override
- public void initialize(@Nonnull NodeBuilder builder) {
- builder.child("foo").child("bar");
- }
- });
- } finally {
- context.getRepository().shutdown();
- }
- }
-
- @Override
- protected void createSourceContent(Repository repository) throws RepositoryException {
- Session session = null;
- try {
- session = repository.login(CREDENTIALS);
-
- registerCustomPrivileges(session);
-
- JcrUtils.getOrCreateByPath("/content/child1/grandchild1", "nt:unstructured", session);
- JcrUtils.getOrCreateByPath("/content/child1/grandchild2", "nt:unstructured", session);
- JcrUtils.getOrCreateByPath("/content/child1/grandchild3", "nt:unstructured", session);
- JcrUtils.getOrCreateByPath("/content/child2/grandchild1", "nt:unstructured", session);
- JcrUtils.getOrCreateByPath("/content/child2/grandchild2", "nt:unstructured", session);
-
- session.save();
- } finally {
- if (session != null && session.isLive()) {
- session.logout();
- }
- }
- }
-
- private void modifySourceContent(Repository repository) throws RepositoryException {
- Session session = null;
- try {
- session = repository.login(CREDENTIALS);
-
- JcrUtils.getOrCreateByPath("/content/child2/grandchild3", "nt:unstructured", session);
- JcrUtils.getOrCreateByPath("/content/child3", "nt:unstructured", session);
-
- final Node child1 = JcrUtils.getOrCreateByPath("/content/child1", "nt:unstructured", session);
- child1.remove();
-
- session.save();
- } finally {
- if (session != null && session.isLive()) {
- session.logout();
- }
- }
- }
-
- private void registerCustomPrivileges(Session session) throws RepositoryException {
- final JackrabbitWorkspace workspace = (JackrabbitWorkspace) session.getWorkspace();
-
- final NamespaceRegistry registry = workspace.getNamespaceRegistry();
- registry.registerNamespace("test", "http://www.example.org/");
-
- final PrivilegeManager privilegeManager = workspace.getPrivilegeManager();
- privilegeManager.registerPrivilege("test:privilege", false, null);
- privilegeManager.registerPrivilege(
- "test:aggregate", false, new String[]{"jcr:read", "test:privilege"});
- }
-
- @Test
- public void shouldReflectSourceAfterModifications() throws Exception {
-
- assertExisting(
- "/",
- "/content",
- "/content/child2",
- "/content/child2/grandchild1",
- "/content/child2/grandchild2",
- "/content/child2/grandchild3",
- "/content/child3"
- );
-
- assertMissing(
- "/content/child1"
- );
- }
-
- @Test
- public void shouldContainCustomInitializerContent() throws Exception {
- assertExisting(
- "/foo",
- "/foo/bar"
- );
- }
-
- @Test
- public void shouldContainUpgradeInitializedContent() throws Exception {
- assertExisting(
- "/rep:security",
- "/oak:index"
- );
- }
-
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.upgrade;
+
+import org.apache.jackrabbit.api.JackrabbitWorkspace;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.annotation.Nonnull;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Test case to simulate an incremental upgrade, where a source repository is
+ * copied to target initially. Then some modifications are made in the source
+ * repository and these are (incrementally) copied to the target repository.
+ * <br>
+ * The expectation is that in the end the state in the target repository is
+ * identical to the state in the source repository, with the exception of any
+ * initial content that the upgrade tool created.
+ */
+public class RepeatedRepositoryUpgradeTest extends AbstractRepositoryUpgradeTest {
+
+ private static boolean upgradeComplete;
+ private static FileStore fileStore;
+
+ @Override
+ protected NodeStore createTargetNodeStore() {
+ return new SegmentNodeStore(fileStore);
+ }
+
+ @BeforeClass
+ public static void initialize() {
+ final File dir = new File(getTestDirectory(), "segments");
+ dir.mkdirs();
+ try {
+ fileStore = FileStore.newFileStore(dir).withMaxFileSize(128).create();
+ upgradeComplete = false;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @AfterClass
+ public static void cleanup() {
+ fileStore.close();
+ fileStore = null;
+ }
+
+ @Before
+ public synchronized void upgradeRepository() throws Exception {
+ if (!upgradeComplete) {
+ final File sourceDir = new File(getTestDirectory(), "jackrabbit2");
+
+ sourceDir.mkdirs();
+
+ RepositoryImpl source = createSourceRepository(sourceDir);
+
+ try {
+ createSourceContent(source);
+ } finally {
+ source.shutdown();
+ }
+
+ final NodeStore target = getTargetNodeStore();
+ doUpgradeRepository(sourceDir, target);
+ fileStore.flush();
+
+ // re-create source repo
+ source = createSourceRepository(sourceDir);
+ try {
+ modifySourceContent(source);
+ } finally {
+ source.shutdown();
+ }
+
+ doUpgradeRepository(sourceDir, target);
+ fileStore.flush();
+
+ upgradeComplete = true;
+ }
+ }
+
+ @Override
+ protected void doUpgradeRepository(File source, NodeStore target) throws RepositoryException {
+ final RepositoryConfig config = RepositoryConfig.create(source);
+ final RepositoryContext context = RepositoryContext.create(config);
+ try {
+ final RepositoryUpgrade repositoryUpgrade = new RepositoryUpgrade(context, target);
+ repositoryUpgrade.copy(new RepositoryInitializer() {
+ @Override
+ public void initialize(@Nonnull NodeBuilder builder) {
+ builder.child("foo").child("bar");
+ }
+ });
+ } finally {
+ context.getRepository().shutdown();
+ }
+ }
+
+ @Override
+ protected void createSourceContent(Repository repository) throws RepositoryException {
+ Session session = null;
+ try {
+ session = repository.login(CREDENTIALS);
+
+ registerCustomPrivileges(session);
+
+ JcrUtils.getOrCreateByPath("/content/child1/grandchild1", "nt:unstructured", session);
+ JcrUtils.getOrCreateByPath("/content/child1/grandchild2", "nt:unstructured", session);
+ JcrUtils.getOrCreateByPath("/content/child1/grandchild3", "nt:unstructured", session);
+ JcrUtils.getOrCreateByPath("/content/child2/grandchild1", "nt:unstructured", session);
+ JcrUtils.getOrCreateByPath("/content/child2/grandchild2", "nt:unstructured", session);
+
+ session.save();
+ } finally {
+ if (session != null && session.isLive()) {
+ session.logout();
+ }
+ }
+ }
+
+ private void modifySourceContent(Repository repository) throws RepositoryException {
+ Session session = null;
+ try {
+ session = repository.login(CREDENTIALS);
+
+ JcrUtils.getOrCreateByPath("/content/child2/grandchild3", "nt:unstructured", session);
+ JcrUtils.getOrCreateByPath("/content/child3", "nt:unstructured", session);
+
+ final Node child1 = JcrUtils.getOrCreateByPath("/content/child1", "nt:unstructured", session);
+ child1.remove();
+
+ session.save();
+ } finally {
+ if (session != null && session.isLive()) {
+ session.logout();
+ }
+ }
+ }
+
+ private void registerCustomPrivileges(Session session) throws RepositoryException {
+ final JackrabbitWorkspace workspace = (JackrabbitWorkspace) session.getWorkspace();
+
+ final NamespaceRegistry registry = workspace.getNamespaceRegistry();
+ registry.registerNamespace("test", "http://www.example.org/");
+
+ final PrivilegeManager privilegeManager = workspace.getPrivilegeManager();
+ privilegeManager.registerPrivilege("test:privilege", false, null);
+ privilegeManager.registerPrivilege(
+ "test:aggregate", false, new String[]{"jcr:read", "test:privilege"});
+ }
+
+ @Test
+ public void shouldReflectSourceAfterModifications() throws Exception {
+
+ assertExisting(
+ "/",
+ "/content",
+ "/content/child2",
+ "/content/child2/grandchild1",
+ "/content/child2/grandchild2",
+ "/content/child2/grandchild3",
+ "/content/child3"
+ );
+
+ assertMissing(
+ "/content/child1"
+ );
+ }
+
+ @Test
+ public void shouldContainCustomInitializerContent() throws Exception {
+ assertExisting(
+ "/foo",
+ "/foo/bar"
+ );
+ }
+
+ @Test
+ public void shouldContainUpgradeInitializedContent() throws Exception {
+ assertExisting(
+ "/rep:security",
+ "/oak:index"
+ );
+ }
+
}
\ No newline at end of file
Propchange: jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopierTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopierTest.java?rev=1692897&r1=1691280&r2=1692897&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopierTest.java (original)
+++ jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopierTest.java Mon Jul 27 15:25:55 2015
@@ -1,183 +1,183 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.jackrabbit.oak.upgrade.nodestate;
-
-import com.google.common.collect.ImmutableSet;
-import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStore;
-import org.junit.Test;
-
-import static com.google.common.collect.ImmutableSet.of;
-import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
-import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.commit;
-import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.create;
-import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.createNodeStoreWithContent;
-import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.expectDifference;
-
-public class NodeStateCopierTest {
-
- private final PropertyState primaryType =
- createProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
-
- @Test
- public void shouldMergeIdenticalContent() throws CommitFailedException {
- final NodeStore source = createPrefilledNodeStore();
- final NodeStore target = createPrefilledNodeStore();
-
- final NodeState before = target.getRoot();
- NodeStateCopier.copyNodeStore(source, target);
- final NodeState after = target.getRoot();
-
- expectDifference().strict().verify(before, after);
- expectDifference().strict().verify(source.getRoot(), after);
- }
-
- private NodeStore createPrefilledNodeStore() throws CommitFailedException {
- final NodeStore store = createNodeStoreWithContent();
- final NodeBuilder builder = store.getRoot().builder();
- create(builder, "/excluded");
- create(builder, "/a", primaryType, createProperty("name", "a"));
- create(builder, "/a/b", primaryType, createProperty("name", "b"));
- create(builder, "/a/b/excluded");
- create(builder, "/a/b/c", primaryType, createProperty("name", "c"));
- create(builder, "/a/b/c/d", primaryType);
- create(builder, "/a/b/c/e", primaryType);
- create(builder, "/a/b/c/f", primaryType);
- commit(store, builder);
- return store;
- }
-
- @Test
- public void shouldRespectMergePaths() throws CommitFailedException {
- final NodeStore source = createNodeStoreWithContent("/content/foo/en", "/content/bar/en");
- final NodeStore target = createNodeStoreWithContent("/content/foo/de");
-
- final NodeBuilder builder = target.getRoot().builder();
- NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/content"));
- commit(target, builder);
- final NodeState after = target.getRoot();
-
- expectDifference()
- .strict()
- .childNodeAdded("/content/foo/de")
- .childNodeChanged("/content", "/content/foo")
- .verify(source.getRoot(), after);
- }
-
-
- @Test
- public void shouldDeleteExistingNodes() throws CommitFailedException {
- final NodeStore source = createNodeStoreWithContent("/content/foo");
- final NodeStore target = createNodeStoreWithContent("/content/bar");
-
- final NodeState before = target.getRoot();
- final NodeBuilder builder = before.builder();
- NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", ImmutableSet.<String>of());
- commit(target, builder);
- final NodeState after = target.getRoot();
-
- expectDifference()
- .strict()
- .childNodeAdded("/content/foo")
- .childNodeChanged("/content")
- .childNodeDeleted("/content/bar")
- .verify(before, after);
- }
-
- @Test
- public void shouldDeleteExistingPropertyIfMissingInSource() throws CommitFailedException {
- final NodeStore source = createNodeStoreWithContent("/a");
- final NodeStore target = createNodeStoreWithContent();
- NodeBuilder builder = target.getRoot().builder();
- create(builder, "/a", primaryType);
- commit(target, builder);
-
- final NodeState before = target.getRoot();
- builder = before.builder();
- NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", ImmutableSet.<String>of());
- commit(target, builder);
- final NodeState after = target.getRoot();
-
- expectDifference()
- .strict()
- .propertyDeleted("/a/jcr:primaryType")
- .childNodeChanged("/a")
- .verify(before, after);
- }
-
- @Test
- public void shouldNotDeleteExistingNodesIfMerged() throws CommitFailedException {
- final NodeStore source = createNodeStoreWithContent("/content/foo");
- final NodeStore target = createNodeStoreWithContent("/content/bar");
-
- final NodeState before = target.getRoot();
- final NodeBuilder builder = before.builder();
- NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/content/bar"));
- commit(target, builder);
- final NodeState after = target.getRoot();
-
- expectDifference()
- .strict()
- .childNodeAdded("/content/foo")
- .childNodeChanged("/content")
- .verify(before, after);
- }
-
- @Test
- public void shouldNotDeleteExistingNodesIfDescendantsOfMerged() throws CommitFailedException {
- final NodeStore source = createNodeStoreWithContent("/content/foo");
- final NodeStore target = createNodeStoreWithContent("/content/bar");
-
- final NodeState before = target.getRoot();
- final NodeBuilder builder = before.builder();
- NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/content"));
- commit(target, builder);
- final NodeState after = target.getRoot();
-
- expectDifference()
- .strict()
- .childNodeAdded("/content/foo")
- .childNodeChanged("/content")
- .verify(before, after);
- }
-
- @Test
- public void shouldIgnoreNonMatchingMergePaths() throws CommitFailedException {
- final NodeStore source = createNodeStoreWithContent("/content/foo");
- final NodeStore target = createNodeStoreWithContent("/content/bar");
-
- final NodeState before = target.getRoot();
- final NodeBuilder builder = before.builder();
- NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/con"));
- commit(target, builder);
- final NodeState after = target.getRoot();
-
- expectDifference()
- .strict()
- .childNodeAdded("/content/foo")
- .childNodeChanged("/content")
- .childNodeDeleted("/content/bar")
- .verify(before, after);
- }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.upgrade.nodestate;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.junit.Test;
+
+import static com.google.common.collect.ImmutableSet.of;
+import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.commit;
+import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.create;
+import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.createNodeStoreWithContent;
+import static org.apache.jackrabbit.oak.upgrade.util.NodeStateTestUtils.expectDifference;
+
+public class NodeStateCopierTest {
+
+ private final PropertyState primaryType =
+ createProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+
+ @Test
+ public void shouldMergeIdenticalContent() throws CommitFailedException {
+ final NodeStore source = createPrefilledNodeStore();
+ final NodeStore target = createPrefilledNodeStore();
+
+ final NodeState before = target.getRoot();
+ NodeStateCopier.copyNodeStore(source, target);
+ final NodeState after = target.getRoot();
+
+ expectDifference().strict().verify(before, after);
+ expectDifference().strict().verify(source.getRoot(), after);
+ }
+
+ private NodeStore createPrefilledNodeStore() throws CommitFailedException {
+ final NodeStore store = createNodeStoreWithContent();
+ final NodeBuilder builder = store.getRoot().builder();
+ create(builder, "/excluded");
+ create(builder, "/a", primaryType, createProperty("name", "a"));
+ create(builder, "/a/b", primaryType, createProperty("name", "b"));
+ create(builder, "/a/b/excluded");
+ create(builder, "/a/b/c", primaryType, createProperty("name", "c"));
+ create(builder, "/a/b/c/d", primaryType);
+ create(builder, "/a/b/c/e", primaryType);
+ create(builder, "/a/b/c/f", primaryType);
+ commit(store, builder);
+ return store;
+ }
+
+ @Test
+ public void shouldRespectMergePaths() throws CommitFailedException {
+ final NodeStore source = createNodeStoreWithContent("/content/foo/en", "/content/bar/en");
+ final NodeStore target = createNodeStoreWithContent("/content/foo/de");
+
+ final NodeBuilder builder = target.getRoot().builder();
+ NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/content"));
+ commit(target, builder);
+ final NodeState after = target.getRoot();
+
+ expectDifference()
+ .strict()
+ .childNodeAdded("/content/foo/de")
+ .childNodeChanged("/content", "/content/foo")
+ .verify(source.getRoot(), after);
+ }
+
+
+ @Test
+ public void shouldDeleteExistingNodes() throws CommitFailedException {
+ final NodeStore source = createNodeStoreWithContent("/content/foo");
+ final NodeStore target = createNodeStoreWithContent("/content/bar");
+
+ final NodeState before = target.getRoot();
+ final NodeBuilder builder = before.builder();
+ NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", ImmutableSet.<String>of());
+ commit(target, builder);
+ final NodeState after = target.getRoot();
+
+ expectDifference()
+ .strict()
+ .childNodeAdded("/content/foo")
+ .childNodeChanged("/content")
+ .childNodeDeleted("/content/bar")
+ .verify(before, after);
+ }
+
+ @Test
+ public void shouldDeleteExistingPropertyIfMissingInSource() throws CommitFailedException {
+ final NodeStore source = createNodeStoreWithContent("/a");
+ final NodeStore target = createNodeStoreWithContent();
+ NodeBuilder builder = target.getRoot().builder();
+ create(builder, "/a", primaryType);
+ commit(target, builder);
+
+ final NodeState before = target.getRoot();
+ builder = before.builder();
+ NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", ImmutableSet.<String>of());
+ commit(target, builder);
+ final NodeState after = target.getRoot();
+
+ expectDifference()
+ .strict()
+ .propertyDeleted("/a/jcr:primaryType")
+ .childNodeChanged("/a")
+ .verify(before, after);
+ }
+
+ @Test
+ public void shouldNotDeleteExistingNodesIfMerged() throws CommitFailedException {
+ final NodeStore source = createNodeStoreWithContent("/content/foo");
+ final NodeStore target = createNodeStoreWithContent("/content/bar");
+
+ final NodeState before = target.getRoot();
+ final NodeBuilder builder = before.builder();
+ NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/content/bar"));
+ commit(target, builder);
+ final NodeState after = target.getRoot();
+
+ expectDifference()
+ .strict()
+ .childNodeAdded("/content/foo")
+ .childNodeChanged("/content")
+ .verify(before, after);
+ }
+
+ @Test
+ public void shouldNotDeleteExistingNodesIfDescendantsOfMerged() throws CommitFailedException {
+ final NodeStore source = createNodeStoreWithContent("/content/foo");
+ final NodeStore target = createNodeStoreWithContent("/content/bar");
+
+ final NodeState before = target.getRoot();
+ final NodeBuilder builder = before.builder();
+ NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/content"));
+ commit(target, builder);
+ final NodeState after = target.getRoot();
+
+ expectDifference()
+ .strict()
+ .childNodeAdded("/content/foo")
+ .childNodeChanged("/content")
+ .verify(before, after);
+ }
+
+ @Test
+ public void shouldIgnoreNonMatchingMergePaths() throws CommitFailedException {
+ final NodeStore source = createNodeStoreWithContent("/content/foo");
+ final NodeStore target = createNodeStoreWithContent("/content/bar");
+
+ final NodeState before = target.getRoot();
+ final NodeBuilder builder = before.builder();
+ NodeStateCopier.copyNodeState(source.getRoot(), builder, "/", of("/con"));
+ commit(target, builder);
+ final NodeState after = target.getRoot();
+
+ expectDifference()
+ .strict()
+ .childNodeAdded("/content/foo")
+ .childNodeChanged("/content")
+ .childNodeDeleted("/content/bar")
+ .verify(before, after);
+ }
+
+}
Propchange: jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopierTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/NodeStateTestUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/NodeStateTestUtils.java?rev=1692897&r1=1691280&r2=1692897&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/NodeStateTestUtils.java (original)
+++ jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/NodeStateTestUtils.java Mon Jul 27 15:25:55 2015
@@ -1,205 +1,205 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.jackrabbit.oak.upgrade.util;
-
-import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
-import org.apache.jackrabbit.oak.spi.commit.DefaultValidator;
-import org.apache.jackrabbit.oak.spi.commit.EditorDiff;
-import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
-import org.apache.jackrabbit.oak.spi.commit.Validator;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStore;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import static org.junit.Assert.assertEquals;
-
-public class NodeStateTestUtils {
-
- private NodeStateTestUtils() {
- // no instances
- }
-
- public static NodeStore createNodeStoreWithContent(String... paths) throws CommitFailedException {
- final SegmentNodeStore store = new SegmentNodeStore();
- final NodeBuilder builder = store.getRoot().builder();
- for (String path : paths) {
- create(builder, path);
- }
- commit(store, builder);
- return store;
- }
-
- public static void create(NodeBuilder rootBuilder, String path, PropertyState... properties) {
- final NodeBuilder builder = createOrGetBuilder(rootBuilder, path);
- for (PropertyState property : properties) {
- builder.setProperty(property);
- }
- }
-
- public static void commit(NodeStore store, NodeBuilder rootBuilder) throws CommitFailedException {
- store.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
- }
-
- public static NodeBuilder createOrGetBuilder(NodeBuilder builder, String path) {
- NodeBuilder current = builder;
- for (final String name : PathUtils.elements(path)) {
- current = current.child(name);
- }
- return current;
- }
-
- public static ExpectedDifference expectDifference() {
- return new ExpectedDifference();
- }
-
- public static class ExpectedDifference {
-
- private ExpectedDifference() {
- }
-
- private final Map<String, Set<String>> expected = new HashMap<String, Set<String>>();
-
- public void verify(NodeState before, NodeState after) {
- final Map<String, Set<String>> actual = TestValidator.compare(before, after);
- for (String type : expected.keySet()) {
- if (!actual.containsKey(type)) {
- actual.put(type, Collections.<String>emptySet());
- }
- assertEquals(type, expected.get(type), actual.get(type));
- }
- }
-
- public ExpectedDifference propertyAdded(String... paths) {
- return expect("propertyAdded", paths);
- }
-
- public ExpectedDifference propertyChanged(String... paths) {
- return expect("propertyChanged", paths);
- }
-
- public ExpectedDifference propertyDeleted(String... paths) {
- return expect("propertyDeleted", paths);
- }
-
- public ExpectedDifference childNodeAdded(String... paths) {
- return expect("childNodeAdded", paths);
- }
-
- public ExpectedDifference childNodeChanged(String... paths) {
- return expect("childNodeChanged", paths);
- }
-
- public ExpectedDifference childNodeDeleted(String... paths) {
- return expect("childNodeDeleted", paths);
- }
-
- public ExpectedDifference strict() {
- return this.propertyAdded()
- .propertyChanged()
- .propertyDeleted()
- .childNodeAdded()
- .childNodeChanged()
- .childNodeDeleted();
- }
-
- private ExpectedDifference expect(String type, String... paths) {
- if (!expected.containsKey(type)) {
- expected.put(type, new TreeSet<String>());
- }
- Collections.addAll(expected.get(type), paths);
- return this;
- }
- }
-
- private static class TestValidator extends DefaultValidator {
-
- final Map<String, Set<String>> actual = new HashMap<String, Set<String>>();
-
- String path = "/";
-
- public static Map<String, Set<String>> compare(NodeState before, NodeState after) {
- final TestValidator validator = new TestValidator();
- EditorDiff.process(validator, before, after);
- return validator.actual;
- }
-
- @Override
- public void leave(NodeState before, NodeState after) throws CommitFailedException {
- path = PathUtils.getParentPath(path);
- }
-
- @Override
- public void propertyAdded(PropertyState after) throws CommitFailedException {
- record("propertyAdded", PathUtils.concat(path, after.getName()));
- }
-
- @Override
- public void propertyChanged(PropertyState before, PropertyState after) throws CommitFailedException {
- record("propertyChanged", PathUtils.concat(path, after.getName()));
- }
-
- @Override
- public void propertyDeleted(PropertyState before) throws CommitFailedException {
- record("propertyDeleted", PathUtils.concat(path, before.getName()));
- }
-
- @Override
- public Validator childNodeAdded(String name, NodeState after) throws CommitFailedException {
- path = PathUtils.concat(path, name);
- record("childNodeAdded", path);
- return this;
- }
-
- @Override
- public Validator childNodeChanged(String name, NodeState before, NodeState after)
- throws CommitFailedException {
- // make sure not to record false positives (inefficient for large trees)
- if (!before.equals(after)) {
- path = PathUtils.concat(path, name);
- record("childNodeChanged", path);
- return this;
- }
- return null;
- }
-
- @Override
- public Validator childNodeDeleted(String name, NodeState before) throws CommitFailedException {
- path = PathUtils.concat(path, name);
- record("childNodeDeleted", path);
- return this;
- }
-
- private void record(String type, String path) {
- if (!actual.containsKey(type)) {
- actual.put(type, new TreeSet<String>());
- }
- actual.get(type).add(path);
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.upgrade.util;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.DefaultValidator;
+import org.apache.jackrabbit.oak.spi.commit.EditorDiff;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static org.junit.Assert.assertEquals;
+
+public class NodeStateTestUtils {
+
+ private NodeStateTestUtils() {
+ // no instances
+ }
+
+ public static NodeStore createNodeStoreWithContent(String... paths) throws CommitFailedException {
+ final SegmentNodeStore store = new SegmentNodeStore();
+ final NodeBuilder builder = store.getRoot().builder();
+ for (String path : paths) {
+ create(builder, path);
+ }
+ commit(store, builder);
+ return store;
+ }
+
+ public static void create(NodeBuilder rootBuilder, String path, PropertyState... properties) {
+ final NodeBuilder builder = createOrGetBuilder(rootBuilder, path);
+ for (PropertyState property : properties) {
+ builder.setProperty(property);
+ }
+ }
+
+ public static void commit(NodeStore store, NodeBuilder rootBuilder) throws CommitFailedException {
+ store.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ }
+
+ public static NodeBuilder createOrGetBuilder(NodeBuilder builder, String path) {
+ NodeBuilder current = builder;
+ for (final String name : PathUtils.elements(path)) {
+ current = current.child(name);
+ }
+ return current;
+ }
+
+ public static ExpectedDifference expectDifference() {
+ return new ExpectedDifference();
+ }
+
+ public static class ExpectedDifference {
+
+ private ExpectedDifference() {
+ }
+
+ private final Map<String, Set<String>> expected = new HashMap<String, Set<String>>();
+
+ public void verify(NodeState before, NodeState after) {
+ final Map<String, Set<String>> actual = TestValidator.compare(before, after);
+ for (String type : expected.keySet()) {
+ if (!actual.containsKey(type)) {
+ actual.put(type, Collections.<String>emptySet());
+ }
+ assertEquals(type, expected.get(type), actual.get(type));
+ }
+ }
+
+ public ExpectedDifference propertyAdded(String... paths) {
+ return expect("propertyAdded", paths);
+ }
+
+ public ExpectedDifference propertyChanged(String... paths) {
+ return expect("propertyChanged", paths);
+ }
+
+ public ExpectedDifference propertyDeleted(String... paths) {
+ return expect("propertyDeleted", paths);
+ }
+
+ public ExpectedDifference childNodeAdded(String... paths) {
+ return expect("childNodeAdded", paths);
+ }
+
+ public ExpectedDifference childNodeChanged(String... paths) {
+ return expect("childNodeChanged", paths);
+ }
+
+ public ExpectedDifference childNodeDeleted(String... paths) {
+ return expect("childNodeDeleted", paths);
+ }
+
+ public ExpectedDifference strict() {
+ return this.propertyAdded()
+ .propertyChanged()
+ .propertyDeleted()
+ .childNodeAdded()
+ .childNodeChanged()
+ .childNodeDeleted();
+ }
+
+ private ExpectedDifference expect(String type, String... paths) {
+ if (!expected.containsKey(type)) {
+ expected.put(type, new TreeSet<String>());
+ }
+ Collections.addAll(expected.get(type), paths);
+ return this;
+ }
+ }
+
+ private static class TestValidator extends DefaultValidator {
+
+ final Map<String, Set<String>> actual = new HashMap<String, Set<String>>();
+
+ String path = "/";
+
+ public static Map<String, Set<String>> compare(NodeState before, NodeState after) {
+ final TestValidator validator = new TestValidator();
+ EditorDiff.process(validator, before, after);
+ return validator.actual;
+ }
+
+ @Override
+ public void leave(NodeState before, NodeState after) throws CommitFailedException {
+ path = PathUtils.getParentPath(path);
+ }
+
+ @Override
+ public void propertyAdded(PropertyState after) throws CommitFailedException {
+ record("propertyAdded", PathUtils.concat(path, after.getName()));
+ }
+
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after) throws CommitFailedException {
+ record("propertyChanged", PathUtils.concat(path, after.getName()));
+ }
+
+ @Override
+ public void propertyDeleted(PropertyState before) throws CommitFailedException {
+ record("propertyDeleted", PathUtils.concat(path, before.getName()));
+ }
+
+ @Override
+ public Validator childNodeAdded(String name, NodeState after) throws CommitFailedException {
+ path = PathUtils.concat(path, name);
+ record("childNodeAdded", path);
+ return this;
+ }
+
+ @Override
+ public Validator childNodeChanged(String name, NodeState before, NodeState after)
+ throws CommitFailedException {
+ // make sure not to record false positives (inefficient for large trees)
+ if (!before.equals(after)) {
+ path = PathUtils.concat(path, name);
+ record("childNodeChanged", path);
+ return this;
+ }
+ return null;
+ }
+
+ @Override
+ public Validator childNodeDeleted(String name, NodeState before) throws CommitFailedException {
+ path = PathUtils.concat(path, name);
+ record("childNodeDeleted", path);
+ return this;
+ }
+
+ private void record(String type, String path) {
+ if (!actual.containsKey(type)) {
+ actual.put(type, new TreeSet<String>());
+ }
+ actual.get(type).add(path);
+ }
+ }
+}
Propchange: jackrabbit/oak/branches/1.2/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/NodeStateTestUtils.java
------------------------------------------------------------------------------
svn:eol-style = native