Author: thomasm
Date: Fri Sep 25 10:18:10 2015
New Revision: 1705265

URL: http://svn.apache.org/viewvc?rev=1705265&view=rev
Log:
OAK-2171 oak-run should support repository upgrades with all available options

Added:
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationOptions.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/OptionParserFactory.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreArguments.java
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreType.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/resources/
    jackrabbit/oak/trunk/oak-upgrade/src/main/resources/logback.xml
    jackrabbit/oak/trunk/oak-upgrade/src/main/resources/upgrade_usage.txt
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Jcr2ToSegmentTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFds.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToSegmentTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Util.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/CopyReferencesTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFbsTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFdsTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToS3Test.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FdsToFbsTest.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/BlobStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/DummyBlobStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileBlobStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileDataStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/JdbcNodeStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/MongoNodeStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/NodeStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/S3DataStoreContainer.java
    
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/SegmentNodeStoreContainer.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/resources/jcr2.zip   (with props)
    jackrabbit/oak/trunk/oak-upgrade/src/test/resources/segmentstore.zip   
(with props)
Removed:
    
jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/ParseVersionCopyArgumentTest.java
Modified:
    jackrabbit/oak/trunk/oak-run/pom.xml
    
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
    jackrabbit/oak/trunk/oak-upgrade/pom.xml
    
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/blob/LengthCachingDataStore.java

Modified: jackrabbit/oak/trunk/oak-run/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/pom.xml?rev=1705265&r1=1705264&r2=1705265&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-run/pom.xml Fri Sep 25 10:18:10 2015
@@ -247,11 +247,6 @@
       </dependency>
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
-      <artifactId>oak-upgrade</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jackrabbit</groupId>
       <artifactId>oak-lucene</artifactId>
       <version>${project.version}</version>
     </dependency>

Modified: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java?rev=1705265&r1=1705264&r2=1705265&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
 Fri Sep 25 10:18:10 2015
@@ -28,12 +28,8 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.sql.Timestamp;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Calendar;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -67,9 +63,6 @@ import joptsimple.OptionSet;
 import joptsimple.OptionSpec;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.time.DateUtils;
-import org.apache.jackrabbit.core.RepositoryContext;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.oak.Oak;
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.benchmark.BenchmarkRunner;
@@ -114,7 +107,6 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.scalability.ScalabilityRunner;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
-import org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade;
 import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet;
 import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet;
 import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
