/* * Copyright 2013 Couchbase, Inc. * * Licensed 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.couchbase.mock.control; import com.google.gson.Gson; import com.google.gson.JsonObject; import org.couchbase.mock.CouchbaseMock; import org.couchbase.mock.control.handlers.*; import org.jetbrains.annotations.NotNull; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; /** * @author Mark Nunberg */ public class MockCommandDispatcher { public static final Map<String, Class> commandMap = new HashMap<String, Class>(); private static final Map<MockCommand.Command, Class> classMap = new EnumMap<MockCommand.Command, Class>(MockCommand.Command.class); private static final Gson gs = new Gson(); private static void registerClass(MockCommand.Command cmd, Class cls) { if (!MockCommand.class.isAssignableFrom(cls)) { throw new RuntimeException("Can process only HarakiriMonitor objects"); } String commandName = cmd.toString().toUpperCase(); commandMap.put(commandName, cls); classMap.put(cmd, cls); } static { registerClass(MockCommand.Command.HICCUP, HiccupCommandHandler.class); registerClass(MockCommand.Command.FAILOVER, FailoverCommandHandler.class); registerClass(MockCommand.Command.TRUNCATE, TruncateCommandHandler.class); registerClass(MockCommand.Command.RESPAWN, RespawnCommandHandler.class); registerClass(MockCommand.Command.MOCKINFO, MockInfoCommandHandler.class); registerClass(MockCommand.Command.CACHE, PersistenceCommandHandler.class); registerClass(MockCommand.Command.UNCACHE, PersistenceCommandHandler.class); registerClass(MockCommand.Command.PERSIST, PersistenceCommandHandler.class); registerClass(MockCommand.Command.UNPERSIST, PersistenceCommandHandler.class); registerClass(MockCommand.Command.ENDURE, PersistenceCommandHandler.class); registerClass(MockCommand.Command.PURGE, PersistenceCommandHandler.class); registerClass(MockCommand.Command.KEYINFO, KeyInfoCommandHandler.class); registerClass(MockCommand.Command.TIME_TRAVEL, TimeTravelCommandHandler.class); registerClass(MockCommand.Command.HELP, MockHelpCommandHandler.class); registerClass(MockCommand.Command.OPFAIL, OpfailCommandHandler.class); registerClass(MockCommand.Command.SET_CCCP, CCCPCommandHandler.class); registerClass(MockCommand.Command.GET_MCPORTS, GetMCPortsHandler.class); registerClass(MockCommand.Command.REGEN_VBCOORDS, RegenCoordsHandler.class); registerClass(MockCommand.Command.RESET_QUERYSTATE, ResetQueryStateHandler.class); registerClass(MockCommand.Command.START_CMDLOG, StartCmdLogCommandHandler.class); registerClass(MockCommand.Command.STOP_CMDLOG, StopCmdLogCommandHandler.class); registerClass(MockCommand.Command.GET_CMDLOG, GetCmdLogCommandHandler.class); registerClass(MockCommand.Command.START_RETRY_VERIFY, StartRetryVerifyComandHandler.class); registerClass(MockCommand.Command.CHECK_RETRY_VERIFY, CheckRetryVerifyCommandHandler.class); } // Instance members private final CouchbaseMock mock; public @NotNull CommandStatus dispatch(String command, JsonObject payload) { MockCommand obj; command = command.replaceAll(" ", "_").toUpperCase(); if (!commandMap.containsKey(command)) { throw new CommandNotFoundException("Unknown command: " + command); } MockCommand.Command cmd; Class cls; try { cmd = MockCommand.Command.valueOf(command.toUpperCase()); } catch (IllegalArgumentException e) { throw new CommandNotFoundException("No such command: " + command, e); } cls = classMap.get(cmd); if (cls == null) { throw new RuntimeException("Can't find class for " + cmd); } try { obj = (MockCommand) cls.newInstance(); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } return obj.execute(mock, cmd, payload); } public MockCommandDispatcher(CouchbaseMock mock) { this.mock = mock; } public CouchbaseMock getMock() { return mock; } /** * Process the input sent from the client utilizing the mock server * and return the response. * * @param input the JSON encoded command from the user * @return a string to send to the client */ public String processInput(String input) { JsonObject object; try { object = gs.fromJson(input, JsonObject.class); } catch (Throwable t) { return "{ \"status\" : \"fail\", \"error\" : \"Failed to parse input\" }"; } String command = object.get("command").getAsString(); JsonObject payload; if (!object.has("payload")) { payload = new JsonObject(); } else { payload = object.get("payload").getAsJsonObject(); } CommandStatus status; try { status = dispatch(command, payload); } catch (CommandNotFoundException ex) { status = new CommandStatus(); status.fail("No such command"); } catch (Throwable t) { status = new CommandStatus(); status.fail(t); } return status.toString(); } }