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 re...@apache.org on 2015/08/07 12:31:01 UTC
svn commit: r1694646 [1/2] - in /jackrabbit/oak/trunk:
oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/
oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/
oak-jcr/src/test/java/org/apache/j...
Author: reschke
Date: Fri Aug 7 10:31:00 2015
New Revision: 1694646
URL: http://svn.apache.org/r1694646
Log:
fix svn:eol-style
Modified:
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugImportAbortTest.java (props changed)
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugImportBesteffortTest.java (props changed)
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugImportIgnoreTest.java (props changed)
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractAddMembersByIdTest.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractRemoveMembersByIdTest.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdAbortTest.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdBestEffortTest.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdIgnoreTest.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdAbortTest.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdBestEffortTest.java (props changed)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdIgnoreTest.java (props changed)
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/HasPermissionTest.java (props changed)
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/version/VersionablePathNodeStoreTest.java (props changed)
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/ManyGroupMembersTest.java (props changed)
jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/ParseVersionCopyArgumentTest.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeState.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopyConfiguration.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistoryTest.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/IncludeExcludeUpgradeTest.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/UpgradeFromTwoSourcesTest.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeStateTest.java (contents, props changed)
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/VersionCopyTestUtils.java (contents, props changed)
Propchange: jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugImportAbortTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugImportBesteffortTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugImportIgnoreTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugSecurityProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractAddMembersByIdTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractRemoveMembersByIdTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdAbortTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdBestEffortTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdIgnoreTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdAbortTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdBestEffortTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdIgnoreTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/HasPermissionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/version/VersionablePathNodeStoreTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/ManyGroupMembersTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/ParseVersionCopyArgumentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/ParseVersionCopyArgumentTest.java?rev=1694646&r1=1694645&r2=1694646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/ParseVersionCopyArgumentTest.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/ParseVersionCopyArgumentTest.java Fri Aug 7 10:31:00 2015
@@ -1,53 +1,53 @@
-/*
- * 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.run;
-
-import java.text.ParseException;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ParseVersionCopyArgumentTest {
-
- @Test
- public void parseTrue() throws ParseException {
- for (String argument : Arrays.asList("true", "TRUE", "TrUe")) {
- final Calendar result = Main.parseVersionCopyArgument(argument);
- Assert.assertEquals(0, result.getTimeInMillis());
- }
- }
-
- @Test
- public void parseDate() throws ParseException {
- final Calendar result = Main.parseVersionCopyArgument("2013-01-01");
- Assert.assertEquals(new GregorianCalendar(2013, 0, 1), result);
- }
-
- @Test
- public void parseFalse() throws ParseException {
- for (String argument : Arrays.asList("false", "FaLse", "", "xyz", null)) {
- final Calendar result = Main.parseVersionCopyArgument(argument);
- Assert.assertNull(result);
- }
- }
-}
+/*
+ * 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.run;
+
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ParseVersionCopyArgumentTest {
+
+ @Test
+ public void parseTrue() throws ParseException {
+ for (String argument : Arrays.asList("true", "TRUE", "TrUe")) {
+ final Calendar result = Main.parseVersionCopyArgument(argument);
+ Assert.assertEquals(0, result.getTimeInMillis());
+ }
+ }
+
+ @Test
+ public void parseDate() throws ParseException {
+ final Calendar result = Main.parseVersionCopyArgument("2013-01-01");
+ Assert.assertEquals(new GregorianCalendar(2013, 0, 1), result);
+ }
+
+ @Test
+ public void parseFalse() throws ParseException {
+ for (String argument : Arrays.asList("false", "FaLse", "", "xyz", null)) {
+ final Calendar result = Main.parseVersionCopyArgument(argument);
+ Assert.assertNull(result);
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/ParseVersionCopyArgumentTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java?rev=1694646&r1=1694645&r2=1694646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java Fri Aug 7 10:31:00 2015
@@ -1,46 +1,46 @@
-package org.apache.jackrabbit.oak.upgrade;
-
-import java.util.ArrayDeque;
-import java.util.Deque;
-import java.util.Iterator;
-
-import org.apache.jackrabbit.commons.iterator.AbstractLazyIterator;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-
-public class DescendantsIterator extends AbstractLazyIterator<NodeState> {
-
- private final Deque<Iterator<? extends ChildNodeEntry>> stack = new ArrayDeque<Iterator<? extends ChildNodeEntry>>();
-
- private final int maxLevel;
-
- public DescendantsIterator(NodeState root, int maxLevel) {
- this.maxLevel = maxLevel;
- stack.push(root.getChildNodeEntries().iterator());
- }
-
- @Override
- protected NodeState getNext() {
- if (!fillStack()) {
- return null;
- }
- return stack.peekFirst().next().getNodeState();
- }
-
- private boolean fillStack() {
- while (stack.size() < maxLevel || !stack.peekFirst().hasNext()) {
- Iterator<? extends ChildNodeEntry> topIterator = stack.peekFirst();
- if (topIterator.hasNext()) {
- final NodeState nextNode = topIterator.next().getNodeState();
- stack.push(nextNode.getChildNodeEntries().iterator());
- } else {
- stack.pop();
- if (stack.isEmpty()) {
- return false;
- }
- }
- }
- return true;
- }
-
-}
+package org.apache.jackrabbit.oak.upgrade;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Iterator;
+
+import org.apache.jackrabbit.commons.iterator.AbstractLazyIterator;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+public class DescendantsIterator extends AbstractLazyIterator<NodeState> {
+
+ private final Deque<Iterator<? extends ChildNodeEntry>> stack = new ArrayDeque<Iterator<? extends ChildNodeEntry>>();
+
+ private final int maxLevel;
+
+ public DescendantsIterator(NodeState root, int maxLevel) {
+ this.maxLevel = maxLevel;
+ stack.push(root.getChildNodeEntries().iterator());
+ }
+
+ @Override
+ protected NodeState getNext() {
+ if (!fillStack()) {
+ return null;
+ }
+ return stack.peekFirst().next().getNodeState();
+ }
+
+ private boolean fillStack() {
+ while (stack.size() < maxLevel || !stack.peekFirst().hasNext()) {
+ Iterator<? extends ChildNodeEntry> topIterator = stack.peekFirst();
+ if (topIterator.hasNext()) {
+ final NodeState nextNode = topIterator.next().getNodeState();
+ stack.push(nextNode.getChildNodeEntries().iterator());
+ } else {
+ stack.pop();
+ if (stack.isEmpty()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeState.java?rev=1694646&r1=1694645&r2=1694646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeState.java Fri Aug 7 10:31:00 2015
@@ -1,334 +1,334 @@
-package org.apache.jackrabbit.oak.upgrade.nodestate;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
-import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
-import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
-import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
-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 javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.Set;
-
-import static org.apache.jackrabbit.oak.plugins.tree.impl.TreeConstants.OAK_CHILD_ORDER;
-
-/**
- * NodeState implementation that decorates another node-state instance
- * in order to hide subtrees or partial subtrees from the consumer of
- * the API.
- * <br>
- * The set of visible subtrees is defined by two parameters: include paths
- * and exclude paths, both of which are sets of absolute paths.
- * <br>
- * Any paths that are equal or are descendants of one of the
- * <b>excluded paths</b> are hidden by this implementation.
- * <br>
- * For all <b>included paths</b>, the direct ancestors, the node-state at
- * the path itself and all descendants are visible. Any siblings of the
- * defined path or its ancestors are implicitly hidden (unless made visible
- * by another include path).
- * <br>
- * The implementation delegates to the decorated node-state instance and
- * filters out hidden node-states in the following methods:
- * <ul>
- * <li>{@link #exists()}</li>
- * <li>{@link #hasChildNode(String)}</li>
- * <li>{@link #getChildNodeEntries()}</li>
- * </ul>
- * Additionally, hidden node-state names are removed from the property
- * {@code :childOrder} in the following two methods:
- * <ul>
- * <li>{@link #getProperties()}</li>
- * <li>{@link #getProperty(String)}</li>
- * </ul>
- */
-public class FilteringNodeState extends AbstractNodeState {
-
- public static final Set<String> ALL = ImmutableSet.of("/");
-
- public static final Set<String> NONE = ImmutableSet.of();
-
- private final NodeState delegate;
-
- private final String path;
-
- private final Set<String> includedPaths;
-
- private final Set<String> excludedPaths;
-
- /**
- * Factory method that conditionally decorates the given node-state
- * iff the node-state is (a) hidden itself or (b) has hidden descendants.
- *
- * @param path The path where the node-state should be assumed to be located.
- * @param delegate The node-state to decorate.
- * @param includePaths A Set of paths that should be visible. Defaults to ["/"] if {@code null).
- * @param excludePaths A Set of paths that should be hidden. Empty if {@code null).
- * @return The decorated node-state if required, the original node-state if decoration is unnecessary.
- * @param excludePaths
- */
- @Nonnull
- public static NodeState wrap(
- @Nonnull final String path,
- @Nonnull final NodeState delegate,
- @Nullable final Set<String> includePaths,
- @Nullable final Set<String> excludePaths
- ) {
- final Set<String> includes = defaultIfEmpty(includePaths, ALL);
- final Set<String> excludes = defaultIfEmpty(excludePaths, NONE);
- if (hasHiddenDescendants(path, includes, excludes)) {
- return new FilteringNodeState(path, delegate, includes, excludes);
- }
- return delegate;
- }
-
- private FilteringNodeState(
- @Nonnull final String path,
- @Nonnull final NodeState delegate,
- @Nonnull final Set<String> includedPaths,
- @Nonnull final Set<String> excludedPaths
- ) {
- this.path = path;
- this.delegate = delegate;
- this.includedPaths = includedPaths;
- this.excludedPaths = excludedPaths;
- }
-
- @Override
- @Nonnull
- public NodeBuilder builder() {
- return new MemoryNodeBuilder(this);
- }
-
- @Override
- public boolean exists() {
- return !isHidden(path, includedPaths, excludedPaths) && delegate.exists();
- }
-
- @Override
- @Nonnull
- public NodeState getChildNode(@Nonnull final String name) throws IllegalArgumentException {
- final String childPath = PathUtils.concat(path, name);
- return wrap(childPath, delegate.getChildNode(name), includedPaths, excludedPaths);
- }
-
- @Override
- public boolean hasChildNode(@Nonnull final String name) {
- final String childPath = PathUtils.concat(path, name);
- return !isHidden(childPath, includedPaths, excludedPaths) && delegate.hasChildNode(name);
- }
-
- @Override
- @Nonnull
- public Iterable<? extends ChildNodeEntry> getChildNodeEntries() {
- final Iterable<ChildNodeEntry> transformed = Iterables.transform(
- delegate.getChildNodeEntries(),
- new Function<ChildNodeEntry, ChildNodeEntry>() {
- @Nullable
- @Override
- public ChildNodeEntry apply(@Nullable final ChildNodeEntry childNodeEntry) {
- if (childNodeEntry != null) {
- final String name = childNodeEntry.getName();
- final String childPath = PathUtils.concat(path, name);
- if (!isHidden(childPath, includedPaths, excludedPaths)) {
- final NodeState nodeState = childNodeEntry.getNodeState();
- final NodeState state = wrap(childPath, nodeState, includedPaths, excludedPaths);
- return new MemoryChildNodeEntry(name, state);
- }
- }
- return null;
- }
- }
- );
- return Iterables.filter(transformed, new Predicate<ChildNodeEntry>() {
- @Override
- public boolean apply(@Nullable final ChildNodeEntry childNodeEntry) {
- return childNodeEntry != null;
- }
- });
- }
-
- @Override
- public long getPropertyCount() {
- return delegate.getPropertyCount();
- }
-
- @Override
- @Nonnull
- public Iterable<? extends PropertyState> getProperties() {
- return Iterables.transform(delegate.getProperties(), new Function<PropertyState, PropertyState>() {
- @Nullable
- @Override
- public PropertyState apply(@Nullable final PropertyState propertyState) {
- return fixChildOrderPropertyState(propertyState);
- }
- });
- }
-
- @Override
- public PropertyState getProperty(String name) {
- return fixChildOrderPropertyState(delegate.getProperty(name));
- }
-
- @Override
- public boolean hasProperty(String name) {
- return delegate.getProperty(name) != null;
- }
-
- /**
- * Utility method to fix the PropertyState of properties called {@code :childOrder}.
- *
- * @param propertyState A property-state.
- * @return The original property-state or if the property name is {@code :childOrder}, a
- * property-state with hidden child names removed from the value.
- */
- @CheckForNull
- private PropertyState fixChildOrderPropertyState(@Nullable final PropertyState propertyState) {
- if (propertyState != null && OAK_CHILD_ORDER.equals(propertyState.getName())) {
- final Iterable<String> values = Iterables.filter(propertyState.getValue(Type.NAMES), new Predicate<String>() {
- @Override
- public boolean apply(@Nullable final String name) {
- if (name == null) {
- return false;
- }
- final String childPath = PathUtils.concat(path, name);
- return !isHidden(childPath, includedPaths, excludedPaths);
- }
- });
- return PropertyStates.createProperty(OAK_CHILD_ORDER, values, Type.NAMES);
- }
- return propertyState;
- }
-
- /**
- * Utility method to determine whether a given path should is hidden given the
- * include paths and exclude paths.
- *
- * @param path Path to be checked
- * @param includes Include paths
- * @param excludes Exclude paths
- * @return Whether the {@code path} is hidden or not.
- */
- public static boolean isHidden(
- @Nonnull final String path,
- @Nonnull final Set<String> includes,
- @Nonnull final Set<String> excludes
- ) {
- return isExcluded(path, excludes) || !isIncluded(path, includes);
- }
-
- /**
- * Utility method to determine whether the path itself or any of its descendants should
- * be hidden given the include paths and exclude paths.
- *
- * @param path Path to be checked
- * @param includePaths Include paths
- * @param excludePaths Exclude paths
- * @return Whether the {@code path} or any of its descendants are hidden or not.
- */
- private static boolean hasHiddenDescendants(
- @Nonnull final String path,
- @Nonnull final Set<String> includePaths,
- @Nonnull final Set<String> excludePaths
- ) {
- return isHidden(path, includePaths, excludePaths)
- || isAncestorOfAnyPath(path, excludePaths)
- || isAncestorOfAnyPath(path, includePaths);
- }
-
- /**
- * Utility method to check whether a given set of include paths cover the given
- * {@code path}. I.e. whether the path is visible or implicitly hidden due to the
- * lack of a matching include path.
- * <br>
- * Note: the ancestors of every include path are considered visible.
- *
- * @param path Path to be checked
- * @param includePaths Include paths
- * @return Whether the path is covered by the include paths or not.
- */
- private static boolean isIncluded(@Nonnull final String path, @Nonnull final Set<String> includePaths) {
- return isAncestorOfAnyPath(path, includePaths)
- || includePaths.contains(path)
- || isDescendantOfAnyPath(path, includePaths);
- }
-
- /**
- * Utility method to check whether a given set of exclude paths cover the given
- * {@code path}. I.e. whether the path is hidden due to the presence of a
- * matching exclude path.
- *
- * @param path Path to be checked
- * @param excludePaths Exclude paths
- * @return Whether the path is covered by the excldue paths or not.
- */
- private static boolean isExcluded(@Nonnull final String path, @Nonnull final Set<String> excludePaths) {
- return excludePaths.contains(path) || isDescendantOfAnyPath(path, excludePaths);
- }
-
- /**
- * Utility method to check whether any of the provided {@code paths} is a descendant
- * of the given ancestor path.
- *
- * @param ancestor Ancestor path
- * @param paths Paths that may be descendants of {@code ancestor}.
- * @return true if {@code paths} contains a descendant of {@code ancestor}, false otherwise.
- */
- private static boolean isAncestorOfAnyPath(@Nonnull final String ancestor, @Nonnull final Set<String> paths) {
- for (final String p : paths) {
- if (PathUtils.isAncestor(ancestor, p)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Utility method to check whether any of the provided {@code paths} is an ancestor
- * of the given descendant path.
- *
- * @param descendant Descendant path
- * @param paths Paths that may be ancestors of {@code descendant}.
- * @return true if {@code paths} contains an ancestor of {@code descendant}, false otherwise.
- */
- private static boolean isDescendantOfAnyPath(@Nonnull final String descendant, @Nonnull final Set<String> paths) {
- for (final String p : paths) {
- if (PathUtils.isAncestor(p, descendant)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Utility method to return the given {@code Set} if it is not empty and a default Set otherwise.
- *
- * @param value Value to check for emptiness
- * @param defaultValue Default value
- * @return return the given {@code Set} if it is not empty and a default Set otherwise
- */
- @Nonnull
- private static <T> Set<T> defaultIfEmpty(@Nullable Set<T> value, @Nonnull Set<T> defaultValue) {
- return !isEmpty(value) ? value : defaultValue;
- }
-
- /**
- * Utility method to check whether a Set is empty, i.e. null or of size 0.
- *
- * @param set The Set to check.
- * @return true if empty, false otherwise
- */
- private static <T> boolean isEmpty(@Nullable final Set<T> set) {
- return set == null || set.isEmpty();
- }
-}
+package org.apache.jackrabbit.oak.upgrade.nodestate;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
+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 javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Set;
+
+import static org.apache.jackrabbit.oak.plugins.tree.impl.TreeConstants.OAK_CHILD_ORDER;
+
+/**
+ * NodeState implementation that decorates another node-state instance
+ * in order to hide subtrees or partial subtrees from the consumer of
+ * the API.
+ * <br>
+ * The set of visible subtrees is defined by two parameters: include paths
+ * and exclude paths, both of which are sets of absolute paths.
+ * <br>
+ * Any paths that are equal or are descendants of one of the
+ * <b>excluded paths</b> are hidden by this implementation.
+ * <br>
+ * For all <b>included paths</b>, the direct ancestors, the node-state at
+ * the path itself and all descendants are visible. Any siblings of the
+ * defined path or its ancestors are implicitly hidden (unless made visible
+ * by another include path).
+ * <br>
+ * The implementation delegates to the decorated node-state instance and
+ * filters out hidden node-states in the following methods:
+ * <ul>
+ * <li>{@link #exists()}</li>
+ * <li>{@link #hasChildNode(String)}</li>
+ * <li>{@link #getChildNodeEntries()}</li>
+ * </ul>
+ * Additionally, hidden node-state names are removed from the property
+ * {@code :childOrder} in the following two methods:
+ * <ul>
+ * <li>{@link #getProperties()}</li>
+ * <li>{@link #getProperty(String)}</li>
+ * </ul>
+ */
+public class FilteringNodeState extends AbstractNodeState {
+
+ public static final Set<String> ALL = ImmutableSet.of("/");
+
+ public static final Set<String> NONE = ImmutableSet.of();
+
+ private final NodeState delegate;
+
+ private final String path;
+
+ private final Set<String> includedPaths;
+
+ private final Set<String> excludedPaths;
+
+ /**
+ * Factory method that conditionally decorates the given node-state
+ * iff the node-state is (a) hidden itself or (b) has hidden descendants.
+ *
+ * @param path The path where the node-state should be assumed to be located.
+ * @param delegate The node-state to decorate.
+ * @param includePaths A Set of paths that should be visible. Defaults to ["/"] if {@code null).
+ * @param excludePaths A Set of paths that should be hidden. Empty if {@code null).
+ * @return The decorated node-state if required, the original node-state if decoration is unnecessary.
+ * @param excludePaths
+ */
+ @Nonnull
+ public static NodeState wrap(
+ @Nonnull final String path,
+ @Nonnull final NodeState delegate,
+ @Nullable final Set<String> includePaths,
+ @Nullable final Set<String> excludePaths
+ ) {
+ final Set<String> includes = defaultIfEmpty(includePaths, ALL);
+ final Set<String> excludes = defaultIfEmpty(excludePaths, NONE);
+ if (hasHiddenDescendants(path, includes, excludes)) {
+ return new FilteringNodeState(path, delegate, includes, excludes);
+ }
+ return delegate;
+ }
+
+ private FilteringNodeState(
+ @Nonnull final String path,
+ @Nonnull final NodeState delegate,
+ @Nonnull final Set<String> includedPaths,
+ @Nonnull final Set<String> excludedPaths
+ ) {
+ this.path = path;
+ this.delegate = delegate;
+ this.includedPaths = includedPaths;
+ this.excludedPaths = excludedPaths;
+ }
+
+ @Override
+ @Nonnull
+ public NodeBuilder builder() {
+ return new MemoryNodeBuilder(this);
+ }
+
+ @Override
+ public boolean exists() {
+ return !isHidden(path, includedPaths, excludedPaths) && delegate.exists();
+ }
+
+ @Override
+ @Nonnull
+ public NodeState getChildNode(@Nonnull final String name) throws IllegalArgumentException {
+ final String childPath = PathUtils.concat(path, name);
+ return wrap(childPath, delegate.getChildNode(name), includedPaths, excludedPaths);
+ }
+
+ @Override
+ public boolean hasChildNode(@Nonnull final String name) {
+ final String childPath = PathUtils.concat(path, name);
+ return !isHidden(childPath, includedPaths, excludedPaths) && delegate.hasChildNode(name);
+ }
+
+ @Override
+ @Nonnull
+ public Iterable<? extends ChildNodeEntry> getChildNodeEntries() {
+ final Iterable<ChildNodeEntry> transformed = Iterables.transform(
+ delegate.getChildNodeEntries(),
+ new Function<ChildNodeEntry, ChildNodeEntry>() {
+ @Nullable
+ @Override
+ public ChildNodeEntry apply(@Nullable final ChildNodeEntry childNodeEntry) {
+ if (childNodeEntry != null) {
+ final String name = childNodeEntry.getName();
+ final String childPath = PathUtils.concat(path, name);
+ if (!isHidden(childPath, includedPaths, excludedPaths)) {
+ final NodeState nodeState = childNodeEntry.getNodeState();
+ final NodeState state = wrap(childPath, nodeState, includedPaths, excludedPaths);
+ return new MemoryChildNodeEntry(name, state);
+ }
+ }
+ return null;
+ }
+ }
+ );
+ return Iterables.filter(transformed, new Predicate<ChildNodeEntry>() {
+ @Override
+ public boolean apply(@Nullable final ChildNodeEntry childNodeEntry) {
+ return childNodeEntry != null;
+ }
+ });
+ }
+
+ @Override
+ public long getPropertyCount() {
+ return delegate.getPropertyCount();
+ }
+
+ @Override
+ @Nonnull
+ public Iterable<? extends PropertyState> getProperties() {
+ return Iterables.transform(delegate.getProperties(), new Function<PropertyState, PropertyState>() {
+ @Nullable
+ @Override
+ public PropertyState apply(@Nullable final PropertyState propertyState) {
+ return fixChildOrderPropertyState(propertyState);
+ }
+ });
+ }
+
+ @Override
+ public PropertyState getProperty(String name) {
+ return fixChildOrderPropertyState(delegate.getProperty(name));
+ }
+
+ @Override
+ public boolean hasProperty(String name) {
+ return delegate.getProperty(name) != null;
+ }
+
+ /**
+ * Utility method to fix the PropertyState of properties called {@code :childOrder}.
+ *
+ * @param propertyState A property-state.
+ * @return The original property-state or if the property name is {@code :childOrder}, a
+ * property-state with hidden child names removed from the value.
+ */
+ @CheckForNull
+ private PropertyState fixChildOrderPropertyState(@Nullable final PropertyState propertyState) {
+ if (propertyState != null && OAK_CHILD_ORDER.equals(propertyState.getName())) {
+ final Iterable<String> values = Iterables.filter(propertyState.getValue(Type.NAMES), new Predicate<String>() {
+ @Override
+ public boolean apply(@Nullable final String name) {
+ if (name == null) {
+ return false;
+ }
+ final String childPath = PathUtils.concat(path, name);
+ return !isHidden(childPath, includedPaths, excludedPaths);
+ }
+ });
+ return PropertyStates.createProperty(OAK_CHILD_ORDER, values, Type.NAMES);
+ }
+ return propertyState;
+ }
+
+ /**
+ * Utility method to determine whether a given path should is hidden given the
+ * include paths and exclude paths.
+ *
+ * @param path Path to be checked
+ * @param includes Include paths
+ * @param excludes Exclude paths
+ * @return Whether the {@code path} is hidden or not.
+ */
+ public static boolean isHidden(
+ @Nonnull final String path,
+ @Nonnull final Set<String> includes,
+ @Nonnull final Set<String> excludes
+ ) {
+ return isExcluded(path, excludes) || !isIncluded(path, includes);
+ }
+
+ /**
+ * Utility method to determine whether the path itself or any of its descendants should
+ * be hidden given the include paths and exclude paths.
+ *
+ * @param path Path to be checked
+ * @param includePaths Include paths
+ * @param excludePaths Exclude paths
+ * @return Whether the {@code path} or any of its descendants are hidden or not.
+ */
+ private static boolean hasHiddenDescendants(
+ @Nonnull final String path,
+ @Nonnull final Set<String> includePaths,
+ @Nonnull final Set<String> excludePaths
+ ) {
+ return isHidden(path, includePaths, excludePaths)
+ || isAncestorOfAnyPath(path, excludePaths)
+ || isAncestorOfAnyPath(path, includePaths);
+ }
+
+ /**
+ * Utility method to check whether a given set of include paths cover the given
+ * {@code path}. I.e. whether the path is visible or implicitly hidden due to the
+ * lack of a matching include path.
+ * <br>
+ * Note: the ancestors of every include path are considered visible.
+ *
+ * @param path Path to be checked
+ * @param includePaths Include paths
+ * @return Whether the path is covered by the include paths or not.
+ */
+ private static boolean isIncluded(@Nonnull final String path, @Nonnull final Set<String> includePaths) {
+ return isAncestorOfAnyPath(path, includePaths)
+ || includePaths.contains(path)
+ || isDescendantOfAnyPath(path, includePaths);
+ }
+
+ /**
+ * Utility method to check whether a given set of exclude paths cover the given
+ * {@code path}. I.e. whether the path is hidden due to the presence of a
+ * matching exclude path.
+ *
+ * @param path Path to be checked
+ * @param excludePaths Exclude paths
+ * @return Whether the path is covered by the excldue paths or not.
+ */
+ private static boolean isExcluded(@Nonnull final String path, @Nonnull final Set<String> excludePaths) {
+ return excludePaths.contains(path) || isDescendantOfAnyPath(path, excludePaths);
+ }
+
+ /**
+ * Utility method to check whether any of the provided {@code paths} is a descendant
+ * of the given ancestor path.
+ *
+ * @param ancestor Ancestor path
+ * @param paths Paths that may be descendants of {@code ancestor}.
+ * @return true if {@code paths} contains a descendant of {@code ancestor}, false otherwise.
+ */
+ private static boolean isAncestorOfAnyPath(@Nonnull final String ancestor, @Nonnull final Set<String> paths) {
+ for (final String p : paths) {
+ if (PathUtils.isAncestor(ancestor, p)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Utility method to check whether any of the provided {@code paths} is an ancestor
+ * of the given descendant path.
+ *
+ * @param descendant Descendant path
+ * @param paths Paths that may be ancestors of {@code descendant}.
+ * @return true if {@code paths} contains an ancestor of {@code descendant}, false otherwise.
+ */
+ private static boolean isDescendantOfAnyPath(@Nonnull final String descendant, @Nonnull final Set<String> paths) {
+ for (final String p : paths) {
+ if (PathUtils.isAncestor(p, descendant)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Utility method to return the given {@code Set} if it is not empty and a default Set otherwise.
+ *
+ * @param value Value to check for emptiness
+ * @param defaultValue Default value
+ * @return return the given {@code Set} if it is not empty and a default Set otherwise
+ */
+ @Nonnull
+ private static <T> Set<T> defaultIfEmpty(@Nullable Set<T> value, @Nonnull Set<T> defaultValue) {
+ return !isEmpty(value) ? value : defaultValue;
+ }
+
+ /**
+ * Utility method to check whether a Set is empty, i.e. null or of size 0.
+ *
+ * @param set The Set to check.
+ * @return true if empty, false otherwise
+ */
+ private static <T> boolean isEmpty(@Nullable final Set<T> set) {
+ return set == null || set.isEmpty();
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeState.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java?rev=1694646&r1=1694645&r2=1694646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java Fri Aug 7 10:31:00 2015
@@ -1,97 +1,97 @@
-/*
- * 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.version;
-
-import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
-import static org.apache.jackrabbit.JcrConstants.NT_VERSION;
-
-import java.util.Calendar;
-
-import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
-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.upgrade.nodestate.NodeStateCopier;
-import org.apache.jackrabbit.util.ISO8601;
-
-import static org.apache.jackrabbit.oak.plugins.version.VersionConstants.VERSION_STORE_PATH;
-
-import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionHistoryPath;
-import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionHistoryNodeState;
-
-/**
- * This class allows to copy the version history, optionally filtering it with a
- * given date.
- */
-public class VersionCopier {
-
- private final TypePredicate isVersion;
-
- private final NodeState sourceRoot;
-
- private final NodeBuilder rootBuilder;
-
- public VersionCopier(NodeState sourceRoot, NodeBuilder rootBuilder) {
- this.isVersion = new TypePredicate(rootBuilder.getNodeState(), NT_VERSION);
- this.sourceRoot = sourceRoot;
- this.rootBuilder = rootBuilder;
- }
-
- /**
- * Copy history filtering versions using passed date and returns @{code
- * true} if at least one version has been copied.
- *
- * @param versionableUuid
- * Name of the version history node
- * @param minDate
- * Only versions older than this date will be copied
- * @return {@code true} if at least one version has been copied
- */
- public boolean copyVersionHistory(String versionableUuid, Calendar minDate) {
- final String versionHistoryPath = getVersionHistoryPath(versionableUuid);
- final NodeState versionHistory = getVersionHistoryNodeState(sourceRoot, versionableUuid);
- final Calendar lastModified = getVersionHistoryLastModified(versionHistory);
-
- if (lastModified.after(minDate) || minDate.getTimeInMillis() == 0) {
- NodeStateCopier.builder()
- .include(versionHistoryPath)
- .merge(VERSION_STORE_PATH)
- .copy(sourceRoot, rootBuilder);
- return true;
- }
- return false;
- }
-
- private Calendar getVersionHistoryLastModified(final NodeState versionHistory) {
- Calendar youngest = Calendar.getInstance();
- youngest.setTimeInMillis(0);
- for (final ChildNodeEntry entry : versionHistory.getChildNodeEntries()) {
- final NodeState version = entry.getNodeState();
- if (!isVersion.apply(version)) {
- continue;
- }
- if (version.hasProperty(JCR_CREATED)) {
- final Calendar created = ISO8601.parse(version.getProperty(JCR_CREATED).getValue(Type.DATE));
- if (created.after(youngest)) {
- youngest = created;
- }
- }
- }
- return youngest;
- }
-}
+/*
+ * 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.version;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
+import static org.apache.jackrabbit.JcrConstants.NT_VERSION;
+
+import java.util.Calendar;
+
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+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.upgrade.nodestate.NodeStateCopier;
+import org.apache.jackrabbit.util.ISO8601;
+
+import static org.apache.jackrabbit.oak.plugins.version.VersionConstants.VERSION_STORE_PATH;
+
+import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionHistoryPath;
+import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionHistoryNodeState;
+
+/**
+ * This class allows to copy the version history, optionally filtering it with a
+ * given date.
+ */
+public class VersionCopier {
+
+ private final TypePredicate isVersion;
+
+ private final NodeState sourceRoot;
+
+ private final NodeBuilder rootBuilder;
+
+ public VersionCopier(NodeState sourceRoot, NodeBuilder rootBuilder) {
+ this.isVersion = new TypePredicate(rootBuilder.getNodeState(), NT_VERSION);
+ this.sourceRoot = sourceRoot;
+ this.rootBuilder = rootBuilder;
+ }
+
+ /**
+ * Copy history filtering versions using passed date and returns @{code
+ * true} if at least one version has been copied.
+ *
+ * @param versionableUuid
+ * Name of the version history node
+ * @param minDate
+ * Only versions older than this date will be copied
+ * @return {@code true} if at least one version has been copied
+ */
+ public boolean copyVersionHistory(String versionableUuid, Calendar minDate) {
+ final String versionHistoryPath = getVersionHistoryPath(versionableUuid);
+ final NodeState versionHistory = getVersionHistoryNodeState(sourceRoot, versionableUuid);
+ final Calendar lastModified = getVersionHistoryLastModified(versionHistory);
+
+ if (lastModified.after(minDate) || minDate.getTimeInMillis() == 0) {
+ NodeStateCopier.builder()
+ .include(versionHistoryPath)
+ .merge(VERSION_STORE_PATH)
+ .copy(sourceRoot, rootBuilder);
+ return true;
+ }
+ return false;
+ }
+
+ private Calendar getVersionHistoryLastModified(final NodeState versionHistory) {
+ Calendar youngest = Calendar.getInstance();
+ youngest.setTimeInMillis(0);
+ for (final ChildNodeEntry entry : versionHistory.getChildNodeEntries()) {
+ final NodeState version = entry.getNodeState();
+ if (!isVersion.apply(version)) {
+ continue;
+ }
+ if (version.hasProperty(JCR_CREATED)) {
+ final Calendar created = ISO8601.parse(version.getProperty(JCR_CREATED).getValue(Type.DATE));
+ if (created.after(youngest)) {
+ youngest = created;
+ }
+ }
+ }
+ return youngest;
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopyConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopyConfiguration.java?rev=1694646&r1=1694645&r2=1694646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopyConfiguration.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopyConfiguration.java Fri Aug 7 10:31:00 2015
@@ -1,67 +1,67 @@
-/*
- * 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.version;
-
-import java.util.Calendar;
-
-/**
- * This class allows to configure the behaviour of the version copier.
- */
-public class VersionCopyConfiguration {
-
- private Calendar copyVersions;
-
- private Calendar copyOrphanedVersions;
-
- public VersionCopyConfiguration() {
- final Calendar epoch = Calendar.getInstance();
- epoch.setTimeInMillis(0);
- this.copyVersions = epoch;
- this.copyOrphanedVersions = epoch;
- }
-
- public void setCopyVersions(Calendar copyVersions) {
- this.copyVersions = copyVersions;
- }
-
- public void setCopyOrphanedVersions(Calendar copyOrphanedVersions) {
- this.copyOrphanedVersions = copyOrphanedVersions;
- }
-
- public Calendar getVersionsMinDate() {
- return copyVersions;
- }
-
- public Calendar getOrphanedMinDate() {
- if (copyVersions == null) {
- return copyVersions;
- } else if (copyOrphanedVersions != null && copyVersions.after(copyOrphanedVersions)) {
- return copyVersions;
- } else {
- return copyOrphanedVersions;
- }
- }
-
- public boolean isCopyVersions() {
- return copyVersions != null;
- }
-
- public boolean skipOrphanedVersionsCopy() {
- return copyVersions == null || copyOrphanedVersions == null;
- }
-
+/*
+ * 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.version;
+
+import java.util.Calendar;
+
+/**
+ * This class allows to configure the behaviour of the version copier.
+ */
+public class VersionCopyConfiguration {
+
+ private Calendar copyVersions;
+
+ private Calendar copyOrphanedVersions;
+
+ public VersionCopyConfiguration() {
+ final Calendar epoch = Calendar.getInstance();
+ epoch.setTimeInMillis(0);
+ this.copyVersions = epoch;
+ this.copyOrphanedVersions = epoch;
+ }
+
+ public void setCopyVersions(Calendar copyVersions) {
+ this.copyVersions = copyVersions;
+ }
+
+ public void setCopyOrphanedVersions(Calendar copyOrphanedVersions) {
+ this.copyOrphanedVersions = copyOrphanedVersions;
+ }
+
+ public Calendar getVersionsMinDate() {
+ return copyVersions;
+ }
+
+ public Calendar getOrphanedMinDate() {
+ if (copyVersions == null) {
+ return copyVersions;
+ } else if (copyOrphanedVersions != null && copyVersions.after(copyOrphanedVersions)) {
+ return copyVersions;
+ } else {
+ return copyOrphanedVersions;
+ }
+ }
+
+ public boolean isCopyVersions() {
+ return copyVersions != null;
+ }
+
+ public boolean skipOrphanedVersionsCopy() {
+ return copyVersions == null || copyOrphanedVersions == null;
+ }
+
}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopyConfiguration.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java?rev=1694646&r1=1694645&r2=1694646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java Fri Aug 7 10:31:00 2015
@@ -1,67 +1,67 @@
-/*
- * 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.version;
-
-import static com.google.common.collect.Iterables.concat;
-import static java.util.Collections.singleton;
-import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
-import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONSTORAGE;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-
-import com.google.common.base.Joiner;
-
-public class VersionHistoryUtil {
-
- public static String getVersionHistoryPath(String versionableUuid) {
- return Joiner.on('/').join(concat(
- singleton(""),
- getVersionHistoryPathSegments(versionableUuid),
- singleton(versionableUuid)));
- }
-
- static NodeState getVersionHistoryNodeState(NodeState root, String versionableUuid) {
- NodeState historyParent = root;
- for (String segment : getVersionHistoryPathSegments(versionableUuid)) {
- historyParent = historyParent.getChildNode(segment);
- }
- return historyParent.getChildNode(versionableUuid);
- }
-
- static NodeBuilder getVersionHistoryBuilder(NodeBuilder root, String versionableUuid) {
- NodeBuilder history = root;
- for (String segment : getVersionHistoryPathSegments(versionableUuid)) {
- history = history.getChildNode(segment);
- }
- return history.getChildNode(versionableUuid);
- }
-
- private static List<String> getVersionHistoryPathSegments(String versionableUuid) {
- final List<String> segments = new ArrayList<String>();
- segments.add(JCR_SYSTEM);
- segments.add(JCR_VERSIONSTORAGE);
- for (int i = 0; i < 3; i++) {
- segments.add(versionableUuid.substring(i * 2, i * 2 + 2));
- }
- return segments;
- }
-
-}
+/*
+ * 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.version;
+
+import static com.google.common.collect.Iterables.concat;
+import static java.util.Collections.singleton;
+import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
+import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONSTORAGE;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.base.Joiner;
+
+public class VersionHistoryUtil {
+
+ public static String getVersionHistoryPath(String versionableUuid) {
+ return Joiner.on('/').join(concat(
+ singleton(""),
+ getVersionHistoryPathSegments(versionableUuid),
+ singleton(versionableUuid)));
+ }
+
+ static NodeState getVersionHistoryNodeState(NodeState root, String versionableUuid) {
+ NodeState historyParent = root;
+ for (String segment : getVersionHistoryPathSegments(versionableUuid)) {
+ historyParent = historyParent.getChildNode(segment);
+ }
+ return historyParent.getChildNode(versionableUuid);
+ }
+
+ static NodeBuilder getVersionHistoryBuilder(NodeBuilder root, String versionableUuid) {
+ NodeBuilder history = root;
+ for (String segment : getVersionHistoryPathSegments(versionableUuid)) {
+ history = history.getChildNode(segment);
+ }
+ return history.getChildNode(versionableUuid);
+ }
+
+ private static List<String> getVersionHistoryPathSegments(String versionableUuid) {
+ final List<String> segments = new ArrayList<String>();
+ segments.add(JCR_SYSTEM);
+ segments.add(JCR_VERSIONSTORAGE);
+ for (int i = 0; i < 3; i++) {
+ segments.add(versionableUuid.substring(i * 2, i * 2 + 2));
+ }
+ return segments;
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java?rev=1694646&r1=1694645&r2=1694646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java Fri Aug 7 10:31:00 2015
@@ -1,226 +1,226 @@
-/*
- * 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.version;
-
-import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
-import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
-import org.apache.jackrabbit.oak.spi.commit.Editor;
-import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-
-import java.util.Set;
-
-import static com.google.common.collect.ImmutableSet.of;
-import static com.google.common.collect.Sets.newHashSet;
-import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
-import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
-import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
-import static org.apache.jackrabbit.JcrConstants.JCR_PREDECESSORS;
-import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
-import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONHISTORY;
-import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
-import static org.apache.jackrabbit.JcrConstants.MIX_VERSIONABLE;
-import static org.apache.jackrabbit.oak.plugins.memory.MultiGenericPropertyState.nameProperty;
-import static org.apache.jackrabbit.oak.plugins.version.VersionConstants.MIX_REP_VERSIONABLE_PATHS;
-
-/**
- * The VersionableEditor provides two possible ways to handle
- * versionable nodes:
- * <ul>
- * <li>it can copy the version histories of versionable nodes, or</li>
- * <li>
- * it can skip copying version histories and remove the
- * {@code mix:versionable} mixin together with any related
- * properties (see {@link #removeVersionProperties(NodeBuilder)}).
- * </li>
- * </ul>
- */
-public class VersionableEditor extends DefaultEditor {
-
- private static final Set<String> SKIPPED_PATHS = of("/oak:index", "/jcr:system/jcr:versionStorage");
-
- private final Provider provider;
-
- private final NodeBuilder rootBuilder;
-
- private final TypePredicate isReferenceable;
-
- private final TypePredicate isVersionable;
-
- private final VersionCopier versionCopier;
-
- private String path;
-
- private VersionableEditor(Provider provider, NodeBuilder builder) {
- this.provider = provider;
- this.rootBuilder = builder;
- this.isVersionable = new TypePredicate(builder.getNodeState(), MIX_VERSIONABLE);
- this.isReferenceable = new TypePredicate(builder.getNodeState(), MIX_REFERENCEABLE);
- this.versionCopier = new VersionCopier(provider.sourceRoot, builder);
- this.path = "/";
- }
-
- public static class Provider implements EditorProvider {
-
- private final NodeState sourceRoot;
-
- private final String workspaceName;
-
- private final VersionCopyConfiguration config;
-
- public Provider(NodeState sourceRoot, String workspaceName, VersionCopyConfiguration config) {
- this.sourceRoot = sourceRoot;
- this.workspaceName = workspaceName;
- this.config = config;
- }
-
- @Override
- public Editor getRootEditor(NodeState before, NodeState after, NodeBuilder builder, CommitInfo info) throws CommitFailedException {
- return new VersionableEditor(this, builder);
- }
- }
-
- @Override
- public Editor childNodeAdded(String name, NodeState after) throws CommitFailedException {
- final String path = PathUtils.concat(this.path, name);
- // skip deleted nodes and well known paths that may not contain versionable nodes
- if (after == null || SKIPPED_PATHS.contains(path)) {
- return null;
- }
-
- // assign path field only after checking that we don't skip this subtree
- this.path = path;
-
- final VersionCopyConfiguration c = provider.config;
- if (isVersionable.apply(after)) {
- final String versionableUuid = getProperty(after, JCR_UUID, Type.STRING);
- boolean versionHistoryExists = isVersionHistoryExists(versionableUuid);
- if (c.isCopyVersions() && c.skipOrphanedVersionsCopy()) {
- versionHistoryExists = copyVersionHistory(after);
- } else if (c.isCopyVersions() && !c.skipOrphanedVersionsCopy()) {
- // all version histories have been copied, but maybe the date
- // range for orphaned entries is narrower
- if (c.getOrphanedMinDate().after(c.getVersionsMinDate())) {
- versionHistoryExists = copyVersionHistory(after);
- }
- } else {
- versionHistoryExists = false;
- }
-
- if (versionHistoryExists) {
- setVersionablePath(versionableUuid);
- } else {
- removeVersionProperties(getNodeBuilder(rootBuilder, this.path));
- }
- }
-
- return this;
- }
-
- private boolean copyVersionHistory(NodeState versionable) {
- assert versionable.exists();
-
- final String versionableUuid = versionable.getProperty(JCR_UUID).getValue(Type.STRING);
- return versionCopier.copyVersionHistory(versionableUuid, provider.config.getVersionsMinDate());
- }
-
- private void setVersionablePath(String versionableUuid) {
- final NodeBuilder versionHistory = VersionHistoryUtil.getVersionHistoryBuilder(rootBuilder, versionableUuid);
- versionHistory.setProperty(provider.workspaceName, path, Type.PATH);
- addMixin(versionHistory, MIX_REP_VERSIONABLE_PATHS);
- }
-
- private boolean isVersionHistoryExists(String versionableUuid) {
- return VersionHistoryUtil.getVersionHistoryNodeState(rootBuilder.getNodeState(), versionableUuid).exists();
- }
-
- private void removeVersionProperties(final NodeBuilder versionableBuilder) {
- assert versionableBuilder.exists();
-
- removeMixin(versionableBuilder, MIX_VERSIONABLE);
-
- // we don't know if the UUID is otherwise referenced,
- // so make sure the node remains referencable
- if (!isReferenceable.apply(versionableBuilder.getNodeState())) {
- addMixin(versionableBuilder, MIX_REFERENCEABLE);
- }
-
- versionableBuilder.removeProperty(JCR_VERSIONHISTORY);
- versionableBuilder.removeProperty(JCR_PREDECESSORS);
- versionableBuilder.removeProperty(JCR_BASEVERSION);
- versionableBuilder.removeProperty(JCR_ISCHECKEDOUT);
- }
-
- @Override
- public Editor childNodeChanged(String name, NodeState before, NodeState after) throws CommitFailedException {
- return childNodeAdded(name, after);
- }
-
- @Override
- public Editor childNodeDeleted(String name, NodeState before) throws CommitFailedException {
- return childNodeAdded(name, null);
- }
-
- @Override
- public void leave(NodeState before, NodeState after) throws CommitFailedException {
- this.path = PathUtils.getParentPath(this.path);
- }
-
- private static <T> T getProperty(NodeState state, String name, Type<T> type) {
- if (state.hasProperty(name)) {
- return state.getProperty(name).getValue(type);
- }
- return null;
- }
-
- private static NodeBuilder getNodeBuilder(NodeBuilder root, String path) {
- NodeBuilder builder = root;
- for (String name : PathUtils.elements(path)) {
- builder = builder.getChildNode(name);
- }
- return builder;
- }
-
- private static void addMixin(NodeBuilder builder, String name) {
- if (builder.hasProperty(JCR_MIXINTYPES)) {
- final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
- if (mixins.add(name)) {
- builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
- }
- } else {
- builder.setProperty(nameProperty(JCR_MIXINTYPES, of(name)));
- }
- }
-
- private static void removeMixin(NodeBuilder builder, String name) {
- if (builder.hasProperty(JCR_MIXINTYPES)) {
- final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
- if (mixins.remove(name)) {
- if (mixins.isEmpty()) {
- builder.removeProperty(JCR_MIXINTYPES);
- } else {
- builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
- }
- }
- }
- }
-}
+/*
+ * 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.version;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
+import org.apache.jackrabbit.oak.spi.commit.Editor;
+import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import java.util.Set;
+
+import static com.google.common.collect.ImmutableSet.of;
+import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PREDECESSORS;
+import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
+import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONHISTORY;
+import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
+import static org.apache.jackrabbit.JcrConstants.MIX_VERSIONABLE;
+import static org.apache.jackrabbit.oak.plugins.memory.MultiGenericPropertyState.nameProperty;
+import static org.apache.jackrabbit.oak.plugins.version.VersionConstants.MIX_REP_VERSIONABLE_PATHS;
+
+/**
+ * The VersionableEditor provides two possible ways to handle
+ * versionable nodes:
+ * <ul>
+ * <li>it can copy the version histories of versionable nodes, or</li>
+ * <li>
+ * it can skip copying version histories and remove the
+ * {@code mix:versionable} mixin together with any related
+ * properties (see {@link #removeVersionProperties(NodeBuilder)}).
+ * </li>
+ * </ul>
+ */
+public class VersionableEditor extends DefaultEditor {
+
+ private static final Set<String> SKIPPED_PATHS = of("/oak:index", "/jcr:system/jcr:versionStorage");
+
+ private final Provider provider;
+
+ private final NodeBuilder rootBuilder;
+
+ private final TypePredicate isReferenceable;
+
+ private final TypePredicate isVersionable;
+
+ private final VersionCopier versionCopier;
+
+ private String path;
+
+ private VersionableEditor(Provider provider, NodeBuilder builder) {
+ this.provider = provider;
+ this.rootBuilder = builder;
+ this.isVersionable = new TypePredicate(builder.getNodeState(), MIX_VERSIONABLE);
+ this.isReferenceable = new TypePredicate(builder.getNodeState(), MIX_REFERENCEABLE);
+ this.versionCopier = new VersionCopier(provider.sourceRoot, builder);
+ this.path = "/";
+ }
+
+ public static class Provider implements EditorProvider {
+
+ private final NodeState sourceRoot;
+
+ private final String workspaceName;
+
+ private final VersionCopyConfiguration config;
+
+ public Provider(NodeState sourceRoot, String workspaceName, VersionCopyConfiguration config) {
+ this.sourceRoot = sourceRoot;
+ this.workspaceName = workspaceName;
+ this.config = config;
+ }
+
+ @Override
+ public Editor getRootEditor(NodeState before, NodeState after, NodeBuilder builder, CommitInfo info) throws CommitFailedException {
+ return new VersionableEditor(this, builder);
+ }
+ }
+
+ @Override
+ public Editor childNodeAdded(String name, NodeState after) throws CommitFailedException {
+ final String path = PathUtils.concat(this.path, name);
+ // skip deleted nodes and well known paths that may not contain versionable nodes
+ if (after == null || SKIPPED_PATHS.contains(path)) {
+ return null;
+ }
+
+ // assign path field only after checking that we don't skip this subtree
+ this.path = path;
+
+ final VersionCopyConfiguration c = provider.config;
+ if (isVersionable.apply(after)) {
+ final String versionableUuid = getProperty(after, JCR_UUID, Type.STRING);
+ boolean versionHistoryExists = isVersionHistoryExists(versionableUuid);
+ if (c.isCopyVersions() && c.skipOrphanedVersionsCopy()) {
+ versionHistoryExists = copyVersionHistory(after);
+ } else if (c.isCopyVersions() && !c.skipOrphanedVersionsCopy()) {
+ // all version histories have been copied, but maybe the date
+ // range for orphaned entries is narrower
+ if (c.getOrphanedMinDate().after(c.getVersionsMinDate())) {
+ versionHistoryExists = copyVersionHistory(after);
+ }
+ } else {
+ versionHistoryExists = false;
+ }
+
+ if (versionHistoryExists) {
+ setVersionablePath(versionableUuid);
+ } else {
+ removeVersionProperties(getNodeBuilder(rootBuilder, this.path));
+ }
+ }
+
+ return this;
+ }
+
+ private boolean copyVersionHistory(NodeState versionable) {
+ assert versionable.exists();
+
+ final String versionableUuid = versionable.getProperty(JCR_UUID).getValue(Type.STRING);
+ return versionCopier.copyVersionHistory(versionableUuid, provider.config.getVersionsMinDate());
+ }
+
+ private void setVersionablePath(String versionableUuid) {
+ final NodeBuilder versionHistory = VersionHistoryUtil.getVersionHistoryBuilder(rootBuilder, versionableUuid);
+ versionHistory.setProperty(provider.workspaceName, path, Type.PATH);
+ addMixin(versionHistory, MIX_REP_VERSIONABLE_PATHS);
+ }
+
+ private boolean isVersionHistoryExists(String versionableUuid) {
+ return VersionHistoryUtil.getVersionHistoryNodeState(rootBuilder.getNodeState(), versionableUuid).exists();
+ }
+
+ private void removeVersionProperties(final NodeBuilder versionableBuilder) {
+ assert versionableBuilder.exists();
+
+ removeMixin(versionableBuilder, MIX_VERSIONABLE);
+
+ // we don't know if the UUID is otherwise referenced,
+ // so make sure the node remains referencable
+ if (!isReferenceable.apply(versionableBuilder.getNodeState())) {
+ addMixin(versionableBuilder, MIX_REFERENCEABLE);
+ }
+
+ versionableBuilder.removeProperty(JCR_VERSIONHISTORY);
+ versionableBuilder.removeProperty(JCR_PREDECESSORS);
+ versionableBuilder.removeProperty(JCR_BASEVERSION);
+ versionableBuilder.removeProperty(JCR_ISCHECKEDOUT);
+ }
+
+ @Override
+ public Editor childNodeChanged(String name, NodeState before, NodeState after) throws CommitFailedException {
+ return childNodeAdded(name, after);
+ }
+
+ @Override
+ public Editor childNodeDeleted(String name, NodeState before) throws CommitFailedException {
+ return childNodeAdded(name, null);
+ }
+
+ @Override
+ public void leave(NodeState before, NodeState after) throws CommitFailedException {
+ this.path = PathUtils.getParentPath(this.path);
+ }
+
+ private static <T> T getProperty(NodeState state, String name, Type<T> type) {
+ if (state.hasProperty(name)) {
+ return state.getProperty(name).getValue(type);
+ }
+ return null;
+ }
+
+ private static NodeBuilder getNodeBuilder(NodeBuilder root, String path) {
+ NodeBuilder builder = root;
+ for (String name : PathUtils.elements(path)) {
+ builder = builder.getChildNode(name);
+ }
+ return builder;
+ }
+
+ private static void addMixin(NodeBuilder builder, String name) {
+ if (builder.hasProperty(JCR_MIXINTYPES)) {
+ final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
+ if (mixins.add(name)) {
+ builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
+ }
+ } else {
+ builder.setProperty(nameProperty(JCR_MIXINTYPES, of(name)));
+ }
+ }
+
+ private static void removeMixin(NodeBuilder builder, String name) {
+ if (builder.hasProperty(JCR_MIXINTYPES)) {
+ final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
+ if (mixins.remove(name)) {
+ if (mixins.isEmpty()) {
+ builder.removeProperty(JCR_MIXINTYPES);
+ } else {
+ builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
+ }
+ }
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java
------------------------------------------------------------------------------
svn:eol-style = native