Author: tomekr
Date: Fri Apr 28 07:16:13 2017
New Revision: 1792993

URL: http://svn.apache.org/viewvc?rev=1792993&view=rev
Log:
OAK-6132: Backport oak-upgrade to 1.0 and 1.2

Added:
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/core/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/core/IndexAccessor.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/LoggingEqualsDiff.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/SameNameSiblingsEditor.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/UpgradeRoot.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/checkpoint/CheckpointRetriever.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/ConstantBlobStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStore.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/SafeDataStoreBlobStore.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/DatastoreArguments.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationOptions.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/OptionParserFactory.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreArguments.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreType.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/AbstractDecoratedNodeState.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeState.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NameFilteringNodeState.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopier.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/LoggingReporter.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/PeriodicReporter.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/Reporter.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/ReportingNodeState.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/AuthorizableFolderEditor.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopyConfiguration.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionablePropertiesEditor.java
    jackrabbit/oak/branches/1.0/oak-upgrade/src/main/resources/
    jackrabbit/oak/branches/1.0/oak-upgrade/src/main/resources/logback.xml
    jackrabbit/oak/branches/1.0/oak-upgrade/src/main/resources/upgrade_usage.txt
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AuthorizableFolderEditorTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/BrokenVersionableTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyCheckpointsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyNodeTypesUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistoryTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/IgnoreMissingBinariesTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/IncludeExcludeSidegradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/IncludeExcludeUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/LongNameTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/PrivilegeUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositorySidegradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepeatedRepositoryUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegradeTest.java
      - copied, changed from r1792992, 
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/SameNodeSiblingsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/UpgradeFromTwoSourcesTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/UpgradeOldSegmentTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Jcr2ToSegmentTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFdsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToSegmentTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToSegmentWithMissingDestinationDirectoryTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Util.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/CopyBinariesTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFbsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFdsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToS3Test.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FdsToFbsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3ToFbsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/StripConfigValueTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/BlobStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/DummyBlobStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileBlobStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileDataStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/JdbcNodeStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/MongoNodeStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/NodeStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/S3DataStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/SegmentNodeStoreContainer.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/parser/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreArgumentsTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/FilteringNodeStateTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/NodeStateCopierTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/AssertingPeriodicReporter.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/PeriodicReporterTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/nodestate/report/ReportingNodeStateTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/NodeStateTestUtils.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/util/VersionCopyTestUtils.java
    jackrabbit/oak/branches/1.0/oak-upgrade/src/test/resources/jcr2.zip
    jackrabbit/oak/branches/1.0/oak-upgrade/src/test/resources/segmentstore.zip
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/resources/test-nodetypes.cnd
    jackrabbit/oak/branches/1.0/oak-upgrade/src/test/resources/test-repo-1.0.zip
Modified:
    jackrabbit/oak/branches/1.0/oak-upgrade/pom.xml
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/JackrabbitNodeState.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/blob/LengthCachingDataStore.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/GroupEditor.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepositoryGroupMemberUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgradeTest.java
    
jackrabbit/oak/branches/1.0/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/blob/LengthCachingDataStoreTest.java
    jackrabbit/oak/branches/1.0/oak-upgrade/src/test/resources/logback-test.xml

Modified: jackrabbit/oak/branches/1.0/oak-upgrade/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/pom.xml?rev=1792993&r1=1792992&r2=1792993&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-upgrade/pom.xml (original)
+++ jackrabbit/oak/branches/1.0/oak-upgrade/pom.xml Fri Apr 28 07:16:13 2017
@@ -37,10 +37,31 @@
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
           <systemPropertyVariables>
-            <derby.stream.error.file>target/derby.log</derby.stream.error.file>
+            <s3.properties>${s3.properties}</s3.properties>
           </systemPropertyVariables>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>1.6</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <createDependencyReducedPom>false</createDependencyReducedPom>
+              <transformers>
+                <transformer 
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  
<mainClass>org.apache.jackrabbit.oak.upgrade.cli.OakUpgrade</mainClass>
+                </transformer>
+              </transformers>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
 
