public String getSerializedApiError(
      ServerApiException ex, Map<String, Object[]> apiCommandParams, String responseType) {
    String responseName = null;
    Class<?> cmdClass = null;
    String responseText = null;

    if (ex == null) {
      // this call should not be invoked with null exception
      return getSerializedApiError(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
          "Some internal error happened",
          apiCommandParams,
          responseType);
    }
    try {
      if (ex.getErrorCode() == ApiErrorCode.UNSUPPORTED_ACTION_ERROR
          || apiCommandParams == null
          || apiCommandParams.isEmpty()) {
        responseName = "errorresponse";
      } else {
        Object cmdObj = apiCommandParams.get("command");
        // cmd name can be null when "command" parameter is missing in
        // the request
        if (cmdObj != null) {
          String cmdName = ((String[]) cmdObj)[0];
          cmdClass = getCmdClass(cmdName);
          if (cmdClass != null) {
            responseName = ((BaseCmd) cmdClass.newInstance()).getCommandName();
          } else {
            responseName = "errorresponse";
          }
        }
      }
      ExceptionResponse apiResponse = new ExceptionResponse();
      apiResponse.setErrorCode(ex.getErrorCode().getHttpCode());
      apiResponse.setErrorText(ex.getDescription());
      apiResponse.setResponseName(responseName);
      ArrayList<String> idList = ex.getIdProxyList();
      if (idList != null) {
        for (int i = 0; i < idList.size(); i++) {
          apiResponse.addProxyObject(idList.get(i));
        }
      }
      // Also copy over the cserror code and the function/layer in which
      // it was thrown.
      apiResponse.setCSErrorCode(ex.getCSErrorCode());

      SerializationContext.current().setUuidTranslation(true);
      responseText = ApiResponseSerializer.toSerializedString(apiResponse, responseType);

    } catch (Exception e) {
      s_logger.error("Exception responding to http request", e);
    }
    return responseText;
  }
  public void init() {
    BaseCmd.setComponents(new ApiResponseHelper());
    BaseListCmd.configure();

    _systemAccount = _accountMgr.getSystemAccount();
    _systemUser = _accountMgr.getSystemUser();
    _dispatcher = ApiDispatcher.getInstance();

    Integer apiPort = null; // api port, null by default
    ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
    ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
    SearchCriteria<ConfigurationVO> sc = configDao.createSearchCriteria();
    sc.addAnd("name", SearchCriteria.Op.EQ, "integration.api.port");
    List<ConfigurationVO> values = configDao.search(sc, null);
    if ((values != null) && (values.size() > 0)) {
      ConfigurationVO apiPortConfig = values.get(0);
      if (apiPortConfig.getValue() != null) {
        apiPort = Integer.parseInt(apiPortConfig.getValue());
      }
    }

    Set<Class<?>> cmdClasses =
        ReflectUtil.getClassesWithAnnotation(
            APICommand.class, new String[] {"org.apache.cloudstack.api", "com.cloud.api"});

    for (Class<?> cmdClass : cmdClasses) {
      String apiName = cmdClass.getAnnotation(APICommand.class).name();
      if (_apiNameCmdClassMap.containsKey(apiName)) {
        s_logger.error("API Cmd class " + cmdClass.getName() + " has non-unique apiname" + apiName);
        continue;
      }
      _apiNameCmdClassMap.put(apiName, cmdClass);
    }

    encodeApiResponse = Boolean.valueOf(configDao.getValue(Config.EncodeApiResponse.key()));
    String jsonType = configDao.getValue(Config.JavaScriptDefaultContentType.key());
    if (jsonType != null) {
      jsonContentType = jsonType;
    }

    if (apiPort != null) {
      ListenerThread listenerThread = new ListenerThread(this, apiPort);
      listenerThread.start();
    }
  }
  public String getSerializedApiError(
      int errorCode,
      String errorText,
      Map<String, Object[]> apiCommandParams,
      String responseType) {
    String responseName = null;
    Class<?> cmdClass = null;
    String responseText = null;

    try {
      if (apiCommandParams == null || apiCommandParams.isEmpty()) {
        responseName = "errorresponse";
      } else {
        Object cmdObj = apiCommandParams.get("command");
        // cmd name can be null when "command" parameter is missing in the request
        if (cmdObj != null) {
          String cmdName = ((String[]) cmdObj)[0];
          cmdClass = getCmdClass(cmdName);
          if (cmdClass != null) {
            responseName = ((BaseCmd) cmdClass.newInstance()).getCommandName();
          } else {
            responseName = "errorresponse";
          }
        }
      }
      ExceptionResponse apiResponse = new ExceptionResponse();
      apiResponse.setErrorCode(errorCode);
      apiResponse.setErrorText(errorText);
      apiResponse.setResponseName(responseName);
      SerializationContext.current().setUuidTranslation(true);
      responseText = ApiResponseSerializer.toSerializedString(apiResponse, responseType);

    } catch (Exception e) {
      s_logger.error("Exception responding to http request", e);
    }
    return responseText;
  }
  @SuppressWarnings("rawtypes")
  public String handleRequest(
      Map params, boolean decode, String responseType, StringBuffer auditTrailSb)
      throws ServerApiException {
    String response = null;
    String[] command = null;
    try {
      command = (String[]) params.get("command");
      if (command == null) {
        s_logger.error("invalid request, no command sent");
        if (s_logger.isTraceEnabled()) {
          s_logger.trace("dumping request parameters");
          for (Object key : params.keySet()) {
            String keyStr = (String) key;
            String[] value = (String[]) params.get(key);
            s_logger.trace(
                "   key: " + keyStr + ", value: " + ((value == null) ? "'null'" : value[0]));
          }
        }
        throw new ServerApiException(
            ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "Invalid request, no command sent");
      } else {
        Map<String, String> paramMap = new HashMap<String, String>();
        Set keys = params.keySet();
        Iterator keysIter = keys.iterator();
        while (keysIter.hasNext()) {
          String key = (String) keysIter.next();
          if ("command".equalsIgnoreCase(key)) {
            continue;
          }
          String[] value = (String[]) params.get(key);

          String decodedValue = null;
          if (decode) {
            try {
              decodedValue = URLDecoder.decode(value[0], "UTF-8");
            } catch (UnsupportedEncodingException usex) {
              s_logger.warn(key + " could not be decoded, value = " + value[0]);
              throw new ServerApiException(
                  ApiErrorCode.PARAM_ERROR,
                  key + " could not be decoded, received value " + value[0]);
            } catch (IllegalArgumentException iae) {
              s_logger.warn(key + " could not be decoded, value = " + value[0]);
              throw new ServerApiException(
                  ApiErrorCode.PARAM_ERROR,
                  key
                      + " could not be decoded, received value "
                      + value[0]
                      + " which contains illegal characters eg.%");
            }
          } else {
            decodedValue = value[0];
          }
          paramMap.put(key, decodedValue);
        }

        Class<?> cmdClass = getCmdClass(command[0]);
        if (cmdClass != null) {
          BaseCmd cmdObj = (BaseCmd) cmdClass.newInstance();
          cmdObj.setFullUrlParams(paramMap);
          cmdObj.setResponseType(responseType);
          // This is where the command is either serialized, or directly dispatched
          response = queueCommand(cmdObj, paramMap);
          buildAuditTrail(auditTrailSb, command[0], response);
        } else {
          if (!command[0].equalsIgnoreCase("login") && !command[0].equalsIgnoreCase("logout")) {
            String errorString =
                "Unknown API command: " + ((command == null) ? "null" : command[0]);
            s_logger.warn(errorString);
            auditTrailSb.append(" " + errorString);
            throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, errorString);
          }
        }
      }
    } catch (InvalidParameterValueException ex) {
      s_logger.info(ex.getMessage());
      throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex);
    } catch (IllegalArgumentException ex) {
      s_logger.info(ex.getMessage());
      throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex);
    } catch (PermissionDeniedException ex) {
      ArrayList<String> idList = ex.getIdProxyList();
      if (idList != null) {
        s_logger.info(
            "PermissionDenied: "
                + ex.getMessage()
                + " on uuids: ["
                + StringUtils.listToCsvTags(idList)
                + "]");
      } else {
        s_logger.info("PermissionDenied: " + ex.getMessage());
      }
      throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, ex.getMessage(), ex);
    } catch (AccountLimitException ex) {
      s_logger.info(ex.getMessage());
      throw new ServerApiException(ApiErrorCode.ACCOUNT_RESOURCE_LIMIT_ERROR, ex.getMessage(), ex);
    } catch (InsufficientCapacityException ex) {
      s_logger.info(ex.getMessage());
      String errorMsg = ex.getMessage();
      if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) {
        // hide internal details to non-admin user for security reason
        errorMsg = BaseCmd.USER_ERROR_MESSAGE;
      }
      throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg, ex);
    } catch (ResourceAllocationException ex) {
      s_logger.info(ex.getMessage());
      String errorMsg = ex.getMessage();
      if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) {
        // hide internal details to non-admin user for security reason
        errorMsg = BaseCmd.USER_ERROR_MESSAGE;
      }
      throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, errorMsg, ex);
    } catch (ResourceUnavailableException ex) {
      s_logger.info(ex.getMessage());
      String errorMsg = ex.getMessage();
      if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) {
        // hide internal details to non-admin user for security reason
        errorMsg = BaseCmd.USER_ERROR_MESSAGE;
      }
      throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, errorMsg, ex);
    } catch (AsyncCommandQueued ex) {
      s_logger.error(
          "unhandled exception executing api command: " + ((command == null) ? "null" : command[0]),
          ex);
      throw new ServerApiException(
          ApiErrorCode.INTERNAL_ERROR, "Internal server error, unable to execute request.");
    } catch (ServerApiException ex) {
      s_logger.info(ex.getDescription());
      throw ex;
    } catch (Exception ex) {
      s_logger.error(
          "unhandled exception executing api command: " + ((command == null) ? "null" : command[0]),
          ex);
      String errorMsg = ex.getMessage();
      if (UserContext.current().getCaller().getType() != Account.ACCOUNT_TYPE_ADMIN) {
        // hide internal details to non-admin user for security reason
        errorMsg = BaseCmd.USER_ERROR_MESSAGE;
      }
      throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg, ex);
    }

    return response;
  }