Repository: camel
Updated Branches:
  refs/heads/master 7c6737bf5 -> 8f89b49dc


CAMEL-8211 - Camel commands - camel-component-info


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/8f89b49d
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/8f89b49d
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/8f89b49d

Branch: refs/heads/master
Commit: 8f89b49dcbcf15df702a788ed47e79ed5766831e
Parents: 9df244d
Author: lburgazzoli <lburgazz...@gmail.com>
Authored: Wed Mar 2 13:23:40 2016 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Fri Mar 11 12:07:46 2016 +0100

----------------------------------------------------------------------
 .../camel/commands/AbstractCamelController.java |  54 ++++++
 .../apache/camel/commands/CamelController.java  |   9 +
 .../camel/commands/CatalogComponentHelper.java  | 188 +++++++++++++++++++
 .../commands/CatalogComponentInfoCommand.java   | 142 ++++++++++++++
 .../camel/commands/CatalogCommandTest.java      |  22 +++
 .../commands/catalog/CatalogComponentInfo.java  |  45 +++++
 .../blueprint/camel-commands-catalog.xml        |   5 +
 7 files changed, 465 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/8f89b49d/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractCamelController.java
----------------------------------------------------------------------
diff --git 
a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractCamelController.java
 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractCamelController.java
index cea1b46..67b2746 100644
--- 
a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractCamelController.java
+++ 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractCamelController.java
@@ -29,6 +29,7 @@ import org.apache.camel.catalog.CatalogHelper;
 import org.apache.camel.catalog.DefaultCamelCatalog;
 import org.apache.camel.commands.internal.RegexUtil;
 import org.apache.camel.util.JsonSchemaHelper;