@@ -176,7 +168,7 @@ public final class Main {
                 server(URI, args);
                 break;
             case UPGRADE:
-                upgrade(args);
+                System.out.println("This command was moved to the oak-upgrade 
module");
                 break;
             case SCALABILITY:
                 ScalabilityRunner.main(args);
@@ -961,89 +953,6 @@ public final class Main {
         return false;
     }
 
-    private static void upgrade(String[] args) throws Exception {
-        OptionParser parser = new OptionParser();
-        parser.accepts("datastore", "keep data store");
-        ArgumentAcceptingOptionSpec<String> copyVersions = 
parser.accepts("copy-versions", "copy referenced versions. valid arguments: 
true|false|yyyy-mm-dd").withRequiredArg().defaultsTo("true");
-        ArgumentAcceptingOptionSpec<String> copyOrphanedVersions = 
parser.accepts("copy-orphaned-versions", "copy all versions. valid arguments: 
true|false|yyyy-mm-dd").withRequiredArg().defaultsTo("true");
-        OptionSpec<String> nonOption = parser.nonOptions();
-        OptionSet options = parser.parse(args);
-
-        List<String> argList = nonOption.values(options);
-        if (argList.size() == 2 || argList.size() == 3) {
-            File dir = new File(argList.get(0));
-            File xml = new File(dir, "repository.xml");
-            String dst = argList.get(1);
-            if (argList.size() == 3) {
-                xml = new File(dst);
-                dst = argList.get(2);
-            }
-
-            RepositoryContext source =
-                    RepositoryContext.create(RepositoryConfig.create(xml, 
dir));
-            try {
-                if (dst.startsWith("mongodb://")) {
-                    MongoClientURI uri = new MongoClientURI(dst);
-                    MongoClient client = new MongoClient(uri);
-                    try {
-                        DocumentNodeStore target = new DocumentMK.Builder()
-                            .setMongoDB(client.getDB(uri.getDatabase()))
-                            .getNodeStore();
-                        try {
-                            RepositoryUpgrade upgrade =
-                                    new RepositoryUpgrade(source, target);
-                            upgrade.setCopyBinariesByReference(
-                                    options.has("datastore"));
-                            setCopyVersionOptions(copyVersions.value(options), 
copyOrphanedVersions.value(options), upgrade);
-                            upgrade.copy(null);
-                        } finally {
-                            target.dispose();
-                        }
-                    } finally {
-                        client.close();
-                    }
-                } else {
-                    FileStore store = new FileStore(new File(dst), 256);
-                    try {
-                        NodeStore target = new SegmentNodeStore(store);
-                        RepositoryUpgrade upgrade =
-                                new RepositoryUpgrade(source, target);
-                        upgrade.setCopyBinariesByReference(
-                                options.has("datastore"));
-                        upgrade.copy(null);
-                    } finally {
-                        store.close();
-                    }
-                }
-            } finally {
-                source.getRepository().shutdown();
-            }
-        } else {
-            System.err.println("usage: upgrade <olddir> <newdir>");
-            System.exit(1);
-        }
-    }
-
-    private static void setCopyVersionOptions(String copyVersions, String 
copyOrphanedVersions, RepositoryUpgrade upgrade) throws ParseException {
-        upgrade.setCopyVersions(parseVersionCopyArgument(copyVersions));
-        
upgrade.setCopyOrphanedVersions(parseVersionCopyArgument(copyOrphanedVersions));
-    }
-
-    static Calendar parseVersionCopyArgument(String string) throws 
ParseException {
-        final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
-        final Calendar calendar;
-
-        if (Boolean.parseBoolean(string)) {
-            calendar = Calendar.getInstance();
-            calendar.setTimeInMillis(0);
-        } else if (string != null && string.matches("^\\d{4}-\\d{2}-\\d{2}$")) 
{
-            calendar = DateUtils.toCalendar(df.parse(string));
-        } else {
-            calendar = null;
-        }
-        return calendar;
-    }
-
     private static void server(String defaultUri, String[] args) throws 
Exception {
         OptionParser parser = new OptionParser();
 

Modified: jackrabbit/oak/trunk/oak-upgrade/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/pom.xml?rev=1705265&r1=1705264&r2=1705265&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-upgrade/pom.xml Fri Sep 25 10:18:10 2015
@@ -38,15 +38,50 @@
         <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>
+              <filters>
+                <filter>
+                  <artifact>*</artifact>
+                  <excludes>
+                  </excludes>
+                </filter>
+              </filters>
+              <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>
 
   <dependencies>
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>oak-blob-cloud</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
       <artifactId>oak-core</artifactId>
       <version>${project.version}</version>
     </dependency>
@@ -61,17 +96,40 @@
       <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>
+      <version>7.0.64</version>
+    </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>
 
@@ -93,11 +151,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 -->
@@ -116,5 +169,4 @@
       </dependencies>
     </profile>
   </profiles>
-
 </project>

Modified: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/blob/LengthCachingDataStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/blob/LengthCachingDataStore.java?rev=1705265&r1=1705264&r2=1705265&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/blob/LengthCachingDataStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/blob/LengthCachingDataStore.java
 Fri Sep 25 10:18:10 2015
@@ -210,6 +210,7 @@ public class LengthCachingDataStore exte
             this.mapping = recordSizeMapping;
         }
 
+        @Override
         public long getLength() throws DataStoreException {
             Long size = mapping.get(getIdentifier().toString());
             if (size == null) {

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,111 @@
+/*
+ * 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.cli;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.CliArgumentException;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationCliArguments;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Closer;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
+
+@SuppressWarnings("restriction")
+public class CliUtils {
+
+    private static final Logger log = 
LoggerFactory.getLogger(OakUpgrade.class);
+
+    public static MigrationCliArguments parseOrExit(OptionParser op, String... 
args) {
+        try {
+            OptionSet options = op.parse(args);
+            if (options.has(OptionParserFactory.HELP) || 
options.nonOptionArguments().isEmpty()) {
+                displayUsage();
+                return null;
+            }
+            return new MigrationCliArguments(options);
+        } catch (Exception e) {
+            System.exit(getReturnCode(e));
+            return null;
+        }
+    }
+
+    public static void displayUsage() throws IOException {
+        System.out.println(getUsage().replace("${command}", "java -jar 
oak-run-*-jr2.jar upgrade"));
+    }
+
+    public static String getUsage() throws IOException {
+        InputStream is = 
CliUtils.class.getClassLoader().getResourceAsStream("upgrade_usage.txt");
+        try {
+            return IOUtils.toString(is);
+        } finally {
+            IOUtils.closeQuietly(is);
+        }
+    }
+
+    public static int getReturnCode(Exception e) {
+        if (e.getMessage() != null) {
+            System.err.println(e.getMessage());
+        }
+        if (e instanceof CliArgumentException) {
+            return ((CliArgumentException) e).getExitCode();
+        } else {
+            e.printStackTrace(System.err);
+            return 1;
+        }
+    }
+
+    public static void handleSigInt(final Closer closer) {
+        SignalHandler handler = new SignalHandler() {
+            @Override
+            public void handle(Signal signal) {
+                try {
+                    closer.close();
+                } catch (IOException e) {
+                    log.error("Can't close", e);
+                }
+                System.exit(0);
+            }
+        };
+        Signal.handle(new Signal("INT"), handler);
+    }
+
+    public static void backupOldJcr2Files(String repositoryDirPath) {
+        // backup old jcr2 files when doing an in-place upgrade
+        File repositoryDir = new File(repositoryDirPath);
+        File crx2 = new File(repositoryDir, "crx2");
+        log.info("Moving existing repository under {}", 
crx2.getAbsolutePath());
+        crx2.mkdir();
+        Pattern pattern = Pattern.compile("crx2|segmentstore");
+        for (File file : repositoryDir.listFiles()) {
+            String name = file.getName();
+            if (!pattern.matcher(name).matches()) {
+                file.renameTo(new File(crx2, name));
+            }
+        }
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,115 @@
+/*
+ * 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.cli;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.upgrade.RepositorySidegrade;
+import org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationOptions;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.StoreArguments;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.Closer;
+
+public class MigrationFactory {
+
+    protected final MigrationOptions options;
+
+    protected final StoreArguments stores;
+
+    protected final Closer closer;
+
+    public MigrationFactory(MigrationOptions options, StoreArguments stores, 
Closer closer) {
+        this.options = options;
+        this.stores = stores;
+        this.closer = closer;
+    }
+
+    public RepositoryUpgrade createUpgrade() throws IOException, 
RepositoryException {
+        RepositoryContext src = stores.getSrcStore().create(closer);
+        BlobStore srcBlobStore = new DataStoreBlobStore(src.getDataStore());
+        NodeStore dstStore = createTarget(closer, srcBlobStore);
+        return createUpgrade(src, dstStore);
+    }
+
+    public RepositorySidegrade createSidegrade() throws IOException {
+        BlobStore srcBlobStore = stores.getSrcBlobStore().create(closer);
+        NodeStore srcStore = stores.getSrcStore().create(srcBlobStore, closer);
+        NodeStore dstStore = createTarget(closer, srcBlobStore);
+        return createSidegrade(srcStore, dstStore);
+    }
+
+    protected NodeStore createTarget(Closer closer, BlobStore srcBlobStore) 
throws IOException {
+        BlobStore dstBlobStore;
+        if (options.isCopyBinariesByReference()) {
+            dstBlobStore = srcBlobStore;
+        } else {
+            dstBlobStore = stores.getDstBlobStore().create(closer);
+        }
+        NodeStore dstStore = stores.getDstStore().create(dstBlobStore, closer);
+        return dstStore;
+    }
+
+    protected RepositoryUpgrade createUpgrade(RepositoryContext source, 
NodeStore dstStore) {
+        RepositoryUpgrade upgrade = new RepositoryUpgrade(source, dstStore);
+        if (source.getDataStore() != null && 
options.isCopyBinariesByReference()) {
+            upgrade.setCopyBinariesByReference(true);
+        }
+        upgrade.setCopyVersions(options.getCopyVersions());
+        upgrade.setCopyOrphanedVersions(options.getCopyOrphanedVersions());
+        if (options.getIncludePaths() != null) {
+            upgrade.setIncludes(options.getIncludePaths());
+        }
+        if (options.getExcludePaths() != null) {
+            upgrade.setExcludes(options.getExcludePaths());
+        }
+        upgrade.setSkipOnError(!options.isFailOnError());
+        upgrade.setEarlyShutdown(options.isEarlyShutdown());
+        ServiceLoader<CommitHook> loader = 
ServiceLoader.load(CommitHook.class);
+        Iterator<CommitHook> iterator = loader.iterator();
+        ImmutableList.Builder<CommitHook> builder = ImmutableList.<CommitHook> 
builder().addAll(iterator);
+        upgrade.setCustomCommitHooks(builder.build());
+        return upgrade;
+    }
+
+    private RepositorySidegrade createSidegrade(NodeStore srcStore, NodeStore 
dstStore) {
+        RepositorySidegrade sidegrade = new RepositorySidegrade(srcStore, 
dstStore);
+        sidegrade.setCopyVersions(options.getCopyVersions());
+        sidegrade.setCopyOrphanedVersions(options.getCopyOrphanedVersions());
+        if (options.getIncludePaths() != null) {
+            sidegrade.setIncludes(options.getIncludePaths());
+        }
+        if (options.getExcludePaths() != null) {
+            sidegrade.setExcludes(options.getExcludePaths());
+        }
+        if (options.getMergePaths() != null) {
+            sidegrade.setMerges(options.getMergePaths());
+        }
+        return sidegrade;
+    }
+
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,81 @@
+/*
+ * 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.cli;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import javax.jcr.RepositoryException;
+
+import com.google.common.collect.Lists;
+import com.google.common.io.Closer;
+
+import org.apache.jackrabbit.oak.spi.lifecycle.CompositeInitializer;
+import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationCliArguments;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationOptions;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.StoreArguments;
+
+public class OakUpgrade {
+
+    public static void main(String... args) throws IOException {
+        MigrationCliArguments cliArguments = 
CliUtils.parseOrExit(OptionParserFactory.create(), args);
+        if (cliArguments == null) {
+            return;
+        }
+        migrate(cliArguments);
+    }
+
+    public static void migrate(MigrationCliArguments argumentParser) throws 
IOException {
+        MigrationOptions options = argumentParser.getOptions();
+        StoreArguments stores = argumentParser.getStoreArguments();
+        Closer closer = Closer.create();
+        CliUtils.handleSigInt(closer);
+        MigrationFactory factory = new MigrationFactory(options, stores, 
closer);
+        try {
+            if (stores.getSrcStore().isJcr2()) {
+                upgrade(factory);
+            } else {
+                sidegrade(factory);
+            }
+        } catch (Throwable t) {
+            throw closer.rethrow(t);
+        } finally {
+            closer.close();
+        }
+        if (stores.isInPlaceUpgrade()) {
+            CliUtils.backupOldJcr2Files(stores.getSrcPaths()[0]);
+        }
+    }
+
+    private static void upgrade(MigrationFactory migrationFactory) throws 
IOException, RepositoryException {
+        migrationFactory.createUpgrade().copy(createCompositeInitializer());
+    }
+
+    private static void sidegrade(MigrationFactory migrationFactory) throws 
IOException, RepositoryException {
+        migrationFactory.createSidegrade().copy();
+    }
+
+    private static RepositoryInitializer createCompositeInitializer() {
+        ServiceLoader<RepositoryInitializer> loader = 
ServiceLoader.load(RepositoryInitializer.class);
+        List<RepositoryInitializer> initializers = 
Lists.newArrayList(loader.iterator());
+        return new CompositeInitializer(initializers);
+    }
+
+}
\ No newline at end of file

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,27 @@
+/*
+ * 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.cli.blob;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+import com.google.common.io.Closer;
+
+public interface BlobStoreFactory {
+    BlobStore create(Closer closer) throws IOException;
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,30 @@
+/*
+ * 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.cli.blob;
+
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+import com.google.common.io.Closer;
+
+public class DummyBlobStoreFactory implements BlobStoreFactory {
+
+    @Override
+    public BlobStore create(Closer closer) {
+        return null;
+    }
+
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,37 @@
+/*
+ * 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.cli.blob;
+
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.blob.FileBlobStore;
+
+import com.google.common.io.Closer;
+
+public class FileBlobStoreFactory implements BlobStoreFactory {
+
+    private final String directory;
+
+    public FileBlobStoreFactory(String directory) {
+        this.directory = directory;
+    }
+
+    @Override
+    public BlobStore create(Closer closer) {
+        return new FileBlobStore(directory);
+    }
+
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,54 @@
+/*
+ * 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.cli.blob;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.apache.jackrabbit.core.data.FileDataStore;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.OakFileDataStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+import com.google.common.io.Closer;
+
+public class FileDataStoreFactory implements BlobStoreFactory {
+
+    private final String directory;
+
+    public FileDataStoreFactory(String directory) {
+        this.directory = directory;
+    }
+
+    @Override
+    public BlobStore create(Closer closer) {
+        OakFileDataStore delegate = new OakFileDataStore();
+        delegate.setPath(directory);
+        delegate.init(null);
+        closer.register(asCloseable(delegate));
+        return new DataStoreBlobStore(delegate);
+    }
+
+    private static Closeable asCloseable(final FileDataStore store) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                store.close();
+            }
+        };
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,89 @@
+/*
+ * 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.cli.blob;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.data.CachingDataStore;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.apache.jackrabbit.oak.blob.cloud.aws.s3.S3DataStore;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Closer;
+
+public class S3DataStoreFactory implements BlobStoreFactory {
+
+    private static final Logger log = 
LoggerFactory.getLogger(S3DataStoreFactory.class);
+
+    private final Properties props;
+
+    private final String directory;
+
+    public S3DataStoreFactory(String configuration, String directory) throws 
IOException {
+        this.props = new Properties();
+        FileReader reader = new FileReader(new File(configuration));
+        try {
+            props.load(reader);
+        } finally {
+            IOUtils.closeQuietly(reader);
+        }
+        this.directory = directory;
+    }
+
+    @Override
+    public BlobStore create(Closer closer) throws IOException {
+        S3DataStore delegate = new S3DataStore();
+        delegate.setProperties(props);
+        delegate.setPath(props.getProperty("path"));
+        try {
+            delegate.init(directory);
+        } catch (RepositoryException e) {
+            throw new IOException(e);
+        }
+        closer.register(asCloseable(delegate));
+        return new DataStoreBlobStore(delegate);
+    }
+
+    private static Closeable asCloseable(final CachingDataStore store) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                try {
+                    while (!store.getPendingUploads().isEmpty()) {
+                        log.info("Waiting for following uploads to finish: " + 
store.getPendingUploads());
+                        Thread.sleep(1000);
+                    }
+                    store.close();
+                } catch (DataStoreException e) {
+                    throw new IOException(e);
+                } catch (InterruptedException e) {
+                    throw new IOException(e);
+                }
+            }
+        };
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,107 @@
+/*
+ * 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.cli.node;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+
+import com.google.common.io.Closer;
+
+public class Jackrabbit2Factory {
+
+    private final File repositoryDir;
+
+    private final File repositoryFile;
+
+    public Jackrabbit2Factory(String repositoryDir, String repositoryFile) {
+        if (!isJcr2Repository(repositoryDir)) {
+            throw new IllegalArgumentException("Repository directory not 
found: " + repositoryDir);
+        }
+        this.repositoryDir = new File(repositoryDir);
+        this.repositoryFile = new File(repositoryFile);
+        if (!isRepositoryXml(repositoryFile)) {
+            throw new IllegalArgumentException("Repository configuration not 
found: " + repositoryFile);
+        }
+    }
+
+    public RepositoryContext create(Closer closer) throws RepositoryException {
+        RepositoryContext source = 
RepositoryContext.create(RepositoryConfig.create(repositoryFile, 
repositoryDir));
+        closer.register(asCloseable(source));
+        return source;
+    }
+
+    public File getRepositoryDir() {
+        return repositoryDir;
+    }
+
+    private static Closeable asCloseable(final RepositoryContext context) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                context.getRepository().shutdown();
+            }
+        };
+    }
+
+    public static boolean isRepositoryXml(String path) {
+        File file = new File(path);
+        if (file.isFile()) {
+            BufferedReader reader = null;
+            try {
+                reader = new BufferedReader(new FileReader(file));
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    if (StringUtils.containsIgnoreCase(line, "<Repository>")) {
+                        return true;
+                    }
+                }
+            } catch (FileNotFoundException e) {
+                return false;
+            } catch (IOException e) {
+                return false;
+            } finally {
+                IOUtils.closeQuietly(reader);
+            }
+        }
+        return false;
+    }
+
+    public static boolean isJcr2Repository(String directory) {
+        File dir = new File(directory);
+        if (!dir.isDirectory()) {
+            return false;
+        }
+        File workspaces = new File(dir, "workspaces");
+        return workspaces.isDirectory();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("JCR2[%s, %s]", repositoryDir, repositoryFile);
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,72 @@
+/*
+ * 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.cli.node;
+
+import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDataSourceFactory;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Closer;
+
+import javax.sql.DataSource;
+
+public class JdbcFactory implements NodeStoreFactory {
+
+    private static final Logger log = 
LoggerFactory.getLogger(JdbcFactory.class);
+
+    private final String jdbcUri;
+
+    private final int cacheSize;
+
+    private final String user;
+
+    private final String password;
+
+    public JdbcFactory(String jdbcUri, int cacheSize, String user, String 
password) {
+        this.jdbcUri = jdbcUri;
+        this.cacheSize = cacheSize;
+        if (user == null || password == null) {
+            throw new IllegalArgumentException("RBD requires username and 
password parameters.");
+        }
+        this.user = user;
+        this.password = password;
+    }
+
+    @Override
+    public NodeStore create(BlobStore blobStore, Closer closer) {
+        DataSource ds = RDBDataSourceFactory.forJdbcUrl(jdbcUri, user, 
password);
+        DocumentMK.Builder builder = MongoFactory.getBuilder(cacheSize);
+        if (blobStore != null) {
+            builder.setBlobStore(blobStore);
+        }
+        builder.setRDBConnection(ds);
+        log.info("Initialized DocumentNodeStore on RDB with Cache size : {} 
MB, Fast migration : {}", cacheSize,
+                builder.isDisableBranches());
+        DocumentNodeStore documentNodeStore = builder.getNodeStore();
+        closer.register(MongoFactory.asCloseable(documentNodeStore));
+        return documentNodeStore;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DocumentNodeStore[%s]", jdbcUri);
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +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.cli.node;
+
+import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+import com.google.common.io.Closer;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientURI;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.UnknownHostException;
+
+public class MongoFactory implements NodeStoreFactory {
+
+    private static final long MB = 1024 * 1024;
+
+    private final MongoClientURI uri;
+
+    private final int cacheSize;
+
+    public MongoFactory(String repoDesc, int cacheSize) {
+        this.uri = new MongoClientURI(repoDesc);
+        this.cacheSize = cacheSize;
+    }
+
+    @Override
+    public NodeStore create(BlobStore blobStore, Closer closer) throws 
UnknownHostException {
+        String db;
+        if (uri.getDatabase() == null) {
+            db = "aem-author"; // assume an author instance
+        } else {
+            db = uri.getDatabase();
+        }
+        DocumentMK.Builder builder = getBuilder(cacheSize);
+        MongoClient client = new MongoClient(uri);
+        closer.register(asCloseable(client));
+        builder.setMongoDB(client.getDB(db));
+        if (blobStore != null) {
+            builder.setBlobStore(blobStore);
+        }
+        DocumentNodeStore documentNodeStore = builder.getNodeStore();
+        closer.register(asCloseable(documentNodeStore));
+        return documentNodeStore;
+    }
+
+    static Closeable asCloseable(final DocumentNodeStore documentNodeStore) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                documentNodeStore.dispose();
+            }
+        };
+    }
+
+    private static Closeable asCloseable(final MongoClient client) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                client.close();
+            }
+        };
+    }
+
+    static DocumentMK.Builder getBuilder(int cacheSize) {
+        boolean fastMigration = 
!Boolean.getBoolean("mongomk.disableFastMigration");
+        DocumentMK.Builder builder = new DocumentMK.Builder();
+        builder.memoryCacheSize(cacheSize * MB);
+        if (fastMigration) {
+            builder.disableBranches();
+        }
+        return builder;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DocumentNodeStore[%s]", uri.toString());
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,29 @@
+/*
+ * 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.cli.node;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+import com.google.common.io.Closer;
+
+public interface NodeStoreFactory {
+
+    NodeStore create(BlobStore blobStore, Closer closer) throws IOException;
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,74 @@
+/*
+ * 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.cli.node;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore.Builder;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+import com.google.common.io.Closer;
+
+public class SegmentFactory implements NodeStoreFactory {
+
+    private final File dir;
+
+    private final boolean mmap;
+
+    public SegmentFactory(String directory, boolean mmap) {
+        this.dir = new File(directory);
+        this.mmap = mmap;
+        if (!dir.isDirectory()) {
+            throw new IllegalArgumentException("Not a directory: " + 
dir.getPath());
+        }
+    }
+
+    @Override
+    public NodeStore create(BlobStore blobStore, Closer closer) throws 
IOException {
+        Builder builder = FileStore.newFileStore(new File(dir, 
"segmentstore"));
+        if (blobStore != null) {
+            builder.withBlobStore(blobStore);
+        }
+        builder.withMaxFileSize(256).withMemoryMapping(mmap);
+        FileStore fs = builder.create();
+        closer.register(asCloseable(fs));
+        return SegmentNodeStore.newSegmentNodeStore(fs).create();
+    }
+
+    public File getRepositoryDir() {
+        return dir;
+    }
+
+    private static Closeable asCloseable(final FileStore fs) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                fs.close();
+            }
+        };
+    }
+
+    @Override
+    public String toString() {
+        return String.format("SegmentNodeStore[%s]", dir);
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java
 Fri Sep 25 10:18:10 2015
@@ -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.cli.node;
+
+import java.io.IOException;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+import com.google.common.io.Closer;
+
+public class StoreFactory {
+
+    private final Jackrabbit2Factory jcr2Factory;
+
+    private final NodeStoreFactory nodeStoreFactory;
+
+    public StoreFactory(Jackrabbit2Factory crx2Factory) {
+        this.jcr2Factory = crx2Factory;
+        this.nodeStoreFactory = null;
+    }
+
+    public StoreFactory(NodeStoreFactory nodeStoreFactory) {
+        this.jcr2Factory = null;
+        this.nodeStoreFactory = nodeStoreFactory;
+    }
+
+    public RepositoryContext create(Closer closer) throws IOException, 
RepositoryException {
+        if (jcr2Factory == null) {
+            throw new UnsupportedOperationException();
+        }
+        return jcr2Factory.create(closer);
+    }
+
+    public NodeStore create(BlobStore blobStore, Closer closer) throws 
IOException {
+        if (nodeStoreFactory == null) {
+            throw new UnsupportedOperationException();
+        }
+        return nodeStoreFactory.create(blobStore, closer);
+    }
+
+    public boolean isJcr2() {
+        return jcr2Factory != null;
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java
 Fri Sep 25 10:18:10 2015
@@ -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.upgrade.cli.parser;
+
+public class CliArgumentException extends Exception {
+
+    private static final long serialVersionUID = -7579563789244874904L;
+
+    private final int exitCode;
+
+    public CliArgumentException(int exitCode) {
+        super();
+        this.exitCode = exitCode;
+    }
+
+    public CliArgumentException(String message, int exitCode) {
+        super(message);
+        this.exitCode = exitCode;
+    }
+
+    public int getExitCode() {
+        return exitCode;
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,81 @@
+/*
+ * 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.cli.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import joptsimple.OptionSet;
+
+public final class MigrationCliArguments {
+
+    private final OptionSet options;
+
+    private final List<String> arguments;
+
+    private final MigrationOptions migrationOptions;
+
+    private final StoreArguments storeArguments;
+
+    public MigrationCliArguments(OptionSet options) throws 
CliArgumentException {
+        this.options = options;
+        arguments = getNonOptionArguments();
+        migrationOptions = new MigrationOptions(this);
+        storeArguments = new StoreArguments(this);
+    }
+
+    private List<String> getNonOptionArguments() {
+        List<String> args = new ArrayList<String>();
+        for (Object o : options.nonOptionArguments()) {
+            args.add(o.toString());
+        }
+        return args;
+    }
+
+    public boolean hasOption(String optionName) {
+        return options.has(optionName);
+    }
+
+    public String getOption(String optionName) {
+        return (String) options.valueOf(optionName);
+    }
+
+    public int getIntOption(String optionName) {
+        return (Integer) options.valueOf(optionName);
+    }
+
+    public String[] getOptionList(String optionName) {
+        String option = getOption(optionName);
+        if (option == null) {
+            return null;
+        } else {
+            return option.split(",");
+        }
+    }
+
+    public MigrationOptions getOptions() {
+        return migrationOptions;
+    }
+
+    public StoreArguments getStoreArguments() {
+        return storeArguments;
+    }
+
+    List<String> getArguments() {
+        return arguments;
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationOptions.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationOptions.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationOptions.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationOptions.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,192 @@
+/*
+ * 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.cli.parser;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MigrationOptions {
+
+    private static final Logger log = 
LoggerFactory.getLogger(MigrationOptions.class);
+
+    private static final DateFormat DATE_FORMAT = new 
SimpleDateFormat("yyyy-MM-dd");
+
+    private final boolean copyBinariesByReference;
+
+    private final boolean mmap;
+
+    private final int cacheSizeInMB;
+
+    private final Calendar copyVersions;
+
+    private final Calendar copyOrphanedVersions;
+
+    private final String[] includePaths;
+
+    private final String[] excludePaths;
+
+    private final String[] mergePaths;
+
+    private final boolean failOnError;
+
+    private final boolean earlyShutdown;
+
+    public MigrationOptions(MigrationCliArguments args) {
+        this.copyBinariesByReference = 
!args.hasOption(OptionParserFactory.COPY_BINARIES);
+        this.mmap = args.hasOption(OptionParserFactory.MMAP);
+        if (args.hasOption(OptionParserFactory.CACHE_SIZE)) {
+            this.cacheSizeInMB = 
args.getIntOption(OptionParserFactory.CACHE_SIZE);
+        } else {
+            this.cacheSizeInMB = 256;
+        }
+
+        final Calendar epoch = Calendar.getInstance();
+        epoch.setTimeInMillis(0);
+        if (args.hasOption(OptionParserFactory.COPY_VERSIONS)) {
+            this.copyVersions = 
parseVersionCopyArgument(args.getOption(OptionParserFactory.COPY_VERSIONS));
+        } else {
+            this.copyVersions = epoch;
+        }
+        if (args.hasOption(OptionParserFactory.COPY_ORPHANED_VERSIONS)) {
+            this.copyOrphanedVersions = 
parseVersionCopyArgument(args.getOption(OptionParserFactory.COPY_ORPHANED_VERSIONS));
+        } else {
+            this.copyOrphanedVersions = epoch;
+        }
+        this.includePaths = 
split(args.getOption(OptionParserFactory.INCLUDE_PATHS));
+        this.excludePaths = 
split(args.getOption(OptionParserFactory.EXCLUDE_PATHS));
+        this.mergePaths = 
split(args.getOption(OptionParserFactory.MERGE_PATHS));
+        this.failOnError = args.hasOption(OptionParserFactory.FAIL_ON_ERROR);
+        this.earlyShutdown = 
args.hasOption(OptionParserFactory.EARLY_SHUTDOWN);
+        logOptions();
+    }
+
+    public boolean isCopyBinariesByReference() {
+        return copyBinariesByReference;
+    }
+
+    public boolean isMmap() {
+        return mmap;
+    }
+
+    public int getCacheSizeInMB() {
+        return cacheSizeInMB;
+    }
+
+    public Calendar getCopyVersions() {
+        return copyVersions;
+    }
+
+    public Calendar getCopyOrphanedVersions() {
+        return copyOrphanedVersions;
+    }
+
+    public String[] getIncludePaths() {
+        return includePaths;
+    }
+
+    public String[] getExcludePaths() {
+        return excludePaths;
+    }
+
+    public String[] getMergePaths() {
+        return mergePaths;
+    }
+
+    public boolean isFailOnError() {
+        return failOnError;
+    }
+
+    public boolean isEarlyShutdown() {
+        return earlyShutdown;
+    }
+
+    private void logOptions() {
+        if (copyBinariesByReference) {
+            log.info("DataStore needs to be shared with new repository");
+        } else {
+            log.info("Binary content would be copied to the NodeStore.");
+        }
+
+        if (mmap) {
+            log.info("Enabling memory mapped file access for Segment Store");
+        }
+
+        if (copyVersions == null) {
+            log.info("copyVersions parameter set to false");
+        } else {
+            log.info("copyVersions parameter set to {}", 
DATE_FORMAT.format(copyVersions.getTime()));
+        }
+
+        if (copyOrphanedVersions == null) {
+            log.info("copyOrphanedVersions parameter set to false");
+        } else {
+            log.info("copyOrphanedVersions parameter set to {}", 
DATE_FORMAT.format(copyOrphanedVersions.getTime()));
+        }
+
+        if (includePaths != null) {
+            log.info("paths to include: {}", (Object) includePaths);
+        }
+
+        if (excludePaths != null) {
+            log.info("paths to exclude: {}", (Object) excludePaths);
+        }
+
+        if (failOnError) {
+            log.info("Unreadable nodes will cause failure of the entire 
transaction");
+        }
+
+        if (earlyShutdown) {
+            log.info("Source repository would be shutdown post copying of 
nodes");
+        }
+
+        log.info("Cache size: {} MB", cacheSizeInMB);
+
+    }
+
+    private static String[] split(String list) {
+        if (list == null) {
+            return null;
+        } else {
+            return list.split(",");
+        }
+    }
+
+    private static Calendar parseVersionCopyArgument(String string) {
+        final Calendar calendar;
+
+        if (Boolean.parseBoolean(string)) {
+            calendar = Calendar.getInstance();
+            calendar.setTimeInMillis(0);
+        } else if (string != null && string.matches("^\\d{4}-\\d{2}-\\d{2}$")) 
{
+            calendar = Calendar.getInstance();
+            try {
+                calendar.setTime(DATE_FORMAT.parse(string));
+            } catch (ParseException e) {
+                return null;
+            }
+        } else {
+            calendar = null;
+        }
+        return calendar;
+    }
+
+}
\ No newline at end of file

Added: 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/OptionParserFactory.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/OptionParserFactory.java?rev=1705265&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/OptionParserFactory.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/OptionParserFactory.java
 Fri Sep 25 10:18:10 2015
@@ -0,0 +1,133 @@
+/*
+ * 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.cli.parser;
+
+import static java.util.Arrays.asList;
+
+import joptsimple.OptionParser;
+
+public class OptionParserFactory {
+
+    public static final String COPY_BINARIES = "copy-binaries";
+
+    public static final String MMAP = "mmap";
+
+    public static final String FAIL_ON_ERROR = "fail-on-error";
+
+    public static final String EARLY_SHUTDOWN = "early-shutdown";
+
+    public static final String CACHE_SIZE = "cache";
+
+    public static final String HELP = "help";
+
+    public static final String DST_USER = "user";
+
+    public static final String DST_PASSWORD = "password";
+
+    public static final String SRC_USER = "src-user";
+
+    public static final String SRC_PASSWORD = "src-password";
+
+    public static final String SRC_FBS = "src-fileblobstore";
+
+    public static final String SRC_FDS = "src-datastore";
+
+    public static final String DST_FDS = "datastore";
+
+    public static final String DST_FBS = "fileblobstore";
+
+    public static final String DST_S3 = "s3datastore";
+
+    public static final String DST_S3_CONFIG = "s3config";
+
+    public static final String COPY_VERSIONS = "copy-versions";
+
+    public static final String COPY_ORPHANED_VERSIONS = 
"copy-orphaned-versions";
+
+    public static final String INCLUDE_PATHS = "include-paths";
+
+    public static final String EXCLUDE_PATHS = "exclude-paths";
+
+    public static final String MERGE_PATHS = "merge-paths";
+
+    public static OptionParser create() {
+        OptionParser op = new OptionParser();
+        addUsageOptions(op);
+        addBlobOptions(op);
+        addRdbOptions(op);
+        addPathsOptions(op);
+        addVersioningOptions(op);
+        addMiscOptions(op);
+
+//        op.nonOptions(
+//                
"[/path/to/oak/repository|/path/to/crx2/repository|mongodb://host:port|<Jdbc 
URI>] [/path/to/repository.xml] 
{/path/to/oak/repository|mongodb://host:port|<Jdbc URI>}");
+
+        return op;
+    }
+
+    private static void addUsageOptions(OptionParser op) {
+        op.acceptsAll(asList("h", "?", HELP), "show help").forHelp();
+    }
+
+    private static void addBlobOptions(OptionParser op) {
+        op.accepts(COPY_BINARIES, "Copy binary content. Use this to disable 
use of existing DataStore in new repo");
+        op.accepts(SRC_FDS, "Datastore directory to be used as a source 
FileDataStore").withRequiredArg()
+                .ofType(String.class);
+        op.accepts(SRC_FBS, "Datastore directory to be used as a source 
FileBlobStore").withRequiredArg()
+                .ofType(String.class);
+        op.accepts(DST_FDS, "Datastore directory to be used as a target 
FileDataStore").withRequiredArg()
+            .ofType(String.class);
+        op.accepts(DST_FBS, "Datastore directory to be used as a target 
FileBlobStore").withRequiredArg()
+                .ofType(String.class);
+        op.accepts(DST_S3, "Repository home to be used for the target 
S3").withRequiredArg().ofType(String.class);
+        op.accepts(DST_S3_CONFIG, "Configuration file for the target 
S3DataStore").withRequiredArg()
+                .ofType(String.class);
+    }
+
+    private static void addRdbOptions(OptionParser op) {
+        op.accepts(SRC_USER, "Source rdb 
user").withRequiredArg().ofType(String.class);
+        op.accepts(SRC_PASSWORD, "Source rdb 
password").withRequiredArg().ofType(String.class);
+        op.accepts(DST_USER, "Target rdb 
user").withRequiredArg().ofType(String.class);
+        op.accepts(DST_PASSWORD, "Target rdb 
password").withRequiredArg().ofType(String.class);
+    }
+
+    private static void addPathsOptions(OptionParser op) {
+        op.accepts(INCLUDE_PATHS, "Comma-separated list of paths to include 
during copy.").withRequiredArg()
+                .ofType(String.class);
+        op.accepts(EXCLUDE_PATHS, "Comma-separated list of paths to exclude 
during copy.").withRequiredArg()
+                .ofType(String.class);
+        op.accepts(MERGE_PATHS, "Comma-separated list of paths to merge during 
copy.").withRequiredArg()
+                .ofType(String.class);
+    }
+
+    private static void addVersioningOptions(OptionParser op) {
+        op.accepts(COPY_VERSIONS,
+                "Copy the version storage. Parameters: { true | false | 
yyyy-mm-dd }. Defaults to true.")
+                .withRequiredArg().ofType(String.class);
+        op.accepts(COPY_ORPHANED_VERSIONS,
+                "Allows to skip copying orphaned versions. Parameters: { true 
| false | yyyy-mm-dd }. Defaults to true.")
+                .withRequiredArg().ofType(String.class);
+    }
+
+    private static void addMiscOptions(OptionParser op) {
+        op.accepts(MMAP, "Enable memory mapped file access for Segment Store");
+        op.accepts(FAIL_ON_ERROR, "Fail completely if nodes can't be read from 
the source repo");
+        op.accepts(EARLY_SHUTDOWN,
+                "Shutdown the source repository after nodes are copied and 
before the commit hooks are applied");
+        op.accepts(CACHE_SIZE, "Cache size in 
MB").withRequiredArg().ofType(Integer.class).defaultsTo(256);
+    }
+}


Reply via email to