You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2015/09/25 12:18:13 UTC

svn commit: r1705265 [2/3] - in /jackrabbit/oak/trunk: oak-run/ oak-run/src/main/java/org/apache/jackrabbit/oak/run/ oak-run/src/test/java/org/apache/jackrabbit/oak/run/ oak-upgrade/ oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/blob/ oak...

Added: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreArguments.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreArguments.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreArguments.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreArguments.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,263 @@
+/*
+ * 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.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.plugins.segment.SegmentVersion;
+import org.apache.jackrabbit.oak.upgrade.cli.blob.BlobStoreFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.blob.DummyBlobStoreFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.blob.FileBlobStoreFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.blob.FileDataStoreFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.blob.S3DataStoreFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.node.StoreFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory.SRC_FBS;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory.SRC_FDS;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory.DST_FBS;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory.DST_FDS;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory.DST_S3;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory.DST_S3_CONFIG;
+
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.StoreType.JCR2_DIR;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.StoreType.JCR2_DIR_XML;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.StoreType.JCR2_XML;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.StoreType.SEGMENT;
+import static org.apache.jackrabbit.oak.upgrade.cli.parser.StoreType.getMatchingType;
+
+public class StoreArguments {
+
+    private static final String DEFAULT_CRX2_REPO = "crx-quickstart/repository";
+
+    private static final String REPOSITORY_XML = "repository.xml";
+
+    private static final Logger log = LoggerFactory.getLogger(StoreArguments.class);
+
+    private final MigrationCliArguments parser;
+
+    private final StoreDescriptor src;
+
+    private final StoreDescriptor dst;
+
+    public StoreArguments(MigrationCliArguments parser) throws CliArgumentException {
+        this.parser = parser;
+
+        List<StoreDescriptor> descriptors = createStoreDescriptors(parser.getArguments());
+
+        src = descriptors.get(0);
+        dst = descriptors.get(1);
+
+        log.info("Source: {}", src);
+        log.info("Destination: {}", dst);
+
+        if (dst.getType() == SEGMENT) {
+            logSegmentVersion();
+        }
+    }
+
+    public StoreFactory getSrcStore() {
+        return src.getFactory(MigrationDirection.SRC, parser);
+    }
+
+    public StoreFactory getDstStore() {
+        return dst.getFactory(MigrationDirection.DST, parser);
+    }
+
+    public BlobStoreFactory getSrcBlobStore() {
+        BlobStoreFactory factory;
+        if (parser.hasOption(SRC_FBS)) {
+            factory = new FileBlobStoreFactory(parser.getOption(SRC_FBS));
+        } else if (parser.hasOption(SRC_FDS)) {
+            factory = new FileDataStoreFactory(parser.getOption(SRC_FDS));
+        } else {
+            factory = new DummyBlobStoreFactory();
+        }
+        return factory;
+    }
+
+    public BlobStoreFactory getDstBlobStore() throws IOException {
+        BlobStoreFactory factory;
+        if (parser.hasOption(DST_FBS)) {
+            factory = new FileBlobStoreFactory(parser.getOption(DST_FBS));
+        } else if (parser.hasOption(DST_S3_CONFIG) && parser.hasOption(DST_S3)) {
+            factory = new S3DataStoreFactory(parser.getOption(DST_S3_CONFIG), parser.getOption(DST_S3));
+        } else if (parser.hasOption(DST_FDS)) {
+            factory = new FileDataStoreFactory(parser.getOption(DST_FDS));
+        } else {
+            factory = new DummyBlobStoreFactory();
+        }
+        return factory;
+    }
+
+    public boolean isInPlaceUpgrade() {
+        if (src.getType() == JCR2_DIR_XML && dst.getType() == SEGMENT) {
+            return src.getPath().equals(dst.getPath());
+        }
+        return false;
+    }
+
+    public String[] getSrcPaths() {
+        return src.getPaths();
+    }
+
+    private static List<StoreDescriptor> createStoreDescriptors(List<String> arguments) throws CliArgumentException {
+        List<StoreDescriptor> descriptors = mapToStoreDescriptors(arguments);
+        mergeCrx2Descriptors(descriptors);
+        addSegmentAsDestination(descriptors);
+        validateDescriptors(descriptors);
+        return descriptors;
+    }
+
+    private static List<StoreDescriptor> mapToStoreDescriptors(List<String> arguments) throws CliArgumentException {
+        List<StoreDescriptor> descriptors = new ArrayList<StoreDescriptor>();
+        boolean jcr2Dir = false;
+        boolean jcr2Xml = false;
+        for (String argument : arguments) {
+            StoreType type = getMatchingType(argument);
+            if (type == JCR2_DIR) {
+                if (jcr2Dir) {
+                    type = SEGMENT;
+                }
+                jcr2Dir = true;
+            }
+            if (type == JCR2_DIR_XML) {
+                if (jcr2Xml) {
+                    throw new CliArgumentException("Too many repository.xml files passed as arguments", 1);
+                }
+                jcr2Xml = true;
+            }
+            descriptors.add(new StoreDescriptor(type, argument));
+        }
+        return descriptors;
+    }
+
+    private static void mergeCrx2Descriptors(List<StoreDescriptor> descriptors) {
+        int crx2DirIndex = -1;
+        int crx2XmlIndex = -1;
+        for (int i = 0; i < descriptors.size(); i++) {
+            StoreType type = descriptors.get(i).getType();
+            if (type == JCR2_DIR) {
+                crx2DirIndex = i;
+            } else if (type == JCR2_XML) {
+                crx2XmlIndex = i;
+            }
+        }
+
+        if (crx2DirIndex > -1 || crx2XmlIndex > -1) {
+            String repoDir;
+            if (crx2DirIndex > -1) {
+                repoDir = descriptors.get(crx2DirIndex).getPath();
+                descriptors.set(crx2DirIndex, null);
+            } else {
+                repoDir = DEFAULT_CRX2_REPO;
+            }
+            String repoXml;
+            if (crx2XmlIndex > -1) {
+                repoXml = descriptors.get(crx2XmlIndex).getPath();
+                descriptors.set(crx2XmlIndex, null);
+            } else {
+                repoXml = repoDir + "/" + REPOSITORY_XML;
+            }
+            descriptors.add(0, new StoreDescriptor(JCR2_DIR_XML, repoDir, repoXml));
+
+            Iterator<StoreDescriptor> it = descriptors.iterator();
+            while (it.hasNext()) {
+                if (it.next() == null) {
+                    it.remove();
+                }
+            }
+        }
+    }
+
+    private static void addSegmentAsDestination(List<StoreDescriptor> descriptors) {
+        if (descriptors.size() == 1) {
+            StoreType type = descriptors.get(0).getType();
+            if (type == JCR2_DIR_XML) {
+                String crx2Dir = descriptors.get(0).getPath();
+                descriptors.add(new StoreDescriptor(SEGMENT, crx2Dir));
+                log.info("In place migration between JCR2 and SegmentNodeStore in {}", crx2Dir);
+            }
+        }
+    }
+
+    private static void validateDescriptors(List<StoreDescriptor> descriptors) throws CliArgumentException {
+        if (descriptors.size() < 2) {
+            throw new CliArgumentException("Not enough node store arguments: " + descriptors.toString(), 1);
+        } else if (descriptors.size() > 2) {
+            throw new CliArgumentException("Too much node store arguments: " + descriptors.toString(), 1);
+        } else if (descriptors.get(1).getType() == JCR2_DIR_XML) {
+            throw new CliArgumentException("Can't use CRX2 as a destination", 1);
+        }
+    }
+
+    private static void logSegmentVersion() {
+        SegmentVersion[] versions = SegmentVersion.values();
+        SegmentVersion lastVersion = versions[versions.length - 1];
+        log.info("Using Oak segment format {} - please make sure your version of AEM supports that format",
+                lastVersion);
+        if (lastVersion == SegmentVersion.V_11) {
+            log.info("Requires Oak 1.0.12, 1.1.7 or later");
+        }
+    }
+
+    enum MigrationDirection {
+        SRC, DST
+    }
+
+    private static class StoreDescriptor {
+
+        private final String[] paths;
+
+        private final StoreType type;
+
+        public StoreDescriptor(StoreType type, String... paths) {
+            this.type = type;
+            this.paths = paths;
+        }
+
+        public String[] getPaths() {
+            return paths;
+        }
+
+        public String getPath() {
+            return paths[0];
+        }
+
+        public StoreType getType() {
+            return type;
+        }
+
+        public StoreFactory getFactory(MigrationDirection direction, MigrationCliArguments arguments) {
+            return type.createFactory(paths, direction, arguments);
+        }
+
+        @Override
+        public String toString() {
+            if (paths.length == 1) {
+                return String.format("%s[%s]", type, getPath());
+            } else {
+                return String.format("%s%s", type, Arrays.toString(getPaths()));
+            }
+        }
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreType.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreType.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreType.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/StoreType.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,118 @@
+/*
+ * 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 org.apache.jackrabbit.oak.upgrade.cli.node.Jackrabbit2Factory.isJcr2Repository;
+import static org.apache.jackrabbit.oak.upgrade.cli.node.Jackrabbit2Factory.isRepositoryXml;
+
+import org.apache.jackrabbit.oak.upgrade.cli.node.Jackrabbit2Factory;
+import org.apache.jackrabbit.oak.upgrade.cli.node.JdbcFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.node.MongoFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.node.SegmentFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.node.StoreFactory;
+import org.apache.jackrabbit.oak.upgrade.cli.parser.StoreArguments.MigrationDirection;
+
+enum StoreType {
+    JCR2_XML {
+        @Override
+        public boolean matches(String argument) {
+            return isRepositoryXml(argument);
+        }
+
+        @Override
+        public StoreFactory createFactory(String[] paths, MigrationDirection direction, MigrationCliArguments arguments) {
+            throw new UnsupportedOperationException();
+        }
+    },
+    JCR2_DIR {
+        @Override
+        public boolean matches(String argument) {
+            return isJcr2Repository(argument);
+        }
+
+        @Override
+        public StoreFactory createFactory(String[] paths, MigrationDirection direction, MigrationCliArguments arguments) {
+            throw new UnsupportedOperationException();
+        }
+    },
+    JCR2_DIR_XML {
+        @Override
+        public boolean matches(String argument) {
+            return false;
+        }
+
+        @Override
+        public StoreFactory createFactory(String[] paths, MigrationDirection direction, MigrationCliArguments arguments) {
+            return new StoreFactory(new Jackrabbit2Factory(paths[0], paths[1]));
+        }
+    },
+    JDBC {
+        @Override
+        public boolean matches(String argument) {
+            return argument.startsWith("jdbc:");
+        }
+
+        @Override
+        public StoreFactory createFactory(String[] paths, MigrationDirection direction, MigrationCliArguments arguments) {
+            String username, password;
+            if (direction == MigrationDirection.SRC) {
+                username = arguments.getOption(OptionParserFactory.SRC_USER);
+                password = arguments.getOption(OptionParserFactory.SRC_PASSWORD);
+            } else {
+                username = arguments.getOption(OptionParserFactory.DST_USER);
+                password = arguments.getOption(OptionParserFactory.DST_PASSWORD);
+            }
+            return new StoreFactory(
+                    new JdbcFactory(paths[0], arguments.getOptions().getCacheSizeInMB(), username, password));
+        }
+    },
+    MONGO {
+        @Override
+        public boolean matches(String argument) {
+            return argument.startsWith("mongodb://");
+        }
+
+        @Override
+        public StoreFactory createFactory(String[] paths, MigrationDirection direction, MigrationCliArguments arguments) {
+            return new StoreFactory(new MongoFactory(paths[0], arguments.getOptions().getCacheSizeInMB()));
+        }
+    },
+    SEGMENT {
+        @Override
+        public boolean matches(String argument) {
+            return true;
+        }
+
+        @Override
+        public StoreFactory createFactory(String[] paths, MigrationDirection direction, MigrationCliArguments arguments) {
+            return new StoreFactory(new SegmentFactory(paths[0], arguments.getOptions().isMmap()));
+        }
+    };
+
+    public static StoreType getMatchingType(String argument) {
+        for (StoreType t : values()) {
+            if (t.matches(argument)) {
+                return t;
+            }
+        }
+        return SEGMENT;
+    }
+
+    public abstract boolean matches(String argument);
+
+    public abstract StoreFactory createFactory(String[] paths, MigrationDirection direction, MigrationCliArguments arguments);
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-upgrade/src/main/resources/logback.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/resources/logback.xml?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/resources/logback.xml (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/resources/logback.xml Fri Sep 25 10:18:10 2015
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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.
+  -->
+<configuration>
+
+  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoders are assigned the type
+         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+    <encoder>
+      <pattern>%d{dd.MM.yyyy HH:mm:ss.SSS} [%thread] *%level*  %logger - %message%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="info">
+    <appender-ref ref="CONSOLE" />
+  </root>
+</configuration>
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-upgrade/src/main/resources/upgrade_usage.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/resources/upgrade_usage.txt?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/resources/upgrade_usage.txt (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/resources/upgrade_usage.txt Fri Sep 25 10:18:10 2015
@@ -0,0 +1,76 @@
+Usage: ${command} [options] jcr2_source [destination]
+       (to upgrade a JCR 2 repository)
+
+       ${command} [options] source destination
+       (to migrate an Oak repository)
+
+# jcr2_source
+
+It's a path to the repository directory and optionally the repository.xml file,
+for instance:
+
+  crx-quickstart/repository
+  my-instance/repository somewhere-else/repository.xml
+
+If there is no destination, repository will be converted to a segment node store
+in-place. Old files will be moved to the repository/crx2 directory.
+
+# source / destination
+
+An descriptor of the Oak node store. Possible options:
+
+  * path to the segment store
+  * jdbc:... (requires passing username and password as separate parameters)
+  * mongodb://host:port/database
+
+# node store options
+
+--cache <int>             Cache size in MB (default: 256)
+--mmap                    Enable memory mapped file access for Segment Store
+
+--src-password            Source rdb password
+--src-user                Source rdb user
+--user                    Target rdb user
+--password                Target rdb password
+
+# migration options
+
+--copy-binaries           Copy binary content. Use this to disable use of
+                            existing DataStore in new repo
+--early-shutdown          Shutdown the source JCR2 repository after nodes are
+                            copied and before the commit hooks are applied
+--fail-on-error           Fail completely if nodes can't be read from the
+                            source repo
+
+# version store options
+
+--copy-orphaned-versions  Allows to skip copying orphaned versions. Parameters:
+                            { true | false | yyyy-mm-dd }. Defaults to true.
+--copy-versions           Copy the version storage. Parameters:
+                            { true | false | yyyy-mm-dd }. Defaults to true.
+
+# paths options
+
+--include-paths           Comma-separated list of paths to include during copy.
+--merge-paths             Comma-separated list of paths to merge during copy.
+--exclude-paths           Comma-separated list of paths to exclude during copy.
+
+# source blob store options
+
+--src-datastore           Datastore directory to be used as a source
+                            FileDataStore
+--src-fileblobstore       Datastore directory to be used as a source
+                            FileBlobStore
+
+# destination blob store options
+
+--datastore               Datastore directory to be used as a target
+                            FileDataStore
+--fileblobstore           Datastore directory to be used as a target
+                            FileBlobStore
+--s3config                Configuration file for the target S3DataStore
+--s3datastore             Repository home to be used for the target S3
+
+# other options
+
+-?, -h, --help            show help
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/AbstractOak2OakTest.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,140 @@
+/*
+ * 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 static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
+import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.upgrade.RepositorySidegrade;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Joiner;
+
+public abstract class AbstractOak2OakTest {
+
+    private static final Logger log = LoggerFactory.getLogger(AbstractOak2OakTest.class);
+
+    protected static SegmentNodeStoreContainer testContent;
+
+    private NodeStore destination;
+
+    private Session session;
+
+    private RepositoryImpl repository;
+
+    protected abstract NodeStoreContainer getSourceContainer();
+
+    protected abstract NodeStoreContainer getDestinationContainer();
+
+    protected abstract String[] getArgs();
+
+    @BeforeClass
+    public static void unpackSegmentRepo() throws IOException {
+        File tempDir = new File("target", "test-segment-store");
+        if (!tempDir.isDirectory()) {
+            Util.unzip(AbstractOak2OakTest.class.getResourceAsStream("/segmentstore.zip"), tempDir);
+        }
+        testContent = new SegmentNodeStoreContainer(tempDir);
+    }
+
+    @Before
+    public void prepare() throws Exception {
+        NodeStore source = getSourceContainer().open();
+        try {
+            initContent(source);
+        } finally {
+            getSourceContainer().close();
+        }
+
+        String[] args = getArgs();
+        log.info("oak2oak {}", Joiner.on(' ').join(args));
+        OakUpgrade.main(args);
+
+        destination = getDestinationContainer().open();
+        repository = (RepositoryImpl) new Jcr(destination).with(new ReferenceIndexProvider()).createRepository();
+        session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
+    }
+
+    @After
+    public void clean() throws IOException {
+        session.logout();
+        repository.shutdown();
+        getDestinationContainer().close();
+        getDestinationContainer().clean();
+    }
+
+    private void initContent(NodeStore target) throws IOException, RepositoryException {
+        NodeStore initialContent = testContent.open();
+        try {
+            RepositorySidegrade sidegrade = new RepositorySidegrade(initialContent, target);
+            sidegrade.copy();
+        } finally {
+            testContent.close();
+        }
+    }
+
+    @Test
+    public void validateMigration() throws RepositoryException, IOException {
+        verifyContent(session);
+        verifyBlob(session);
+    }
+
+    static void verifyContent(Session session) throws RepositoryException {
+        Node allow = session.getNode("/apps");
+        assertEquals("sling:Folder", allow.getProperty("jcr:primaryType").getString());
+        assertEquals("admin", allow.getProperty("jcr:createdBy").getString());
+
+        Node nodeType = session.getNode("/jcr:system/jcr:nodeTypes/sling:OrderedFolder");
+        assertEquals("rep:NodeType", nodeType.getProperty("jcr:primaryType").getString());
+        assertEquals("jcr:mixinTypes", nodeType.getProperty("rep:protectedProperties").getValues()[0].getString());
+        assertEquals("false", nodeType.getProperty("jcr:isAbstract").getString());
+    }
+
+    static void verifyBlob(Session session) throws IOException, RepositoryException {
+        Property p = session.getProperty("/sling-logo.png/jcr:content/jcr:data");
+        InputStream is = p.getValue().getBinary().getStream();
+        String expectedMD5 = "35504d8c59455ab12a31f3d06f139a05";
+        try {
+            assertEquals(expectedMD5, DigestUtils.md5Hex(is));
+        } finally {
+            is.close();
+        }
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Jcr2ToSegmentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Jcr2ToSegmentTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Jcr2ToSegmentTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Jcr2ToSegmentTest.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;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
+import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class Jcr2ToSegmentTest {
+
+    private final NodeStoreContainer destinationContainer = new SegmentNodeStoreContainer();
+
+    private NodeStore destination;
+
+    private RepositoryImpl repository;
+
+    private Session session;
+
+    @Before
+    public void prepare() throws Exception {
+        File tempDir = new File("target", "test-jcr2");
+        if (!tempDir.isDirectory()) {
+            Util.unzip(AbstractOak2OakTest.class.getResourceAsStream("/jcr2.zip"), tempDir);
+        }
+
+        OakUpgrade.main("--copy-binaries", tempDir.getPath(), destinationContainer.getDescription());
+
+        destination = destinationContainer.open();
+        repository = (RepositoryImpl) new Jcr(destination).with(new ReferenceIndexProvider()).createRepository();
+        session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
+    }
+
+    @After
+    public void clean() throws IOException {
+        session.logout();
+        repository.shutdown();
+        destinationContainer.close();
+        destinationContainer.clean();
+    }
+
+    @Test
+    public void validateMigration() throws RepositoryException, IOException {
+        AbstractOak2OakTest.verifyContent(session);
+        AbstractOak2OakTest.verifyBlob(session);
+    }
+
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/JdbcToSegmentTest.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,51 @@
+/*
+ * 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 org.apache.jackrabbit.oak.upgrade.cli.container.JdbcNodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class JdbcToSegmentTest extends AbstractOak2OakTest {
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public JdbcToSegmentTest() throws IOException {
+        source = new JdbcNodeStoreContainer();
+        destination = new SegmentNodeStoreContainer();
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--src-user", "sa", "--src-password", "sa", source.getDescription(),
+                destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFbsTest.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;
+
+import java.io.IOException;
+
+import static org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer.isMongoAvailable;
+import static org.junit.Assume.assumeTrue;
+
+import org.apache.jackrabbit.oak.upgrade.cli.container.BlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileBlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+
+/**
+ * This covers the bug GRANITE-8719.
+ */
+public class MongoToMongoFbsTest extends AbstractOak2OakTest {
+
+    private final BlobStoreContainer destinationBlob;
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public MongoToMongoFbsTest() throws IOException {
+        assumeTrue(isMongoAvailable());
+        destinationBlob = new FileBlobStoreContainer();
+        source = new MongoNodeStoreContainer();
+        destination = new MongoNodeStoreContainer(destinationBlob);
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--copy-binaries", "--fileblobstore", destinationBlob.getDescription(),
+                source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFds.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFds.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFds.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToMongoFds.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,59 @@
+/*
+ * 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 static org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer.isMongoAvailable;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.upgrade.cli.container.BlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileDataStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+
+public class MongoToMongoFds extends AbstractOak2OakTest {
+
+    private final BlobStoreContainer destinationBlob;
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public MongoToMongoFds() throws IOException {
+        assumeTrue(isMongoAvailable());
+        destinationBlob = new FileDataStoreContainer();
+        source = new MongoNodeStoreContainer();
+        destination = new MongoNodeStoreContainer(destinationBlob);
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--copy-binaries", "--fileblobstore", destinationBlob.getDescription(),
+                source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/MongoToSegmentTest.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;
+
+import static org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer.isMongoAvailable;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class MongoToSegmentTest extends AbstractOak2OakTest {
+
+    private final MongoNodeStoreContainer source;
+
+    private final SegmentNodeStoreContainer destination;
+
+    public MongoToSegmentTest() throws IOException {
+        assumeTrue(isMongoAvailable());
+        source = new MongoNodeStoreContainer();
+        destination = new SegmentNodeStoreContainer();
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToJdbcTest.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,51 @@
+/*
+ * 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 org.apache.jackrabbit.oak.upgrade.cli.container.JdbcNodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class SegmentToJdbcTest extends AbstractOak2OakTest {
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public SegmentToJdbcTest() throws IOException {
+        source = new SegmentNodeStoreContainer();
+        destination = new JdbcNodeStoreContainer();
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--user", "sa", "--password", "sa", source.getDescription(),
+                destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToMongoTest.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;
+
+import static org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer.isMongoAvailable;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.upgrade.cli.container.MongoNodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class SegmentToMongoTest extends AbstractOak2OakTest {
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public SegmentToMongoTest() throws IOException {
+        assumeTrue(isMongoAvailable());
+        source = new SegmentNodeStoreContainer();
+        destination = new MongoNodeStoreContainer();
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToSegmentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToSegmentTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToSegmentTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/SegmentToSegmentTest.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,47 @@
+/*
+ * 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 org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class SegmentToSegmentTest extends AbstractOak2OakTest {
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public SegmentToSegmentTest() {
+        source = new SegmentNodeStoreContainer();
+        destination = new SegmentNodeStoreContainer();
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Util.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Util.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Util.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/Util.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,66 @@
+/*
+ * 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.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class Util {
+
+    private static final Logger log = LoggerFactory.getLogger(Util.class);
+
+    private Util() {
+    }
+
+    public static void unzip(InputStream is, File targetDir) throws IOException {
+        long start = System.currentTimeMillis();
+        log.info("Unzipping to {}", targetDir.getAbsolutePath());
+        final ZipInputStream zis = new ZipInputStream(is);
+        try {
+            ZipEntry entry = null;
+            while((entry = zis.getNextEntry()) != null) {
+                if (entry.isDirectory()) {
+                    new File(targetDir, entry.getName()).mkdirs();
+                } else {
+                    File target = new File(targetDir, entry.getName());
+                    target.getParentFile().mkdirs();
+                    OutputStream output = new FileOutputStream(target);
+                    try {
+                        IOUtils.copy(zis, output);
+                    } finally {
+                        output.close();
+                    }
+                }
+            }
+        } finally {
+            zis.close();
+        }
+        final long delta = System.currentTimeMillis() - start;
+        if(delta > 1000L) {
+            log.info("Unzip took {} msec", delta);
+        }
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/CopyReferencesTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/CopyReferencesTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/CopyReferencesTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/CopyReferencesTest.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 org.apache.jackrabbit.oak.upgrade.cli.AbstractOak2OakTest;
+import org.apache.jackrabbit.oak.upgrade.cli.container.BlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileDataStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class CopyReferencesTest extends AbstractOak2OakTest {
+
+    private final BlobStoreContainer sourceBlob;
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public CopyReferencesTest() {
+        sourceBlob = new FileDataStoreContainer();
+        source = new SegmentNodeStoreContainer(sourceBlob);
+        destination = new SegmentNodeStoreContainer(sourceBlob);
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--src-datastore", sourceBlob.getDescription(), source.getDescription(),
+                destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFbsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFbsTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFbsTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFbsTest.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,57 @@
+/*
+ * 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.upgrade.cli.AbstractOak2OakTest;
+import org.apache.jackrabbit.oak.upgrade.cli.container.BlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileBlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class FbsToFbsTest extends AbstractOak2OakTest {
+
+    private final BlobStoreContainer sourceBlob;
+
+    private final BlobStoreContainer destinationBlob;
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public FbsToFbsTest() {
+        sourceBlob = new FileBlobStoreContainer();
+        destinationBlob = new FileBlobStoreContainer();
+        source = new SegmentNodeStoreContainer(sourceBlob);
+        destination = new SegmentNodeStoreContainer(destinationBlob);
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--copy-binaries", "--src-fileblobstore", sourceBlob.getDescription(), "--fileblobstore",
+                destinationBlob.getDescription(), source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFdsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFdsTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFdsTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToFdsTest.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,58 @@
+/*
+ * 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.upgrade.cli.AbstractOak2OakTest;
+import org.apache.jackrabbit.oak.upgrade.cli.container.BlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileBlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileDataStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class FbsToFdsTest extends AbstractOak2OakTest {
+
+    private final BlobStoreContainer sourceBlob;
+
+    private final BlobStoreContainer destinationBlob;
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public FbsToFdsTest() {
+        sourceBlob = new FileBlobStoreContainer();
+        destinationBlob = new FileDataStoreContainer();
+        source = new SegmentNodeStoreContainer(sourceBlob);
+        destination = new SegmentNodeStoreContainer(destinationBlob);
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--copy-binaries", "--src-fileblobstore", sourceBlob.getDescription(), "--datastore",
+                destinationBlob.getDescription(), source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToS3Test.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToS3Test.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToS3Test.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FbsToS3Test.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,63 @@
+/*
+ * 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.upgrade.cli.AbstractOak2OakTest;
+import org.apache.jackrabbit.oak.upgrade.cli.container.BlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileBlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.S3DataStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+import org.junit.Assume;
+
+public class FbsToS3Test extends AbstractOak2OakTest {
+
+    private static final String S3_PROPERTIES = System.getProperty("s3.properties");
+
+    private final BlobStoreContainer sourceBlob;
+
+    private final BlobStoreContainer destinationBlob;
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public FbsToS3Test() {
+        Assume.assumeTrue(S3_PROPERTIES != null);
+        sourceBlob = new FileBlobStoreContainer();
+        destinationBlob = new S3DataStoreContainer(S3_PROPERTIES);
+        source = new SegmentNodeStoreContainer(sourceBlob);
+        destination = new SegmentNodeStoreContainer(destinationBlob);
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--copy-binaries", "--src-fileblobstore", sourceBlob.getDescription(), "--s3datastore",
+                destinationBlob.getDescription(), "--s3config", S3_PROPERTIES, source.getDescription(),
+                destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FdsToFbsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FdsToFbsTest.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FdsToFbsTest.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FdsToFbsTest.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,58 @@
+/*
+ * 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.upgrade.cli.AbstractOak2OakTest;
+import org.apache.jackrabbit.oak.upgrade.cli.container.BlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileBlobStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.FileDataStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.NodeStoreContainer;
+import org.apache.jackrabbit.oak.upgrade.cli.container.SegmentNodeStoreContainer;
+
+public class FdsToFbsTest extends AbstractOak2OakTest {
+
+    private final BlobStoreContainer sourceBlob;
+
+    private final BlobStoreContainer destinationBlob;
+
+    private final NodeStoreContainer source;
+
+    private final NodeStoreContainer destination;
+
+    public FdsToFbsTest() {
+        sourceBlob = new FileDataStoreContainer();
+        destinationBlob = new FileBlobStoreContainer();
+        source = new SegmentNodeStoreContainer(sourceBlob);
+        destination = new SegmentNodeStoreContainer(destinationBlob);
+    }
+
+    @Override
+    protected NodeStoreContainer getSourceContainer() {
+        return source;
+    }
+
+    @Override
+    protected NodeStoreContainer getDestinationContainer() {
+        return destination;
+    }
+
+    @Override
+    protected String[] getArgs() {
+        return new String[] { "--copy-binaries", "--src-datastore", sourceBlob.getDescription(), "--fileblobstore",
+                destinationBlob.getDescription(), source.getDescription(), destination.getDescription() };
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/BlobStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/BlobStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/BlobStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/BlobStoreContainer.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,32 @@
+/*
+ * 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.container;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+public interface BlobStoreContainer extends Closeable {
+
+    BlobStore open() throws IOException;
+
+    void clean() throws IOException;
+
+    String getDescription();
+
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/DummyBlobStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/DummyBlobStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/DummyBlobStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/DummyBlobStoreContainer.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,43 @@
+/*
+ * 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.container;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+public class DummyBlobStoreContainer implements BlobStoreContainer {
+
+    @Override
+    public BlobStore open() throws IOException {
+        return null;
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public void clean() throws IOException {
+    }
+
+    @Override
+    public String getDescription() {
+        return "";
+    }
+
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileBlobStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileBlobStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileBlobStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileBlobStoreContainer.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,55 @@
+/*
+ * 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.container;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.blob.FileBlobStore;
+
+import com.google.common.io.Files;
+
+public class FileBlobStoreContainer implements BlobStoreContainer {
+
+    private final File directory;
+
+    public FileBlobStoreContainer() {
+        this.directory = Files.createTempDir();
+    }
+
+    @Override
+    public BlobStore open() throws IOException {
+        return new FileBlobStore(directory.getPath());
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public void clean() throws IOException {
+        FileUtils.deleteDirectory(directory);
+    }
+
+    @Override
+    public String getDescription() {
+        return directory.getPath();
+    }
+
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileDataStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileDataStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileDataStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/FileDataStoreContainer.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,60 @@
+/*
+ * 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.container;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.upgrade.cli.blob.FileDataStoreFactory;
+
+import com.google.common.io.Closer;
+import com.google.common.io.Files;
+
+public class FileDataStoreContainer implements BlobStoreContainer {
+
+    private final File directory;
+
+    private final Closer closer;
+    
+    public FileDataStoreContainer() {
+        this.directory = Files.createTempDir();
+        this.closer = Closer.create();
+    }
+
+    @Override
+    public BlobStore open() throws IOException {
+        return new FileDataStoreFactory(directory.getPath()).create(closer);
+    }
+
+    @Override
+    public void close() throws IOException {
+        closer.close();
+    }
+
+    @Override
+    public void clean() throws IOException {
+        FileUtils.deleteDirectory(directory);
+    }
+
+    @Override
+    public String getDescription() {
+        return directory.getPath();
+    }
+
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/JdbcNodeStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/JdbcNodeStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/JdbcNodeStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/JdbcNodeStoreContainer.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.container;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.upgrade.cli.node.JdbcFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Closer;
+import com.google.common.io.Files;
+
+public class JdbcNodeStoreContainer implements NodeStoreContainer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JdbcNodeStoreContainer.class);
+
+    private final File h2Dir;
+
+    private final String jdbcUri;
+
+    private final JdbcFactory jdbcFactory;
+
+    private final BlobStoreContainer blob;
+
+    private Closer closer;
+
+    public JdbcNodeStoreContainer() throws IOException {
+        this(new DummyBlobStoreContainer());
+    }
+
+    public JdbcNodeStoreContainer(BlobStoreContainer blob) {
+        this.blob = blob;
+        this.h2Dir = Files.createTempDir();
+        this.jdbcUri = String.format("jdbc:h2:%s", h2Dir.getPath());
+        this.jdbcFactory = new JdbcFactory(jdbcUri, 2, "sa", "sa");
+    }
+
+    @Override
+    public NodeStore open() throws IOException {
+        this.closer = Closer.create();
+        return jdbcFactory.create(blob.open(), closer);
+    }
+
+    @Override
+    public void close() {
+        try {
+            closer.close();
+        } catch (IOException e) {
+            LOG.error("Can't close document node store", e);
+        }
+    }
+
+    @Override
+    public void clean() throws IOException {
+        FileUtils.deleteDirectory(h2Dir);
+        blob.clean();
+    }
+
+    @Override
+    public String getDescription() {
+        return jdbcUri;
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/MongoNodeStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/MongoNodeStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/MongoNodeStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/MongoNodeStoreContainer.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,105 @@
+/*
+ * 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.container;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.upgrade.cli.node.MongoFactory;
+import org.junit.Assume;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Closer;
+import com.mongodb.Mongo;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientURI;
+
+public class MongoNodeStoreContainer implements NodeStoreContainer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MongoNodeStoreContainer.class);
+
+    private static final String MONGO_URI = System.getProperty("oak.mongo.uri",
+            "mongodb://localhost:27017/oak-migration");
+
+    private static final AtomicInteger DATABASE_SUFFIX = new AtomicInteger(1);
+
+    private final MongoFactory mongoFactory;
+
+    private final BlobStoreContainer blob;
+
+    private final String mongoUri;
+
+    private Closer closer;
+
+    public MongoNodeStoreContainer() throws IOException {
+        this(new DummyBlobStoreContainer());
+    }
+
+    public MongoNodeStoreContainer(BlobStoreContainer blob) throws IOException {
+        Assume.assumeTrue(isMongoAvailable());
+        this.mongoUri = String.format("%s-%d", MONGO_URI, DATABASE_SUFFIX.getAndIncrement());
+        this.mongoFactory = new MongoFactory(mongoUri, 2);
+        this.blob = blob;
+        clean();
+    }
+
+    public static boolean isMongoAvailable() {
+        Mongo mongo = null;
+        try {
+            MongoClientURI uri = new MongoClientURI(MONGO_URI);
+            mongo = new MongoClient(uri);
+            mongo.getDatabaseNames();
+            return true;
+        } catch (Exception e) {
+            return false;
+        } finally {
+            if (mongo != null) {
+                mongo.close();
+            }
+        }
+    }
+
+    @Override
+    public NodeStore open() throws IOException {
+        this.closer = Closer.create();
+        return mongoFactory.create(blob.open(), closer);
+    }
+
+    @Override
+    public void close() {
+        try {
+            closer.close();
+        } catch (IOException e) {
+            LOG.error("Can't close document node store", e);
+        }
+    }
+
+    @Override
+    public void clean() throws IOException {
+        MongoClientURI uri = new MongoClientURI(mongoUri);
+        MongoClient client = new MongoClient(uri);
+        client.dropDatabase(uri.getDatabase());
+        blob.clean();
+    }
+
+    @Override
+    public String getDescription() {
+        return mongoUri;
+    }
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/NodeStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/NodeStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/NodeStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/NodeStoreContainer.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,32 @@
+/*
+ * 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.container;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+public interface NodeStoreContainer extends Closeable {
+    NodeStore open() throws IOException;
+
+    void close();
+
+    void clean() throws IOException;
+
+    String getDescription();
+}

Added: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/S3DataStoreContainer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/S3DataStoreContainer.java?rev=1705265&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/S3DataStoreContainer.java (added)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/cli/container/S3DataStoreContainer.java Fri Sep 25 10:18:10 2015
@@ -0,0 +1,92 @@
+/*
+ * 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.container;
+
+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.FileUtils;
+import org.apache.commons.io.IOUtils;
+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.Files;
+
+public class S3DataStoreContainer implements BlobStoreContainer {
+
+    private static final Logger log = LoggerFactory.getLogger(S3DataStoreContainer.class);
+
+    private final String configFile;
+
+    private final File homeDir;
+
+    private S3DataStore s3DataStore;
+
+    public S3DataStoreContainer(String configFile) {
+        this.configFile = configFile;
+        this.homeDir = Files.createTempDir();
+    }
+
+    @Override
+    public BlobStore open() throws IOException {
+        Properties props = new Properties();
+        FileReader reader = new FileReader(new File(configFile));
+        try {
+            props.load(reader);
+        } finally {
+            IOUtils.closeQuietly(reader);
+        }
+        props.setProperty("path", new File(homeDir, "repository/datastore").getPath());
+
+        S3DataStore delegate = new S3DataStore();
+        delegate.setProperties(props);
+        try {
+            delegate.init(homeDir.getPath());
+        } catch (RepositoryException e) {
+            throw new IOException(e);
+        }
+        return new DataStoreBlobStore(delegate);
+    }
+
+    @Override
+    public void close() {
+        try {
+            s3DataStore.close();
+        } catch (DataStoreException e) {
+            log.error("Can't close s3datastore", e);
+        }
+    }
+
+    @Override
+    public void clean() throws IOException {
+        FileUtils.deleteDirectory(homeDir);
+    }
+
+    @Override
+    public String getDescription() {
+        return homeDir.getPath();
+    }
+
+}
\ No newline at end of file