/**
  * runs all filters of the filterType sType/ Use this method within filters to run custom filters
  * by type
  *
  * @param sType the filterType.
  * @return
  * @throws Throwable throws up an arbitrary exception
  */
 public Object runFilters(String sType) throws Throwable {
   if (RequestContext.getCurrentContext().debugRouting()) {
     Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
   }
   boolean bResult = false;
   List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
   if (list != null) {
     for (int i = 0; i < list.size(); i++) {
       ZuulFilter zuulFilter = list.get(i);
       Object result = processZuulFilter(zuulFilter);
       if (result != null && result instanceof Boolean) {
         bResult |= ((Boolean) result);
       }
     }
   }
   return bResult;
 }
  /**
   * Processes an individual ZuulFilter. This method adds Debug information. Any uncaught Thowables
   * are caught by this method and converted to a ZuulException with a 500 status code.
   *
   * @param filter
   * @return the return value for that filter
   * @throws ZuulException
   */
  public Object processZuulFilter(ZuulFilter filter) throws ZuulException {

    RequestContext ctx = RequestContext.getCurrentContext();
    boolean bDebug = ctx.debugRouting();
    final String metricPrefix = "zuul.filter-";
    long execTime = 0;
    String filterName = "";
    try {
      long ltime = System.currentTimeMillis();
      filterName = filter.getClass().getSimpleName();

      RequestContext copy = null;
      Object o = null;
      Throwable t = null;

      if (bDebug) {
        Debug.addRoutingDebug(
            "Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);
        copy = ctx.copy();
      }

      ZuulFilterResult result = filter.runFilter();
      ExecutionStatus s = result.getStatus();
      execTime = System.currentTimeMillis() - ltime;

      switch (s) {
        case FAILED:
          t = result.getException();
          ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
          break;
        case SUCCESS:
          o = result.getResult();
          ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);
          if (bDebug) {
            Debug.addRoutingDebug(
                "Filter {"
                    + filterName
                    + " TYPE:"
                    + filter.filterType()
                    + " ORDER:"
                    + filter.filterOrder()
                    + "} Execution time = "
                    + execTime
                    + "ms");
            Debug.compareContextState(filterName, copy);
          }
          break;
        default:
          break;
      }

      if (t != null) throw t;

      usageNotifier.notify(filter, s);
      return o;

    } catch (Throwable e) {
      if (bDebug) {
        Debug.addRoutingDebug(
            "Running Filter failed "
                + filterName
                + " type:"
                + filter.filterType()
                + " order:"
                + filter.filterOrder()
                + " "
                + e.getMessage());
      }
      usageNotifier.notify(filter, ExecutionStatus.FAILED);
      if (e instanceof ZuulException) {
        throw (ZuulException) e;
      } else {
        ZuulException ex =
            new ZuulException(
                e, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);
        ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
        throw ex;
      }
    }
  }