+import org.apache.camel.util.ObjectHelper;
 
 /**
  * Abstract {@link org.apache.camel.commands.CamelController} that 
implementators should extend.
@@ -102,6 +103,59 @@ public abstract class AbstractCamelController implements 
CamelController {
         return answer;
     }
 
+    protected Map<String, Object> loadProperties(String json, String group, 
Map<String, Object> answer) {
+        List<Map<String, String>> kv = JsonSchemaHelper.parseJsonSchema(group, 
json, true);
+        if (kv.isEmpty()) {
+            return answer;
+        }
+
+        Map<String, Object> groupkv = new LinkedHashMap<>();
+        answer.put(group, groupkv);
+
+        for (Map<String, String> map : kv) {
+            boolean first = true;
+            Map<String, Object> properties = new LinkedHashMap<>();
+            for (Map.Entry<String, String> entry : map.entrySet()) {
+                if (first) {
+                    if (!ObjectHelper.equal(entry.getKey(), "name")) {
+                        throw new IllegalStateException("First entry should be 
the property name");
+                    }
+                    groupkv.put(entry.getValue(), properties);
+                    first = false;
+                } else {
+                    properties.put(entry.getKey(), entry.getValue());
+                }
+            }
+        }
+
+        return answer;
+    }
+
+    @Override
+    public Map<String, Object> componentInfo(String filter) throws Exception {
+        Map<String, Object> answer = new LinkedHashMap<>();
+        List<String> names = catalog.findComponentNames();
+        for (String name : names) {
+            if (name.equalsIgnoreCase(filter)) {
+                String json = catalog.componentJSonSchema(name);
+
+                List<Map<String, String>> kv;
+
+                kv = JsonSchemaHelper.parseJsonSchema("component", json, 
false);
+                for (Map<String, String> map : kv) {
+                    answer.putAll(map);
+                }
+
+                loadProperties(json, "componentProperties", answer);
+                loadProperties(json, "properties", answer);
+
+                break;
+            }
+        }
+
+        return answer;
+    }
+
     @Override
     public List<Map<String, String>> listComponentsCatalog(String filter) 
throws Exception {
         List<Map<String, String>> answer = new ArrayList<Map<String, 
String>>();

http://git-wip-us.apache.org/repos/asf/camel/blob/8f89b49d/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
----------------------------------------------------------------------
diff --git 
a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
index b9fbcd1..65c2139 100644
--- 
a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
+++ 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
@@ -284,6 +284,15 @@ public interface CamelController {
     Map<String, Set<String>> listEipsLabelCatalog() throws Exception;
 
     /**
+     * Collects information about a Camel component from catalog
+     *
+     * @param name the component name
+     * @return a map of key/value pairs with component information
+     * @throws java.lang.Exception can be thrown
+     */
+    Map<String, Object> componentInfo(String name) throws Exception;
+
+    /**
      * Lists all components from the Camel components catalog
      *
      * @param filter optional filter to filter by labels

http://git-wip-us.apache.org/repos/asf/camel/blob/8f89b49d/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentHelper.java
----------------------------------------------------------------------
diff --git 
a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentHelper.java
 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentHelper.java
new file mode 100644
index 0000000..d243539
--- /dev/null
+++ 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentHelper.java
@@ -0,0 +1,188 @@
+/**
+ * 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.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.util.ObjectHelper;
+
+public final class CatalogComponentHelper {
+    private CatalogComponentHelper() {
+    }
+
+    public static final class TableColumn {
+        private final String header;
+        private final String key;
+        private int maxLen;
+        private String formatString;
+
+        public TableColumn(String header, String key) {
+            this.header = header;
+            this.key = key;
+            this.maxLen = header.length();
+            this.formatString = null;
+        }
+
+        public String getHeader() {
+            return header;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public int getMaxLen() {
+            return maxLen;
+        }
+
+        public void computeMaxLen(Map<String, String> row) {
+            String val = row.get(key);
+            if (val != null) {
+                maxLen = Math.max(maxLen, val.length());
+            }
+        }
+
+        private String headerSeparator() {
+            StringBuilder sb = new StringBuilder(header.length());
+            while (sb.length() < header.length()) {
+                sb.append('-');
+            }
+
+            return sb.toString();
+        }
+
+        private String formatString() {
+            if (formatString == null) {
+                formatString = new StringBuilder()
+                    
.append("%-").append(maxLen).append('.').append(maxLen).append('s')
+                    .toString();
+            }
+
+            return formatString;
+        }
+
+        public void printHeader(PrintStream out, boolean newLine) {
+            String outStr = String.format(formatString(), header);
+
+            if (newLine) {
+                out.println(outStr.trim());
+            } else {
+                out.print(outStr);
+                out.print(' ');
+            }
+        }
+
+        public void printHeaderSeparator(PrintStream out, boolean newLine) {
+            String outStr = String.format(formatString(), headerSeparator());
+
+            if (newLine) {
+                out.println(outStr.trim());
+            } else {
+                out.print(outStr);
+                out.print(' ');
+            }
+        }
+
+        public void printValue(PrintStream out, Map<String, String> row, 
boolean newLine) {
+            String val = row.get(key);
+            if (val == null) {
+                val = "";
+            }
+
+            String outStr = String.format(formatString(), val);
+
+            if (newLine) {
+                out.println(outStr.trim());
+            } else {
+                out.print(outStr);
+                out.print(' ');
+            }
+        }
+    }
+
+    public static final class Table {
+        private final List<TableColumn> columns;
+        private final List<Map<String, String>> rows;
+
+        public Table(String[] headers, String[] keys) {
+            assert headers.length == keys.length;
+
+            this.columns = new LinkedList<>();
+            this.rows = new LinkedList<>();
+
+            for (int i = 0; i < headers.length; i++) {
+                columns.add(new TableColumn(headers[i], keys[i]));
+            }
+        }
+
+        public boolean isEmpty() {
+            return rows.isEmpty();
+        }
+
+        public void addRow(String name, Map<String, Object> row) {
+            Map<String, String> rowData = null;
+
+            for (TableColumn column : columns) {
+                Object val = row.get(column.getKey());
+                if (ObjectHelper.isNotEmpty(val)) {
+                    if (rowData == null) {
+                        rowData = new LinkedHashMap<>();
+                    }
+
+                    rowData.put(column.getKey(), val.toString());
+                }
+            }
+
+            if (rowData != null) {
+                rowData.put("key", name);
+                rows.add(rowData);
+
+                for (TableColumn column : columns) {
+                    column.computeMaxLen(rowData);
+                }
+            }
+        }
+
+        public void print(PrintStream out) {
+            for (int r = 0; r < rows.size(); r++) {
+                if (r == 0) {
+                    printHeader(out);
+                }
+
+                Map<String, String> row = rows.get(r);
+                for (int c = 0; c < columns.size(); c++) {
+                    columns.get(c).printValue(out, row, c == columns.size() - 
1);
+                }
+            }
+        }
+
+        private void printHeader(PrintStream out) {
+            for (int c = 0; c < columns.size(); c++) {
+                TableColumn column = columns.get(c);
+                column.printHeader(out, c == columns.size() - 1);
+            }
+            for (int c = 0; c < columns.size(); c++) {
+                TableColumn column = columns.get(c);
+                column.printHeaderSeparator(out, c == columns.size() - 1);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/8f89b49d/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentInfoCommand.java
----------------------------------------------------------------------
diff --git 
a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentInfoCommand.java
 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentInfoCommand.java
new file mode 100644
index 0000000..b94d5b1
--- /dev/null
+++ 
b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CatalogComponentInfoCommand.java
@@ -0,0 +1,142 @@
+/**
+ * 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.Map;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.camel.catalog.CatalogHelper;
+import org.apache.camel.commands.internal.RegexUtil;
+
+/**
+ * Shows properties of a component from Catalog
+ */
+public class CatalogComponentInfoCommand extends AbstractCamelCommand {
+    private static final String[][] COMPONENT_PROPERTIES = new String[][] {
+        {"Property", "Description"},
+        {"key", "description"}
+    };
+
+    private static final String[][] COMPONENT_PROPERTIES_VERBOSE = new 
String[][] {
+        {"Property", "Description"},
+        {"key", "description"}
+    };
+
+    private static final String[][] PROPERTIES = new String[][] {
+        {"Property", "Description"},
+        {"key", "description"}
+    };
+
+    private static final String[][] PROPERTIES_VERBOSE = new String[][] {
+        {"Property", "Group", "Default Value", "Description"},
+        {"key", "group", "defaultValue", "description"}
+    };
+
+    private final String name;
+    private final boolean verbose;
+    private final String labelFilter;
+
+    public CatalogComponentInfoCommand(String name, boolean verbose, String 
labelFilter) {
+        this.name = name;
+        this.verbose = verbose;
+        this.labelFilter = labelFilter != null ? 
RegexUtil.wildcardAsRegex(labelFilter) : null;
+    }
+
+    @Override
+    public Object execute(CamelController camelController, PrintStream out, 
PrintStream err) throws Exception {
+        final Map<String, Object> info = camelController.componentInfo(name);
+
+        String component = name.toUpperCase();
+        if (info.containsKey("description")) {
+            component += " :: " +  info.get("description");
+        }
+
+        out.println("");
+        out.println(component);
+        out.println(buildSeparatorString(component.length(), '-'));
+        out.println("");
+
+
+        if (info.containsKey("label")) {
+            out.printf("label: %s\n", info.get("label"));
+        }
+
+        if (info.containsKey("groupId") && info.containsKey("artifactId") && 
info.containsKey("version")) {
+            out.printf("maven: %s\n", info.get("groupId") + "/" + 
info.get("artifactId") + "/" + info.get("version"));
+        }
+
+        dumpProperties("componentProperties", info, verbose ? 
COMPONENT_PROPERTIES_VERBOSE : COMPONENT_PROPERTIES, out);
+        dumpProperties("properties", info, verbose ? PROPERTIES_VERBOSE : 
PROPERTIES, out);
+
+        return null;
+    }
+
+    private void dumpProperties(String groupName, Map<String, Object> info, 
String[][] tableStruct, PrintStream out) {
+        Map<String, Object> group = (Map<String, Object>)info.get(groupName);
+        if (group != null) {
+            CatalogComponentHelper.Table table = new 
CatalogComponentHelper.Table(tableStruct[0], tableStruct[1]);
+            for (Map.Entry<String, Object> entry : group.entrySet()) {
+                if (entry.getValue() instanceof Map) {
+                    Map<String, Object> data = (Map<String, Object>) 
entry.getValue();
+                    if (matchLabel(data)) {
+                        table.addRow(entry.getKey(), data);
+                    }
+                }
+            }
+
+            if (!table.isEmpty()) {
+                out.println("");
+                out.println(groupName);
+                out.println("");
+
+                table.print(out);
+            }
+        }
+    }
+
+    private static String buildSeparatorString(int len, char pad) {
+        StringBuilder sb = new StringBuilder(len);
+        while (sb.length() < len) {
+            sb.append(pad);
+        }
+
+        return sb.toString();
+    }
+
+    private boolean matchLabel(Map<String, Object> properties) {
+        if (labelFilter == null) {
+            return true;
+        }
+
+        final String label = (String)properties.get("label");
+        if (label != null) {
+            String[] parts = label.split(",");
+            for (String part : parts) {
+                try {
+                    if (part.equalsIgnoreCase(labelFilter) || 
CatalogHelper.matchWildcard(part, labelFilter) || part.matches(labelFilter)) {
+                        return true;
+                    }
+                } catch (PatternSyntaxException e) {
+                    // ignore as filter is maybe not a pattern
+                }
+            }
+        }
+
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/8f89b49d/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/CatalogCommandTest.java
----------------------------------------------------------------------
diff --git 
a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/CatalogCommandTest.java
 
b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/CatalogCommandTest.java
index be4b941..4d03fb0 100644
--- 
a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/CatalogCommandTest.java
+++ 
b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/CatalogCommandTest.java
@@ -54,4 +54,26 @@ public class CatalogCommandTest {
         context.stop();
     }
 
+
+    @Test
+    public void testComponentInfo() throws Exception {
+        CamelContext context = new DefaultCamelContext();
+        context.setNameStrategy(new 
ExplicitCamelContextNameStrategy("foobar"));
+        context.start();
+
+        CamelController controller = new DummyCamelController(context);
+
+        OutputStream os = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(os);
+
+        CatalogComponentInfoCommand command = new 
CatalogComponentInfoCommand("hdfs", true, "consumer");
+        command.execute(controller, ps, null);
+
+        String out = os.toString();
+        assertNotNull(out);
+        LOG.info("\n\n{}\n", out);
+
+        context.stop();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/8f89b49d/platforms/karaf/commands-catalog/src/main/java/org/apache/camel/karaf/commands/catalog/CatalogComponentInfo.java
----------------------------------------------------------------------
diff --git 
a/platforms/karaf/commands-catalog/src/main/java/org/apache/camel/karaf/commands/catalog/CatalogComponentInfo.java
 
b/platforms/karaf/commands-catalog/src/main/java/org/apache/camel/karaf/commands/catalog/CatalogComponentInfo.java
new file mode 100644
index 0000000..7ecae74
--- /dev/null
+++ 
b/platforms/karaf/commands-catalog/src/main/java/org/apache/camel/karaf/commands/catalog/CatalogComponentInfo.java
@@ -0,0 +1,45 @@
+/**
+ * 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.karaf.commands.catalog;
+
+import org.apache.camel.commands.CamelCommand;
+import org.apache.camel.commands.CatalogComponentInfoCommand;
+import org.apache.camel.karaf.commands.CamelCommandSupport;
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "camel", name = "catalog-component-info", description = "Show 
information about a Camel component from the Camel catalog")
+public class CatalogComponentInfo extends CamelCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The name of the Camel 
component.",
+            required = true, multiValued = false)
+    String name;
+
+    @Option(name = "--verbose", aliases = "-v", description = "Verbose output 
which shows more information",
+            required = false, multiValued = false, valueToShowInHelp = "false")
+    boolean verbose;
+
+    @Option(name = "--label", aliases = "-l", description = "To filter 
properties by their label(s), such as database",
+            required = false, multiValued = false)
+    String label;
+
+    protected Object doExecute() throws Exception {
+        CamelCommand command = new CatalogComponentInfoCommand(name, verbose, 
label);
+        return command.execute(camelController, System.out, System.err);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/8f89b49d/platforms/karaf/commands-catalog/src/main/resources/OSGI-INF/blueprint/camel-commands-catalog.xml
----------------------------------------------------------------------
diff --git 
a/platforms/karaf/commands-catalog/src/main/resources/OSGI-INF/blueprint/camel-commands-catalog.xml
 
b/platforms/karaf/commands-catalog/src/main/resources/OSGI-INF/blueprint/camel-commands-catalog.xml
index eb002fc..bad7f72 100644
--- 
a/platforms/karaf/commands-catalog/src/main/resources/OSGI-INF/blueprint/camel-commands-catalog.xml
+++ 
b/platforms/karaf/commands-catalog/src/main/resources/OSGI-INF/blueprint/camel-commands-catalog.xml
@@ -24,6 +24,11 @@
         <property name="camelController" ref="camelController"/>
       </action>
     </command>
+    <command name="camel-catalog/component-info">
+      <action 
class="org.apache.camel.karaf.commands.catalog.CatalogComponentInfo">
+        <property name="camelController" ref="camelController"/>
+      </action>
+    </command>
     <command name="camel-catalog/dataformat-list">
       <action 
class="org.apache.camel.karaf.commands.catalog.CatalogDataFormatList">
         <property name="camelController" ref="camelController"/>

Reply via email to