@@ -57,39 +78,71 @@
     </dependency>
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-data</artifactId>
+      <version>${jackrabbit.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-aws-ext</artifactId>
+      <version>${jackrabbit.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
       <artifactId>jackrabbit-spi</artifactId>
       <version>${jackrabbit.version}</version>
     </dependency>
 
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>net.sf.jopt-simple</groupId>
+      <artifactId>jopt-simple</artifactId>
+      <version>4.6</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mongodb</groupId>
+      <artifactId>mongo-java-driver</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat</groupId>
+      <artifactId>tomcat-jdbc</artifactId>
+    </dependency>
+
     <!-- Logging -->
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
 
     <!-- Findbugs annotations -->
     <dependency>
       <groupId>com.google.code.findbugs</groupId>
       <artifactId>jsr305</artifactId>
-      <version>2.0.0</version>
       <scope>provided</scope>
     </dependency>
 
     <!-- Test Dependencies -->
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-all</artifactId>
+      <version>1.3</version>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.jackrabbit</groupId>
-      <artifactId>oak-jcr</artifactId>
-      <version>${project.version}</version>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
-      <artifactId>oak-mk</artifactId>
+      <artifactId>oak-jcr</artifactId>
       <version>${project.version}</version>
       <scope>test</scope>
     </dependency>
@@ -99,11 +152,6 @@
       <version>${h2.version}</version>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <!-- Workaround for http://bugs.java.com/view_bug.do?bug_id=6550655 -->
@@ -122,5 +170,4 @@
       </dependencies>
     </profile>
   </profiles>
-
 </project>

Added: 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/core/IndexAccessor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/core/IndexAccessor.java?rev=1792993&view=auto
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/core/IndexAccessor.java
 (added)
+++ 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/core/IndexAccessor.java
 Fri Apr 28 07:16:13 2017
@@ -0,0 +1,42 @@
+/*
+ * 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.core;
+
+import org.apache.jackrabbit.core.query.QueryHandler;
+import org.apache.jackrabbit.core.query.lucene.SearchIndex;
+import org.apache.lucene.index.IndexReader;
+
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+
+public final class IndexAccessor {
+
+    private IndexAccessor() {
+    }
+
+    public static IndexReader getReader(RepositoryContext ctx) throws 
RepositoryException, IOException {
+        RepositoryImpl repo = ctx.getRepository();
+        SearchManager searchMgr = 
repo.getSearchManager(ctx.getRepositoryConfig().getDefaultWorkspaceName());
+        if (searchMgr == null) {
+            return null;
+        }
+        QueryHandler handler = searchMgr.getQueryHandler();
+        SearchIndex index = (SearchIndex) handler;
+        return index.getIndexReader();
+    }
+
+}

Added: 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java?rev=1792993&view=auto
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java
 (added)
+++ 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointRetriever.java
 Fri Apr 28 07:16:13 2017
@@ -0,0 +1,38 @@
+/*
+ * 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.plugins.document;
+
+import org.apache.jackrabbit.oak.upgrade.checkpoint.CheckpointRetriever;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class DocumentCheckpointRetriever {
+
+    public static List<CheckpointRetriever.Checkpoint> 
getCheckpoints(DocumentNodeStore nodeStore) {
+        List<CheckpointRetriever.Checkpoint> result = new 
ArrayList<CheckpointRetriever.Checkpoint>();
+        for (Map.Entry<Revision, String> e : 
nodeStore.getCheckpoints().getCheckpoints().entrySet()) {
+            long created = e.getKey().getTimestamp();
+            result.add(new 
CheckpointRetriever.Checkpoint(e.getKey().toString(), created, 
Long.parseLong(e.getValue())));
+        }
+        return result;
+    }
+
+}
\ No newline at end of file

Added: 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java?rev=1792993&view=auto
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java
 (added)
+++ 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/DescendantsIterator.java
 Fri Apr 28 07:16:13 2017
@@ -0,0 +1,62 @@
+/*
+ * 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 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;
+    }
+
+}

Modified: 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/JackrabbitNodeState.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/JackrabbitNodeState.java?rev=1792993&r1=1792992&r2=1792993&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/JackrabbitNodeState.java
 (original)
+++ 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/JackrabbitNodeState.java
 Fri Apr 28 07:16:13 2017
@@ -18,9 +18,8 @@ package org.apache.jackrabbit.oak.upgrad
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Iterables.addAll;
-import static com.google.common.collect.Iterables.skip;
-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 com.google.common.collect.Maps.newLinkedHashMap;
@@ -32,13 +31,15 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 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.JcrConstants.NT_BASE;
 import static org.apache.jackrabbit.JcrConstants.NT_FROZENNODE;
 import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
 import static org.apache.jackrabbit.JcrConstants.NT_VERSIONHISTORY;
+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;
 import static org.apache.jackrabbit.oak.api.Type.NAME;
 import static org.apache.jackrabbit.oak.api.Type.NAMES;
 import static org.apache.jackrabbit.oak.api.Type.STRING;
@@ -48,15 +49,21 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
 import javax.jcr.Binary;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import org.apache.jackrabbit.api.ReferenceBinary;
+import org.apache.jackrabbit.core.RepositoryContext;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
 import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
@@ -87,16 +94,7 @@ class JackrabbitNodeState extends Abstra
     private static final Logger log =
             LoggerFactory.getLogger(JackrabbitNodeState.class);
 
-    private static long count = 0;
-
-    private static void logNewNode(JackrabbitNodeState state) {
-        count++;
-        if (count % 10000 == 0) {
-            log.info("Migrating node #" + count + ": " + state.getPath());
-        }
-    }
-
-    private final JackrabbitNodeState parent;
+    private JackrabbitNodeState parent;
 
     private final String name;
 
@@ -107,6 +105,10 @@ class JackrabbitNodeState extends Abstra
      */
     private final BundleLoader loader;
 
+    /**
+     * Workspace name used for versionable paths. This is null
+     * for the jcr:versionStorage and jcr:activities nodes.
+     */
     private final String workspaceName;
 
     private final TypePredicate isReferenceable;
@@ -126,17 +128,60 @@ class JackrabbitNodeState extends Abstra
      */
     private final Map<String, String> uriToPrefix;
 
-    private final Map<String, String> versionablePaths;
-
     private final boolean useBinaryReferences;
 
     private final Map<String, NodeId> nodes;
 
     private final Map<String, PropertyState> properties;
 
+    private final Map<NodeId, JackrabbitNodeState> mountPoints;
+
+    private final Map<NodeId, JackrabbitNodeState> nodeStateCache;
+
+    private final List<String> ignoredPaths = 
ImmutableList.of("/jcr:system/jcr:nodeTypes");
+
+    public static JackrabbitNodeState createRootNodeState(
+            RepositoryContext context,
+            String workspaceName,
+            NodeState root,
+            Map<String, String> uriToPrefix,
+            boolean copyBinariesByReference,
+            boolean skipOnError
+    ) throws RepositoryException {
+
+        final Map<NodeId, JackrabbitNodeState> emptyMountPoints = 
ImmutableMap.of();
+        final PersistenceManager versionPM = 
context.getInternalVersionManager().getPersistenceManager();
+        final JackrabbitNodeState versionStorage = new JackrabbitNodeState(
+                versionPM, root, uriToPrefix,
+                VERSION_STORAGE_NODE_ID, "/jcr:system/jcr:versionStorage",
+                null,
+                emptyMountPoints,
+                copyBinariesByReference,
+                skipOnError
+        );
+
+        final JackrabbitNodeState activities = new JackrabbitNodeState(
+                versionPM, root, uriToPrefix,
+                ACTIVITIES_NODE_ID, "/jcr:system/jcr:activities",
+                null,
+                emptyMountPoints,
+                copyBinariesByReference,
+                skipOnError
+        );
+
+
+        PersistenceManager pm = 
context.getWorkspaceInfo(workspaceName).getPersistenceManager();
+        final Map<NodeId, JackrabbitNodeState> mountPoints = ImmutableMap.of(
+                VERSION_STORAGE_NODE_ID, versionStorage,
+                ACTIVITIES_NODE_ID, activities
+        );
+        return new JackrabbitNodeState(
+                pm, root, uriToPrefix, ROOT_NODE_ID, "/",
+                workspaceName, mountPoints, copyBinariesByReference, 
skipOnError);
+    }
+
     private JackrabbitNodeState(
-            JackrabbitNodeState parent, String name, NodePropBundle bundle,
-            boolean skipOnError) {
+            JackrabbitNodeState parent, String name, NodePropBundle bundle) {
         this.parent = parent;
         this.name = name;
         this.path = null;
@@ -148,24 +193,24 @@ class JackrabbitNodeState extends Abstra
         this.isVersionHistory = parent.isVersionHistory;
         this.isFrozenNode = parent.isFrozenNode;
         this.uriToPrefix = parent.uriToPrefix;
-        this.versionablePaths = parent.versionablePaths;
         this.useBinaryReferences = parent.useBinaryReferences;
         this.properties = createProperties(bundle);
         this.nodes = createNodes(bundle);
-        this.skipOnError = skipOnError;
+        this.skipOnError = parent.skipOnError;
+        this.mountPoints = parent.mountPoints;
+        this.nodeStateCache = parent.nodeStateCache;
         setChildOrder();
-        setVersionablePaths();
         fixFrozenUuid();
-        logNewNode(this);
     }
 
     JackrabbitNodeState(
             PersistenceManager source, NodeState root,
             Map<String, String> uriToPrefix, NodeId id, String path,
-            String workspaceName, Map<String, String> versionablePaths,
+            String workspaceName,
+            Map<NodeId, JackrabbitNodeState> mountPoints,
             boolean useBinaryReferences, boolean skipOnError) {
         this.parent = null;
-        this.name = null;
+        this.name = PathUtils.getName(path);
         this.path = path;
         this.loader = new BundleLoader(source);
         this.workspaceName = workspaceName;
@@ -175,7 +220,14 @@ class JackrabbitNodeState extends Abstra
         this.isVersionHistory = new TypePredicate(root, NT_VERSIONHISTORY);
         this.isFrozenNode = new TypePredicate(root, NT_FROZENNODE);
         this.uriToPrefix = uriToPrefix;
-        this.versionablePaths = versionablePaths;
+        this.mountPoints = mountPoints;
+        final int cacheSize = 50; // cache size 50 results in > 25% cache hits 
during version copy
+        this.nodeStateCache = new LinkedHashMap<NodeId, 
JackrabbitNodeState>(cacheSize, 0.75f, true) {
+            @Override
+            protected boolean removeEldestEntry(Map.Entry<NodeId, 
JackrabbitNodeState> eldest) {
+                return size() >= cacheSize;
+            }
+        };
         this.useBinaryReferences = useBinaryReferences;
         this.skipOnError = skipOnError;
         try {
@@ -186,7 +238,6 @@ class JackrabbitNodeState extends Abstra
         } catch (ItemStateException e) {
             throw new IllegalStateException("Unable to access node " + id, e);
         }
-        logNewNode(this);
     }
 
     @Override
@@ -207,15 +258,16 @@ class JackrabbitNodeState extends Abstra
     }
 
     @Override
-    public boolean hasProperty(String name) {
+    public boolean hasProperty(@Nonnull String name) {
         return properties.containsKey(name);
     }
 
     @Override
-    public PropertyState getProperty(String name) {
+    public PropertyState getProperty(@Nonnull String name) {
         return properties.get(name);
     }
 
+    @Nonnull
     @Override
     public Iterable<PropertyState> getProperties() {
         return properties.values();
@@ -227,30 +279,20 @@ class JackrabbitNodeState extends Abstra
     }
 
     @Override
-    public boolean hasChildNode(String name) {
+    public boolean hasChildNode(@Nonnull String name) {
         return nodes.containsKey(name);
     }
 
+    @Nonnull
     @Override
-    public NodeState getChildNode(String name) {
+    public NodeState getChildNode(@Nonnull String name) {
         NodeId id = nodes.get(name);
+        NodeState state = null;
         if (id != null) {
-            try {
-                return new JackrabbitNodeState(
-                        this, name, loader.loadBundle(id), skipOnError);
-            } catch (ItemStateException e) {
-                if (!skipOnError) {
-                    throw new IllegalStateException(
-                            "Unable to access child node " + name, e);
-                }
-                warn("Skipping broken child node entry " + name + " and 
changing the primary type to nt:unstructured", e);
-                properties.put(JCR_PRIMARYTYPE, PropertyStates.createProperty(
-                        JCR_PRIMARYTYPE, NT_UNSTRUCTURED, Type.NAME));
-
-            }
+            state = createChildNodeState(id, name);
         }
         checkValidName(name);
-        return EmptyNodeState.MISSING_NODE;
+        return state != null ? state : EmptyNodeState.MISSING_NODE;
     }
 
     @Override
@@ -258,22 +300,21 @@ class JackrabbitNodeState extends Abstra
         return nodes.keySet();
     }
 
+    @Nonnull
     @Override
     public Iterable<MemoryChildNodeEntry> getChildNodeEntries() {
-        List<MemoryChildNodeEntry> entries = newArrayList();
+        List<MemoryChildNodeEntry> entries = 
newArrayListWithCapacity(nodes.size());
         for (Map.Entry<String, NodeId> entry : nodes.entrySet()) {
             String name = entry.getKey();
-            try {
-                JackrabbitNodeState child = new JackrabbitNodeState(
-                        this, name, loader.loadBundle(entry.getValue()), 
skipOnError);
+            final NodeState child = createChildNodeState(entry.getValue(), 
name);
+            if (child != null) {
                 entries.add(new MemoryChildNodeEntry(name, child));
-            } catch (ItemStateException e) {
-                warn("Skipping broken child node entry " + name, e);
             }
         }
         return entries;
     }
 
+    @Nonnull
     @Override
     public NodeBuilder builder() {
         return new MemoryNodeBuilder(this);
@@ -281,6 +322,40 @@ class JackrabbitNodeState extends Abstra
 
     //-----------------------------------------------------------< private >--
 
+    @CheckForNull
+    private JackrabbitNodeState createChildNodeState(NodeId id, String name) {
+        if (mountPoints.containsKey(id)) {
+            final JackrabbitNodeState nodeState = mountPoints.get(id);
+            checkState(name.equals(nodeState.name),
+                    "Expected mounted node " + id + " to be called " + 
nodeState.name +
+                            " instead of " + name);
+            nodeState.parent = this;
+            return nodeState;
+        }
+
+        JackrabbitNodeState state = nodeStateCache.get(id);
+        if (state == null) {
+            try {
+                state = new JackrabbitNodeState(this, name, 
loader.loadBundle(id));
+                nodeStateCache.put(id, state);
+            } catch (ItemStateException e) {
+                handleBundleLoadingException(name, e);
+            } catch (NullPointerException e) {
+                handleBundleLoadingException(name, e);
+            }
+        }
+        return state;
+    }
+
+    private void handleBundleLoadingException(final @Nonnull String name, 
final Exception e) {
+        if (!skipOnError) {
+            throw new IllegalStateException("Unable to access child node " + 
name + " of " + getPath(), e);
+        }
+        warn("Skipping broken child node entry " + name + " and changing the 
primary type to nt:unstructured", e);
+        properties.put(JCR_PRIMARYTYPE, PropertyStates.createProperty(
+                JCR_PRIMARYTYPE, NT_UNSTRUCTURED, Type.NAME));
+    }
+
     private void setChildOrder() {
         if (isOrderable.apply(this)) {
             properties.put(OAK_CHILD_ORDER, PropertyStates.createProperty(
@@ -288,21 +363,6 @@ class JackrabbitNodeState extends Abstra
         }
     }
 
-    private void setVersionablePaths() {
-        if (isVersionable.apply(this)) {
-            String uuid = getString(JCR_VERSIONHISTORY);
-            if (uuid != null) {
-                versionablePaths.put(uuid, getPath());
-            }
-        } else if (isVersionHistory.apply(this)) {
-            String uuid = getString(JCR_UUID);
-            String path = versionablePaths.get(uuid);
-            if (path != null) {
-                properties.put(workspaceName, 
PropertyStates.createProperty(workspaceName, path, Type.PATH));
-            }
-        }
-    }
-
     private Map<String, NodeId> createNodes(NodePropBundle bundle) {
         Map<String, NodeId> children = newLinkedHashMap();
         for (ChildNodeEntry entry : bundle.getChildNodeEntries()) {
@@ -311,7 +371,10 @@ class JackrabbitNodeState extends Abstra
             for (int i = 2; children.containsKey(name); i++) {
                 name = base + '[' + i + ']';
             }
-            children.put(name, entry.getId());
+
+            if (!ignoredPaths.contains(PathUtils.concat(getPath(), name))) {
+                children.put(name, entry.getId());
+            }
         }
         return children;
     }
@@ -351,6 +414,11 @@ class JackrabbitNodeState extends Abstra
                 mixins.add(createName(mixin));
             }
         }
+
+        if (mixins.remove("mix:simpleVersionable")) {
+            mixins.add(MIX_VERSIONABLE);
+        }
+
         if (!mixins.isEmpty()) {
             properties.put(JCR_MIXINTYPES, PropertyStates.createProperty(
                     JCR_MIXINTYPES, mixins, Type.NAMES));
@@ -533,6 +601,8 @@ class JackrabbitNodeState extends Abstra
                     return 0;
                 }
             }
+
+            @Nonnull
             @Override
             public InputStream getNewStream() {
                 try {
@@ -542,6 +612,7 @@ class JackrabbitNodeState extends Abstra
                     return new ByteArrayInputStream(new byte[0]);
                 }
             }
+
             @Override
             public String getReference() {
                 if (!useBinaryReferences) {
@@ -563,6 +634,22 @@ class JackrabbitNodeState extends Abstra
                     return null;
                 }
             }
+
+            @Override
+            public String getContentIdentity() {
+                final String reference = getReference();
+                if (reference != null) {
+                    final int pos = reference.indexOf(":");
+                    final String blobHash;
+                    if (pos > -1) {
+                        blobHash = reference.substring(0, pos);
+                    } else {
+                        blobHash = reference;
+                    }
+                    return blobHash + "#" + length();
+                }
+                return super.getContentIdentity();
+            }
         };
     }
 

Added: 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/LoggingEqualsDiff.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/LoggingEqualsDiff.java?rev=1792993&view=auto
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/LoggingEqualsDiff.java
 (added)
+++ 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/LoggingEqualsDiff.java
 Fri Apr 28 07:16:13 2017
@@ -0,0 +1,87 @@
+/*
+ * 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.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.slf4j.Logger;
+
+public class LoggingEqualsDiff implements NodeStateDiff {
+
+    private final Logger log;
+
+    private final String path;
+
+    private boolean pathDisplayed;
+
+    public LoggingEqualsDiff(Logger log, String path) {
+        this.log = log;
+        this.path = path;
+    }
+
+    @Override
+    public boolean propertyAdded(PropertyState after) {
+        displayPath();
+        log.info("  + {}<{}>", after.getName(), after.getType());
+        return false;
+    }
+
+    @Override
+    public boolean propertyChanged(PropertyState before, PropertyState after) {
+        displayPath();
+        log.info("  ^ {}<{}>", before.getName(), before.getType());
+        return false;
+    }
+
+    @Override
+    public boolean propertyDeleted(PropertyState before) {
+        displayPath();
+        log.info("  - {}<{}>", before.getName(), before.getType());
+        return false;
+    }
+
+    @Override
+    public boolean childNodeAdded(String name, NodeState after) {
+        String childPath = PathUtils.concat(path, name);
+        log.info("+ {}", childPath);
+        return false;
+    }
+
+    @Override
+    public boolean childNodeChanged(String name, NodeState before, NodeState 
after) {
+        String childPath = PathUtils.concat(path, name);
+        return after.compareAgainstBaseState(before, new 
LoggingEqualsDiff(log, childPath));
+    }
+
+    @Override
+    public boolean childNodeDeleted(String name, NodeState before) {
+        String childPath = PathUtils.concat(path, name);
+        log.info("- {}", childPath);
+        return false;
+    }
+
+    private void displayPath() {
+        if (!pathDisplayed) {
+            log.info("^ {}", path);
+            pathDisplayed = true;
+        }
+    }
+}

Modified: 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java?rev=1792993&r1=1792992&r2=1792993&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
 (original)
+++ 
jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
 Fri Apr 28 07:16:13 2017
@@ -16,30 +16,69 @@
  */
 package org.apache.jackrabbit.oak.upgrade;
 
-import java.io.File;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
 import javax.jcr.RepositoryException;
 
-import com.google.common.base.Charsets;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeBuilder;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.state.ApplyDiff;
 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.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.LoggingCompositeHook;
+import org.apache.jackrabbit.oak.upgrade.checkpoint.CheckpointRetriever;
+import org.apache.jackrabbit.oak.upgrade.cli.node.TarNodeStore;
+import org.apache.jackrabbit.oak.upgrade.nodestate.NameFilteringNodeState;
+import org.apache.jackrabbit.oak.upgrade.nodestate.report.LoggingReporter;
+import org.apache.jackrabbit.oak.upgrade.nodestate.report.ReportingNodeState;
+import org.apache.jackrabbit.oak.upgrade.nodestate.NodeStateCopier;
+import org.apache.jackrabbit.oak.upgrade.version.VersionCopyConfiguration;
+import org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil;
+import org.apache.jackrabbit.oak.upgrade.version.VersionableEditor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.ImmutableSet.copyOf;
+import static com.google.common.collect.ImmutableSet.of;
+import static com.google.common.collect.Sets.union;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
+import static 
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants.NT_REP_PERMISSION_STORE;
+import static 
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants.REP_PERMISSION_STORE;
+import static 
org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.DEFAULT_EXCLUDE_PATHS;
+import static 
org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.DEFAULT_INCLUDE_PATHS;
+import static 
org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.DEFAULT_MERGE_PATHS;
+import static 
org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.calculateEffectiveIncludePaths;
+import static 
org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.createIndexEditorProvider;
+import static 
org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade.createTypeEditorProvider;
+import static 
org.apache.jackrabbit.oak.upgrade.nodestate.NodeStateCopier.copyProperties;
+import static 
org.apache.jackrabbit.oak.upgrade.version.VersionCopier.copyVersionStorage;
+import static 
org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionStorage;
+
 public class RepositorySidegrade {
 
-    /**
-     * Logger instance
-     */
-    private static final Logger logger =
-        LoggerFactory.getLogger(RepositorySidegrade.class);
+    private static final Logger LOG = 
LoggerFactory.getLogger(RepositorySidegrade.class);
+
+    private static final int LOG_NODE_COPY = 
Integer.getInteger("oak.upgrade.logNodeCopy", 10000);
+
+    private static final String WORKSPACE_NAME_PROP = 
"oak.upgrade.workspaceName";
 
     /**
      * Target node store.
@@ -48,7 +87,67 @@ public class RepositorySidegrade {
 
     private final NodeStore source;
 
-    private boolean copyBinariesByReference = false;
+    /**
+     * Paths to include during the copy process. Defaults to the root path "/".
+     */
+    private Set<String> includePaths = DEFAULT_INCLUDE_PATHS;
+
+    /**
+     * Paths to exclude during the copy process. Empty by default.
+     */
+    private Set<String> excludePaths = DEFAULT_EXCLUDE_PATHS;
+
+    /**
+     * Paths to merge during the copy process. Empty by default.
+     */
+    private Set<String> mergePaths = DEFAULT_MERGE_PATHS;
+
+    private boolean skipCheckpoints = false;
+
+    private boolean filterLongNames = true;
+
+    private boolean verify = false;
+
+    private boolean onlyVerify = false;
+
+    private List<CommitHook> customCommitHooks = null;
+
+    VersionCopyConfiguration versionCopyConfiguration = new 
VersionCopyConfiguration();
+
+    /**
+     * Configures the version storage copy. Be default all versions are copied.
+     * One may disable it completely by setting {@code null} here or limit it 
to
+     * a selected date range: {@code <minDate, now()>}.
+     * 
+     * @param minDate
+     *            minimum date of the versions to copy or {@code null} to
+     *            disable the storage version copying completely. Default 
value:
+     *            {@code 1970-01-01 00:00:00}.
+     */
+    public void setCopyVersions(Calendar minDate) {
+        versionCopyConfiguration.setCopyVersions(minDate);
+    }
+
+    /**
+     * Configures copying of the orphaned version histories (eg. ones that are
+     * not referenced by the existing nodes). By default all orphaned version
+     * histories are copied. One may disable it completely by setting
+     * {@code null} here or limit it to a selected date range:
+     * {@code <minDate, now()>}. <br>
+     * <br>
+     * Please notice, that this option is overriden by the
+     * {@link #setCopyVersions(Calendar)}. You can't copy orphaned versions
+     * older than set in {@link #setCopyVersions(Calendar)} and if you set
+     * {@code null} there, this option will be ignored.
+     * 
+     * @param minDate
+     *            minimum date of the orphaned versions to copy or {@code null}
+     *            to not copy them at all. Default value:
+     *            {@code 1970-01-01 00:00:00}.
+     */
+    public void setCopyOrphanedVersions(Calendar minDate) {
+        versionCopyConfiguration.setCopyOrphanedVersions(minDate);
+    }
 
     /**
      * Creates a tool for copying the full contents of the source repository
@@ -63,32 +162,72 @@ public class RepositorySidegrade {
         this.target = target;
     }
 
-    public boolean isCopyBinariesByReference() {
-        return copyBinariesByReference;
+    /**
+     * Returns the list of custom CommitHooks to be applied before the final
+     * type validation, reference and indexing hooks.
+     *
+     * @return the list of custom CommitHooks
+     */
+    public List<CommitHook> getCustomCommitHooks() {
+        return customCommitHooks;
     }
 
-    public void setCopyBinariesByReference(boolean copyBinariesByReference) {
-        this.copyBinariesByReference = copyBinariesByReference;
+    /**
+     * Sets the list of custom CommitHooks to be applied before the final
+     * type validation, reference and indexing hooks.
+     *
+     * @param customCommitHooks the list of custom CommitHooks
+     */
+    public void setCustomCommitHooks(List<CommitHook> customCommitHooks) {
+        this.customCommitHooks = customCommitHooks;
     }
 
     /**
-     * Copies the full content from the source to the target repository.
-     * <p>
-     * The source repository <strong>must not be modified</strong> while
-     * the copy operation is running to avoid an inconsistent copy.
-     * <p>
-     * Note that both the source and the target repository must be closed
-     * during the copy operation as this method requires exclusive access
-     * to the repositories.
+     * Sets the paths that should be included when the source repository
+     * is copied to the target repository.
      *
-     * @param source source node store
-     * @param target target node store
-     * @throws RepositoryException if the copy operation fails
+     * @param includes Paths to be included in the copy.
+     */
+    public void setIncludes(@Nonnull String... includes) {
+        this.includePaths = copyOf(checkNotNull(includes));
+    }
+
+    /**
+     * Sets the paths that should be excluded when the source repository
+     * is copied to the target repository.
+     *
+     * @param excludes Paths to be excluded from the copy.
      */
-    public static void copy(NodeStore source, NodeStore target)
-            throws RepositoryException {
-        new RepositorySidegrade(source, target).copy();
+    public void setExcludes(@Nonnull String... excludes) {
+        this.excludePaths = copyOf(checkNotNull(excludes));
     }
+
+    /**
+     * Sets the paths that should be merged when the source repository
+     * is copied to the target repository.
+     *
+     * @param merges Paths to be merged during copy.
+     */
+    public void setMerges(@Nonnull String... merges) {
+        this.mergePaths = copyOf(checkNotNull(merges));
+    }
+
+    public void setFilterLongNames(boolean filterLongNames) {
+        this.filterLongNames = filterLongNames;
+    }
+
+    public void setVerify(boolean verify) {
+        this.verify = verify;
+    }
+
+    public void setOnlyVerify(boolean onlyVerify) {
+        this.onlyVerify = onlyVerify;
+    }
+
+    public void setSkipCheckpoints(boolean skipCheckpoints) {
+        this.skipCheckpoints = skipCheckpoints;
+    }
+
     /**
      * Copies the full content from the source to the target repository.
      * <p>
@@ -103,51 +242,230 @@ public class RepositorySidegrade {
      */
     public void copy() throws RepositoryException {
         try {
-            NodeState root = source.getRoot();
-            NodeBuilder builder = target.getRoot().builder();
-
-            new InitialContent().initialize(builder);
-
-            copyState(builder, root);
+            if (!onlyVerify) {
+                if 
(VersionHistoryUtil.getVersionStorage(target.getRoot()).exists() && 
!versionCopyConfiguration.skipOrphanedVersionsCopy()) {
+                    LOG.warn("The version storage on destination already 
exists. Orphaned version histories will be skipped.");
+                    versionCopyConfiguration.setCopyOrphanedVersions(null);
+                }
+                copyState();
+            }
+            if (verify || onlyVerify) {
+                verify();
+            }
 
-            target.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
         } catch (Exception e) {
             throw new RepositoryException("Failed to copy content", e);
         }
     }
 
-    private void copyState(NodeBuilder parent, NodeState state) throws 
CommitFailedException {
-        boolean isSegmentNodeBuilder = parent instanceof SegmentNodeBuilder;
-        for (PropertyState property : state.getProperties()) {
-            parent.setProperty(property);
-        }
-        for (ChildNodeEntry entry : state.getChildNodeEntries()) {
-            if (isSegmentNodeBuilder) {
-                parent.setChildNode(entry.getName(), entry.getNodeState());
+    private void removeCheckpointReferences(NodeBuilder builder) throws 
CommitFailedException {
+        // removing references to the checkpoints,
+        // which don't exist in the new repository
+        builder.setChildNode(":async");
+    }
+
+    private void copyState() throws CommitFailedException, RepositoryException 
{
+        final List<CommitHook> hooks = new ArrayList<CommitHook>();
+        if (customCommitHooks != null) {
+            hooks.addAll(customCommitHooks);
+        }
+
+        boolean migrateCheckpoints = true;
+        if (!isCompleteMigration()) {
+            LOG.info("Checkpoints won't be migrated because of the specified 
paths");
+            migrateCheckpoints = false;
+        }
+        if (!versionCopyConfiguration.isCopyAll()) {
+            LOG.info("Checkpoints won't be migrated because of the specified 
version settings");
+            migrateCheckpoints = false;
+        }
+        if (skipCheckpoints) {
+            LOG.info("Checkpoints won't be migrated because of the 
--skip-checkpoints options");
+            migrateCheckpoints = false;
+        }
+        if (migrateCheckpoints) {
+            migrateCheckpoints = migrateWithCheckpoints();
+        }
+        if (!migrateCheckpoints) {
+            NodeState sourceRoot = wrapSource(source.getRoot());
+            NodeBuilder targetRoot = target.getRoot().builder();
+            copyWorkspace(sourceRoot, targetRoot);
+            removeCheckpointReferences(targetRoot);
+            if (!versionCopyConfiguration.isCopyAll()) {
+                NodeBuilder versionStorage = 
VersionHistoryUtil.getVersionStorage(targetRoot);
+                if (!versionStorage.exists()) { // it's possible that this is 
a new repository and the version storage
+                                                // hasn't been created/copied 
yet
+                    versionStorage = 
VersionHistoryUtil.createVersionStorage(targetRoot);
+                }
+                if (!versionCopyConfiguration.skipOrphanedVersionsCopy()) {
+                    copyVersionStorage(targetRoot, 
getVersionStorage(sourceRoot), versionStorage, versionCopyConfiguration);
+                }
+                hooks.add(new EditorHook(new 
VersionableEditor.Provider(sourceRoot, getWorkspaceName(), 
versionCopyConfiguration)));
+            }
+            // type validation, reference and indexing hooks
+            hooks.add(new EditorHook(new CompositeEditorProvider(
+                    createTypeEditorProvider(),
+                    createIndexEditorProvider()
+            )));
+            target.merge(targetRoot, new LoggingCompositeHook(hooks, null, 
false), CommitInfo.EMPTY);
+        }
+    }
+
+    private boolean migrateWithCheckpoints() throws CommitFailedException {
+        List<CheckpointRetriever.Checkpoint> checkpoints = 
CheckpointRetriever.getCheckpoints(source);
+        if (checkpoints == null) {
+            return false;
+        }
+
+        Map<String, String> nameToRevision = new LinkedHashMap<String, 
String>();
+        Map<String, String> checkpointSegmentToDoc = new LinkedHashMap<String, 
String>();
+        NodeState previousRoot = null;
+        NodeBuilder targetRoot = target.getRoot().builder();
+        for (CheckpointRetriever.Checkpoint checkpoint : checkpoints) {
+            NodeState checkpointRoot = source.retrieve(checkpoint.getName());
+            if (previousRoot == null) {
+                LOG.info("Migrating first checkpoint: {}", 
checkpoint.getName());
+                NodeStateCopier.builder()
+                        
.include(calculateEffectiveIncludePaths(DEFAULT_INCLUDE_PATHS, checkpointRoot))
+                        .merge(of("/jcr:system"))
+                        .copy(wrapSource(checkpointRoot), targetRoot);
+                copyProperties(checkpointRoot, targetRoot);
             } else {
-                setChildNode(parent, entry.getName(), entry.getNodeState());
+                LOG.info("Applying diff to {}", checkpoint.getName());
+                checkpointRoot.compareAgainstBaseState(previousRoot, new 
ApplyDiff(targetRoot));
             }
+            target.merge(targetRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+            previousRoot = checkpointRoot;
+
+            String newCheckpointName = 
target.checkpoint(checkpoint.getExpiryTime() - System.currentTimeMillis());
+            checkpointSegmentToDoc.put(checkpoint.getName(), 
newCheckpointName);
+        }
+
+        NodeState sourceRoot = source.getRoot();
+        if (previousRoot == null) {
+            LOG.info("No checkpoints found; migrating head");
+            NodeStateCopier.builder()
+                    
.include(calculateEffectiveIncludePaths(DEFAULT_INCLUDE_PATHS, sourceRoot))
+                    .merge(of("/jcr:system"))
+                    .copy(wrapSource(sourceRoot), targetRoot);
+            copyProperties(sourceRoot, targetRoot);
+        } else {
+            LOG.info("Applying diff to head");
+            sourceRoot.compareAgainstBaseState(previousRoot, new 
ApplyDiff(targetRoot));
+        }
+
+        LOG.info("Rewriting checkpoint names in /:async {}", nameToRevision);
+        NodeBuilder async = targetRoot.getChildNode(":async");
+        for (Map.Entry<String, String> e : nameToRevision.entrySet()) {
+            async.setProperty(e.getKey(), e.getValue(), Type.STRING);
+
+            PropertyState temp = async.getProperty(e.getKey() + "-temp");
+            if (temp == null) {
+                continue;
+            }
+            List<String> tempValues = 
Lists.newArrayList(temp.getValue(Type.STRINGS));
+            for (Map.Entry<String, String> sToD : 
checkpointSegmentToDoc.entrySet()) {
+                if (tempValues.contains(sToD.getKey())) {
+                    tempValues.set(tempValues.indexOf(sToD.getKey()), 
sToD.getValue());
+                }
+            }
+            async.setProperty(e.getKey() + "-temp", tempValues, Type.STRINGS);
+        }
+
+        target.merge(targetRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        return true;
+    }
+
+    private boolean isCompleteMigration() {
+        return includePaths.equals(DEFAULT_INCLUDE_PATHS) && 
excludePaths.equals(DEFAULT_EXCLUDE_PATHS) && 
mergePaths.equals(DEFAULT_MERGE_PATHS);
+    }
+
+    private void copyWorkspace(NodeState sourceRoot, NodeBuilder targetRoot) {
+        final Set<String> includes = 
calculateEffectiveIncludePaths(includePaths, sourceRoot);
+        final Set<String> excludes;
+        if (versionCopyConfiguration.isCopyAll()) {
+            excludes = copyOf(this.excludePaths);
+        } else {
+            excludes = union(copyOf(this.excludePaths), 
of("/jcr:system/jcr:versionStorage"));
+        }
+        final Set<String> merges = union(copyOf(this.mergePaths), 
of("/jcr:system"));
+
+        NodeStateCopier.builder()
+            .include(includes)
+            .exclude(excludes)
+            .merge(merges)
+            .copy(sourceRoot, targetRoot);
+
+        if (includePaths.contains("/")) {
+            copyProperties(sourceRoot, targetRoot);
+        }
+    }
+
+    private String getWorkspaceName() throws RepositoryException {
+        String definedName = System.getProperty(WORKSPACE_NAME_PROP);
+        String detectedName = deriveWorkspaceName();
+        if (StringUtils.isNotBlank(definedName)) {
+            return definedName;
+        } else if (StringUtils.isNotBlank(detectedName)) {
+            return detectedName;
+        } else {
+            throw new RepositoryException("Can't detect the workspace name. 
Please use the system property " + WORKSPACE_NAME_PROP + " to set it 
manually.");
         }
-        target.merge(parent, EmptyHook.INSTANCE, CommitInfo.EMPTY);
     }
 
     /**
-     * NodeState are copied by value by recursing down the complete tree
-     * This is a temporary approach for OAK-1760 for 1.0 branch.
+     * This method tries to derive the workspace name from the source 
repository. It uses the
+     * fact that the /jcr:system/rep:permissionStore usually contains just one 
child
+     * named after the workspace.
+     *
+     * @return the workspace name or null if it can't be derived
      */
-    private void setChildNode(NodeBuilder parent, String name, NodeState 
state) {
-        // 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);
-            return;
+    private String deriveWorkspaceName() {
+        NodeState permissionStore = 
source.getRoot().getChildNode(JCR_SYSTEM).getChildNode(REP_PERMISSION_STORE);
+        List<String> nameCandidates = new ArrayList<String>();
+        for (ChildNodeEntry e : permissionStore.getChildNodeEntries()) {
+            String primaryType = e.getNodeState().getName(JCR_PRIMARYTYPE);
+            if (NT_REP_PERMISSION_STORE.equals(primaryType)) {
+                nameCandidates.add(e.getName());
+            }
         }
-        NodeBuilder builder = parent.setChildNode(name);
-        for (PropertyState property : state.getProperties()) {
-            builder.setProperty(property);
+        if (nameCandidates.size() == 1) {
+            return nameCandidates.get(0);
+        } else {
+            return null;
         }
-        for (ChildNodeEntry child : state.getChildNodeEntries()) {
-            setChildNode(builder, child.getName(), child.getNodeState());
+    }
+
+    private void verify() {
+        final NodeState sourceRoot;
+        final NodeState targetRoot;
+
+        if (source instanceof TarNodeStore && target instanceof TarNodeStore) {
+            sourceRoot = ((TarNodeStore) source).getSuperRoot();
+            targetRoot = ((TarNodeStore) target).getSuperRoot();
+        } else {
+            sourceRoot = source.getRoot();
+            targetRoot = target.getRoot();
+        }
+
+        final NodeState reportingSource = ReportingNodeState.wrap(sourceRoot, 
new LoggingReporter(LOG, "Verifying", LOG_NODE_COPY, -1));
+
+        LOG.info("Verifying whether repositories are identical");
+        if (targetRoot.compareAgainstBaseState(reportingSource, new 
LoggingEqualsDiff(LOG, "/"))) {
+            LOG.info("Verification result: both repositories are identical");
+        } else {
+            LOG.warn("Verification result: repositories are not identical");
+        }
+    }
+
+    private NodeState wrapSource(NodeState source) {
+        final NodeState reportingSourceRoot = ReportingNodeState.wrap(source, 
new LoggingReporter(LOG, "Copying", LOG_NODE_COPY, -1));
+        final NodeState sourceRoot;
+        if (filterLongNames) {
+            sourceRoot = NameFilteringNodeState.wrap(reportingSourceRoot);
+        } else {
+            sourceRoot = reportingSourceRoot;
         }
+        return sourceRoot;
     }
 }


Reply via email to