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 ch...@apache.org on 2017/05/15 08:35:04 UTC

svn commit: r1795145 - in /jackrabbit/oak/trunk/oak-run/src: main/java/org/apache/jackrabbit/oak/console/ main/java/org/apache/jackrabbit/oak/run/cli/ test/java/org/apache/jackrabbit/oak/run/cli/

Author: chetanm
Date: Mon May 15 08:35:04 2017
New Revision: 1795145

URL: http://svn.apache.org/viewvc?rev=1795145&view=rev
Log:
OAK-6210 - Provide a consistent and extensible way to handle oak-run options while creating NodeStore

Added:
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/BlobStoreFixture.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreFixtureProvider.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreOptions.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/CommonOptions.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/DocumentNodeStoreOptions.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/NodeStoreFixtureProvider.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionBeans.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/Options.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBean.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBeanFactory.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/RDBStoreOptions.java   (with props)
    jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/cli/
    jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/cli/OptionsTest.java   (with props)

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/BlobStoreFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/BlobStoreFixture.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/BlobStoreFixture.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/BlobStoreFixture.java Mon May 15 08:35:04 2017
@@ -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.console;
+
+import java.io.Closeable;
+
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+public interface BlobStoreFixture extends Closeable {
+
+    BlobStore getBlobStore();
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/BlobStoreFixture.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreFixtureProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreFixtureProvider.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreFixtureProvider.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreFixtureProvider.java Mon May 15 08:35:04 2017
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import javax.annotation.CheckForNull;
+
+import com.google.common.collect.Maps;
+import com.google.common.io.Closer;
+import com.google.common.io.Files;
+import org.apache.commons.io.FileUtils;
+import org.apache.felix.cm.file.ConfigurationHandler;
+import org.apache.jackrabbit.core.data.DataStore;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.apache.jackrabbit.oak.blob.cloud.aws.s3.SharedS3DataStore;
+import org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage.AzureDataStore;
+import org.apache.jackrabbit.oak.console.BlobStoreFixture;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.OakFileDataStore;
+import org.apache.jackrabbit.oak.run.cli.BlobStoreOptions.Type;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+
+import static org.apache.jackrabbit.oak.commons.PropertiesUtil.populate;
+
+public class BlobStoreFixtureProvider {
+
+    @CheckForNull
+    public static BlobStoreFixture create(Options options) throws Exception{
+        BlobStoreOptions bsopts = options.getOptionBean(BlobStoreOptions.class);
+
+        if (bsopts == null){
+            return null;
+        }
+
+        Type bsType = bsopts.getBlobStoreType();
+
+        if (bsType == Type.NONE){
+            return null;
+        }
+        Closer closer = Closer.create();
+        DataStore delegate;
+        if (bsType == Type.S3){
+            SharedS3DataStore s3ds = new SharedS3DataStore();
+            Properties props = loadAndTransformProps(bsopts.getS3ConfigPath());
+            s3ds.setProperties(props);
+            s3ds.init(null);
+            delegate = s3ds;
+        } else if(bsType == Type.AZURE){
+            AzureDataStore azureds = new AzureDataStore();
+            String cfgPath = bsopts.getAzureConfigPath();
+            Properties props = loadAndTransformProps(cfgPath);
+            azureds.setProperties(props);
+            File homeDir =  Files.createTempDir();
+            azureds.init(homeDir.getAbsolutePath());
+            closer.register(asCloseable(homeDir));
+            delegate = azureds;
+        } else {
+            delegate = new OakFileDataStore();
+            String cfgPath = bsopts.getFDSConfigPath();
+            Properties props = loadAndTransformProps(cfgPath);
+            populate(delegate, Maps.fromProperties(props), true);
+            delegate.init(null);
+        }
+        DataStoreBlobStore blobStore = new DataStoreBlobStore(delegate);
+        return new DataStoreFixture(blobStore, closer);
+    }
+
+    private static class DataStoreFixture implements BlobStoreFixture {
+        private final DataStoreBlobStore blobStore;
+        private final Closer closer;
+
+        private DataStoreFixture(DataStoreBlobStore blobStore, Closer closer) {
+            this.blobStore = blobStore;
+            this.closer = closer;
+        }
+
+        @Override
+        public BlobStore getBlobStore() {
+            return blobStore;
+        }
+
+        @Override
+        public void close() throws IOException {
+            closer.close();
+            try {
+                blobStore.close();
+            } catch (DataStoreException e) {
+                throw new IOException(e);
+            }
+        }
+    }
+
+    private static Properties loadAndTransformProps(String cfgPath) throws IOException {
+        Dictionary dict = ConfigurationHandler.read(new FileInputStream(cfgPath));
+        Properties props = new Properties();
+        Enumeration keys = dict.keys();
+        while (keys.hasMoreElements()) {
+            String key = (String) keys.nextElement();
+            props.put(key, dict.get(key));
+        }
+        return props;
+    }
+
+    private static Closeable asCloseable(final File dir) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                FileUtils.deleteDirectory(dir);
+            }
+        };
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreFixtureProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreOptions.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreOptions.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreOptions.java Mon May 15 08:35:04 2017
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+
+import static java.util.Arrays.asList;
+
+public class BlobStoreOptions implements OptionsBean {
+    public enum Type {FDS, S3, AZURE, NONE}
+    private final OptionSpec<String> fdsOption;
+    private final OptionSpec<String> s3Option;
+    private final OptionSpec<String> azureOption;
+    private OptionSet options;
+
+    public BlobStoreOptions(OptionParser parser){
+        fdsOption = parser.acceptsAll(asList("fds", "fds-path"), "FileDataStore config")
+                .withRequiredArg().ofType(String.class);
+        s3Option = parser.accepts("s3ds", "S3DataStore config")
+                .withRequiredArg().ofType(String.class);
+        azureOption = parser.accepts("azureblobds", "AzureBlobStorageDataStore config")
+                .withRequiredArg().ofType(String.class);
+    }
+
+    @Override
+    public void configure(OptionSet options) {
+        this.options = options;
+    }
+
+    public String getFDSConfigPath(){
+        return fdsOption.value(options);
+    }
+
+    public String getS3ConfigPath(){
+        return s3Option.value(options);
+    }
+
+    public String getAzureConfigPath(){
+        return azureOption.value(options);
+    }
+
+    public Type getBlobStoreType(){
+        if (options.has(fdsOption)){
+            return Type.FDS;
+        } else if (options.has(s3Option)){
+            return Type.S3;
+        } else if (options.has(azureOption)){
+            return Type.AZURE;
+        }
+        return Type.NONE;
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/BlobStoreOptions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/CommonOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/CommonOptions.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/CommonOptions.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/CommonOptions.java Mon May 15 08:35:04 2017
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import java.util.List;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+
+import static java.util.Arrays.asList;
+
+public class CommonOptions implements OptionsBean {
+    private final OptionSpec<Void> help;
+    private final OptionSpec<Void> readWriteOption;
+    private final OptionSpec<String> nonOption;
+    private OptionSet options;
+
+    public CommonOptions(OptionParser parser){
+        help = parser.acceptsAll(asList("h", "?", "help"), "show help").forHelp();
+        readWriteOption = parser.accepts("read-write", "connect to repository in read-write mode");
+        nonOption = parser.nonOptions("{<path-to-repository> | <mongodb-uri>}");
+    }
+
+    @Override
+    public void configure(OptionSet options) {
+        this.options = options;
+    }
+
+    public boolean isHelpRequested(){
+        return options.has(help);
+    }
+
+    public boolean isReadWrite(){
+        return options.has(readWriteOption);
+    }
+
+    public List<String> getNonOptions(){
+        return nonOption.values(options);
+    }
+
+    public boolean isMongo(){
+        return getStoreArg().startsWith("mongodb://");
+    }
+
+    public boolean isRDB(){
+        return getStoreArg().startsWith("jdbc");
+    }
+
+    public boolean isSegment(){
+        return !isMongo() && !isRDB();
+    }
+
+    public String getStoreArg() {
+        List<String> nonOptions = nonOption.values(options);
+        return nonOptions.size() > 0 ? nonOptions.get(0) : "";
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/CommonOptions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/DocumentNodeStoreOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/DocumentNodeStoreOptions.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/DocumentNodeStoreOptions.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/DocumentNodeStoreOptions.java Mon May 15 08:35:04 2017
@@ -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.run.cli;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+
+public class DocumentNodeStoreOptions implements OptionsBean {
+    private final OptionSpec<Integer> clusterId;
+    private final OptionSpec<Void> disableBranchesSpec;
+    private final OptionSpec<Integer> cacheSizeSpec;
+    private OptionSet options;
+
+    public DocumentNodeStoreOptions(OptionParser parser){
+        clusterId = parser.accepts("clusterId", "MongoMK clusterId")
+                .withRequiredArg().ofType(Integer.class).defaultsTo(0);
+        disableBranchesSpec = parser.
+                accepts("disableBranches", "disable branches");
+        cacheSizeSpec = parser.
+                accepts("cacheSize", "cache size")
+                .withRequiredArg().ofType(Integer.class).defaultsTo(0);
+    }
+
+    @Override
+    public void configure(OptionSet options) {
+        this.options = options;
+    }
+
+    public int getClusterId(){
+        return clusterId.value(options);
+    }
+
+    public int getCacheSize() {
+        return cacheSizeSpec.value(options);
+    }
+
+    public boolean disableBranchesSpec() {
+        return options.has(disableBranchesSpec);
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/DocumentNodeStoreOptions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/NodeStoreFixtureProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/NodeStoreFixtureProvider.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/NodeStoreFixtureProvider.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/NodeStoreFixtureProvider.java Mon May 15 08:35:04 2017
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.net.UnknownHostException;
+
+import javax.sql.DataSource;
+
+import com.google.common.io.Closer;
+import com.mongodb.MongoClientURI;
+import org.apache.jackrabbit.oak.console.BlobStoreFixture;
+import org.apache.jackrabbit.oak.console.NodeStoreFixture;
+import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
+import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDataSourceFactory;
+import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection;
+import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder;
+import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
+import org.apache.jackrabbit.oak.segment.file.ReadOnlyFileStore;
+import org.apache.jackrabbit.oak.spi.blob.BlobStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;
+
+public class NodeStoreFixtureProvider {
+    private static final long MB = 1024 * 1024;
+
+    public static NodeStoreFixture create(Options options) throws Exception {
+        return create(options, !options.getOptionBean(CommonOptions.class).isReadWrite());
+    }
+
+    public static NodeStoreFixture create(Options options, boolean readOnly) throws Exception {
+        CommonOptions commonOpts = options.getOptionBean(CommonOptions.class);
+
+        Closer closer = Closer.create();
+        BlobStoreFixture blobFixture = BlobStoreFixtureProvider.create(options);
+        BlobStore blobStore = null;
+        if (blobFixture != null) {
+            blobStore = blobFixture.getBlobStore();
+            closer.register(blobFixture);
+        }
+
+        NodeStore store = null;
+        if (commonOpts.isMongo() || commonOpts.isRDB()) {
+            store = configureDocumentMk(options, blobStore, closer, readOnly);
+        } else {
+            store = configureSegment(options, blobStore, closer, readOnly);
+        }
+
+        return new SimpleNodeStoreFixture(store, closer);
+    }
+
+
+    private static NodeStore configureDocumentMk(Options options,
+                                                 BlobStore blobStore, Closer closer,
+                                                 boolean readOnly) throws UnknownHostException {
+        DocumentMK.Builder builder = new DocumentMK.Builder();
+
+        if (blobStore != null) {
+            builder.setBlobStore(blobStore);
+        }
+
+        DocumentNodeStoreOptions docStoreOpts = options.getOptionBean(DocumentNodeStoreOptions.class);
+
+        builder.setClusterId(docStoreOpts.getClusterId());
+
+        if (readOnly) {
+            builder.setReadOnlyMode();
+        }
+
+        int cacheSize = docStoreOpts.getCacheSize();
+        if (cacheSize != 0) {
+            builder.memoryCacheSize(cacheSize * MB);
+        }
+
+        if (docStoreOpts.disableBranchesSpec()) {
+            builder.disableBranches();
+        }
+
+        CommonOptions commonOpts = options.getOptionBean(CommonOptions.class);
+
+        if (commonOpts.isMongo()) {
+            MongoClientURI uri = new MongoClientURI(commonOpts.getStoreArg());
+            if (uri.getDatabase() == null) {
+                System.err.println("Database missing in MongoDB URI: "
+                        + uri.getURI());
+                System.exit(1);
+            }
+            MongoConnection mongo = new MongoConnection(uri.getURI());
+            closer.register(asCloseable(mongo));
+            builder.setMongoDB(mongo.getDB());
+        } else if (commonOpts.isRDB()) {
+            RDBStoreOptions rdbOpts = options.getOptionBean(RDBStoreOptions.class);
+            DataSource ds = RDBDataSourceFactory.forJdbcUrl(commonOpts.getStoreArg(),
+                    rdbOpts.getUser(), rdbOpts.getPassword());
+            builder.setRDBConnection(ds);
+        }
+
+        return builder.getNodeStore();
+    }
+
+    private static NodeStore configureSegment(Options options, BlobStore blobStore, Closer closer, boolean readOnly)
+            throws IOException, InvalidFileStoreVersionException {
+
+        String path = options.getOptionBean(CommonOptions.class).getStoreArg();
+        FileStoreBuilder builder = fileStoreBuilder(new File(path)).withMaxFileSize(256);
+
+        if (blobStore != null) {
+            builder.withBlobStore(blobStore);
+        }
+
+        NodeStore nodeStore;
+        if (readOnly) {
+            ReadOnlyFileStore fileStore = builder.buildReadOnly();
+            closer.register(fileStore);
+            nodeStore = SegmentNodeStoreBuilders.builder(fileStore).build();
+        } else {
+            FileStore fileStore = builder.build();
+            closer.register(fileStore);
+            nodeStore = SegmentNodeStoreBuilders.builder(fileStore).build();
+        }
+
+        return nodeStore;
+    }
+
+    private static Closeable asCloseable(final MongoConnection con) {
+        return new Closeable() {
+            @Override
+            public void close() throws IOException {
+                con.close();
+            }
+        };
+    }
+
+    private static class SimpleNodeStoreFixture implements NodeStoreFixture {
+        private final Closer closer;
+        private final NodeStore nodeStore;
+
+        private SimpleNodeStoreFixture(NodeStore nodeStore, Closer closer) {
+            this.closer = closer;
+            this.nodeStore = nodeStore;
+        }
+
+        @Override
+        public NodeStore getStore() {
+            return nodeStore;
+        }
+
+        @Override
+        public void close() throws IOException {
+            closer.close();
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/NodeStoreFixtureProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionBeans.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionBeans.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionBeans.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionBeans.java Mon May 15 08:35:04 2017
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import joptsimple.OptionParser;
+
+public enum OptionBeans implements OptionsBeanFactory {
+
+    RDB_STORE {
+        @Override
+        public OptionsBean newInstance(OptionParser parser){
+            return new RDBStoreOptions(parser);
+        }
+    },
+    DOCUMENT_NODE_STORE {
+        @Override
+        public OptionsBean newInstance(OptionParser parser){
+            return new DocumentNodeStoreOptions(parser);
+        }
+    },
+    COMMON {
+        @Override
+        public OptionsBean newInstance(OptionParser parser){
+            return new CommonOptions(parser);
+        }
+    },
+    BLOB_STORE {
+        @Override
+        public OptionsBean newInstance(OptionParser parser){
+            return new BlobStoreOptions(parser);
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionBeans.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/Options.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/Options.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/Options.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/Options.java Mon May 15 08:35:04 2017
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.MutableClassToInstanceMap;
+import com.google.common.collect.Sets;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Arrays.asList;
+
+public class Options {
+    private final Set<OptionsBeanFactory> beanFactories = Sets.newHashSet();
+    private final EnumSet<OptionBeans> oakRunOptions;
+    private final ClassToInstanceMap<OptionsBean> optionBeans = MutableClassToInstanceMap.create();
+    private OptionSet optionSet;
+
+    public Options(){
+        this.oakRunOptions = EnumSet.allOf(OptionBeans.class);
+    }
+
+    public Options(OptionBeans... options) {
+        this.oakRunOptions = Sets.newEnumSet(asList(options), OptionBeans.class);
+    }
+
+    public OptionSet parseAndConfigure(OptionParser parser, String[] args){
+        for (OptionsBeanFactory o : Iterables.concat(oakRunOptions, beanFactories)){
+            OptionsBean bean = o.newInstance(parser);
+            optionBeans.put(bean.getClass(), bean);
+        }
+        optionSet = parser.parse(args);
+        configure(optionSet);
+        return optionSet;
+    }
+
+    public OptionSet getOptionSet() {
+        return optionSet;
+    }
+
+    public <T extends OptionsBean> T getOptionBean(Class<T> clazz){
+        Object o = optionBeans.get(clazz);
+        checkNotNull(o, "No [%s] found in [%s]",
+                clazz.getSimpleName(), optionBeans);
+        return (T) o;
+    }
+
+    public void registerOptionsFactory(OptionsBeanFactory factory){
+        beanFactories.add(factory);
+    }
+
+    public CommonOptions getCommonOpts(){
+        return getOptionBean(CommonOptions.class);
+    }
+
+    private void configure(OptionSet optionSet){
+        for (OptionsBean bean : optionBeans.values()){
+            bean.configure(optionSet);
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/Options.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBean.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBean.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBean.java Mon May 15 08:35:04 2017
@@ -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.run.cli;
+
+import joptsimple.OptionSet;
+
+public interface OptionsBean {
+
+    void configure(OptionSet options);
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBeanFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBeanFactory.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBeanFactory.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBeanFactory.java Mon May 15 08:35:04 2017
@@ -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.run.cli;
+
+import joptsimple.OptionParser;
+
+public interface OptionsBeanFactory {
+
+    OptionsBean newInstance(OptionParser parser);
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/OptionsBeanFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/RDBStoreOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/RDBStoreOptions.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/RDBStoreOptions.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/RDBStoreOptions.java Mon May 15 08:35:04 2017
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+
+public class RDBStoreOptions implements OptionsBean {
+    private final OptionSpec<String> rdbjdbcuser;
+    private final OptionSpec<String> rdbjdbcpasswd;
+    private OptionSet options;
+
+    public RDBStoreOptions(OptionParser parser){
+        rdbjdbcuser = parser.accepts("rdbjdbcuser", "RDB JDBC user").withOptionalArg().defaultsTo("");
+        rdbjdbcpasswd = parser.accepts("rdbjdbcpasswd", "RDB JDBC password").withOptionalArg().defaultsTo("");
+    }
+
+    @Override
+    public void configure(OptionSet options) {
+        this.options = options;
+    }
+
+    public String getUser(){
+        return rdbjdbcuser.value(options);
+    }
+
+    public String getPassword(){
+        return rdbjdbcpasswd.value(options);
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/cli/RDBStoreOptions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/cli/OptionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/cli/OptionsTest.java?rev=1795145&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/cli/OptionsTest.java (added)
+++ jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/cli/OptionsTest.java Mon May 15 08:35:04 2017
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.run.cli;
+
+import joptsimple.OptionParser;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class OptionsTest {
+
+    @Test
+    public void noArgs() throws Exception{
+        OptionParser parser = new OptionParser();
+        Options opts = new Options();
+        opts.parseAndConfigure(parser, new String[]{});
+        assertNotNull(opts.getCommonOpts());
+    }
+
+    @Test
+    public void help() throws Exception{
+        OptionParser parser = new OptionParser();
+        Options opts = new Options();
+        opts.parseAndConfigure(parser, new String[]{"-h"});
+        assertTrue(opts.getCommonOpts().isHelpRequested());
+
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/run/cli/OptionsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native