Modified: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java?rev=1727599&r1=1727598&r2=1727599&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
 Fri Jan 29 15:17:44 2016
@@ -16,1382 +16,83 @@
  */
 package org.apache.jackrabbit.oak.run;
 
-import static com.google.common.collect.Sets.newHashSet;
-import static java.util.Arrays.asList;
-import static org.apache.commons.io.FileUtils.byteCountToDisplaySize;
-import static 
org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.isValidFileStoreOrFail;
-import static 
org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openFileStore;
-import static 
org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openReadOnlyFileStore;
-import static 
org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.newBasicReadOnlyBlobStore;
-import static org.apache.jackrabbit.oak.plugins.segment.RecordType.NODE;
-import static 
org.apache.jackrabbit.oak.plugins.segment.SegmentGraph.writeGCGraph;
-import static 
org.apache.jackrabbit.oak.plugins.segment.SegmentGraph.writeSegmentGraph;
-import static 
org.apache.jackrabbit.oak.plugins.segment.file.tooling.ConsistencyChecker.checkConsistency;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.io.BufferedWriter;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileOutputStream;
+import static java.util.Arrays.copyOfRange;
+import static org.apache.jackrabbit.oak.commons.IOUtils.closeQuietly;
+
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.RandomAccessFile;
-import java.sql.Timestamp;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Properties;
-import java.util.Queue;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.jcr.Repository;
-
-import com.google.common.base.Charsets;
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import com.google.common.base.Joiner;
-import com.google.common.base.StandardSystemProperty;
-import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Queues;
-import com.google.common.io.Closer;
-import com.google.common.io.Files;
-import com.google.common.util.concurrent.AbstractScheduledService;
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientURI;
-import com.mongodb.MongoURI;
-import joptsimple.ArgumentAcceptingOptionSpec;
-import joptsimple.OptionParser;
-import joptsimple.OptionSet;
-import joptsimple.OptionSpec;
-import org.apache.commons.io.FileUtils;
-import org.apache.jackrabbit.oak.Oak;
-import org.apache.jackrabbit.oak.api.ContentRepository;
-import org.apache.jackrabbit.oak.benchmark.BenchmarkRunner;
-import org.apache.jackrabbit.oak.checkpoint.Checkpoints;
-import org.apache.jackrabbit.oak.checkpoint.Checkpoints.CP;
-import org.apache.jackrabbit.oak.commons.IOUtils;
-import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
-import org.apache.jackrabbit.oak.console.Console;
-import org.apache.jackrabbit.oak.explorer.Explorer;
-import org.apache.jackrabbit.oak.explorer.NodeStoreTree;
-import org.apache.jackrabbit.oak.fixture.OakFixture;
-import org.apache.jackrabbit.oak.http.OakServlet;
-import org.apache.jackrabbit.oak.jcr.Jcr;
-import org.apache.jackrabbit.oak.json.JsopDiff;
-import org.apache.jackrabbit.oak.plugins.backup.FileStoreBackup;
-import org.apache.jackrabbit.oak.plugins.backup.FileStoreRestore;
-import org.apache.jackrabbit.oak.plugins.blob.BlobReferenceRetriever;
-import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
-import 
org.apache.jackrabbit.oak.plugins.document.DocumentBlobReferenceRetriever;
-import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
-import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
-import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreHelper;
-import org.apache.jackrabbit.oak.plugins.document.LastRevRecoveryAgent;
-import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
-import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore;
-import 
org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStoreHelper;
-import 
org.apache.jackrabbit.oak.plugins.document.mongo.MongoMissingLastRevSeeker;
-import org.apache.jackrabbit.oak.plugins.document.util.CloseableIterable;
-import org.apache.jackrabbit.oak.plugins.document.util.MapDBMapFactory;
-import org.apache.jackrabbit.oak.plugins.document.util.MapFactory;
-import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection;
-import org.apache.jackrabbit.oak.plugins.segment.FileStoreDiff;
-import org.apache.jackrabbit.oak.plugins.segment.PCMAnalyser;
-import org.apache.jackrabbit.oak.plugins.segment.RecordId;
-import org.apache.jackrabbit.oak.plugins.segment.RecordUsageAnalyser;
-import org.apache.jackrabbit.oak.plugins.segment.Segment;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentBlobReferenceRetriever;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentId;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
-import org.apache.jackrabbit.oak.plugins.segment.SegmentTracker;
-import org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy;
-import 
org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy.CleanupType;
-import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
-import org.apache.jackrabbit.oak.plugins.segment.file.FileStore.ReadOnlyStore;
-import 
org.apache.jackrabbit.oak.plugins.segment.file.FileStoreRevisionRecovery;
-import org.apache.jackrabbit.oak.plugins.segment.file.JournalReader;
-import org.apache.jackrabbit.oak.plugins.segment.file.tooling.RevisionHistory;
-import 
org.apache.jackrabbit.oak.plugins.segment.file.tooling.RevisionHistory.HistoryElement;
-import org.apache.jackrabbit.oak.plugins.segment.standby.client.StandbyClient;
-import org.apache.jackrabbit.oak.plugins.segment.standby.server.StandbyServer;
-import org.apache.jackrabbit.oak.plugins.tika.TextExtractorMain;
-import org.apache.jackrabbit.oak.remote.content.ContentRemoteRepository;
-import org.apache.jackrabbit.oak.remote.http.RemoteServlet;
-import org.apache.jackrabbit.oak.scalability.ScalabilityRunner;
-import org.apache.jackrabbit.oak.spi.blob.BlobStore;
-import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStore;
-import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet;
-import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet;
-import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
-import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
 
 public final class Main {
 
-    public static final int PORT = 8080;
-    public static final String URI = "http://localhost:"; + PORT + "/";
-
-    private static final int MB = 1024 * 1024;
-
     private Main() {
+        // Prevent instantiation.
     }
 
     public static void main(String[] args) throws Exception {
         printProductInfo(args);
 
         Mode mode = Mode.SERVER;
-        if (args.length > 0) {
-            try {
-                mode = Mode.valueOf(args[0].toUpperCase(Locale.ENGLISH));
-            } catch (IllegalArgumentException e) {
-                System.err.println("Unknown run mode: " + args[0]);
-                mode = Mode.HELP;
-            }
-            String[] tail = new String[args.length - 1];
-            System.arraycopy(args, 1, tail, 0, tail.length);
-            args = tail;
-        }
-        switch (mode) {
-            case BACKUP:
-                backup(args);
-                break;
-            case RESTORE:
-                restore(args);
-                break;
-            case BENCHMARK:
-                BenchmarkRunner.main(args);
-                break;
-            case CONSOLE:
-                Console.main(args);
-                break;
-            case DEBUG:
-                debug(args);
-                break;
-            case GRAPH:
-                graph(args);
-                break;
-            case HISTORY:
-                history(args);
-                break;
-            case CHECK:
-                check(args);
-                break;
-            case COMPACT:
-                compact(args);
-                break;
-            case SERVER:
-                server(URI, args);
-                break;
-            case UPGRADE:
-                System.out.println("This command was moved to the oak-upgrade 
module");
-                break;
-            case SCALABILITY:
-                ScalabilityRunner.main(args);
-                break;
-            case EXPLORE:
-                Explorer.main(args);
-                break;
-            case STANDBY:
-                standbyInstance(args);
-                break;
-            case PRIMARY:
-                primaryInstance(args);
-                break;
-            case CHECKPOINTS:
-                checkpoints(args);
-                break;
-            case RECOVERY:
-                recovery(args);
-                break;
-            case REPAIR:
-                repair(args);
-                break;
-            case TIKA:
-                TextExtractorMain.main(args);
-                break;
-            case GARBAGE:
-                garbage(args);
-                break;
-            case TARMKDIFF:
-                FileStoreDiff.main(args);
-                break;
-            case TARMKRECOVERY:
-                FileStoreRevisionRecovery.main(args);
-                break;
-            case DUMPDATASTOREREFS:
-                dumpBlobRefs(args);
-                break;
-            case HELP:
-            default:
-                System.err.print("Available run modes: ");
-                System.err.println(Joiner.on(',').join(Mode.values()));
-                System.exit(1);
-
-        }
-    }
-
-    public static String getProductInfo(){
-        String version = null;
-
-        try {
-            InputStream stream = Main.class
-                    
.getResourceAsStream("/META-INF/maven/org.apache.jackrabbit/oak-run/pom.properties");
-            if (stream != null) {
-                try {
-                    Properties properties = new Properties();
-                    properties.load(stream);
-                    version = properties.getProperty("version");
-                } finally {
-                    stream.close();
-                }
-            }
-        } catch (Exception ignore) {
-        }
-
-        String product;
-        if (version != null) {
-            product = "Apache Jackrabbit Oak " + version;
-        } else {
-            product = "Apache Jackrabbit Oak";
-        }
-
-        return product;
-    }
-
-    private static void printProductInfo(String[] args) {
-        if(!Arrays.asList(args).contains("--quiet")) {
-            System.out.println(getProductInfo());
-        }
-    }
-
-    private static void backup(String[] args) throws IOException {
-        boolean fakeBlobStore = FileStoreBackup.USE_FAKE_BLOBSTORE;
-        Closer closer = Closer.create();
-        try {
-            FileStore fs;
-            if (fakeBlobStore) {
-                fs = openReadOnlyFileStore(new File(args[0]),
-                        newBasicReadOnlyBlobStore());
-            } else {
-                fs = openReadOnlyFileStore(new File(args[0]));
-            }
-            closer.register(asCloseable(fs));
-            NodeStore store = 
SegmentNodeStore.newSegmentNodeStore(fs).create();
-            FileStoreBackup.backup(store, new File(args[1]));
-        } catch (Throwable e) {
-            throw closer.rethrow(e);
-        } finally {
-            closer.close();
-        }
-    }
-
-    private static void restore(String[] args) throws IOException {
-        FileStoreRestore.restore(new File(args[1]), new File(args[0]));
-    }
-
-    //TODO react to state changes of FailoverClient (triggered via JMX), once 
the state model of FailoverClient is complete.
-    private static class ScheduledSyncService extends AbstractScheduledService 
{
-
-        private final StandbyClient failoverClient;
-        private final int interval;
-
-        public ScheduledSyncService(StandbyClient failoverClient, int 
interval) {
-            this.failoverClient = failoverClient;
-            this.interval = interval;
-        }
-
-        @Override
-        public void runOneIteration() throws Exception {
-            failoverClient.run();
-        }
-
-        @Override
-        protected Scheduler scheduler() {
-            return Scheduler.newFixedDelaySchedule(0, interval, 
TimeUnit.SECONDS);
-        }
-    }
-
-
-    private static void standbyInstance(String[] args) throws Exception {
-
-        final String defaultHost = "127.0.0.1";
-        final int defaultPort = 8023;
-
-        final OptionParser parser = new OptionParser();
-        final OptionSpec<String> host = parser.accepts("host", "master 
host").withRequiredArg().ofType(String.class).defaultsTo(defaultHost);
-        final OptionSpec<Integer> port = parser.accepts("port", "master 
port").withRequiredArg().ofType(Integer.class).defaultsTo(defaultPort);
-        final OptionSpec<Integer> interval = parser.accepts("interval", 
"interval between successive 
executions").withRequiredArg().ofType(Integer.class);
-        final OptionSpec<Boolean> secure = parser.accepts("secure", "use 
secure connections").withRequiredArg().ofType(Boolean.class);
-        final OptionSpec<?> help = parser.acceptsAll(asList("h", "?", "help"), 
"show help").forHelp();
-        final OptionSpec<String> nonOption = parser.nonOptions(Mode.STANDBY + 
" <path to repository>");
-
-        final OptionSet options = parser.parse(args);
-        final List<String> nonOptions = nonOption.values(options);
-
-        if (options.has(help)) {
-            parser.printHelpOn(System.out);
-            System.exit(0);
-        }
-
-        if (nonOptions.isEmpty()) {
-            parser.printHelpOn(System.err);
-            System.exit(1);
-        }
-
-        FileStore store = null;
-        StandbyClient failoverClient = null;
-        try {
-            store = openFileStore(nonOptions.get(0));
-            failoverClient = new StandbyClient(
-                    options.has(host)? options.valueOf(host) : defaultHost,
-                    options.has(port)? options.valueOf(port) : defaultPort,
-                    store,
-                    options.has(secure) && options.valueOf(secure), 10000);
-            if (!options.has(interval)) {
-                failoverClient.run();
-            } else {
-                ScheduledSyncService syncService = new 
ScheduledSyncService(failoverClient, options.valueOf(interval));
-                syncService.startAsync();
-                syncService.awaitTerminated();
-            }
-        } finally {
-            if (store != null) {
-                store.close();
-            }
-            if (failoverClient != null) {
-                failoverClient.close();
-            }
-        }
-    }
-
-    private static void primaryInstance(String[] args) throws Exception {
-
-        final int defaultPort = 8023;
-
-        final OptionParser parser = new OptionParser();
-        final OptionSpec<Integer> port = parser.accepts("port", "port to 
listen").withRequiredArg().ofType(Integer.class).defaultsTo(defaultPort);
-        final OptionSpec<Boolean> secure = parser.accepts("secure", "use 
secure connections").withRequiredArg().ofType(Boolean.class);
-        final OptionSpec<String> admissible = parser.accepts("admissible", 
"list of admissible slave host names or ip 
ranges").withRequiredArg().ofType(String.class);
-        final OptionSpec<?> help = parser.acceptsAll(asList("h", "?", "help"), 
"show help").forHelp();
-        final OptionSpec<String> nonOption = parser.nonOptions(Mode.PRIMARY + 
" <path to repository>");
-
-        final OptionSet options = parser.parse(args);
-        final List<String> nonOptions = nonOption.values(options);
-
-        if (options.has(help)) {
-            parser.printHelpOn(System.out);
-            System.exit(0);
-        }
-
-        if (nonOptions.isEmpty()) {
-            parser.printHelpOn(System.err);
-            System.exit(1);
-        }
 
-        List<String> admissibleSlaves = options.has(admissible) ? 
options.valuesOf(admissible) : Collections.EMPTY_LIST;
+        if (args.length > 0) {
+            mode = getMode(args[0]);
 
-        FileStore store = null;
-        StandbyServer failoverServer = null;
-        try {
-            store = openFileStore(nonOptions.get(0));
-            failoverServer = new StandbyServer(
-                    options.has(port)? options.valueOf(port) : defaultPort,
-                    store,
-                    admissibleSlaves.toArray(new 
String[admissibleSlaves.size()]),
-                    options.has(secure) && options.valueOf(secure));
-            failoverServer.startAndWait();
-        } finally {
-            if (store != null) {
-                store.close();
-            }
-            if (failoverServer != null) {
-                failoverServer.close();
+            if (mode == null) {
+                mode = Mode.HELP;
             }
-        }
-    }
 
-    public static NodeStore bootstrapNodeStore(String[] args, Closer closer, 
String h) throws IOException {
-        //TODO add support for other NodeStore flags
-        OptionParser parser = new OptionParser();
-        OptionSpec<Integer> clusterId = parser
-                .accepts("clusterId", "MongoMK clusterId").withRequiredArg()
-                .ofType(Integer.class).defaultsTo(0);
-        OptionSpec<?> help = parser.acceptsAll(asList("h", "?", "help"),
-                "show help").forHelp();
-        OptionSpec<String> nonOption = parser
-                .nonOptions(h);
-
-        OptionSet options = parser.parse(args);
-        List<String> nonOptions = nonOption.values(options);
-
-        if (options.has(help)) {
-            parser.printHelpOn(System.out);
-            System.exit(0);
+            args = copyOfRange(args, 1, args.length);
         }
 
-        if (nonOptions.isEmpty()) {
-            parser.printHelpOn(System.err);
-            System.exit(1);
-        }
-
-        String src = nonOptions.get(0);
-        if (src.startsWith(MongoURI.MONGODB_PREFIX)) {
-            MongoClientURI uri = new MongoClientURI(src);
-            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));
-            DocumentNodeStore store = new DocumentMK.Builder()
-                    .setMongoDB(mongo.getDB())
-                    .setLeaseCheck(false)
-                    .setClusterId(clusterId.value(options)).getNodeStore();
-            closer.register(asCloseable(store));
-            return store;
-        }
-
-        FileStore fs = openFileStore(src);
-        closer.register(asCloseable(fs));
-        return SegmentNodeStore.newSegmentNodeStore(fs).create();
-    }
-
-    private static Closeable asCloseable(final FileStore fs) {
-        return new Closeable() {
-
-            @Override
-            public void close() throws IOException {
-                fs.close();
-            }
-        };
+        mode.execute(args);
     }
 
-    private static Closeable asCloseable(final DocumentNodeStore dns) {
-        return new Closeable() {
-
-            @Override
-            public void close() throws IOException {
-                dns.dispose();
-            }
-        };
-    }
-
-    private static Closeable asCloseable(final MongoConnection con) {
-        return new Closeable() {
-
-            @Override
-            public void close() throws IOException {
-                con.close();
-            }
-        };
-    }
-
-    private static void compact(String[] args) throws IOException {
-        OptionParser parser = new OptionParser();
-        OptionSpec<String> directoryArg = parser.nonOptions(
-            "Path to segment store (required)").ofType(String.class);
-        OptionSpec<Void> forceFlag = parser.accepts(
-            "force", "Force compaction and ignore non matching segment 
version");
-        OptionSet options = parser.parse(args);
-
-        String path = directoryArg.value(options);
-        if (path == null) {
-            System.err.println("Compact a file store. Usage: compact [path] 
<options>");
-            parser.printHelpOn(System.err);
-            System.exit(-1);
-        }
-        Stopwatch watch = Stopwatch.createStarted();
-        FileStore store = openFileStore(path, options.has(forceFlag));
-        File directory = new File(path);
-        try {
-            boolean persistCM = Boolean.getBoolean("tar.PersistCompactionMap");
-            System.out.println("Compacting " + directory);
-            System.out.println("    before " + 
Arrays.toString(directory.list()));
-            long sizeBefore = FileUtils.sizeOfDirectory(directory);
-            System.out.println("    size "
-                    + IOUtils.humanReadableByteCount(sizeBefore) + " (" + 
sizeBefore
-                    + " bytes)");
-
-            System.out.println("    -> compacting");
-
-            CompactionStrategy compactionStrategy = new CompactionStrategy(
-                    false, CompactionStrategy.CLONE_BINARIES_DEFAULT,
-                    CleanupType.CLEAN_ALL, 0,
-                    CompactionStrategy.MEMORY_THRESHOLD_DEFAULT) {
-                @Override
-                public boolean compacted(Callable<Boolean> setHead)
-                        throws Exception {
-                    // oak-run is doing compaction single-threaded
-                    // hence no guarding needed - go straight ahead
-                    // and call setHead
-                    return setHead.call();
-                }
-            };
-            compactionStrategy.setOfflineCompaction(true);
-            compactionStrategy.setPersistCompactionMap(persistCM);
-            store.setCompactionStrategy(compactionStrategy);
-            store.compact();
-        } finally {
-            store.close();
-        }
-
-        System.out.println("    -> cleaning up");
-        store = openFileStore(path, false);
-        try {
-            for (File file : store.cleanup()) {
-                if (!file.exists() || file.delete()) {
-                    System.out.println("    -> removed old file " + 
file.getName());
-                } else {
-                    System.out.println("    -> failed to remove old file " + 
file.getName());
-                }
-            }
-
-            String head;
-            File journal = new File(directory, "journal.log");
-            JournalReader journalReader = new JournalReader(journal);
-            try {
-                head = journalReader.iterator().next() + " root\n";
-            } finally {
-                journalReader.close();
-            }
-
-            RandomAccessFile journalFile = new RandomAccessFile(journal, "rw");
-            try {
-                System.out.println("    -> writing new " + journal.getName() + 
": " + head);
-                journalFile.setLength(0);
-                journalFile.writeBytes(head);
-                journalFile.getChannel().force(false);
-            } finally {
-                journalFile.close();
-            }
-        } finally {
-            store.close();
-        }
-        watch.stop();
-        System.out.println("    after  "
-                + Arrays.toString(directory.list()));
-        long sizeAfter = FileUtils.sizeOfDirectory(directory);
-        System.out.println("    size "
-                + IOUtils.humanReadableByteCount(sizeAfter) + " (" + sizeAfter
-                + " bytes)");
-        System.out.println("    duration  " + watch.toString() + " ("
-                + watch.elapsed(TimeUnit.SECONDS) + "s).");
-    }
+    public static String getProductInfo(){
+        String version = getProductVersion();
 
-    private static void checkpoints(String[] args) throws IOException {
-        if (args.length == 0) {
-            System.out
-                    .println("usage: checkpoints {<path>|<mongo-uri>} 
[list|rm-all|rm-unreferenced|rm <checkpoint>]");
-            System.exit(1);
+        if (version == null) {
+            return "Apache Jackrabbit Oak";
         }
-        boolean success = false;
-        Checkpoints cps;
-        Closer closer = Closer.create();
-        try {
-            String op = "list";
-            if (args.length >= 2) {
-                op = args[1];
-                if (!"list".equals(op) && !"rm-all".equals(op) && 
!"rm-unreferenced".equals(op) && !"rm".equals(op)) {
-                    failWith("Unknown command.");
-                }
-            }
-
-            if (args[0].startsWith(MongoURI.MONGODB_PREFIX)) {
-                MongoClientURI uri = new MongoClientURI(args[0]);
-                MongoClient client = new MongoClient(uri);
-                final DocumentNodeStore store = new DocumentMK.Builder()
-                        .setMongoDB(client.getDB(uri.getDatabase()))
-                        .getNodeStore();
-                closer.register(asCloseable(store));
-                cps = Checkpoints.onDocumentMK(store);
-            } else {
-                FileStore store = openFileStore(args[0]);
-                closer.register(asCloseable(store));
-                cps = Checkpoints.onTarMK(store);
-            }
 
-            System.out.println("Checkpoints " + args[0]);
-            if ("list".equals(op)) {
-                int cnt = 0;
-                for (CP cp : cps.list()) {
-                    System.out.printf("- %s created %s expires %s%n",
-                            cp.id,
-                            new Timestamp(cp.created),
-                            new Timestamp(cp.expires));
-                    cnt++;
-                }
-                System.out.println("Found " + cnt + " checkpoints");
-            } else if ("rm-all".equals(op)) {
-                long time = System.currentTimeMillis();
-                long cnt = cps.removeAll();
-                time = System.currentTimeMillis() - time;
-                if (cnt != -1) {
-                    System.out.println("Removed " + cnt + " checkpoints in " + 
time + "ms.");
-                } else {
-                    failWith("Failed to remove all checkpoints.");
-                }
-            } else if ("rm-unreferenced".equals(op)) {
-                long time = System.currentTimeMillis();
-                long cnt = cps.removeUnreferenced();
-                time = System.currentTimeMillis() - time;
-                if (cnt != -1) {
-                    System.out.println("Removed " + cnt + " checkpoints in " + 
time + "ms.");
-                } else {
-                    failWith("Failed to remove unreferenced checkpoints.");
-                }
-            } else if ("rm".equals(op)) {
-                if (args.length != 3) {
-                    failWith("Missing checkpoint id");
-                } else {
-                    String cp = args[2];
-                    long time = System.currentTimeMillis();
-                    int cnt = cps.remove(cp);
-                    time = System.currentTimeMillis() - time;
-                    if (cnt != 0) {
-                        if (cnt == 1) {
-                            System.out.println("Removed checkpoint " + cp + " 
in "
-                                    + time + "ms.");
-                        } else {
-                            failWith("Failed to remove checkpoint " + cp);
-                        }
-                    } else {
-                        failWith("Checkpoint '" + cp + "' not found.");
-                    }
-                }
-            }
-            success = true;
-        } catch (Throwable t) {
-            System.err.println(t.getMessage());
-        } finally {
-            closer.close();
-        }
-        if (!success) {
-            System.exit(1);
-        }
+        return "Apache Jackrabbit Oak " + version;
     }
 
-    private static void failWith(String message) {
-        throw new RuntimeException(message);
-    }
+    private static String getProductVersion() {
+        InputStream stream = 
Main.class.getResourceAsStream("/META-INF/maven/org.apache.jackrabbit/oak-run/pom.properties");
 
-    private static void recovery(String[] args) throws IOException {
-        MapFactory.setInstance(new MapDBMapFactory());
-        Closer closer = Closer.create();
-        String h = "recovery mongodb://host:port/database { dryRun }";
         try {
-            NodeStore store = bootstrapNodeStore(args, closer, h);
-            if (!(store instanceof DocumentNodeStore)) {
-                System.err.println("Recovery only available for 
DocumentNodeStore");
-                System.exit(1);
-            }
-            DocumentNodeStore dns = (DocumentNodeStore) store;
-            if (!(dns.getDocumentStore() instanceof MongoDocumentStore)) {
-                System.err.println("Recovery only available for 
MongoDocumentStore");
-                System.exit(1);
-            }
-            MongoDocumentStore docStore = (MongoDocumentStore) 
dns.getDocumentStore();
-            LastRevRecoveryAgent agent = new LastRevRecoveryAgent(dns);
-            MongoMissingLastRevSeeker seeker = new 
MongoMissingLastRevSeeker(docStore);
-            CloseableIterable<NodeDocument> docs = seeker.getCandidates(0);
-            closer.register(docs);
-            boolean dryRun = Arrays.asList(args).contains("dryRun");
-            agent.recover(docs.iterator(), dns.getClusterId(), dryRun);
-        } catch (Throwable e) {
-            throw closer.rethrow(e);
+            return getProductVersion(stream);
         } finally {
-            closer.close();
+            closeQuietly(stream);
         }
     }
 
-    private static void repair(String[] args) throws IOException {
-        Closer closer = Closer.create();
-        String h = "repair mongodb://host:port/database path";
-        try {
-            NodeStore store = bootstrapNodeStore(args, closer, h);
-            if (!(store instanceof DocumentNodeStore)) {
-                System.err.println("Repair only available for 
DocumentNodeStore");
-                System.exit(1);
-            }
-            DocumentNodeStore dns = (DocumentNodeStore) store;
-            if (!(dns.getDocumentStore() instanceof MongoDocumentStore)) {
-                System.err.println("Repair only available for 
MongoDocumentStore");
-                System.exit(1);
-            }
-            MongoDocumentStore docStore = (MongoDocumentStore) 
dns.getDocumentStore();
-
-            String path = args[args.length - 1];
-            MongoDocumentStoreHelper.repair(docStore, path);
-        } catch (Throwable e) {
-            throw closer.rethrow(e);
-        } finally {
-            closer.close();
-        }
-    }
+    private static String getProductVersion(InputStream stream) {
+        Properties properties = new Properties();
 
-    private static void garbage(String[] args) throws IOException {
-        Closer closer = Closer.create();
-        String h = "garbage mongodb://host:port/database";
         try {
-            NodeStore store = bootstrapNodeStore(args, closer, h);
-            if (!(store instanceof DocumentNodeStore)) {
-                System.err.println("Garbage mode only available for 
DocumentNodeStore");
-                System.exit(1);
-            }
-            DocumentNodeStore dns = (DocumentNodeStore) store;
-
-            DocumentNodeStoreHelper.garbageReport(dns);
-        } catch (Throwable e) {
-            throw closer.rethrow(e);
-        } finally {
-            closer.close();
+            properties.load(stream);
+        } catch (IOException e) {
+            return null;
         }
-    }
-
-    private static void debug(String[] args) throws IOException {
-        if (args.length == 0) {
-            System.err.println("usage: debug <path> [id...]");
-            System.exit(1);
-        } else {
-            // TODO: enable debug information for other node store 
implementations
-            File file = new File(args[0]);
-            System.out.println("Debug " + file);
-            FileStore store = openReadOnlyFileStore(file);
-            try {
-                if (args.length == 1) {
-                    debugFileStore(store);
-                } else {
-                    if (args[1].endsWith(".tar")) {
-                        debugTarFile(store, args);
-                    } else {
-                        debugSegment(store, args);
-                    }
-                }
-            } finally {
-                store.close();
-            }
-        }
-    }
-
-    private static void graph(String[] args) throws Exception {
-        OptionParser parser = new OptionParser();
-        OptionSpec<File> directoryArg = parser.nonOptions(
-                "Path to segment store (required)").ofType(File.class);
-        OptionSpec<File> outFileArg = parser.accepts(
-                "output", "Output file").withRequiredArg().ofType(File.class)
-                .defaultsTo(new File("segments.gdf"));
-        OptionSpec<Long> epochArg = parser.accepts(
-                "epoch", "Epoch of the segment time stamps (derived from 
journal.log if not given)")
-                .withRequiredArg().ofType(Long.class);
-        OptionSpec<Void> gcGraphArg = parser.accepts(
-                "gc", "Write the gc generation graph instead of the full 
graph");
-        OptionSpec<String> regExpArg = parser.accepts(
-                "pattern", "Regular exception specifying which nodes to 
include (optional). " +
-                "Ignore when --gc is specified.")
-                .withRequiredArg().ofType(String.class);
-
-        OptionSet options = parser.parse(args);
-
-        File directory = directoryArg.value(options);
-        if (directory == null) {
-            System.err.println("Dump the segment graph to a file. Usage: graph 
[File] <options>");
-            parser.printHelpOn(System.err);
-            System.exit(-1);
-        }
-        System.out.println("Opening file store at " + directory);
-        ReadOnlyStore fileStore = openReadOnlyFileStore(directory);
-
-        String regExp = regExpArg.value(options);
-
-        File outFile = outFileArg.value(options);
-        Date epoch;
-        if (options.has(epochArg)) {
-            epoch = new Date(epochArg.value(options));
-        } else {
-            Calendar c = Calendar.getInstance();
-            c.setTimeInMillis(new File(directory, 
"journal.log").lastModified());
-            c.set(Calendar.HOUR_OF_DAY, 0);
-            c.set(Calendar.MINUTE, 0);
-            c.set(Calendar.SECOND, 0);
-            c.set(Calendar.MILLISECOND, 0);
-            epoch = c.getTime();
-        }
-
-        if (outFile.exists()) {
-            outFile.delete();
-        }
-
-        System.out.println("Setting epoch to " + epoch);
-        System.out.println("Writing graph to " + outFile.getAbsolutePath());
-
-        FileOutputStream out = new FileOutputStream(outFile);
-        if (options.has(gcGraphArg)) {
-            writeGCGraph(fileStore, out);
-        } else {
-            writeSegmentGraph(fileStore, out, epoch, regExp);
-        }
-    }
-
-    private static void check(String[] args) throws IOException {
-        OptionParser parser = new OptionParser();
-        ArgumentAcceptingOptionSpec<String> path = parser.accepts(
-                "path", "path to the segment store (required)")
-                .withRequiredArg().ofType(String.class);
-        ArgumentAcceptingOptionSpec<String> journal = parser.accepts(
-                "journal", "journal file")
-                
.withRequiredArg().ofType(String.class).defaultsTo("journal.log");
-        ArgumentAcceptingOptionSpec<Long> deep = parser.accepts(
-                "deep", "enable deep consistency checking. An optional long " +
-                        "specifies the number of seconds between progress 
notifications")
-                
.withOptionalArg().ofType(Long.class).defaultsTo(Long.MAX_VALUE);
-        ArgumentAcceptingOptionSpec<Long> bin = parser.accepts(
-                "bin", "read the n first bytes from binary properties. -1 for 
all bytes.")
-                .withOptionalArg().ofType(Long.class).defaultsTo(0L);
-
-        OptionSet options = parser.parse(args);
-
-        if (!options.has(path)) {
-            System.err.println("usage: check <options>");
-            parser.printHelpOn(System.err);
-            System.exit(1);
-        }
-
-        File dir = isValidFileStoreOrFail(new File(path.value(options)));
-        String journalFileName = journal.value(options);
-        boolean fullTraversal = options.has(deep);
-        long debugLevel = deep.value(options);
-        long binLen = bin.value(options);
-        checkConsistency(dir, journalFileName, fullTraversal, debugLevel, 
binLen);
-    }
-
-    private static void history(String[] args) throws IOException {
-        OptionParser parser = new OptionParser();
-        OptionSpec<File> directoryArg = parser.nonOptions(
-            "Path to segment store (required)").ofType(File.class);
-        OptionSpec<String> journalArg = parser.accepts(
-            "journal", "journal file").withRequiredArg().ofType(String.class)
-            .defaultsTo("journal.log");
-        OptionSpec<String> pathArg = parser.accepts(
-            "path", "Path for which to trace the 
history").withRequiredArg().ofType(String.class)
-            .defaultsTo("/");
-        OptionSpec<Integer> depthArg = parser.accepts(
-            "depth", "Depth up to which to dump node 
states").withRequiredArg().ofType(Integer.class)
-            .defaultsTo(0);
-        OptionSet options = parser.parse(args);
-
-        File directory = directoryArg.value(options);
-        if (directory == null) {
-            System.err.println("Trace the history of a path. Usage: history 
[File] <options>");
-            parser.printHelpOn(System.err);
-            System.exit(-1);
-        }
-
-        String path = pathArg.value(options);
-        int depth = depthArg.value(options);
-        String journalName = journalArg.value(options);
-        File journal = new File(isValidFileStoreOrFail(directory), 
journalName);
-
-        Iterable<HistoryElement> history = new 
RevisionHistory(directory).getHistory(journal, path);
-        for (HistoryElement historyElement : history) {
-            System.out.println(historyElement.toString(depth));
-        }
-    }
-
-    private static void debugTarFile(FileStore store, String[] args) {
-        File root = new File(args[0]);
-        for (int i = 1; i < args.length; i++) {
-            String f = args[i];
-            if (!f.endsWith(".tar")) {
-                System.out.println("skipping " + f);
-                continue;
-            }
-            File tar = new File(root, f);
-            if (!tar.exists()) {
-                System.out.println("file doesn't exist, skipping " + f);
-                continue;
-            }
-            System.out.println("Debug file " + tar + "(" + tar.length() + ")");
-            Set<UUID> uuids = new HashSet<UUID>();
-            boolean hasrefs = false;
-            for (Entry<String, Set<UUID>> e : store.getTarReaderIndex()
-                    .entrySet()) {
-                if (e.getKey().endsWith(f)) {
-                    hasrefs = true;
-                    uuids = e.getValue();
-                }
-            }
-            if (hasrefs) {
-                System.out.println("SegmentNodeState references to " + f);
-                List<String> paths = new ArrayList<String>();
-                NodeStoreTree.filterNodeStates(uuids, paths, store.getHead(),
-                        "/");
-                for (String p : paths) {
-                    System.out.println("  " + p);
-                }
-            } else {
-                System.out.println("No references to " + f);
-            }
-
-            try {
-                Map<UUID, List<UUID>> graph = store.getTarGraph(f);
-                System.out.println();
-                System.out.println("Tar graph:");
-                for (Entry<UUID, List<UUID>> entry : graph.entrySet()) {
-                    System.out.println("" + entry.getKey() + '=' + 
entry.getValue());
-                }
-            } catch (IOException e) {
-                System.out.println("Error getting tar graph:");
-            }
-
-        }
-    }
-
-    private static void debugSegment(FileStore store, String[] args) {
-        Pattern pattern = Pattern
-                
.compile("([0-9a-f-]+)|(([0-9a-f-]+:[0-9a-f]+)(-([0-9a-f-]+:[0-9a-f]+))?)?(/.*)?");
-        for (int i = 1; i < args.length; i++) {
-            Matcher matcher = pattern.matcher(args[i]);
-            if (!matcher.matches()) {
-                System.err.println("Unknown argument: " + args[i]);
-            } else if (matcher.group(1) != null) {
-                UUID uuid = UUID.fromString(matcher.group(1));
-                SegmentId id = store.getTracker().getSegmentId(
-                        uuid.getMostSignificantBits(),
-                        uuid.getLeastSignificantBits());
-                System.out.println(id.getSegment());
-            } else {
-                RecordId id1 = store.getHead().getRecordId();
-                RecordId id2 = null;
-                if (matcher.group(2) != null) {
-                    id1 = RecordId.fromString(store.getTracker(),
-                            matcher.group(3));
-                    if (matcher.group(4) != null) {
-                        id2 = RecordId.fromString(store.getTracker(),
-                                matcher.group(5));
-                    }
-                }
-                String path = "/";
-                if (matcher.group(6) != null) {
-                    path = matcher.group(6);
-                }
-
-                if (id2 == null) {
-                    NodeState node = new SegmentNodeState(id1);
-                    System.out.println("/ (" + id1 + ") -> " + node);
-                    for (String name : PathUtils.elements(path)) {
-                        node = node.getChildNode(name);
-                        RecordId nid = null;
-                        if (node instanceof SegmentNodeState) {
-                            nid = ((SegmentNodeState) node).getRecordId();
-                        }
-                        System.out.println("  " + name + " (" + nid + ") -> "
-                                + node);
-                    }
-                } else {
-                    NodeState node1 = new SegmentNodeState(id1);
-                    NodeState node2 = new SegmentNodeState(id2);
-                    for (String name : PathUtils.elements(path)) {
-                        node1 = node1.getChildNode(name);
-                        node2 = node2.getChildNode(name);
-                    }
-                    System.out.println(JsopBuilder.prettyPrint(JsopDiff
-                            .diffToJsop(node1, node2)));
-                }
-            }
-        }
-    }
-
-    private static void debugFileStore(FileStore store) {
-        Map<SegmentId, List<SegmentId>> idmap = Maps.newHashMap();
-        int dataCount = 0;
-        long dataSize = 0;
-        int bulkCount = 0;
-        long bulkSize = 0;
-
-        ((Logger) getLogger(SegmentTracker.class)).setLevel(Level.OFF);
-        RecordUsageAnalyser analyser = new RecordUsageAnalyser();
-
-        for (SegmentId id : store.getSegmentIds()) {
-            if (id.isDataSegmentId()) {
-                Segment segment = id.getSegment();
-                dataCount++;
-                dataSize += segment.size();
-                idmap.put(id, segment.getReferencedIds());
-                analyseSegment(segment, analyser);
-            } else if (id.isBulkSegmentId()) {
-                bulkCount++;
-                bulkSize += id.getSegment().size();
-                idmap.put(id, Collections.<SegmentId>emptyList());
-            }
-        }
-        System.out.println("Total size:");
-        System.out.format(
-                "%s in %6d data segments%n",
-                byteCountToDisplaySize(dataSize), dataCount);
-        System.out.format(
-                "%s in %6d bulk segments%n",
-                byteCountToDisplaySize(bulkSize), bulkCount);
-        System.out.println(analyser.toString());
-
-        Set<SegmentId> garbage = newHashSet(idmap.keySet());
-        Queue<SegmentId> queue = Queues.newArrayDeque();
-        queue.add(store.getHead().getRecordId().getSegmentId());
-        while (!queue.isEmpty()) {
-            SegmentId id = queue.remove();
-            if (garbage.remove(id)) {
-                queue.addAll(idmap.get(id));
-            }
-        }
-        dataCount = 0;
-        dataSize = 0;
-        bulkCount = 0;
-        bulkSize = 0;
-        for (SegmentId id : garbage) {
-            if (id.isDataSegmentId()) {
-                dataCount++;
-                dataSize += id.getSegment().size();
-            } else if (id.isBulkSegmentId()) {
-                bulkCount++;
-                bulkSize += id.getSegment().size();
-            }
-        }
-        System.out.format("%nAvailable for garbage collection:%n");
-        System.out.format("%s in %6d data segments%n",
-                byteCountToDisplaySize(dataSize), dataCount);
-        System.out.format("%s in %6d bulk segments%n",
-                byteCountToDisplaySize(bulkSize), bulkCount);
-        System.out.format("%n%s", new PCMAnalyser(store).toString());
-    }
 
-    private static void analyseSegment(Segment segment, RecordUsageAnalyser 
analyser) {
-        for (int k = 0; k < segment.getRootCount(); k++) {
-            if (segment.getRootType(k) == NODE) {
-                RecordId nodeId = new RecordId(segment.getSegmentId(), 
segment.getRootOffset(k));
-                try {
-                    analyser.analyseNode(nodeId);
-                } catch (Exception e) {
-                    System.err.format("Error while processing node at %s", 
nodeId);
-                    e.printStackTrace();
-                }
-            }
-        }
+        return properties.getProperty("version");
     }
 
-    private static void server(String defaultUri, String[] args) throws 
Exception {
-        OptionParser parser = new OptionParser();
-
-        OptionSpec<Integer> cache = parser.accepts("cache", "cache size 
(MB)").withRequiredArg().ofType(Integer.class).defaultsTo(100);
-
-        // tar/h2 specific option
-        OptionSpec<File> base = parser.accepts("base", "Base 
directory").withRequiredArg().ofType(File.class);
-        OptionSpec<Boolean> mmap = parser.accepts("mmap", "TarMK memory 
mapping").withOptionalArg().ofType(Boolean.class).defaultsTo("64".equals(System.getProperty("sun.arch.data.model")));
-
-        // mongo specific options:
-        OptionSpec<String> host = parser.accepts("host", "MongoDB 
host").withRequiredArg().defaultsTo("127.0.0.1");
-        OptionSpec<Integer> port = parser.accepts("port", "MongoDB 
port").withRequiredArg().ofType(Integer.class).defaultsTo(27017);
-        OptionSpec<String> dbName = parser.accepts("db", "MongoDB 
database").withRequiredArg();
-        OptionSpec<Integer> clusterIds = parser.accepts("clusterIds", "Cluster 
Ids").withOptionalArg().ofType(Integer.class).withValuesSeparatedBy(',');
-
-        // RDB specific options
-        OptionSpec<String> rdbjdbcuri = parser.accepts("rdbjdbcuri", "RDB JDBC 
URI").withOptionalArg().defaultsTo("");
-        OptionSpec<String> rdbjdbcuser = parser.accepts("rdbjdbcuser", "RDB 
JDBC user").withOptionalArg().defaultsTo("");
-        OptionSpec<String> rdbjdbcpasswd = parser.accepts("rdbjdbcpasswd", 
"RDB JDBC password").withOptionalArg().defaultsTo("");
-        OptionSpec<String> rdbjdbctableprefix = 
parser.accepts("rdbjdbctableprefix", "RDB JDBC table prefix")
-                .withOptionalArg().defaultsTo("");
-
-        OptionSpec<String> nonOption = parser.nonOptions();
-        OptionSpec<?> help = parser.acceptsAll(asList("h", "?", "help"), "show 
help").forHelp();
-        OptionSet options = parser.parse(args);
-
-        if (options.has(help)) {
-            parser.printHelpOn(System.out);
-            System.exit(0);
-        }
-
-        OakFixture oakFixture;
-
-        List<String> arglist = nonOption.values(options);
-        String uri = (arglist.isEmpty()) ? defaultUri : arglist.get(0);
-        String fix = (arglist.size() <= 1) ? OakFixture.OAK_MEMORY : 
arglist.get(1);
-
-        int cacheSize = cache.value(options);
-        List<Integer> cIds = Collections.emptyList();
-        if (fix.startsWith(OakFixture.OAK_MEMORY)) {
-            if (OakFixture.OAK_MEMORY_NS.equals(fix)) {
-                oakFixture = OakFixture.getMemoryNS(cacheSize * MB);
-            } else {
-                oakFixture = OakFixture.getMemory(cacheSize * MB);
-            }
-        } else if (fix.startsWith(OakFixture.OAK_MONGO)) {
-            cIds = clusterIds.values(options);
-            String db = dbName.value(options);
-            if (db == null) {
-                throw new IllegalArgumentException("Required argument db 
missing");
-            }
-            if (OakFixture.OAK_MONGO_NS.equals(fix)) {
-                oakFixture = OakFixture.getMongoNS(
-                        host.value(options), port.value(options),
-                        db, false,
-                        cacheSize * MB);
-            } else {
-                oakFixture = OakFixture.getMongo(
-                        host.value(options), port.value(options),
-                        db, false, cacheSize * MB);
-            }
-
-        } else if (fix.equals(OakFixture.OAK_TAR)) {
-            File baseFile = base.value(options);
-            if (baseFile == null) {
-                throw new IllegalArgumentException("Required argument base 
missing.");
-            }
-            oakFixture = OakFixture.getTar(OakFixture.OAK_TAR, baseFile, 256, 
cacheSize, mmap.value(options), false);
-        } else if (fix.equals(OakFixture.OAK_RDB)) {
-            oakFixture = OakFixture.getRDB(OakFixture.OAK_RDB, 
rdbjdbcuri.value(options), rdbjdbcuser.value(options),
-                    rdbjdbcpasswd.value(options), 
rdbjdbctableprefix.value(options), false, cacheSize);
-        } else {
-            throw new IllegalArgumentException("Unsupported repository setup " 
+ fix);
+    private static void printProductInfo(String[] args) {
+        if(!Arrays.asList(args).contains("--quiet")) {
+            System.out.println(getProductInfo());
         }
-
-        startOakServer(oakFixture, uri, cIds);
     }
 
-    private static void dumpBlobRefs(String[] args) throws IOException {
-        if (args.length == 0) {
-            System.out
-                .println("usage: dumpdatastorerefs {<path>|<mongo-uri>} 
<dump_path>]");
-            System.exit(1);
-        }
-
-        Closer closer = Closer.create();
+    private static Mode getMode(String name) {
         try {
-            BlobReferenceRetriever marker = null;
-            BlobStore blobStore = null;
-
-            if (args[0].startsWith(MongoURI.MONGODB_PREFIX)) {
-                MongoClientURI uri = new MongoClientURI(args[0]);
-                MongoClient client = new MongoClient(uri);
-                final DocumentNodeStore store = new 
DocumentMK.Builder().setMongoDB(client.getDB(uri.getDatabase())).getNodeStore();
-                blobStore = store.getBlobStore();
-                closer.register(asCloseable(store));
-                marker = new DocumentBlobReferenceRetriever(store);
-            } else {
-                FileStore store = openFileStore(args[0]);
-                closer.register(asCloseable(store));
-                marker = new SegmentBlobReferenceRetriever(store.getTracker());
-            }
-
-            String dumpPath = StandardSystemProperty.JAVA_IO_TMPDIR.value();
-            if (args.length == 2) {
-                dumpPath = args[1];
-            }
-            File dumpFile = new File(dumpPath, "marked-" + 
System.currentTimeMillis());
-            final BufferedWriter writer = Files.newWriter(dumpFile, 
Charsets.UTF_8);
-            final AtomicInteger count = new AtomicInteger();
-            try {
-                final List<String> idBatch = 
Lists.newArrayListWithCapacity(1024);
-                final Joiner delimJoiner = Joiner.on(",").skipNulls();
-                final GarbageCollectableBlobStore gcBlobStore =
-                    (blobStore != null && blobStore instanceof 
GarbageCollectableBlobStore
-                        ? (GarbageCollectableBlobStore) blobStore
-                        : null);
-                marker.collectReferences(
-                    new ReferenceCollector() {
-                        @Override
-                        public void addReference(String blobId, String nodeId) 
{
-                            try {
-                                Iterator<String> idIter = null;
-                                if (gcBlobStore != null) {
-                                    idIter = gcBlobStore.resolveChunks(blobId);
-                                } else{
-                                    idIter = 
Iterators.singletonIterator(blobId);
-                                }
-
-                                while (idIter.hasNext()) {
-                                    String id = idIter.next();
-                                    idBatch.add(delimJoiner.join(id, nodeId));
-                                    count.getAndIncrement();
-                                    if (idBatch.size() >= 1024) {
-                                        
writer.append(Joiner.on(StandardSystemProperty.LINE_SEPARATOR.value()).join(idBatch));
-                                        
writer.append(StandardSystemProperty.LINE_SEPARATOR.value());
-                                        writer.flush();
-                                        idBatch.clear();
-                                    }
-                                }
-                            } catch (Exception e) {
-                                throw new RuntimeException("Error in 
retrieving references", e);
-                            }
-                        }
-                    }
-                );
-                if (!idBatch.isEmpty()) {
-                    
writer.append(Joiner.on(StandardSystemProperty.LINE_SEPARATOR.value()).join(idBatch));
-                    
writer.append(StandardSystemProperty.LINE_SEPARATOR.value());
-                    writer.flush();
-                    idBatch.clear();
-                }
-                System.out.println(count.get() + " DataStore references dumped 
in " + dumpFile);
-            } finally {
-                IOUtils.closeQuietly(writer);
-            }
-        } catch (Throwable t) {
-            System.err.println(t.getMessage());
-        } finally {
-            closer.close();
-        }
-    }
-
-    private static void startOakServer(OakFixture oakFixture, String uri, 
List<Integer> cIds) throws Exception {
-        Map<Oak, String> m;
-        if (cIds.isEmpty()) {
-            System.out.println("Starting " + oakFixture.toString() + " 
repository -> " + uri);
-            m = Collections.singletonMap(oakFixture.getOak(0), "");
-        } else {
-            System.out.println("Starting a clustered repository " + 
oakFixture.toString() + " -> " + uri);
-            m = new HashMap<Oak, String>(cIds.size());
-
-            for (int i = 0; i < cIds.size(); i++) {
-                m.put(oakFixture.getOak(i), "/node" + i);
-            }
+            return Mode.valueOf(name.toUpperCase(Locale.ENGLISH));
+        } catch (IllegalArgumentException e) {
+            return null;
         }
-        new HttpServer(uri, m);
     }
 
-    public static class HttpServer {
-
-        private final ServletContextHandler context;
-
-        private final Server server;
-
-        public HttpServer(String uri) throws Exception {
-            this(uri, Collections.singletonMap(new Oak(), ""));
-        }
-
-        public HttpServer(String uri, Map<Oak, String> oakMap) throws 
Exception {
-            int port = java.net.URI.create(uri).getPort();
-            if (port == -1) {
-                // use default
-                port = PORT;
-            }
-
-            context = new ServletContextHandler();
-            context.setContextPath("/");
-
-            for (Map.Entry<Oak, String> entry : oakMap.entrySet()) {
-                addServlets(entry.getKey(), entry.getValue());
-            }
-
-            server = new Server(port);
-            server.setHandler(context);
-            server.start();
-        }
-
-        public void join() throws Exception {
-            server.join();
-        }
-
-        public void stop() throws Exception {
-            server.stop();
-        }
-
-        private void addServlets(Oak oak, String path) {
-            Jcr jcr = new Jcr(oak);
-
-            // 1 - OakServer
-            ContentRepository repository = jcr.createContentRepository();
-            ServletHolder holder = new ServletHolder(new 
OakServlet(repository));
-            context.addServlet(holder, path + "/*");
-
-            ServletHolder remoteServlet = new ServletHolder(new 
RemoteServlet(new ContentRemoteRepository(repository)));
-            context.addServlet(remoteServlet, path + "/api/*");
-
-            // 2 - Webdav Server on JCR repository
-            final Repository jcrRepository = jcr.createRepository();
-            @SuppressWarnings("serial")
-            ServletHolder webdav = new ServletHolder(new SimpleWebdavServlet() 
{
-                @Override
-                public Repository getRepository() {
-                    return jcrRepository;
-                }
-            });
-            
webdav.setInitParameter(SimpleWebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, 
path + "/webdav");
-            
webdav.setInitParameter(AbstractWebdavServlet.INIT_PARAM_AUTHENTICATE_HEADER, 
"Basic realm=\"Oak\"");
-            context.addServlet(webdav, path + "/webdav/*");
-
-            // 3 - JCR Remoting Server
-            @SuppressWarnings("serial")
-            ServletHolder jcrremote = new ServletHolder(new 
JcrRemotingServlet() {
-                @Override
-                protected Repository getRepository() {
-                    return jcrRepository;
-                }
-            });
-            
jcrremote.setInitParameter(JCRWebdavServerServlet.INIT_PARAM_RESOURCE_PATH_PREFIX,
 path + "/jcrremote");
-            
jcrremote.setInitParameter(AbstractWebdavServlet.INIT_PARAM_AUTHENTICATE_HEADER,
 "Basic realm=\"Oak\"");
-            context.addServlet(jcrremote, path + "/jcrremote/*");
-        }
-
-    }
-
-    public enum Mode {
-
-        BACKUP("backup"),
-        RESTORE("restore"),
-        BENCHMARK("benchmark"),
-        CONSOLE("console"),
-        DEBUG("debug"),
-        GRAPH("graph"),
-        HISTORY("history"),
-        CHECK("check"),
-        COMPACT("compact"),
-        SERVER("server"),
-        UPGRADE("upgrade"),
-        SCALABILITY("scalability"),
-        EXPLORE("explore"),
-        PRIMARY("primary"),
-        STANDBY("standy"),
-        HELP("help"),
-        CHECKPOINTS("checkpoints"),
-        RECOVERY("recovery"),
-        REPAIR("repair"),
-        TIKA("tika"),
-        GARBAGE("garbage"),
-        TARMKDIFF("tarmkdiff"),
-        TARMKRECOVERY("tarmkrecovery"),
-        DUMPDATASTOREREFS("dumpdatastorerefs");
-
-        private final String name;
-
-        Mode(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
 }

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java?rev=1727599&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java
 Fri Jan 29 15:17:44 2016
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+enum Mode {
+
+    BACKUP("backup", new BackupCommand()),
+    RESTORE("restore", new RestoreCommand()),
+    BENCHMARK("benchmark", new BenchmarkCommand()),
+    CONSOLE("console", new ConsoleCommand()),
+    DEBUG("debug", new DebugCommand()),
+    GRAPH("graph", new GraphCommand()),
+    HISTORY("history", new HistoryCommand()),
+    CHECK("check", new CheckCommand()),
+    COMPACT("compact", new CompactCommand()),
+    SERVER("server", new ServerCommand()),
+    UPGRADE("upgrade", new UpgradeCommand()),
+    SCALABILITY("scalability", new ScalabilityCommand()),
+    EXPLORE("explore", new ExploreCommand()),
+    PRIMARY("primary", new PrimaryCommand()),
+    STANDBY("standy", new StandbyCommand()),
+    CHECKPOINTS("checkpoints", new CheckpointsCommand()),
+    RECOVERY("recovery", new RecoveryCommand()),
+    REPAIR("repair", new RepairCommand()),
+    TIKA("tika", new TikaCommand()),
+    GARBAGE("garbage", new GarbageCommand()),
+    TARMKDIFF("tarmkdiff", new FileStoreDiffCommand()),
+    TARMKRECOVERY("tarmkrecovery", new FileStoreRevisionRecoveryCommand()),
+    DUMPDATASTOREREFS("dumpdatastorerefs", new 
DumpDataStoreReferencesCommand()),
+    HELP("help", new HelpCommand());
+
+    private final String name;
+
+    private final Command command;
+
+    Mode(String name, Command command) {
+        this.name = name;
+        this.command = command;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    public void execute(String... args) throws Exception {
+        command.execute(args);
+    }
+
+}

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

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrimaryCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrimaryCommand.java?rev=1727599&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrimaryCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PrimaryCommand.java
 Fri Jan 29 15:17:44 2016
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.run;
+
+import static java.util.Arrays.asList;
+import static 
org.apache.jackrabbit.oak.plugins.segment.FileStoreHelper.openFileStore;
+
+import java.util.Collections;
+import java.util.List;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
+import org.apache.jackrabbit.oak.plugins.segment.standby.server.StandbyServer;
+
+class PrimaryCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        final int defaultPort = 8023;
+
+        final OptionParser parser = new OptionParser();
+        final OptionSpec<Integer> port = parser.accepts("port", "port to 
listen").withRequiredArg().ofType(Integer.class).defaultsTo(defaultPort);
+        final OptionSpec<Boolean> secure = parser.accepts("secure", "use 
secure connections").withRequiredArg().ofType(Boolean.class);
+        final OptionSpec<String> admissible = parser.accepts("admissible", 
"list of admissible slave host names or ip 
ranges").withRequiredArg().ofType(String.class);
+        final OptionSpec<?> help = parser.acceptsAll(asList("h", "?", "help"), 
"show help").forHelp();
+        final OptionSpec<String> nonOption = parser.nonOptions("<path to 
repository>");
+
+        final OptionSet options = parser.parse(args);
+        final List<String> nonOptions = nonOption.values(options);
+
+        if (options.has(help)) {
+            parser.printHelpOn(System.out);
+            System.exit(0);
+        }
+
+        if (nonOptions.isEmpty()) {
+            parser.printHelpOn(System.err);
+            System.exit(1);
+        }
+
+        List<String> admissibleSlaves = options.has(admissible) ? 
options.valuesOf(admissible) : Collections.EMPTY_LIST;
+
+        FileStore store = null;
+        StandbyServer failoverServer = null;
+        try {
+            store = openFileStore(nonOptions.get(0));
+            failoverServer = new StandbyServer(
+                    options.has(port)? options.valueOf(port) : defaultPort,
+                    store,
+                    admissibleSlaves.toArray(new 
String[admissibleSlaves.size()]),
+                    options.has(secure) && options.valueOf(secure));
+            failoverServer.startAndWait();
+        } finally {
+            if (store != null) {
+                store.close();
+            }
+            if (failoverServer != null) {
+                failoverServer.close();
+            }
+        }
+    }
+
+}

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

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java?rev=1727599&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java
 Fri Jan 29 15:17:44 2016
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.run;
+
+import java.util.Arrays;
+
+import com.google.common.io.Closer;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.plugins.document.LastRevRecoveryAgent;
+import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
+import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore;
+import 
org.apache.jackrabbit.oak.plugins.document.mongo.MongoMissingLastRevSeeker;
+import org.apache.jackrabbit.oak.plugins.document.util.CloseableIterable;
+import org.apache.jackrabbit.oak.plugins.document.util.MapDBMapFactory;
+import org.apache.jackrabbit.oak.plugins.document.util.MapFactory;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+class RecoveryCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        MapFactory.setInstance(new MapDBMapFactory());
+        Closer closer = Closer.create();
+        String h = "recovery mongodb://host:port/database { dryRun }";
+        try {
+            NodeStore store = Utils.bootstrapNodeStore(args, closer, h);
+            if (!(store instanceof DocumentNodeStore)) {
+                System.err.println("Recovery only available for 
DocumentNodeStore");
+                System.exit(1);
+            }
+            DocumentNodeStore dns = (DocumentNodeStore) store;
+            if (!(dns.getDocumentStore() instanceof MongoDocumentStore)) {
+                System.err.println("Recovery only available for 
MongoDocumentStore");
+                System.exit(1);
+            }
+            MongoDocumentStore docStore = (MongoDocumentStore) 
dns.getDocumentStore();
+            LastRevRecoveryAgent agent = new LastRevRecoveryAgent(dns);
+            MongoMissingLastRevSeeker seeker = new 
MongoMissingLastRevSeeker(docStore);
+            CloseableIterable<NodeDocument> docs = seeker.getCandidates(0);
+            closer.register(docs);
+            boolean dryRun = Arrays.asList(args).contains("dryRun");
+            agent.recover(docs.iterator(), dns.getClusterId(), dryRun);
+        } catch (Throwable e) {
+            throw closer.rethrow(e);
+        } finally {
+            closer.close();
+        }
+    }
+
+}

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

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java?rev=1727599&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java
 Fri Jan 29 15:17:44 2016
@@ -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.run;
+
+import com.google.common.io.Closer;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore;
+import 
org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStoreHelper;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+class RepairCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        Closer closer = Closer.create();
+        String h = "repair mongodb://host:port/database path";
+        try {
+            NodeStore store = Utils.bootstrapNodeStore(args, closer, h);
+            if (!(store instanceof DocumentNodeStore)) {
+                System.err.println("Repair only available for 
DocumentNodeStore");
+                System.exit(1);
+            }
+            DocumentNodeStore dns = (DocumentNodeStore) store;
+            if (!(dns.getDocumentStore() instanceof MongoDocumentStore)) {
+                System.err.println("Repair only available for 
MongoDocumentStore");
+                System.exit(1);
+            }
+            MongoDocumentStore docStore = (MongoDocumentStore) 
dns.getDocumentStore();
+
+            String path = args[args.length - 1];
+            MongoDocumentStoreHelper.repair(docStore, path);
+        } catch (Throwable e) {
+            throw closer.rethrow(e);
+        } finally {
+            closer.close();
+        }
+    }
+
+}

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

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java?rev=1727599&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java
 Fri Jan 29 15:17:44 2016
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.run;
+
+import java.io.File;
+
+import org.apache.jackrabbit.oak.plugins.backup.FileStoreRestore;
+
+class RestoreCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        FileStoreRestore.restore(new File(args[1]), new File(args[0]));
+    }
+
+}

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

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java?rev=1727599&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java
 Fri Jan 29 15:17:44 2016
@@ -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.run;
+
+import org.apache.jackrabbit.oak.scalability.ScalabilityRunner;
+
+class ScalabilityCommand implements Command {
+
+    @Override
+    public void execute(String... args) throws Exception {
+        ScalabilityRunner.main(args);
+    }
+
+}

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

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java?rev=1727599&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java
 Fri Jan 29 15:17:44 2016
@@ -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;
+
+import static java.util.Arrays.asList;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.fixture.OakFixture;
+
+class ServerCommand implements Command {
+
+    private static final String DEFAULT_URI = "http://localhost:8080/";;
+
+    private static final int MB = 1024 * 1024;
+
+    private static void startOakServer(OakFixture oakFixture, String uri, 
List<Integer> cIds) throws Exception {
+        Map<Oak, String> m;
+        if (cIds.isEmpty()) {
+            System.out.println("Starting " + oakFixture.toString() + " 
repository -> " + uri);
+            m = Collections.singletonMap(oakFixture.getOak(0), "");
+        } else {
+            System.out.println("Starting a clustered repository " + 
oakFixture.toString() + " -> " + uri);
+            m = new HashMap<Oak, String>(cIds.size());
+
+            for (int i = 0; i < cIds.size(); i++) {
+                m.put(oakFixture.getOak(i), "/node" + i);
+            }
+        }
+        new HttpServer(URI.create(uri).getPort(), m);
+    }
+
+    @Override
+    public void execute(String... args) throws Exception {
+        OptionParser parser = new OptionParser();
+
+        OptionSpec<Integer> cache = parser.accepts("cache", "cache size 
(MB)").withRequiredArg().ofType(Integer.class).defaultsTo(100);
+
+        // tar/h2 specific option
+        OptionSpec<File> base = parser.accepts("base", "Base 
directory").withRequiredArg().ofType(File.class);
+        OptionSpec<Boolean> mmap = parser.accepts("mmap", "TarMK memory 
mapping").withOptionalArg().ofType(Boolean.class).defaultsTo("64".equals(System.getProperty("sun.arch.data.model")));
+
+        // mongo specific options:
+        OptionSpec<String> host = parser.accepts("host", "MongoDB 
host").withRequiredArg().defaultsTo("127.0.0.1");
+        OptionSpec<Integer> port = parser.accepts("port", "MongoDB 
port").withRequiredArg().ofType(Integer.class).defaultsTo(27017);
+        OptionSpec<String> dbName = parser.accepts("db", "MongoDB 
database").withRequiredArg();
+        OptionSpec<Integer> clusterIds = parser.accepts("clusterIds", "Cluster 
Ids").withOptionalArg().ofType(Integer.class).withValuesSeparatedBy(',');
+
+        // RDB specific options
+        OptionSpec<String> rdbjdbcuri = parser.accepts("rdbjdbcuri", "RDB JDBC 
URI").withOptionalArg().defaultsTo("");
+        OptionSpec<String> rdbjdbcuser = parser.accepts("rdbjdbcuser", "RDB 
JDBC user").withOptionalArg().defaultsTo("");
+        OptionSpec<String> rdbjdbcpasswd = parser.accepts("rdbjdbcpasswd", 
"RDB JDBC password").withOptionalArg().defaultsTo("");
+        OptionSpec<String> rdbjdbctableprefix = 
parser.accepts("rdbjdbctableprefix", "RDB JDBC table prefix")
+                .withOptionalArg().defaultsTo("");
+
+        OptionSpec<String> nonOption = parser.nonOptions();
+        OptionSpec<?> help = parser.acceptsAll(asList("h", "?", "help"), "show 
help").forHelp();
+        OptionSet options = parser.parse(args);
+
+        if (options.has(help)) {
+            parser.printHelpOn(System.out);
+            System.exit(0);
+        }
+
+        OakFixture oakFixture;
+
+        List<String> arglist = nonOption.values(options);
+        String uri = (arglist.isEmpty()) ? DEFAULT_URI : arglist.get(0);
+        String fix = (arglist.size() <= 1) ? OakFixture.OAK_MEMORY : 
arglist.get(1);
+
+        int cacheSize = cache.value(options);
+        List<Integer> cIds = Collections.emptyList();
+        if (fix.startsWith(OakFixture.OAK_MEMORY)) {
+            if (OakFixture.OAK_MEMORY_NS.equals(fix)) {
+                oakFixture = OakFixture.getMemoryNS(cacheSize * MB);
+            } else {
+                oakFixture = OakFixture.getMemory(cacheSize * MB);
+            }
+        } else if (fix.startsWith(OakFixture.OAK_MONGO)) {
+            cIds = clusterIds.values(options);
+            String db = dbName.value(options);
+            if (db == null) {
+                throw new IllegalArgumentException("Required argument db 
missing");
+            }
+            if (OakFixture.OAK_MONGO_NS.equals(fix)) {
+                oakFixture = OakFixture.getMongoNS(
+                        host.value(options), port.value(options),
+                        db, false,
+                        cacheSize * MB);
+            } else {
+                oakFixture = OakFixture.getMongo(
+                        host.value(options), port.value(options),
+                        db, false, cacheSize * MB);
+            }
+
+        } else if (fix.equals(OakFixture.OAK_TAR)) {
+            File baseFile = base.value(options);
+            if (baseFile == null) {
+                throw new IllegalArgumentException("Required argument base 
missing.");
+            }
+            oakFixture = OakFixture.getTar(OakFixture.OAK_TAR, baseFile, 256, 
cacheSize, mmap.value(options), false);
+        } else if (fix.equals(OakFixture.OAK_RDB)) {
+            oakFixture = OakFixture.getRDB(OakFixture.OAK_RDB, 
rdbjdbcuri.value(options), rdbjdbcuser.value(options),
+                    rdbjdbcpasswd.value(options), 
rdbjdbctableprefix.value(options), false, cacheSize);
+        } else {
+            throw new IllegalArgumentException("Unsupported repository setup " 
+ fix);
+        }
+
+        startOakServer(oakFixture, uri, cIds);
+    }
+
+}

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


Reply via email to