CAMEL-8041: Camel commands should be reusable.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/796aa092 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/796aa092 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/796aa092 Branch: refs/heads/master Commit: 796aa09281461c90291f41406027dd8360fbc8f9 Parents: cfb04fd Author: Claus Ibsen <davscl...@apache.org> Authored: Thu Nov 13 10:21:31 2014 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Thu Nov 13 10:21:31 2014 +0100 ---------------------------------------------------------------------- .../camel/commands/EndpointExplainCommand.java | 132 +++++++++++ .../camel/commands/EndpointListCommand.java | 230 +++++++++++++++++++ .../camel/commands/RestRegistryListCommand.java | 203 ++++++++++++++++ .../apache/camel/commands/RestShowCommand.java | 46 ++++ .../apache/camel/commands/RouteInfoCommand.java | 141 ++++++++++++ .../camel/karaf/commands/EndpointExplain.java | 102 +------- .../camel/karaf/commands/EndpointList.java | 197 +--------------- .../camel/karaf/commands/RestRegistryList.java | 172 +------------- .../apache/camel/karaf/commands/RestShow.java | 18 +- .../apache/camel/karaf/commands/RouteInfo.java | 123 +--------- .../OSGI-INF/blueprint/camel-commands.xml | 1 + 11 files changed, 776 insertions(+), 589 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointExplainCommand.java ---------------------------------------------------------------------- diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointExplainCommand.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointExplainCommand.java new file mode 100644 index 0000000..9709428 --- /dev/null +++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointExplainCommand.java @@ -0,0 +1,132 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.commands; + +import java.io.PrintStream; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.camel.Endpoint; +import org.apache.camel.util.EndpointHelper; +import org.apache.camel.util.JsonSchemaHelper; +import org.apache.camel.util.URISupport; + +public class EndpointExplainCommand extends AbstractCamelCommand { + + private String name; + private boolean verbose; + private String filter; + + public EndpointExplainCommand(String name, boolean verbose, String filter) { + this.name = name; + this.verbose = verbose; + this.filter = filter; + } + + @Override + public Object execute(CamelController camelController, PrintStream out, PrintStream err) throws Exception { + List<Endpoint> endpoints = camelController.getEndpoints(name); + if (endpoints == null || endpoints.isEmpty()) { + return null; + } + + // filter endpoints + if (filter != null) { + Iterator<Endpoint> it = endpoints.iterator(); + while (it.hasNext()) { + Endpoint endpoint = it.next(); + if (!EndpointHelper.matchPattern(endpoint.getEndpointUri(), filter)) { + // did not match + it.remove(); + } + } + } + + for (Endpoint endpoint : endpoints) { + String json = camelController.explainEndpoint(endpoint.getCamelContext().getName(), endpoint.getEndpointUri(), verbose); + + out.println("Context:\t" + endpoint.getCamelContext().getName()); + + // sanitize and mask uri so we dont see passwords + String uri = URISupport.sanitizeUri(endpoint.getEndpointUri()); + String header = "Uri: " + uri; + out.println(header); + for (int i = 0; i < header.length(); i++) { + out.print('-'); + } + out.println(); + + // use a basic json parser + List<Map<String, String>> options = JsonSchemaHelper.parseJsonSchema("properties", json, true); + + // lets sort the options by name + Collections.sort(options, new Comparator<Map<String, String>>() { + @Override + public int compare(Map<String, String> o1, Map<String, String> o2) { + // sort by kind first (need to -1 as we want path on top), then name + int answer = -1 * o1.get("kind").compareTo(o2.get("kind")); + if (answer == 0) { + answer = o1.get("name").compareTo(o2.get("name")); + } + return answer; + } + }); + + for (Map<String, String> option : options) { + out.print("Option:\t\t"); + out.println(option.get("name")); + out.print("Kind:\t\t"); + out.println(option.get("kind")); + String type = option.get("type"); + if (type != null) { + out.print("Type:\t\t"); + out.println(type); + } + String javaType = option.get("javaType"); + if (javaType != null) { + out.print("Java Type:\t"); + out.println(javaType); + } + String value = option.get("value"); + if (value != null) { + out.print("Value:\t\t"); + out.println(value); + } + String defaultValue = option.get("defaultValue"); + if (defaultValue != null) { + out.print("Default Value:\t"); + out.println(defaultValue); + } + String description = option.get("description"); + if (description != null) { + out.print("Description:\t"); + out.println(description); + } + out.println(); + } + + if (options.isEmpty()) { + out.println(); + } + } + + return null; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointListCommand.java ---------------------------------------------------------------------- diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointListCommand.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointListCommand.java new file mode 100644 index 0000000..8bb99e2 --- /dev/null +++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/EndpointListCommand.java @@ -0,0 +1,230 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.commands; + +import java.io.PrintStream; +import java.net.URLDecoder; +import java.util.Collections; +import java.util.Comparator; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.apache.camel.Endpoint; +import org.apache.camel.ServiceStatus; +import org.apache.camel.StatefulService; +import org.apache.camel.util.JsonSchemaHelper; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.URISupport; + +public class EndpointListCommand extends AbstractCamelCommand { + + private static final String CONTEXT_COLUMN_LABEL = "Context"; + private static final String URI_COLUMN_LABEL = "Uri"; + private static final String STATUS_COLUMN_LABEL = "Status"; + + private static final int DEFAULT_COLUMN_WIDTH_INCREMENT = 0; + private static final String DEFAULT_FIELD_PREAMBLE = " "; + private static final String DEFAULT_FIELD_POSTAMBLE = " "; + private static final String DEFAULT_HEADER_PREAMBLE = " "; + private static final String DEFAULT_HEADER_POSTAMBLE = " "; + private static final int DEFAULT_FORMAT_BUFFER_LENGTH = 24; + // endpoint uris can be very long so clip by default after 120 chars + private static final int MAX_COLUMN_WIDTH = 120; + private static final int MIN_COLUMN_WIDTH = 12; + + String name; + boolean decode = true; + boolean verbose; + boolean explain; + + public EndpointListCommand(String name, boolean decode, boolean verbose, boolean explain) { + this.name = name; + this.decode = decode; + this.verbose = verbose; + this.explain = explain; + } + + @Override + public Object execute(CamelController camelController, PrintStream out, PrintStream err) throws Exception { + List<Endpoint> endpoints = camelController.getEndpoints(name); + + final Map<String, Integer> columnWidths = computeColumnWidths(endpoints); + final String headerFormat = buildFormatString(columnWidths, true); + final String rowFormat = buildFormatString(columnWidths, false); + + if (endpoints.size() > 0) { + out.println(String.format(headerFormat, CONTEXT_COLUMN_LABEL, URI_COLUMN_LABEL, STATUS_COLUMN_LABEL)); + out.println(String.format(headerFormat, "-------", "---", "------")); + for (final Endpoint endpoint : endpoints) { + String contextId = endpoint.getCamelContext().getName(); + String uri = endpoint.getEndpointUri(); + if (decode) { + // decode uri so its more human readable + uri = URLDecoder.decode(uri, "UTF-8"); + } + // sanitize and mask uri so we dont see passwords + uri = URISupport.sanitizeUri(uri); + String state = getEndpointState(endpoint); + out.println(String.format(rowFormat, contextId, uri, state)); + + if (explain) { + boolean first = true; + String json = camelController.explainEndpoint(endpoint.getCamelContext().getName(), endpoint.getEndpointUri(), verbose); + // use a basic json parser + List<Map<String, String>> options = JsonSchemaHelper.parseJsonSchema("properties", json, true); + + // lets sort the options by name + Collections.sort(options, new Comparator<Map<String, String>>() { + @Override + public int compare(Map<String, String> o1, Map<String, String> o2) { + // sort by kind first (need to -1 as we want path on top), then name + int answer = -1 * o1.get("kind").compareTo(o2.get("kind")); + if (answer == 0) { + answer = o1.get("name").compareTo(o2.get("name")); + } + return answer; + } + }); + + for (Map<String, String> option : options) { + String key = option.get("name"); + String kind = option.get("kind"); + String type = option.get("type"); + String javaType = option.get("javaType"); + String value = option.get("value"); + if (ObjectHelper.isEmpty(value)) { + value = option.get("defaultValue"); + } + String desc = option.get("description"); + if (key != null && value != null) { + if (first) { + out.println(); + first = false; + } + String line; + if ("path".equals(kind)) { + line = "\t" + key + " (endpoint path) = " + value; + } else { + line = "\t" + key + " = " + value; + } + out.println(String.format(rowFormat, "", line, "")); + + if (type != null) { + String displayType = type; + if (javaType != null && !displayType.equals(javaType)) { + displayType = type + " (" + javaType + ")"; + } + out.println(String.format(rowFormat, "", "\t" + displayType, "")); + } + if (desc != null) { + // TODO: split desc in multi lines so it does not overflow + out.println(String.format(rowFormat, "", "\t" + desc, "")); + } + out.println(); + } + } + } + } + } + + return null; + } + + private Map<String, Integer> computeColumnWidths(final Iterable<Endpoint> endpoints) throws Exception { + if (endpoints == null) { + throw new IllegalArgumentException("Unable to determine column widths from null Iterable<Endpoint>"); + } else { + int maxContextLen = 0; + int maxUriLen = 0; + int maxStatusLen = 0; + + for (final Endpoint endpoint : endpoints) { + final String name = endpoint.getCamelContext().getName(); + maxContextLen = java.lang.Math.max(maxContextLen, name == null ? 0 : name.length()); + + String uri = endpoint.getEndpointUri(); + if (decode) { + // decode uri so its more human readable + uri = URLDecoder.decode(uri, "UTF-8"); + } + // sanitize and mask uri so we dont see passwords + uri = URISupport.sanitizeUri(uri); + + maxUriLen = java.lang.Math.max(maxUriLen, uri == null ? 0 : uri.length()); + + final String status = getEndpointState(endpoint); + maxStatusLen = java.lang.Math.max(maxStatusLen, status == null ? 0 : status.length()); + } + + final Map<String, Integer> retval = new Hashtable<String, Integer>(3); + retval.put(CONTEXT_COLUMN_LABEL, maxContextLen); + retval.put(URI_COLUMN_LABEL, maxUriLen); + retval.put(STATUS_COLUMN_LABEL, maxStatusLen); + + return retval; + } + } + + private String buildFormatString(final Map<String, Integer> columnWidths, final boolean isHeader) { + final String fieldPreamble; + final String fieldPostamble; + final int columnWidthIncrement; + + if (isHeader) { + fieldPreamble = DEFAULT_HEADER_PREAMBLE; + fieldPostamble = DEFAULT_HEADER_POSTAMBLE; + } else { + fieldPreamble = DEFAULT_FIELD_PREAMBLE; + fieldPostamble = DEFAULT_FIELD_POSTAMBLE; + } + columnWidthIncrement = DEFAULT_COLUMN_WIDTH_INCREMENT; + + int contextLen = java.lang.Math.min(columnWidths.get(CONTEXT_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + int uriLen = java.lang.Math.min(columnWidths.get(URI_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + int statusLen = java.lang.Math.min(columnWidths.get(STATUS_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + contextLen = Math.max(MIN_COLUMN_WIDTH, contextLen); + uriLen = Math.max(MIN_COLUMN_WIDTH, uriLen); + // last row does not have min width + + final StringBuilder retval = new StringBuilder(DEFAULT_FORMAT_BUFFER_LENGTH); + retval.append(fieldPreamble).append("%-").append(contextLen).append('.').append(contextLen).append('s').append(fieldPostamble).append(' '); + retval.append(fieldPreamble).append("%-").append(uriLen).append('.').append(uriLen).append('s').append(fieldPostamble).append(' '); + retval.append(fieldPreamble).append("%-").append(statusLen).append('.').append(statusLen).append('s').append(fieldPostamble).append(' '); + + return retval.toString(); + } + + private int getMaxColumnWidth() { + if (verbose) { + return Integer.MAX_VALUE; + } else { + return MAX_COLUMN_WIDTH; + } + } + + private static String getEndpointState(Endpoint endpoint) { + // must use String type to be sure remote JMX can read the attribute without requiring Camel classes. + if (endpoint instanceof StatefulService) { + ServiceStatus status = ((StatefulService) endpoint).getStatus(); + return status.name(); + } + + // assume started if not a ServiceSupport instance + return ServiceStatus.Started.name(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestRegistryListCommand.java ---------------------------------------------------------------------- diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestRegistryListCommand.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestRegistryListCommand.java new file mode 100644 index 0000000..6dec7fa --- /dev/null +++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestRegistryListCommand.java @@ -0,0 +1,203 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.commands; + +import java.io.PrintStream; +import java.net.URLDecoder; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.apache.camel.spi.RestRegistry; +import org.apache.camel.util.URISupport; + +public class RestRegistryListCommand extends AbstractCamelCommand { + + private static final String CONTEXT_COLUMN_LABEL = "Context"; + private static final String URL_COLUMN_NAME = "Url"; + private static final String BASE_PATH_LABEL = "Base Path"; + private static final String URI_TEMPLATE_LABEL = "Uri Template"; + private static final String METHOD_COLUMN_LABEL = "Method"; + private static final String STATE_COLUMN_LABEL = "State"; + + private static final int DEFAULT_COLUMN_WIDTH_INCREMENT = 0; + private static final String DEFAULT_FIELD_PREAMBLE = " "; + private static final String DEFAULT_FIELD_POSTAMBLE = " "; + private static final String DEFAULT_HEADER_PREAMBLE = " "; + private static final String DEFAULT_HEADER_POSTAMBLE = " "; + private static final int DEFAULT_FORMAT_BUFFER_LENGTH = 24; + // endpoint uris can be very long so clip by default after 120 chars + private static final int MAX_COLUMN_WIDTH = 120; + private static final int MIN_COLUMN_WIDTH = 12; + + String name; + Boolean decode = true; + Boolean verbose = false; + + public RestRegistryListCommand(String name, Boolean decode, Boolean verbose) { + this.name = name; + this.decode = decode; + this.verbose = verbose; + } + + @Override + public Object execute(CamelController camelController, PrintStream out, PrintStream err) throws Exception { + Map<String, List<RestRegistry.RestService>> services = camelController.getRestServices(name); + if (services.isEmpty()) { + out.print("There are no REST services"); + return null; + } + + final Map<String, Integer> columnWidths = computeColumnWidths(services); + final String headerFormat = buildFormatString(columnWidths, true, verbose); + final String rowFormat = buildFormatString(columnWidths, false, verbose); + + if (services.size() > 0) { + if (verbose) { + out.println(String.format(headerFormat, CONTEXT_COLUMN_LABEL, URL_COLUMN_NAME, BASE_PATH_LABEL, URI_TEMPLATE_LABEL, METHOD_COLUMN_LABEL, STATE_COLUMN_LABEL)); + out.println(String.format(headerFormat, "-------", "---", "---------", "------------", "------", "-----")); + } else { + out.println(String.format(headerFormat, CONTEXT_COLUMN_LABEL, BASE_PATH_LABEL, URI_TEMPLATE_LABEL, METHOD_COLUMN_LABEL, STATE_COLUMN_LABEL)); + out.println(String.format(headerFormat, "-------", "---------", "------------", "------", "-----")); + } + for (Map.Entry<String, List<RestRegistry.RestService>> entry : services.entrySet()) { + String contextName = entry.getKey(); + for (final RestRegistry.RestService service : entry.getValue()) { + String contextId = contextName; + + String uri = null; + if (verbose) { + uri = service.getUrl(); + if (decode == null || decode) { + // decode uri so its more human readable + uri = URLDecoder.decode(uri, "UTF-8"); + } + // sanitize and mask uri so we dont see passwords + uri = URISupport.sanitizeUri(uri); + } + String basePath = service.getBasePath(); + String uriTemplate = service.getUriTemplate() != null ? service.getUriTemplate() : ""; + String method = service.getMethod(); + String state = service.getState(); + if (verbose) { + out.println(String.format(rowFormat, contextId, uri, basePath, uriTemplate, method, state)); + } else { + out.println(String.format(rowFormat, contextId, basePath, uriTemplate, method, state)); + } + } + } + } + + return null; + } + + private Map<String, Integer> computeColumnWidths(Map<String, List<RestRegistry.RestService>> services) throws Exception { + int maxContextLen = 0; + int maxUriLen = 0; + int maxBasePathLen = 0; + int maxUriTemplateLen = 0; + int maxMethodLen = 0; + int maxStatusLen = 0; + + for (Map.Entry<String, List<RestRegistry.RestService>> entry : services.entrySet()) { + String contextName = entry.getKey(); + for (final RestRegistry.RestService service : entry.getValue()) { + maxContextLen = Math.max(maxContextLen, contextName == null ? 0 : contextName.length()); + + String uri = service.getUrl(); + if (decode == null || decode) { + // decode uri so its more human readable + uri = URLDecoder.decode(uri, "UTF-8"); + } + // sanitize and mask uri so we dont see passwords + uri = URISupport.sanitizeUri(uri); + maxUriLen = Math.max(maxUriLen, uri == null ? 0 : uri.length()); + + String basePath = service.getBasePath(); + maxBasePathLen = Math.max(maxBasePathLen, basePath == null ? 0 : basePath.length()); + + String uriTemplate = service.getUriTemplate(); + maxUriTemplateLen = Math.max(maxUriTemplateLen, uriTemplate == null ? 0 : uriTemplate.length()); + + String method = service.getMethod(); + maxMethodLen = Math.max(maxMethodLen, method == null ? 0 : method.length()); + + String status = service.getState(); + maxStatusLen = Math.max(maxStatusLen, status == null ? 0 : status.length()); + } + } + + final Map<String, Integer> retval = new Hashtable<String, Integer>(6); + retval.put(CONTEXT_COLUMN_LABEL, maxContextLen); + retval.put(URL_COLUMN_NAME, maxUriLen); + retval.put(BASE_PATH_LABEL, maxBasePathLen); + retval.put(URI_TEMPLATE_LABEL, maxUriTemplateLen); + retval.put(METHOD_COLUMN_LABEL, maxMethodLen); + retval.put(STATE_COLUMN_LABEL, maxStatusLen); + + return retval; + } + + private String buildFormatString(final Map<String, Integer> columnWidths, final boolean isHeader, final boolean isVerbose) { + final String fieldPreamble; + final String fieldPostamble; + final int columnWidthIncrement; + + if (isHeader) { + fieldPreamble = DEFAULT_HEADER_PREAMBLE; + fieldPostamble = DEFAULT_HEADER_POSTAMBLE; + } else { + fieldPreamble = DEFAULT_FIELD_PREAMBLE; + fieldPostamble = DEFAULT_FIELD_POSTAMBLE; + } + columnWidthIncrement = DEFAULT_COLUMN_WIDTH_INCREMENT; + + int contextLen = Math.min(columnWidths.get(CONTEXT_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + int uriLen = Math.min(columnWidths.get(URL_COLUMN_NAME) + columnWidthIncrement, getMaxColumnWidth()); + int basePathLen = Math.min(columnWidths.get(BASE_PATH_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + int uriTemplateLen = Math.min(columnWidths.get(URI_TEMPLATE_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + int methodLen = Math.min(columnWidths.get(METHOD_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + int statusLen = Math.min(columnWidths.get(STATE_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); + contextLen = Math.max(MIN_COLUMN_WIDTH, contextLen); + basePathLen = Math.max(MIN_COLUMN_WIDTH, basePathLen); + uriLen = Math.max(MIN_COLUMN_WIDTH, uriLen); + uriTemplateLen = Math.max(MIN_COLUMN_WIDTH, uriTemplateLen); + methodLen = Math.max(MIN_COLUMN_WIDTH, methodLen); + + // last row does not have min width + + final StringBuilder retval = new StringBuilder(DEFAULT_FORMAT_BUFFER_LENGTH); + retval.append(fieldPreamble).append("%-").append(contextLen).append('.').append(contextLen).append('s').append(fieldPostamble).append(' '); + if (isVerbose) { + retval.append(fieldPreamble).append("%-").append(uriLen).append('.').append(uriLen).append('s').append(fieldPostamble).append(' '); + } + retval.append(fieldPreamble).append("%-").append(basePathLen).append('.').append(basePathLen).append('s').append(fieldPostamble).append(' '); + retval.append(fieldPreamble).append("%-").append(uriTemplateLen).append('.').append(uriTemplateLen).append('s').append(fieldPostamble).append(' '); + retval.append(fieldPreamble).append("%-").append(methodLen).append('.').append(methodLen).append('s').append(fieldPostamble).append(' '); + retval.append(fieldPreamble).append("%-").append(statusLen).append('.').append(statusLen).append('s').append(fieldPostamble).append(' '); + + return retval.toString(); + } + + private int getMaxColumnWidth() { + if (verbose != null && verbose) { + return Integer.MAX_VALUE; + } else { + return MAX_COLUMN_WIDTH; + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestShowCommand.java ---------------------------------------------------------------------- diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestShowCommand.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestShowCommand.java new file mode 100644 index 0000000..889246d --- /dev/null +++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RestShowCommand.java @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.commands; + +import java.io.PrintStream; +import java.util.List; + +import org.apache.camel.CamelContext; +import org.apache.camel.model.ModelHelper; +import org.apache.camel.model.rest.RestDefinition; +import org.apache.camel.model.rest.RestsDefinition; + +public class RestShowCommand extends AbstractContextCommand { + + public RestShowCommand(String context) { + super(context); + } + + @Override + protected Object performContextCommand(CamelController camelController, CamelContext camelContext, PrintStream out, PrintStream err) throws Exception { + List<RestDefinition> rests = camelController.getRestDefinitions(context); + if (rests == null || rests.isEmpty()) { + out.print("There are no REST services in CamelContext with name: " + context); + return null; + } + // use a routes definition to dump the rests + RestsDefinition def = new RestsDefinition(); + def.setRests(rests); + out.println(ModelHelper.dumpModelAsXml(def)); + return null; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RouteInfoCommand.java ---------------------------------------------------------------------- diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RouteInfoCommand.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RouteInfoCommand.java new file mode 100644 index 0000000..288a2ff --- /dev/null +++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/RouteInfoCommand.java @@ -0,0 +1,141 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.commands; + +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.camel.CamelContext; +import org.apache.camel.Route; +import org.apache.camel.model.ModelHelper; +import org.apache.camel.model.RouteDefinition; +import org.apache.camel.spi.ManagementAgent; + +public class RouteInfoCommand extends AbstractRouteCommand { + + private StringEscape stringEscape; + + public RouteInfoCommand(String route, String context) { + super(route, context); + } + + /** + * Sets the {@link org.apache.camel.commands.StringEscape} to use. + */ + public void setStringEscape(StringEscape stringEscape) { + this.stringEscape = stringEscape; + } + + @Override + public void executeOnRoute(CamelController camelController, CamelContext camelContext, Route camelRoute, PrintStream out, PrintStream err) throws Exception { + out.println(stringEscape.unescapeJava("\u001B[1m\u001B[33mCamel Route " + camelRoute.getId() + "\u001B[0m")); + out.println(stringEscape.unescapeJava("\tCamel Context: " + camelRoute.getRouteContext().getCamelContext().getName())); + out.println(""); + out.println(stringEscape.unescapeJava("\u001B[1mProperties\u001B[0m")); + for (Map.Entry<String, Object> entry : camelRoute.getProperties().entrySet()) { + out.println(stringEscape.unescapeJava("\t" + entry.getKey() + " = " + entry.getValue())); + } + out.println(""); + out.println(stringEscape.unescapeJava("\u001B[1mStatistics\u001B[0m")); + if (camelContext != null) { + ManagementAgent agent = camelContext.getManagementStrategy().getManagementAgent(); + if (agent != null) { + MBeanServer mBeanServer = agent.getMBeanServer(); + Set<ObjectName> set = mBeanServer.queryNames(new ObjectName(agent.getMBeanObjectDomainName() + ":type=routes,name=\"" + camelRoute.getId() + "\",*"), null); + Iterator<ObjectName> iterator = set.iterator(); + if (iterator.hasNext()) { + ObjectName routeMBean = iterator.next(); + + // the route must be part of the camel context + String camelId = (String) mBeanServer.getAttribute(routeMBean, "CamelId"); + if (camelId != null && camelId.equals(camelContext.getName())) { + Integer inflightExchange = (Integer) mBeanServer.getAttribute(routeMBean, "InflightExchanges"); + out.println(stringEscape.unescapeJava("\tInflight Exchanges: " + inflightExchange)); + Long exchangesTotal = (Long) mBeanServer.getAttribute(routeMBean, "ExchangesTotal"); + out.println(stringEscape.unescapeJava("\tExchanges Total: " + exchangesTotal)); + Long exchangesCompleted = (Long) mBeanServer.getAttribute(routeMBean, "ExchangesCompleted"); + out.println(stringEscape.unescapeJava("\tExchanges Completed: " + exchangesCompleted)); + Long exchangesFailed = (Long) mBeanServer.getAttribute(routeMBean, "ExchangesFailed"); + out.println(stringEscape.unescapeJava("\tExchanges Failed: " + exchangesFailed)); + Long minProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "MinProcessingTime"); + out.println(stringEscape.unescapeJava("\tMin Processing Time: " + minProcessingTime + " ms")); + Long maxProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "MaxProcessingTime"); + out.println(stringEscape.unescapeJava("\tMax Processing Time: " + maxProcessingTime + " ms")); + Long meanProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "MeanProcessingTime"); + out.println(stringEscape.unescapeJava("\tMean Processing Time: " + meanProcessingTime + " ms")); + Long totalProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "TotalProcessingTime"); + out.println(stringEscape.unescapeJava("\tTotal Processing Time: " + totalProcessingTime + " ms")); + Long lastProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "LastProcessingTime"); + out.println(stringEscape.unescapeJava("\tLast Processing Time: " + lastProcessingTime + " ms")); + Long deltaProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "DeltaProcessingTime"); + out.println(stringEscape.unescapeJava("\tDelta Processing Time: " + deltaProcessingTime + " ms")); + String load01 = (String) mBeanServer.getAttribute(routeMBean, "Load01"); + String load05 = (String) mBeanServer.getAttribute(routeMBean, "Load05"); + String load15 = (String) mBeanServer.getAttribute(routeMBean, "Load15"); + out.println(stringEscape.unescapeJava("\tLoad Avg: " + load01 + ", " + load05 + ", " + load15)); + + // Test for null to see if a any exchanges have been processed first to avoid NPE + Object resetTimestampObj = mBeanServer.getAttribute(routeMBean, "ResetTimestamp"); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + if (resetTimestampObj == null) { + // Print an empty value for scripting + out.println(stringEscape.unescapeJava("\tReset Statistics Date:")); + } else { + Date firstExchangeTimestamp = (Date) resetTimestampObj; + out.println(stringEscape.unescapeJava("\tReset Statistics Date: " + format.format(firstExchangeTimestamp))); + } + + // Test for null to see if a any exchanges have been processed first to avoid NPE + Object firstExchangeTimestampObj = mBeanServer.getAttribute(routeMBean, "FirstExchangeCompletedTimestamp"); + if (firstExchangeTimestampObj == null) { + // Print an empty value for scripting + out.println(stringEscape.unescapeJava("\tFirst Exchange Date:")); + } else { + Date firstExchangeTimestamp = (Date) firstExchangeTimestampObj; + out.println(stringEscape.unescapeJava("\tFirst Exchange Date: " + format.format(firstExchangeTimestamp))); + } + + // Again, check for null to avoid NPE + Object lastExchangeCompletedTimestampObj = mBeanServer.getAttribute(routeMBean, "LastExchangeCompletedTimestamp"); + if (lastExchangeCompletedTimestampObj == null) { + // Print an empty value for scripting + out.println(stringEscape.unescapeJava("\tLast Exchange Completed Date:")); + } else { + Date lastExchangeCompletedTimestamp = (Date) lastExchangeCompletedTimestampObj; + out.println(stringEscape.unescapeJava("\tLast Exchange Completed Date: " + format.format(lastExchangeCompletedTimestamp))); + } + } + } + } else { + out.println(""); + out.println(stringEscape.unescapeJava("\u001B[31mJMX Agent of Camel is not reachable. Maybe it has been disabled on the Camel context")); + out.println(stringEscape.unescapeJava("In consequence, some statistics are not available.\u001B[0m")); + } + + out.println(""); + out.println(stringEscape.unescapeJava("\u001B[1mDefinition\u001B[0m")); + RouteDefinition definition = camelController.getRouteDefinition(camelRoute.getId(), camelRoute.getRouteContext().getCamelContext().getName()); + out.println(stringEscape.unescapeJava(ModelHelper.dumpModelAsXml(definition))); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointExplain.java ---------------------------------------------------------------------- diff --git a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointExplain.java b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointExplain.java index c950a20..b680aef 100644 --- a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointExplain.java +++ b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointExplain.java @@ -16,17 +16,7 @@ */ package org.apache.camel.karaf.commands; -import java.io.PrintStream; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.camel.Endpoint; -import org.apache.camel.util.EndpointHelper; -import org.apache.camel.util.JsonSchemaHelper; -import org.apache.camel.util.URISupport; +import org.apache.camel.commands.EndpointExplainCommand; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; import org.apache.felix.gogo.commands.Option; @@ -49,94 +39,8 @@ public class EndpointExplain extends CamelCommandSupport { String filter; protected Object doExecute() throws Exception { - List<Endpoint> endpoints = camelController.getEndpoints(name); - if (endpoints == null || endpoints.isEmpty()) { - return null; - } - - // filter endpoints - if (filter != null) { - Iterator<Endpoint> it = endpoints.iterator(); - while (it.hasNext()) { - Endpoint endpoint = it.next(); - if (!EndpointHelper.matchPattern(endpoint.getEndpointUri(), filter)) { - // did not match - it.remove(); - } - } - } - - final PrintStream out = System.out; - - for (Endpoint endpoint : endpoints) { - String json = camelController.explainEndpoint(endpoint.getCamelContext().getName(), endpoint.getEndpointUri(), verbose); - - out.println("Context:\t" + endpoint.getCamelContext().getName()); - - // sanitize and mask uri so we dont see passwords - String uri = URISupport.sanitizeUri(endpoint.getEndpointUri()); - String header = "Uri: " + uri; - out.println(header); - for (int i = 0; i < header.length(); i++) { - out.print('-'); - } - out.println(); - - // use a basic json parser - List<Map<String, String>> options = JsonSchemaHelper.parseJsonSchema("properties", json, true); - - // lets sort the options by name - Collections.sort(options, new Comparator<Map<String, String>>() { - @Override - public int compare(Map<String, String> o1, Map<String, String> o2) { - // sort by kind first (need to -1 as we want path on top), then name - int answer = -1 * o1.get("kind").compareTo(o2.get("kind")); - if (answer == 0) { - answer = o1.get("name").compareTo(o2.get("name")); - } - return answer; - } - }); - - for (Map<String, String> option : options) { - out.print("Option:\t\t"); - out.println(option.get("name")); - out.print("Kind:\t\t"); - out.println(option.get("kind")); - String type = option.get("type"); - if (type != null) { - out.print("Type:\t\t"); - out.println(type); - } - String javaType = option.get("javaType"); - if (javaType != null) { - out.print("Java Type:\t"); - out.println(javaType); - } - String value = option.get("value"); - if (value != null) { - out.print("Value:\t\t"); - out.println(value); - } - String defaultValue = option.get("defaultValue"); - if (defaultValue != null) { - out.print("Default Value:\t"); - out.println(defaultValue); - } - String description = option.get("description"); - if (description != null) { - out.print("Description:\t"); - out.println(description); - } - out.println(); - } - - if (options.isEmpty()) { - out.println(); - } - } - - return null; + EndpointExplainCommand command = new EndpointExplainCommand(name, verbose, filter); + return command.execute(camelController, System.out, System.err); } } http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointList.java ---------------------------------------------------------------------- diff --git a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointList.java b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointList.java index d39f2e0..3105ffa 100644 --- a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointList.java +++ b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/EndpointList.java @@ -16,20 +16,7 @@ */ package org.apache.camel.karaf.commands; -import java.io.PrintStream; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.Comparator; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; - -import org.apache.camel.Endpoint; -import org.apache.camel.ServiceStatus; -import org.apache.camel.StatefulService; -import org.apache.camel.util.JsonSchemaHelper; -import org.apache.camel.util.ObjectHelper; -import org.apache.camel.util.URISupport; +import org.apache.camel.commands.EndpointListCommand; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; import org.apache.felix.gogo.commands.Option; @@ -40,20 +27,6 @@ import org.apache.felix.gogo.commands.Option; @Command(scope = "camel", name = "endpoint-list", description = "Lists all Camel endpoints available in CamelContexts.") public class EndpointList extends CamelCommandSupport { - private static final String CONTEXT_COLUMN_LABEL = "Context"; - private static final String URI_COLUMN_LABEL = "Uri"; - private static final String STATUS_COLUMN_LABEL = "Status"; - - private static final int DEFAULT_COLUMN_WIDTH_INCREMENT = 0; - private static final String DEFAULT_FIELD_PREAMBLE = " "; - private static final String DEFAULT_FIELD_POSTAMBLE = " "; - private static final String DEFAULT_HEADER_PREAMBLE = " "; - private static final String DEFAULT_HEADER_POSTAMBLE = " "; - private static final int DEFAULT_FORMAT_BUFFER_LENGTH = 24; - // endpoint uris can be very long so clip by default after 120 chars - private static final int MAX_COLUMN_WIDTH = 120; - private static final int MIN_COLUMN_WIDTH = 12; - @Argument(index = 0, name = "name", description = "The Camel context name where to look for the endpoints", required = false, multiValued = false) String name; @@ -70,172 +43,8 @@ public class EndpointList extends CamelCommandSupport { boolean explain; protected Object doExecute() throws Exception { - List<Endpoint> endpoints = camelController.getEndpoints(name); - - final Map<String, Integer> columnWidths = computeColumnWidths(endpoints); - final String headerFormat = buildFormatString(columnWidths, true); - final String rowFormat = buildFormatString(columnWidths, false); - final PrintStream out = System.out; - - if (endpoints.size() > 0) { - out.println(String.format(headerFormat, CONTEXT_COLUMN_LABEL, URI_COLUMN_LABEL, STATUS_COLUMN_LABEL)); - out.println(String.format(headerFormat, "-------", "---", "------")); - for (final Endpoint endpoint : endpoints) { - String contextId = endpoint.getCamelContext().getName(); - String uri = endpoint.getEndpointUri(); - if (decode) { - // decode uri so its more human readable - uri = URLDecoder.decode(uri, "UTF-8"); - } - // sanitize and mask uri so we dont see passwords - uri = URISupport.sanitizeUri(uri); - String state = getEndpointState(endpoint); - out.println(String.format(rowFormat, contextId, uri, state)); - - if (explain) { - boolean first = true; - String json = camelController.explainEndpoint(endpoint.getCamelContext().getName(), endpoint.getEndpointUri(), verbose); - // use a basic json parser - List<Map<String, String>> options = JsonSchemaHelper.parseJsonSchema("properties", json, true); - - // lets sort the options by name - Collections.sort(options, new Comparator<Map<String, String>>() { - @Override - public int compare(Map<String, String> o1, Map<String, String> o2) { - // sort by kind first (need to -1 as we want path on top), then name - int answer = -1 * o1.get("kind").compareTo(o2.get("kind")); - if (answer == 0) { - answer = o1.get("name").compareTo(o2.get("name")); - } - return answer; - } - }); - - for (Map<String, String> option : options) { - String key = option.get("name"); - String kind = option.get("kind"); - String type = option.get("type"); - String javaType = option.get("javaType"); - String value = option.get("value"); - if (ObjectHelper.isEmpty(value)) { - value = option.get("defaultValue"); - } - String desc = option.get("description"); - if (key != null && value != null) { - if (first) { - out.println(); - first = false; - } - String line; - if ("path".equals(kind)) { - line = "\t" + key + " (endpoint path) = " + value; - } else { - line = "\t" + key + " = " + value; - } - out.println(String.format(rowFormat, "", line, "")); - - if (type != null) { - String displayType = type; - if (javaType != null && !displayType.equals(javaType)) { - displayType = type + " (" + javaType + ")"; - } - out.println(String.format(rowFormat, "", "\t" + displayType, "")); - } - if (desc != null) { - // TODO: split desc in multi lines so it does not overflow - out.println(String.format(rowFormat, "", "\t" + desc, "")); - } - out.println(); - } - } - } - } - } - - return null; - } - - private Map<String, Integer> computeColumnWidths(final Iterable<Endpoint> endpoints) throws Exception { - if (endpoints == null) { - throw new IllegalArgumentException("Unable to determine column widths from null Iterable<Endpoint>"); - } else { - int maxContextLen = 0; - int maxUriLen = 0; - int maxStatusLen = 0; - - for (final Endpoint endpoint : endpoints) { - final String name = endpoint.getCamelContext().getName(); - maxContextLen = java.lang.Math.max(maxContextLen, name == null ? 0 : name.length()); - - String uri = endpoint.getEndpointUri(); - if (decode) { - // decode uri so its more human readable - uri = URLDecoder.decode(uri, "UTF-8"); - } - // sanitize and mask uri so we dont see passwords - uri = URISupport.sanitizeUri(uri); - - maxUriLen = java.lang.Math.max(maxUriLen, uri == null ? 0 : uri.length()); - - final String status = getEndpointState(endpoint); - maxStatusLen = java.lang.Math.max(maxStatusLen, status == null ? 0 : status.length()); - } - - final Map<String, Integer> retval = new Hashtable<String, Integer>(3); - retval.put(CONTEXT_COLUMN_LABEL, maxContextLen); - retval.put(URI_COLUMN_LABEL, maxUriLen); - retval.put(STATUS_COLUMN_LABEL, maxStatusLen); - - return retval; - } - } - - private String buildFormatString(final Map<String, Integer> columnWidths, final boolean isHeader) { - final String fieldPreamble; - final String fieldPostamble; - final int columnWidthIncrement; - - if (isHeader) { - fieldPreamble = DEFAULT_HEADER_PREAMBLE; - fieldPostamble = DEFAULT_HEADER_POSTAMBLE; - } else { - fieldPreamble = DEFAULT_FIELD_PREAMBLE; - fieldPostamble = DEFAULT_FIELD_POSTAMBLE; - } - columnWidthIncrement = DEFAULT_COLUMN_WIDTH_INCREMENT; - - int contextLen = java.lang.Math.min(columnWidths.get(CONTEXT_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - int uriLen = java.lang.Math.min(columnWidths.get(URI_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - int statusLen = java.lang.Math.min(columnWidths.get(STATUS_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - contextLen = Math.max(MIN_COLUMN_WIDTH, contextLen); - uriLen = Math.max(MIN_COLUMN_WIDTH, uriLen); - // last row does not have min width - - final StringBuilder retval = new StringBuilder(DEFAULT_FORMAT_BUFFER_LENGTH); - retval.append(fieldPreamble).append("%-").append(contextLen).append('.').append(contextLen).append('s').append(fieldPostamble).append(' '); - retval.append(fieldPreamble).append("%-").append(uriLen).append('.').append(uriLen).append('s').append(fieldPostamble).append(' '); - retval.append(fieldPreamble).append("%-").append(statusLen).append('.').append(statusLen).append('s').append(fieldPostamble).append(' '); - - return retval.toString(); - } - - private int getMaxColumnWidth() { - if (verbose) { - return Integer.MAX_VALUE; - } else { - return MAX_COLUMN_WIDTH; - } - } - - private static String getEndpointState(Endpoint endpoint) { - // must use String type to be sure remote JMX can read the attribute without requiring Camel classes. - if (endpoint instanceof StatefulService) { - ServiceStatus status = ((StatefulService) endpoint).getStatus(); - return status.name(); - } - - // assume started if not a ServiceSupport instance - return ServiceStatus.Started.name(); + EndpointListCommand command = new EndpointListCommand(name, decode, verbose, explain); + return command.execute(camelController, System.out, System.err); } } http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestRegistryList.java ---------------------------------------------------------------------- diff --git a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestRegistryList.java b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestRegistryList.java index f048828..169e1c2 100644 --- a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestRegistryList.java +++ b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestRegistryList.java @@ -16,14 +16,7 @@ */ package org.apache.camel.karaf.commands; -import java.io.PrintStream; -import java.net.URLDecoder; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; - -import org.apache.camel.spi.RestRegistry; -import org.apache.camel.util.URISupport; +import org.apache.camel.commands.RestRegistryListCommand; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; import org.apache.felix.gogo.commands.Option; @@ -34,23 +27,6 @@ import org.apache.felix.gogo.commands.Option; @Command(scope = "camel", name = "rest-registry-list", description = "Lists all Camel REST services enlisted in the Rest Registry from all CamelContexts.") public class RestRegistryList extends CamelCommandSupport { - private static final String CONTEXT_COLUMN_LABEL = "Context"; - private static final String URL_COLUMN_NAME = "Url"; - private static final String BASE_PATH_LABEL = "Base Path"; - private static final String URI_TEMPLATE_LABEL = "Uri Template"; - private static final String METHOD_COLUMN_LABEL = "Method"; - private static final String STATE_COLUMN_LABEL = "State"; - - private static final int DEFAULT_COLUMN_WIDTH_INCREMENT = 0; - private static final String DEFAULT_FIELD_PREAMBLE = " "; - private static final String DEFAULT_FIELD_POSTAMBLE = " "; - private static final String DEFAULT_HEADER_PREAMBLE = " "; - private static final String DEFAULT_HEADER_POSTAMBLE = " "; - private static final int DEFAULT_FORMAT_BUFFER_LENGTH = 24; - // endpoint uris can be very long so clip by default after 120 chars - private static final int MAX_COLUMN_WIDTH = 120; - private static final int MIN_COLUMN_WIDTH = 12; - @Argument(index = 0, name = "name", description = "The Camel context name where to look for the REST services", required = false, multiValued = false) String name; @@ -63,150 +39,8 @@ public class RestRegistryList extends CamelCommandSupport { Boolean verbose = false; protected Object doExecute() throws Exception { - Map<String, List<RestRegistry.RestService>> services = camelController.getRestServices(name); - if (services.isEmpty()) { - System.out.print("There are no REST services"); - return null; - } - - final Map<String, Integer> columnWidths = computeColumnWidths(services); - final String headerFormat = buildFormatString(columnWidths, true, verbose); - final String rowFormat = buildFormatString(columnWidths, false, verbose); - final PrintStream out = System.out; - - if (services.size() > 0) { - if (verbose) { - out.println(String.format(headerFormat, CONTEXT_COLUMN_LABEL, URL_COLUMN_NAME, BASE_PATH_LABEL, URI_TEMPLATE_LABEL, METHOD_COLUMN_LABEL, STATE_COLUMN_LABEL)); - out.println(String.format(headerFormat, "-------", "---", "---------", "------------", "------", "-----")); - } else { - out.println(String.format(headerFormat, CONTEXT_COLUMN_LABEL, BASE_PATH_LABEL, URI_TEMPLATE_LABEL, METHOD_COLUMN_LABEL, STATE_COLUMN_LABEL)); - out.println(String.format(headerFormat, "-------", "---------", "------------", "------", "-----")); - } - for (Map.Entry<String, List<RestRegistry.RestService>> entry : services.entrySet()) { - String contextName = entry.getKey(); - for (final RestRegistry.RestService service : entry.getValue()) { - String contextId = contextName; - - String uri = null; - if (verbose) { - uri = service.getUrl(); - if (decode == null || decode) { - // decode uri so its more human readable - uri = URLDecoder.decode(uri, "UTF-8"); - } - // sanitize and mask uri so we dont see passwords - uri = URISupport.sanitizeUri(uri); - } - String basePath = service.getBasePath(); - String uriTemplate = service.getUriTemplate() != null ? service.getUriTemplate() : ""; - String method = service.getMethod(); - String state = service.getState(); - if (verbose) { - out.println(String.format(rowFormat, contextId, uri, basePath, uriTemplate, method, state)); - } else { - out.println(String.format(rowFormat, contextId, basePath, uriTemplate, method, state)); - } - } - } - } - - return null; - } - - private Map<String, Integer> computeColumnWidths(Map<String, List<RestRegistry.RestService>> services) throws Exception { - int maxContextLen = 0; - int maxUriLen = 0; - int maxBasePathLen = 0; - int maxUriTemplateLen = 0; - int maxMethodLen = 0; - int maxStatusLen = 0; - - for (Map.Entry<String, List<RestRegistry.RestService>> entry : services.entrySet()) { - String contextName = entry.getKey(); - for (final RestRegistry.RestService service : entry.getValue()) { - maxContextLen = Math.max(maxContextLen, contextName == null ? 0 : contextName.length()); - - String uri = service.getUrl(); - if (decode == null || decode) { - // decode uri so its more human readable - uri = URLDecoder.decode(uri, "UTF-8"); - } - // sanitize and mask uri so we dont see passwords - uri = URISupport.sanitizeUri(uri); - maxUriLen = Math.max(maxUriLen, uri == null ? 0 : uri.length()); - - String basePath = service.getBasePath(); - maxBasePathLen = Math.max(maxBasePathLen, basePath == null ? 0 : basePath.length()); - - String uriTemplate = service.getUriTemplate(); - maxUriTemplateLen = Math.max(maxUriTemplateLen, uriTemplate == null ? 0 : uriTemplate.length()); - - String method = service.getMethod(); - maxMethodLen = Math.max(maxMethodLen, method == null ? 0 : method.length()); - - String status = service.getState(); - maxStatusLen = Math.max(maxStatusLen, status == null ? 0 : status.length()); - } - } - - final Map<String, Integer> retval = new Hashtable<String, Integer>(6); - retval.put(CONTEXT_COLUMN_LABEL, maxContextLen); - retval.put(URL_COLUMN_NAME, maxUriLen); - retval.put(BASE_PATH_LABEL, maxBasePathLen); - retval.put(URI_TEMPLATE_LABEL, maxUriTemplateLen); - retval.put(METHOD_COLUMN_LABEL, maxMethodLen); - retval.put(STATE_COLUMN_LABEL, maxStatusLen); - - return retval; - } - - private String buildFormatString(final Map<String, Integer> columnWidths, final boolean isHeader, final boolean isVerbose) { - final String fieldPreamble; - final String fieldPostamble; - final int columnWidthIncrement; - - if (isHeader) { - fieldPreamble = DEFAULT_HEADER_PREAMBLE; - fieldPostamble = DEFAULT_HEADER_POSTAMBLE; - } else { - fieldPreamble = DEFAULT_FIELD_PREAMBLE; - fieldPostamble = DEFAULT_FIELD_POSTAMBLE; - } - columnWidthIncrement = DEFAULT_COLUMN_WIDTH_INCREMENT; - - int contextLen = Math.min(columnWidths.get(CONTEXT_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - int uriLen = Math.min(columnWidths.get(URL_COLUMN_NAME) + columnWidthIncrement, getMaxColumnWidth()); - int basePathLen = Math.min(columnWidths.get(BASE_PATH_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - int uriTemplateLen = Math.min(columnWidths.get(URI_TEMPLATE_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - int methodLen = Math.min(columnWidths.get(METHOD_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - int statusLen = Math.min(columnWidths.get(STATE_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth()); - contextLen = Math.max(MIN_COLUMN_WIDTH, contextLen); - basePathLen = Math.max(MIN_COLUMN_WIDTH, basePathLen); - uriLen = Math.max(MIN_COLUMN_WIDTH, uriLen); - uriTemplateLen = Math.max(MIN_COLUMN_WIDTH, uriTemplateLen); - methodLen = Math.max(MIN_COLUMN_WIDTH, methodLen); - - // last row does not have min width - - final StringBuilder retval = new StringBuilder(DEFAULT_FORMAT_BUFFER_LENGTH); - retval.append(fieldPreamble).append("%-").append(contextLen).append('.').append(contextLen).append('s').append(fieldPostamble).append(' '); - if (isVerbose) { - retval.append(fieldPreamble).append("%-").append(uriLen).append('.').append(uriLen).append('s').append(fieldPostamble).append(' '); - } - retval.append(fieldPreamble).append("%-").append(basePathLen).append('.').append(basePathLen).append('s').append(fieldPostamble).append(' '); - retval.append(fieldPreamble).append("%-").append(uriTemplateLen).append('.').append(uriTemplateLen).append('s').append(fieldPostamble).append(' '); - retval.append(fieldPreamble).append("%-").append(methodLen).append('.').append(methodLen).append('s').append(fieldPostamble).append(' '); - retval.append(fieldPreamble).append("%-").append(statusLen).append('.').append(statusLen).append('s').append(fieldPostamble).append(' '); - - return retval.toString(); - } - - private int getMaxColumnWidth() { - if (verbose != null && verbose) { - return Integer.MAX_VALUE; - } else { - return MAX_COLUMN_WIDTH; - } + RestRegistryListCommand command = new RestRegistryListCommand(name, decode, verbose); + return command.execute(camelController, System.out, System.err); } } http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestShow.java ---------------------------------------------------------------------- diff --git a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestShow.java b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestShow.java index 44d9420..53c11f5 100644 --- a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestShow.java +++ b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RestShow.java @@ -16,11 +16,7 @@ */ package org.apache.camel.karaf.commands; -import java.util.List; - -import org.apache.camel.model.ModelHelper; -import org.apache.camel.model.rest.RestDefinition; -import org.apache.camel.model.rest.RestsDefinition; +import org.apache.camel.commands.RestShowCommand; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; @@ -34,16 +30,8 @@ public class RestShow extends CamelCommandSupport { String context; public Object doExecute() throws Exception { - List<RestDefinition> rests = camelController.getRestDefinitions(context); - if (rests == null || rests.isEmpty()) { - System.out.print("There are no REST services in CamelContext with name: " + context); - return null; - } - // use a routes definition to dump the rests - RestsDefinition def = new RestsDefinition(); - def.setRests(rests); - System.out.println(ModelHelper.dumpModelAsXml(def)); - return null; + RestShowCommand command = new RestShowCommand(context); + return command.execute(camelController, System.out, System.err); } } http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RouteInfo.java ---------------------------------------------------------------------- diff --git a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RouteInfo.java b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RouteInfo.java index 5fdb214..db3a775 100644 --- a/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RouteInfo.java +++ b/platforms/karaf/commands/src/main/java/org/apache/camel/karaf/commands/RouteInfo.java @@ -16,23 +16,10 @@ */ package org.apache.camel.karaf.commands; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import org.apache.camel.CamelContext; -import org.apache.camel.Route; -import org.apache.camel.model.ModelHelper; -import org.apache.camel.model.RouteDefinition; -import org.apache.camel.spi.ManagementAgent; +import org.apache.camel.commands.RouteInfoCommand; +import org.apache.camel.commands.StringEscape; import org.apache.felix.gogo.commands.Argument; import org.apache.felix.gogo.commands.Command; -import org.apache.karaf.util.StringEscapeUtils; /** * Command to display detailed information about a Camel route. @@ -46,104 +33,16 @@ public class RouteInfo extends CamelCommandSupport { @Argument(index = 1, name = "context", description = "The Camel context name.", required = false, multiValued = false) String context; - public Object doExecute() throws Exception { - Route camelRoute = camelController.getRoute(route, context); - - if (camelRoute == null) { - System.err.println("Camel route " + route + " not found."); - return null; - } - - System.out.println(StringEscapeUtils.unescapeJava("\u001B[1m\u001B[33mCamel Route " + camelRoute.getId() + "\u001B[0m")); - System.out.println(StringEscapeUtils.unescapeJava("\tCamel Context: " + camelRoute.getRouteContext().getCamelContext().getName())); - System.out.println(""); - System.out.println(StringEscapeUtils.unescapeJava("\u001B[1mProperties\u001B[0m")); - for (Map.Entry<String, Object> entry : camelRoute.getProperties().entrySet()) { - System.out.println(StringEscapeUtils.unescapeJava("\t" + entry.getKey() + " = " + entry.getValue())); - } - System.out.println(""); - System.out.println(StringEscapeUtils.unescapeJava("\u001B[1mStatistics\u001B[0m")); - CamelContext camelContext = camelRoute.getRouteContext().getCamelContext(); - if (camelContext != null) { - ManagementAgent agent = camelContext.getManagementStrategy().getManagementAgent(); - if (agent != null) { - MBeanServer mBeanServer = agent.getMBeanServer(); - Set<ObjectName> set = mBeanServer.queryNames(new ObjectName(agent.getMBeanObjectDomainName() + ":type=routes,name=\"" + route + "\",*"), null); - Iterator<ObjectName> iterator = set.iterator(); - if (iterator.hasNext()) { - ObjectName routeMBean = iterator.next(); - - // the route must be part of the camel context - String camelId = (String) mBeanServer.getAttribute(routeMBean, "CamelId"); - if (camelId != null && camelId.equals(camelContext.getName())) { - Integer inflightExchange = (Integer) mBeanServer.getAttribute(routeMBean, "InflightExchanges"); - System.out.println(StringEscapeUtils.unescapeJava("\tInflight Exchanges: " + inflightExchange)); - Long exchangesTotal = (Long) mBeanServer.getAttribute(routeMBean, "ExchangesTotal"); - System.out.println(StringEscapeUtils.unescapeJava("\tExchanges Total: " + exchangesTotal)); - Long exchangesCompleted = (Long) mBeanServer.getAttribute(routeMBean, "ExchangesCompleted"); - System.out.println(StringEscapeUtils.unescapeJava("\tExchanges Completed: " + exchangesCompleted)); - Long exchangesFailed = (Long) mBeanServer.getAttribute(routeMBean, "ExchangesFailed"); - System.out.println(StringEscapeUtils.unescapeJava("\tExchanges Failed: " + exchangesFailed)); - Long minProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "MinProcessingTime"); - System.out.println(StringEscapeUtils.unescapeJava("\tMin Processing Time: " + minProcessingTime + " ms")); - Long maxProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "MaxProcessingTime"); - System.out.println(StringEscapeUtils.unescapeJava("\tMax Processing Time: " + maxProcessingTime + " ms")); - Long meanProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "MeanProcessingTime"); - System.out.println(StringEscapeUtils.unescapeJava("\tMean Processing Time: " + meanProcessingTime + " ms")); - Long totalProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "TotalProcessingTime"); - System.out.println(StringEscapeUtils.unescapeJava("\tTotal Processing Time: " + totalProcessingTime + " ms")); - Long lastProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "LastProcessingTime"); - System.out.println(StringEscapeUtils.unescapeJava("\tLast Processing Time: " + lastProcessingTime + " ms")); - Long deltaProcessingTime = (Long) mBeanServer.getAttribute(routeMBean, "DeltaProcessingTime"); - System.out.println(StringEscapeUtils.unescapeJava("\tDelta Processing Time: " + deltaProcessingTime + " ms")); - String load01 = (String) mBeanServer.getAttribute(routeMBean, "Load01"); - String load05 = (String) mBeanServer.getAttribute(routeMBean, "Load05"); - String load15 = (String) mBeanServer.getAttribute(routeMBean, "Load15"); - System.out.println(StringEscapeUtils.unescapeJava("\tLoad Avg: " + load01 + ", " + load05 + ", " + load15)); + private StringEscape stringEscape; - // Test for null to see if a any exchanges have been processed first to avoid NPE - Object resetTimestampObj = mBeanServer.getAttribute(routeMBean, "ResetTimestamp"); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - if (resetTimestampObj == null) { - // Print an empty value for scripting - System.out.println(StringEscapeUtils.unescapeJava("\tReset Statistics Date:")); - } else { - Date firstExchangeTimestamp = (Date) resetTimestampObj; - System.out.println(StringEscapeUtils.unescapeJava("\tReset Statistics Date: " + format.format(firstExchangeTimestamp))); - } - - // Test for null to see if a any exchanges have been processed first to avoid NPE - Object firstExchangeTimestampObj = mBeanServer.getAttribute(routeMBean, "FirstExchangeCompletedTimestamp"); - if (firstExchangeTimestampObj == null) { - // Print an empty value for scripting - System.out.println(StringEscapeUtils.unescapeJava("\tFirst Exchange Date:")); - } else { - Date firstExchangeTimestamp = (Date) firstExchangeTimestampObj; - System.out.println(StringEscapeUtils.unescapeJava("\tFirst Exchange Date: " + format.format(firstExchangeTimestamp))); - } - - // Again, check for null to avoid NPE - Object lastExchangeCompletedTimestampObj = mBeanServer.getAttribute(routeMBean, "LastExchangeCompletedTimestamp"); - if (lastExchangeCompletedTimestampObj == null) { - // Print an empty value for scripting - System.out.println(StringEscapeUtils.unescapeJava("\tLast Exchange Completed Date:")); - } else { - Date lastExchangeCompletedTimestamp = (Date) lastExchangeCompletedTimestampObj; - System.out.println(StringEscapeUtils.unescapeJava("\tLast Exchange Completed Date: " + format.format(lastExchangeCompletedTimestamp))); - } - } - } - } else { - System.out.println(""); - System.out.println(StringEscapeUtils.unescapeJava("\u001B[31mJMX Agent of Camel is not reachable. Maybe it has been disabled on the Camel context")); - System.out.println(StringEscapeUtils.unescapeJava("In consequence, some statistics are not available.\u001B[0m")); - } + public void setStringEscape(StringEscape stringEscape) { + this.stringEscape = stringEscape; + } - System.out.println(""); - System.out.println(StringEscapeUtils.unescapeJava("\u001B[1mDefinition\u001B[0m")); - RouteDefinition definition = camelController.getRouteDefinition(route, camelRoute.getRouteContext().getCamelContext().getName()); - System.out.println(StringEscapeUtils.unescapeJava(ModelHelper.dumpModelAsXml(definition))); - } - return null; + public Object doExecute() throws Exception { + RouteInfoCommand command = new RouteInfoCommand(route, context); + command.setStringEscape(stringEscape); + return command.execute(camelController, System.out, System.err); } + } http://git-wip-us.apache.org/repos/asf/camel/blob/796aa092/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/camel-commands.xml ---------------------------------------------------------------------- diff --git a/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/camel-commands.xml b/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/camel-commands.xml index 424e2e6..cf0f525 100644 --- a/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/camel-commands.xml +++ b/platforms/karaf/commands/src/main/resources/OSGI-INF/blueprint/camel-commands.xml @@ -81,6 +81,7 @@ <command name="camel/route-info"> <action class="org.apache.camel.karaf.commands.RouteInfo"> <property name="camelController" ref="camelController"/> + <property name="stringEscape" ref="stringEscape"/> </action> <completers> <ref component-id="routeCompleter"/>