@Override
  public String getRouteStatsAsXml(
      String routeId, String camelContextName, boolean fullStats, boolean includeProcessors)
      throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      String pattern =
          String.format(
              "%s:context=%s,type=routes,name=\"%s\"",
              found.getDomain(), found.getKeyProperty("context"), routeId);
      ObjectName on = ObjectName.getInstance(pattern);
      J4pExecResponse response =
          jolokia.execute(
              new J4pExecRequest(
                  on, "dumpRouteStatsAsXml(boolean,boolean)", fullStats, includeProcessors));
      if (response != null) {
        String xml = response.getValue();
        return xml;
      }
    }

    return null;
  }
  @Override
  public List<Map<String, String>> getEndpointRuntimeStatistics(String camelContextName)
      throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      String pattern =
          String.format(
              "%s:context=%s,type=services,name=DefaultRuntimeEndpointRegistry",
              found.getDomain(), found.getKeyProperty("context"));
      ObjectName on = ObjectName.getInstance(pattern);

      J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "endpointStatistics()"));
      if (response != null) {
        JSONObject data = response.getValue();
        for (Object obj : data.values()) {
          JSONObject data2 = (JSONObject) obj;
          JSONObject service = (JSONObject) data2.values().iterator().next();

          Map<String, String> row = new LinkedHashMap<String, String>();
          row.put("index", asString(service.get("index")));
          row.put("url", asString(service.get("url")));
          row.put("routeId", asString(service.get("routeId")));
          row.put("direction", asString(service.get("direction")));
          row.put("static", asString(service.get("static")));
          row.put("dynamic", asString(service.get("dynamic")));
          row.put("hits", asString(service.get("hits")));
          answer.add(row);
        }
      }

      // sort the list
      Collections.sort(
          answer,
          new Comparator<Map<String, String>>() {
            @Override
            public int compare(Map<String, String> endpoint1, Map<String, String> endpoint2) {
              // sort by route id
              String route1 = endpoint1.get("routeId");
              String route2 = endpoint2.get("routeId");
              int num = route1.compareTo(route2);
              if (num == 0) {
                // we want in before out
                String dir1 = endpoint1.get("direction");
                String dir2 = endpoint2.get("direction");
                num = dir1.compareTo(dir2);
              }
              return num;
            }
          });
    }

    return answer;
  }
  @Override
  public List<Map<String, String>> getRestServices(String camelContextName) throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      String pattern =
          String.format(
              "%s:context=%s,type=services,name=DefaultRestRegistry",
              found.getDomain(), found.getKeyProperty("context"));
      ObjectName on = ObjectName.getInstance(pattern);

      J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "listRestServices()"));
      if (response != null) {
        JSONObject data = response.getValue();
        if (data != null) {
          for (Object obj : data.values()) {
            JSONObject data2 = (JSONObject) obj;
            JSONObject service = (JSONObject) data2.values().iterator().next();

            Map<String, String> row = new LinkedHashMap<String, String>();
            row.put("basePath", asString(service.get("basePath")));
            row.put("baseUrl", asString(service.get("baseUrl")));
            row.put("consumes", asString(service.get("consumes")));
            row.put("description", asString(service.get("description")));
            row.put("inType", asString(service.get("inType")));
            row.put("method", asString(service.get("method")));
            row.put("outType", asString(service.get("outType")));
            row.put("produces", asString(service.get("produces")));
            row.put("routeId", asString(service.get("routeId")));
            row.put("state", asString(service.get("state")));
            row.put("uriTemplate", asString(service.get("uriTemplate")));
            row.put("url", asString(service.get("url")));
            answer.add(row);
          }
        }
      }

      // sort the list
      Collections.sort(
          answer,
          new Comparator<Map<String, String>>() {
            @Override
            public int compare(Map<String, String> service1, Map<String, String> service2) {
              String url1 = service1.get("url");
              String url2 = service2.get("url");
              return url1.compareTo(url2);
            }
          });
    }

    return answer;
  }
  @Override
  public String getRestModelAsXml(String camelContextName) throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      J4pExecResponse response = jolokia.execute(new J4pExecRequest(found, "dumpRestsAsXml()"));
      if (response != null) {
        String xml = response.getValue();
        return xml;
      }
    }

    return null;
  }
  @Override
  public List<Map<String, String>> listComponents(String camelContextName) throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      J4pExecResponse response = jolokia.execute(new J4pExecRequest(found, "listComponents()"));
      if (response != null) {
        JSONObject data = response.getValue();
        for (Object obj : data.values()) {
          JSONObject component = (JSONObject) obj;

          Map<String, String> row = new LinkedHashMap<String, String>();
          row.put("artifactId", asString(component.get("artifactId")));
          row.put("title", asString(component.get("title")));
          row.put("description", asString(component.get("description")));
          row.put("groupId", asString(component.get("groupId")));
          row.put("label", asString(component.get("label")));
          row.put("name", asString(component.get("name")));
          row.put("status", asString(component.get("status")));
          row.put("type", asString(component.get("type")));
          row.put("version", asString(component.get("version")));
          answer.add(row);
        }
      }

      // sort the list
      Collections.sort(
          answer,
          new Comparator<Map<String, String>>() {
            @Override
            public int compare(Map<String, String> component1, Map<String, String> component2) {
              String name1 = component1.get("name");
              String name2 = component2.get("name");
              return name1.compareTo(name2);
            }
          });
    }

    return answer;
  }
  @Override
  public String explainEipAsJSon(String camelContextName, String nameOrId, boolean allOptions)
      throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      J4pExecResponse response =
          jolokia.execute(
              new J4pExecRequest(
                  found, "explainEipJson(java.lang.String,boolean)", nameOrId, allOptions));
      if (response != null) {
        String json = response.getValue();
        return json;
      }
    }

    return null;
  }
  @Override
  public String getCamelContextStatsAsXml(
      String camelContextName, boolean fullStats, boolean includeProcessors) throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      J4pExecResponse er =
          jolokia.execute(
              new J4pExecRequest(
                  found, "dumpRoutesStatsAsXml(boolean,boolean)", fullStats, includeProcessors));
      if (er != null) {
        String xml = er.getValue();
        return xml;
      }
    }

    return null;
  }
  @Override
  public List<Map<String, Object>> browseInflightExchanges(
      String camelContextName, int limit, boolean sortByLongestDuration) throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    List<Map<String, Object>> answer = new ArrayList<Map<String, Object>>();

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      String pattern =
          String.format(
              "%s:context=%s,type=services,name=DefaultInflightRepository",
              found.getDomain(), found.getKeyProperty("context"));
      ObjectName on = ObjectName.getInstance(pattern);
      J4pExecResponse er =
          jolokia.execute(
              new J4pExecRequest(on, "browse(int,boolean)", limit, sortByLongestDuration));
      if (er != null) {
        JSONObject data = er.getValue();
        if (data != null) {
          for (Object obj : data.values()) {
            JSONObject inflight = (JSONObject) obj;

            Map<String, Object> row = new LinkedHashMap<String, Object>();
            row.put("exchangeId", asString(inflight.get("exchangeId")));
            row.put("fromRouteId", asString(inflight.get("fromRouteId")));
            row.put("routeId", asString(inflight.get("routeId")));
            row.put("nodeId", asString(inflight.get("nodeId")));
            row.put("elapsed", asString(inflight.get("elapsed")));
            row.put("duration", asString(inflight.get("duration")));
            answer.add(row);
          }
        }
      }
    }

    return answer;
  }
  @Override
  public String getRestApiDocAsJson(String camelContextName) throws Exception {
    if (jolokia == null) {
      throw new IllegalStateException("Need to connect to remote jolokia first");
    }

    ObjectName found = lookupCamelContext(camelContextName);
    if (found != null) {
      String pattern =
          String.format(
              "%s:context=%s,type=services,name=DefaultRestRegistry",
              found.getDomain(), found.getKeyProperty("context"));
      ObjectName on = ObjectName.getInstance(pattern);

      J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "apiDocAsJson()"));
      if (response != null) {
        String json = response.getValue();
        return json;
      }
    }

    return null;
  }