Author: mreutegg Date: Wed May 21 12:29:56 2014 New Revision: 1596557 URL: http://svn.apache.org/r1596557 Log: OAK-1805: Debugging console
Initial version of a command line tool Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Command.java jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/ConsoleSession.java Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Command.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Command.java?rev=1596557&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Command.java (added) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Command.java Wed May 21 12:29:56 2014 @@ -0,0 +1,527 @@ +/* + * 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.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nonnull; + +import org.apache.jackrabbit.oak.commons.PathUtils; +import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; +import org.apache.jackrabbit.oak.plugins.document.NodeDocument; +import org.apache.jackrabbit.oak.plugins.document.util.Utils; +import org.apache.jackrabbit.oak.spi.state.AbstractNodeState; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; + +import com.google.common.base.StandardSystemProperty; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES; + +/** + * All available console commands. + */ +public abstract class Command { + + private static final char[] SPACES = new char[4]; + + static { + Arrays.fill(SPACES, ' '); + } + + protected String args; + protected String description; + protected String usage; + + @Nonnull + public static Command create(String line) throws IOException { + StringBuilder sb = new StringBuilder(); + int i = 0; + for (; i < line.length(); i++) { + char c = line.charAt(i); + if (Character.isWhitespace(c)) { + if (sb.length() == 0) { + continue; + } else { + break; + } + } + if (sb.length() == 0) { + c = Character.toUpperCase(c); + } else { + c = Character.toLowerCase(c); + } + sb.append(c); + } + + if (sb.length() == 0) { + return new NoOp(); + } + + Command cmd; + try { + cmd = Class.forName(Command.class.getName() + "$" + sb.toString()) + .asSubclass(Command.class).newInstance(); + } catch (Exception e) { + cmd = new Unknown(sb.toString().toLowerCase(Locale.US)); + } + cmd.init(line.substring(i).trim()); + return cmd; + } + + protected final void init(String args) { + this.args = args; + } + + public abstract void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws Exception; + + public String getName() { + return getClass().getSimpleName().toLowerCase(Locale.US); + } + + protected void println(Object value, OutputStream out) throws IOException { + Writer writer = new OutputStreamWriter(out); + if (value == null) { + writer.write("[null]"); + } else { + writer.write(value.toString()); + } + println(writer); + writer.flush(); + } + + protected static void println(Writer writer) throws IOException { + writer.write(StandardSystemProperty.LINE_SEPARATOR.value()); + } + + private static final class Unknown extends Command { + + private final String cmd; + + private Unknown(String cmd) { + this.cmd = cmd; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + println("Unknown command: " + cmd + " " + args, out); + } + } + + private static final class NoOp extends Command { + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + } + } + + public static final class Help extends Command { + + public Help() { + this.description = "List all available command."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws Exception { + SortedMap<String, Command> commands = Maps.newTreeMap(); + SortedMap<String, Command> docCommands = Maps.newTreeMap(); + Class[] classes = Command.class.getDeclaredClasses(); + int maxCmdLength = 0; + for (Class clazz : classes) { + if (!Modifier.isPublic(clazz.getModifiers()) + || !Command.class.isAssignableFrom(clazz)) { + continue; + } + Command cmd = (Command) clazz.newInstance(); + if (DocumentNodeStoreCommand.class.isAssignableFrom(clazz)) { + docCommands.put(cmd.getName(), cmd); + } else { + commands.put(cmd.getName(), cmd); + } + maxCmdLength = Math.max(maxCmdLength, cmd.getName().length()); + } + println("Generic commands:", out); + Writer writer = new OutputStreamWriter(out); + printCommands(commands, maxCmdLength, writer); + println(writer); + writer.flush(); + println("DocumentNodeStore specific commands:", out); + printCommands(docCommands, maxCmdLength, writer); + writer.flush(); + } + + private void printCommands(SortedMap<String, Command> commands, + int maxCmdLength, + Writer writer) throws IOException { + for (String c : commands.keySet()) { + Command cmd = commands.get(c); + writer.write(SPACES); + writer.write(c); + int numSpaces = maxCmdLength - c.length() + 4; + for (int i = 0; i < numSpaces; i++) { + writer.write(" "); + } + if (cmd.description != null) { + writer.write(cmd.description); + } + println(writer); + } + } + } + + public static final class Pwd extends Command { + + public Pwd() { + this.description = "Print the full path of the current working node."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + println(session.getWorkingPath(), out); + } + } + + public static final class Exit extends Command { + + public Exit() { + this.description = "Quit this console."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + println("Good bye.", out); + } + } + + public static final class Cd extends Command { + + public Cd() { + this.description = "Change the current working directory to a specific node."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + if (!PathUtils.isValid(args)) { + println("Not a valid path: " + args, out); + return; + } + String path; + if (PathUtils.isAbsolute(args)) { + path = args; + } else { + path = PathUtils.concat(session.getWorkingPath(), args); + } + List<String> elements = Lists.newArrayList(); + for (String element : PathUtils.elements(path)) { + if (PathUtils.denotesParent(element)) { + if (!elements.isEmpty()) { + elements.remove(elements.size() - 1); + } + } else if (!PathUtils.denotesCurrent(element)) { + elements.add(element); + } + } + path = PathUtils.concat("/", elements.toArray(new String[elements.size()])); + String old = session.setWorkingPath(path); + if (!session.getWorkingNode().exists()) { + session.setWorkingPath(old); + println("No such node", out); + } + } + } + + public static final class Ls extends Command { + + public Ls() { + this.description = "List the names of the children of the current node."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + for (String name : session.getWorkingNode().getChildNodeNames()) { + println(name, out); + } + } + } + + public static final class Pn extends Command { + + public Pn() { + this.description = "Print the current node."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + println(AbstractNodeState.toString(session.getWorkingNode()), out); + } + } + + public static final class Refresh extends Command { + + public Refresh() { + this.description = "Control how the current session is refreshed."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + if (args.contains("auto")) { + session.setAutoRefresh(true); + println("Enabled auto refresh", out); + } else if (args.contains("manual")) { + session.setAutoRefresh(false); + println("Disabled auto refresh", out); + } else if (args.trim().length() == 0) { + session.refresh(); + println("Session refreshed", out); + } else { + println("Unrecognized arguments: " + args, out); + } + + } + } + + public static final class Checkpoint extends Command { + + public Checkpoint() { + this.description = "Create a checkpoint."; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws Exception { + long time = TimeUnit.HOURS.toSeconds(1); + if (args.trim().length() > 0) { + try { + time = Long.parseLong(args.trim()); + } catch (NumberFormatException e) { + println("Not a number: " + args, out); + return; + } + } + StringBuilder msg = new StringBuilder(); + msg.append("Checkpoint created: "); + msg.append(session.checkpoint(time)); + msg.append(" (expires: "); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, (int) time); + msg.append(cal.getTime().toString()); + msg.append(")."); + println(msg, out); + } + } + + public static final class Retrieve extends Command { + + public Retrieve() { + this.description = "Retrieve a snapshot of the given checkpoint"; + } + + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws Exception { + if (session.isAutoRefresh()) { + session.setAutoRefresh(false); + println("Auto refresh disabled.", out); + } + session.retrieve(args.trim()); + println("Root node is now at " + args.trim(), out); + } + } + + //-----------------------< DocumentNodeStore specific >--------------------- + + abstract static class DocumentNodeStoreCommand extends Command { + @Override + public void execute(@Nonnull ConsoleSession session, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + if (session.getStore() instanceof DocumentNodeStore) { + execute(session, (DocumentNodeStore) session.getStore(), in, out); + } else { + println("Can only execute command on a DocumentNodeStore", out); + } + } + + protected abstract void execute(@Nonnull ConsoleSession session, + @Nonnull DocumentNodeStore store, + @Nonnull InputStream in, + @Nonnull OutputStream out) + throws IOException; + } + + public static final class Pd extends DocumentNodeStoreCommand { + + public Pd() { + this.description = "Print the current document."; + } + + @Override + protected void execute(@Nonnull ConsoleSession session, + @Nonnull DocumentNodeStore store, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + String id = Utils.getIdFromPath(session.getWorkingPath()); + NodeDocument doc = store.getDocumentStore().find(NODES, id); + if (doc == null) { + println("[null]", out); + } else { + println(doc, out); + } + } + + private void println(NodeDocument doc, OutputStream out) + throws IOException { + int level = 1; + Writer writer = new OutputStreamWriter(out); + Set<String> mapKeys = Sets.newHashSet(); + writer.write('{'); + String comma = ""; + for (String key : doc.keySet()) { + Object value = doc.get(key); + if (value instanceof Map) { + mapKeys.add(key); + continue; + } + writer.write(comma); + comma = ","; + println(writer); + printIndent(level, writer); + printJson(key, value, writer); + } + for (String key : mapKeys) { + writer.write(comma); + comma = ","; + println(writer); + printIndent(level, writer); + writer.write(JSONObject.escape(key)); + writer.write(": {"); + println((Map) doc.get(key), level + 1, writer); + println(writer); + printIndent(level, writer); + writer.write("}"); + } + println(writer); + writer.write('}'); + println(writer); + writer.flush(); + } + + private void println(Map map, int level, Writer writer) + throws IOException { + String comma = ""; + for (Object obj : map.keySet()) { + String key = obj.toString(); + Object value = map.get(obj); + writer.write(comma); + comma = ","; + println(writer); + printIndent(level, writer); + printJson(key, value, writer); + } + } + + private void printJson(String key, Object value, Writer writer) + throws IOException { + writer.write(JSONObject.escape(key)); + writer.write(": "); + writer.write(jsonEscape(value)); + } + + private String jsonEscape(Object value) { + String escaped = JSONValue.toJSONString(value); + return escaped.replaceAll("\\\\/", "/"); + } + + private void printIndent(int level, Writer writer) throws IOException { + for (int i = 0; i < level; i++) { + writer.write(SPACES); + } + } + } + + public static final class Lsd extends DocumentNodeStoreCommand { + + public Lsd() { + this.description = "List the identifiers of the child documents at the current path."; + } + + @Override + protected void execute(@Nonnull ConsoleSession session, + @Nonnull DocumentNodeStore store, + @Nonnull InputStream in, + @Nonnull OutputStream out) throws IOException { + Writer writer = new OutputStreamWriter(out); + String path = session.getWorkingPath(); + String fromKey = Utils.getKeyLowerLimit(path); + String toKey = Utils.getKeyUpperLimit(path); + int num = 0; + for (NodeDocument doc : store.getDocumentStore().query( + NODES, fromKey, toKey, Integer.MAX_VALUE)) { + writer.write(doc.getId()); + println(writer); + num++; + } + println(writer); + writer.write("Found " + num + " document"); + if (num != 1) { + writer.write("s"); + } + writer.write("."); + println(writer); + writer.flush(); + } + } + +} Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java?rev=1596557&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java (added) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java Wed May 21 12:29:56 2014 @@ -0,0 +1,129 @@ +/* + * 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.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Set; + +import org.apache.jackrabbit.oak.fixture.OakFixture; +import org.apache.jackrabbit.oak.plugins.document.DocumentMK; +import org.apache.jackrabbit.oak.plugins.document.util.MongoConnection; +import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore; +import org.apache.jackrabbit.oak.plugins.segment.file.FileStore; +import org.apache.jackrabbit.oak.spi.state.NodeStore; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; + +/** + * A command line console. + */ +public class Console { + + public static void main(String[] args) throws Exception { + OptionParser parser = new OptionParser(); + OptionSpec<File> base = parser.accepts("base", "Base directory") + .withRequiredArg().ofType(File.class) + .defaultsTo(new File(".")); + OptionSpec<String> host = parser.accepts("host", "MongoDB host") + .withRequiredArg().defaultsTo("localhost"); + OptionSpec<Integer> port = parser.accepts("port", "MongoDB port") + .withRequiredArg().ofType(Integer.class).defaultsTo(27017); + OptionSpec<String> dbName = parser.accepts("db", "MongoDB database") + .withRequiredArg().defaultsTo("oak"); + OptionSpec<Integer> clusterId = parser.accepts("clusterId", "MongoMK clusterId") + .withRequiredArg().ofType(Integer.class).defaultsTo(1); + OptionSpec<Integer> cache = parser.accepts("cache", "cache size (MB)") + .withRequiredArg().ofType(Integer.class).defaultsTo(100); + + OptionSet options = parser.parse(args); + Set<String> argset = Sets.newHashSet(options.nonOptionArguments()); + + String uri = "mongodb://" + host.value(options) + ":" + + port.value(options) + "/" + dbName.value(options); + NodeStore store; + if (argset.contains(OakFixture.OAK_MONGO)) { + MongoConnection mongo = new MongoConnection(uri); + store = new DocumentMK.Builder(). + setMongoDB(mongo.getDB()). + memoryCacheSize(cache.value(options)). + setClusterId(clusterId.value(options)).getNodeStore(); + } else if (argset.contains(OakFixture.OAK_TAR)) { + store = new SegmentNodeStore(new FileStore(base.value(options), 256)); + } else { + System.out.println("No repository specified. " + + "Was expecting one of: " + Lists.newArrayList( + OakFixture.OAK_TAR, OakFixture.OAK_MONGO)); + System.exit(1); + return; + } + + System.exit(new Console(store, System.in, System.out).run()); + } + + private final NodeStore store; + private final InputStream in; + private final OutputStream out; + + public Console(NodeStore store, InputStream in, OutputStream out) { + this.store = store; + this.in = in; + this.out = out; + } + + public int run() throws Exception { + int code = 1; + ConsoleSession session = ConsoleSession.create(store); + for (;;) { + prompt(); + String line = readLine(in); + if (line == null) { + break; + } + Command c = Command.create(line); + try { + c.execute(session, in, out); + } catch (Exception e) { + e.printStackTrace(new PrintWriter(out)); + } + if (c.getName().equals("exit")) { + code = 0; + break; + } + + } + return code; + } + + private void prompt() throws IOException { + out.write("> ".getBytes()); + } + + private static String readLine(InputStream in) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + return reader.readLine(); + } +} Added: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/ConsoleSession.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/ConsoleSession.java?rev=1596557&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/ConsoleSession.java (added) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/console/ConsoleSession.java Wed May 21 12:29:56 2014 @@ -0,0 +1,165 @@ +/* + * 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.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nonnull; + +import org.apache.jackrabbit.oak.commons.PathUtils; +import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.spi.state.NodeStore; + +import com.google.common.collect.Maps; + +/** + * Light weight session to a NodeStore, holding context information. + */ +public abstract class ConsoleSession { + + private final Map<String, Object> context = Maps.newHashMap(); + + private final NodeStore store; + + private ConsoleSession(NodeStore store) { + this.store = store; + } + + public static ConsoleSession create(NodeStore store) { + return new DefaultSession(store); + } + + /** + * Returns the current working path. This method will return the path + * of the root node if none is set explicity. + * + * @return the current working path. + */ + public String getWorkingPath() { + String path = (String) context.get("workingPath"); + if (path == null) { + path = "/"; + context.put("workingPath", path); + } + return path; + } + + /** + * Sets a new working path and returns the previously set. + * + * @param path the new working path. + * @return the previously set working path. + */ + public String setWorkingPath(String path) { + String old = getWorkingPath(); + context.put("workingPath", path); + return old; + } + + /** + * Creates and returns a checkpoint with the given lifetime in seconds. + * + * @param lifetimeSeconds the lifetime of the checkpoint in seconds. + * @return the checkpoint reference. + */ + public String checkpoint(long lifetimeSeconds) { + return store.checkpoint(TimeUnit.SECONDS.toMillis(lifetimeSeconds)); + } + + /** + * Retrieves the root node from a previously created checkpoint. The root + * node is available with {@link #getRoot()}. + * + * @param checkpoint the checkpoint reference. + */ + public void retrieve(String checkpoint) { + context.put("root", store.retrieve(checkpoint)); + } + + /** + * Returns the currently set root node. If {@link #isAutoRefresh()} is set, + * a fresh root node is retrieved from the store. + * + * @return the current root node. + */ + public NodeState getRoot() { + NodeState root = (NodeState) context.get("root"); + if (root == null || isAutoRefresh()) { + root = store.getRoot(); + context.put("root", root); + } + return root; + } + + /** + * @return the underlying node store. + */ + public NodeStore getStore() { + return store; + } + + /** + * The node state for the current working path. Possibly non-existent. + * + * @return the working node state. + */ + @Nonnull + public NodeState getWorkingNode() { + NodeState current = getRoot(); + for (String element : PathUtils.elements(getWorkingPath())) { + current = current.getChildNode(element); + } + return current; + } + + /** + * Enables or disables auto-refresh of the root node state on + * {@link #getRoot()}. + * + * @param enable enables or disables auto-refresh. + */ + public void setAutoRefresh(boolean enable) { + if (enable) { + context.put("auto-refresh", "true"); + } else { + context.remove("auto-refresh"); + } + } + + /** + * @return <code>true</code> if auto-refresh is enabled; <code>false</code> + * otherwise. + */ + public boolean isAutoRefresh() { + return context.containsKey("auto-refresh"); + } + + /** + * Performs a manual refresh of the root node state. + */ + public void refresh() { + context.put("root", store.getRoot()); + } + + private static final class DefaultSession extends ConsoleSession { + + DefaultSession(NodeStore store) { + super(store); + } + } +} 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=1596557&r1=1596556&r2=1596557&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 Wed May 21 12:29:56 2014 @@ -48,6 +48,7 @@ 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.commons.PathUtils; +import org.apache.jackrabbit.oak.console.Console; import org.apache.jackrabbit.oak.fixture.OakFixture; import org.apache.jackrabbit.oak.http.OakServlet; import org.apache.jackrabbit.oak.jcr.Jcr; @@ -99,6 +100,9 @@ public class Main { case BENCHMARK: BenchmarkRunner.main(args); break; + case CONSOLE: + Console.main(args); + break; case DEBUG: debug(args); break; @@ -487,6 +491,7 @@ public class Main { BACKUP("backup"), BENCHMARK("benchmark"), + CONSOLE("debug"), DEBUG("debug"), SERVER("server"), UPGRADE("upgrade"),