/** Main dispatch method called from the LatherBoss. */
  public LatherValue dispatch(LatherContext ctx, String method, LatherValue arg)
      throws LatherRemoteException {

    Integer agentId = null;
    if (!haService.alertTriggersHaveInitialized()) {
      if (log.isDebugEnabled()) {
        log.debug("Not ready - received request for " + method + " from " + ctx.getCallerIP());
      }
      throw new LatherRemoteException("Server still initializing");
    }

    if (log.isDebugEnabled()) {
      log.debug("Request for " + method + "() from " + ctx.getCallerIP());
    }

    if (!HAUtil.isMasterNode()) {
      log.warn("Non-primary server received communication from an agent.  Request will be denied.");
      throw new LatherRemoteException(
          "This server is not the primary node in the HA configuration. Agent request denied.");
    }

    if (secureCommands.contains(method)) {
      if (!(arg instanceof SecureAgentLatherValue)) {
        log.warn(
            "Authenticated call made from "
                + ctx.getCallerIP()
                + " which did not subclass the correct authentication class");
        throw new LatherRemoteException("Unauthorized agent denied");
      }

      String agentToken = ((SecureAgentLatherValue) arg).getAgentToken();
      validateAgent(ctx, agentToken);
      synchronized (tokensToTime) {
        tokensToTime.put(agentToken, System.currentTimeMillis());
      }
      try {
        Agent a = agentManager.getAgent(agentToken);
        agentId = a.getId();
      } catch (AgentNotFoundException e) {
        log.debug(e, e);
      }
    }

    AgentConnection conn = null;
    long start = 0;
    try {
      conn = agentManager.getAgentConnection(method, ctx.getCallerIP(), agentId);
      start = now();
      return runCommand(ctx, method, arg);
    } catch (LatherRemoteException e) {
      concurrentStatsCollector.addStat(1, LATHER_REMOTE_EXCEPTION);
      throw e;
    } finally {
      if (conn != null) {
        agentManager.disconnectAgent(conn);
      }
      long duration = now() - start;
      concurrentStatsCollector.addStat(duration, LATHER_RUN_COMMAND_TIME);
    }
  }
 private LatherValue runCommand(LatherContext ctx, String method, LatherValue arg)
     throws LatherRemoteException {
   LatherValue rtn = null;
   long start = now();
   if (method.equals(CommandInfo.CMD_PING)) {
     rtn = cmdPing(arg);
     concurrentStatsCollector.addStat(now() - start, ConcurrentStatsCollector.CMD_PING);
   } else if (method.equals(CommandInfo.CMD_USERISVALID)) {
     rtn = cmdUserIsValid(ctx, (UserIsValid_args) arg);
     concurrentStatsCollector.addStat(now() - start, ConcurrentStatsCollector.CMD_USERISVALID);
   } else if (method.equals(CommandInfo.CMD_MEASUREMENT_SEND_REPORT)) {
     rtn = cmdMeasurementSendReport((MeasurementSendReport_args) arg);
     concurrentStatsCollector.addStat(
         now() - start, ConcurrentStatsCollector.CMD_MEASUREMENT_SEND_REPORT);
   } else if (method.equals(CommandInfo.CMD_MEASUREMENT_GET_CONFIGS)) {
     rtn = cmdMeasurementGetConfigs((MeasurementGetConfigs_args) arg);
     concurrentStatsCollector.addStat(
         now() - start, ConcurrentStatsCollector.CMD_MEASUREMENT_GET_CONFIGS);
   } else if (method.equals(CommandInfo.CMD_REGISTER_AGENT)) {
     rtn = cmdRegisterAgent(ctx, (RegisterAgent_args) arg);
     concurrentStatsCollector.addStat(now() - start, ConcurrentStatsCollector.CMD_REGISTER_AGENT);
   } else if (method.equals(CommandInfo.CMD_UPDATE_AGENT)) {
     rtn = cmdUpdateAgent(ctx, (UpdateAgent_args) arg);
     concurrentStatsCollector.addStat(now() - start, ConcurrentStatsCollector.CMD_UPDATE_AGENT);
   } else if (method.equals(CommandInfo.CMD_AI_SEND_REPORT)) {
     rtn = cmdAiSendReport((AiSendReport_args) arg);
     concurrentStatsCollector.addStat(now() - start, ConcurrentStatsCollector.CMD_AI_SEND_REPORT);
   } else if (method.equals(CommandInfo.CMD_AI_SEND_RUNTIME_REPORT)) {
     rtn = cmdAiSendRuntimeReport((AiSendRuntimeReport_args) arg);
     concurrentStatsCollector.addStat(
         now() - start, ConcurrentStatsCollector.CMD_AI_SEND_RUNTIME_REPORT);
   } else if (method.equals(CommandInfo.CMD_TRACK_SEND_LOG)) {
     rtn = cmdTrackLogMessage((TrackSend_args) arg);
     concurrentStatsCollector.addStat(now() - start, ConcurrentStatsCollector.CMD_TRACK_SEND_LOG);
   } else if (method.equals(CommandInfo.CMD_TRACK_SEND_CONFIG_CHANGE)) {
     rtn = cmdTrackConfigChange((TrackSend_args) arg);
     concurrentStatsCollector.addStat(
         now() - start, ConcurrentStatsCollector.CMD_TRACK_SEND_CONFIG_CHANGE);
   } else if (method.equals(CommandInfo.CMD_CONTROL_GET_PLUGIN_CONFIG)) {
     rtn = cmdControlGetPluginConfig((ControlGetPluginConfig_args) arg);
     concurrentStatsCollector.addStat(
         now() - start, ConcurrentStatsCollector.CMD_CONTROL_GET_PLUGIN_CONFIG);
   } else if (method.equals(CommandInfo.CMD_CONTROL_SEND_COMMAND_RESULT)) {
     rtn = cmdControlSendCommandResult((ControlSendCommandResult_args) arg);
     concurrentStatsCollector.addStat(
         now() - start, ConcurrentStatsCollector.CMD_CONTROL_SEND_COMMAND_RESULT);
   } else if (method.equals(CommandInfo.CMD_PLUGIN_SEND_REPORT)) {
     rtn = cmdAgentPluginReport((PluginReport_args) arg);
     concurrentStatsCollector.addStat(
         now() - start, ConcurrentStatsCollector.CMD_PLUGIN_SEND_REPORT);
   } else if (method.equals(CommandInfo.CMD_TOPN_SEND_REPORT)) {
     rtn = cmdTopNSendReport((TopNSendReport_args) arg);
   } else {
     log.warn(
         ctx.getCallerIP() + " attempted to invoke '" + method + "' which could not be found");
     throw new LatherRemoteException("Unknown method, '" + method + "'");
   }
   return rtn;
 }
 @PostConstruct
 public void initStatsCollector() {
   concurrentStatsCollector.register(LATHER_RUN_COMMAND_TIME);
   concurrentStatsCollector.register(LATHER_REMOTE_EXCEPTION);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_PING);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_USERISVALID);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_MEASUREMENT_SEND_REPORT);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_MEASUREMENT_GET_CONFIGS);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_REGISTER_AGENT);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_UPDATE_AGENT);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_AI_SEND_REPORT);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_AI_SEND_RUNTIME_REPORT);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_TRACK_SEND_LOG);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_TRACK_SEND_CONFIG_CHANGE);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_CONTROL_GET_PLUGIN_CONFIG);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_CONTROL_SEND_COMMAND_RESULT);
   concurrentStatsCollector.register(ConcurrentStatsCollector.CMD_PLUGIN_SEND_REPORT);
 }