CAMEL-7999: Add component details to json

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

Branch: refs/heads/master
Commit: 7e0d92c64b631397026c25118c88de842c0e9ab5
Parents: fc3a01c
Author: Claus Ibsen <davscl...@apache.org>
Authored: Sun Nov 9 15:51:11 2014 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Sun Nov 9 16:09:10 2014 +0100

----------------------------------------------------------------------
 .../apache/camel/impl/DefaultCamelContext.java  |   2 +-
 .../camel/management/mbean/ManagedEndpoint.java |   2 +-
 .../org/apache/camel/util/JsonSchemaHelper.java |  19 ++-
 .../tools/apt/EndpointAnnotationProcessor.java  | 160 +++++++++++++++++--
 .../org/apache/camel/tools/apt/IOHelper.java    |  82 ++++++++++
 5 files changed, 246 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/7e0d92c6/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java 
b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 01cdefb..addcc63 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -1151,7 +1151,7 @@ public class DefaultCamelContext extends ServiceSupport 
implements ModelCamelCon
                 return null;
             }
 
-            List<Map<String, String>> rows = 
JsonSchemaHelper.parseJsonSchema(json);
+            List<Map<String, String>> rows = 
JsonSchemaHelper.parseJsonSchema("properties", json);
 
             // selected rows to use for answer
             Map<String, String[]> selected = new LinkedHashMap<String, 
String[]>();

http://git-wip-us.apache.org/repos/asf/camel/blob/7e0d92c6/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedEndpoint.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedEndpoint.java
 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedEndpoint.java
index e6ae3e3..7e55502 100644
--- 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedEndpoint.java
+++ 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedEndpoint.java
@@ -87,7 +87,7 @@ public class ManagedEndpoint implements ManagedInstance, 
ManagedEndpointMBean {
     public TabularData explain(boolean allOptions) {
         try {
             String json = 
endpoint.getCamelContext().explainEndpointJson(getEndpointUri(), allOptions);
-            List<Map<String, String>> rows = 
JsonSchemaHelper.parseJsonSchema(json);
+            List<Map<String, String>> rows = 
JsonSchemaHelper.parseJsonSchema("properties", json);
 
             TabularData answer = new 
TabularDataSupport(CamelOpenMBeanTypes.explainEndpointTabularType());
 

http://git-wip-us.apache.org/repos/asf/camel/blob/7e0d92c6/camel-core/src/main/java/org/apache/camel/util/JsonSchemaHelper.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/JsonSchemaHelper.java 
b/camel-core/src/main/java/org/apache/camel/util/JsonSchemaHelper.java
index 8690939..4233a14 100644
--- a/camel-core/src/main/java/org/apache/camel/util/JsonSchemaHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/JsonSchemaHelper.java
@@ -111,20 +111,31 @@ public final class JsonSchemaHelper {
     /**
      * Parses the json schema to split it into a list or rows, where each row 
contains key value pairs with the metadata
      *
+     * @param group the group to parse from such as <tt>component</tt>, 
<tt>componentProperties</tt>, or <tt>properties</tt>.
      * @param json the json
      * @return a list of all the rows, where each row is a set of key value 
pairs with metadata
      */
-    public static List<Map<String, String>> parseJsonSchema(String json) {
+    public static List<Map<String, String>> parseJsonSchema(String group, 
String json) {
         List<Map<String, String>> answer = new ArrayList<Map<String, 
String>>();
         if (json == null) {
             return answer;
         }
 
+        boolean found = false;
+
         // parse line by line
-        // skip first 2 lines as they are leading
         String[] lines = json.split("\n");
-        for (int i = 2; i < lines.length; i++) {
-            String line = lines[i];
+        for (String line : lines) {
+            // we need to find the group first
+            if (!found) {
+                found = line.startsWith("  \"" + group + "\":");
+                continue;
+            }
+
+            // we should stop when we end the group
+            if (line.equals("  },") || line.equals("  }")) {
+                break;
+            }
 
             Map<String, String> row = new LinkedHashMap<String, String>();
             Matcher matcher = PATTERN.matcher(line);

http://git-wip-us.apache.org/repos/asf/camel/blob/7e0d92c6/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
----------------------------------------------------------------------
diff --git 
a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
 
b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
index ca85271..2149bed 100644
--- 
a/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
+++ 
b/tooling/apt/src/main/java/org/apache/camel/tools/apt/EndpointAnnotationProcessor.java
@@ -19,12 +19,15 @@ package org.apache.camel.tools.apt;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.net.URI;
+import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import javax.annotation.processing.AbstractProcessor;
 import javax.annotation.processing.Filer;
@@ -49,6 +52,8 @@ import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.spi.UriParams;
 
+import static org.apache.camel.tools.apt.IOHelper.loadText;
+import static org.apache.camel.tools.apt.JsonSchemaHelper.sanitizeDescription;
 import static org.apache.camel.tools.apt.Strings.canonicalClassName;
 import static org.apache.camel.tools.apt.Strings.isNullOrEmpty;
 
@@ -144,27 +149,36 @@ public class EndpointAnnotationProcessor extends 
AbstractProcessor {
     }
 
     protected void writeJSonSchemeDocumentation(PrintWriter writer, 
RoundEnvironment roundEnv, TypeElement classElement, UriEndpoint uriEndpoint) {
+        // gather component information
         String scheme = uriEndpoint.scheme();
-
-        String classDoc = 
processingEnv.getElementUtils().getDocComment(classElement);
-        if (!isNullOrEmpty(classDoc)) {
-            classDoc = JsonSchemaHelper.sanitizeDescription(classDoc);
-        }
-
-        // TODO: include component meta-data such as scheme name, java class, 
mvn coordinate etc.
-        // also component summary, eg grab <description> from mvn pom.xml
+        ComponentModel componentModel = findComponentProperties(roundEnv, 
scheme);
 
         Set<EndpointOption> endpointOptions = new LinkedHashSet<>();
         findClassProperties(roundEnv, endpointOptions, classElement, "");
         if (!endpointOptions.isEmpty()) {
-            String json = createParameterJsonSchema(endpointOptions);
+            String json = createParameterJsonSchema(componentModel, 
endpointOptions);
             writer.println(json);
         }
     }
 
-
-    public String createParameterJsonSchema(Set<EndpointOption> options) {
-        StringBuilder buffer = new StringBuilder("{\n  \"properties\": {");
+    public String createParameterJsonSchema(ComponentModel componentModel, 
Set<EndpointOption> options) {
+        StringBuilder buffer = new StringBuilder("{");
+        // component model
+        buffer.append("\n \"component\": {");
+        buffer.append("\n    \"scheme\": \"" + componentModel.getScheme() + 
"\",");
+        buffer.append("\n    \"description\": \"" + 
sanitizeDescription(componentModel.getDescription()) + "\",");
+        buffer.append("\n    \"javaType\": \"" + componentModel.getJavaType() 
+ "\",");
+        buffer.append("\n    \"groupId\": \"" + componentModel.getGroupId() + 
"\",");
+        buffer.append("\n    \"artifactId\": \"" + 
componentModel.getArtifactId() + "\",");
+        buffer.append("\n    \"version\": \"" + componentModel.getVersionId() 
+ "\"");
+        buffer.append("\n  },");
+
+        // and empty component properties as placeholder for future improvement
+        buffer.append("\n  \"componentProperties\": {");
+        buffer.append("\n  },");
+
+        // endpoint properties was named properties at first, and hence we 
stick with that naming to be compatible
+        buffer.append("\n  \"properties\": {");
         boolean first = true;
         for (EndpointOption entry : options) {
             if (first) {
@@ -175,7 +189,9 @@ public class EndpointAnnotationProcessor extends 
AbstractProcessor {
             buffer.append("\n    ");
             buffer.append(JsonSchemaHelper.toJson(entry.getName(), 
entry.getType(), entry.getDefaultValue(), entry.getDocumentationWithNotes(), 
entry.isEnumType(), entry.getEnums()));
         }
-        buffer.append("\n  }\n}\n");
+        buffer.append("\n  }");
+
+        buffer.append("\n}\n");
         return buffer.toString();
     }
 
@@ -212,6 +228,28 @@ public class EndpointAnnotationProcessor extends 
AbstractProcessor {
         }
     }
 
+    protected ComponentModel findComponentProperties(RoundEnvironment 
roundEnv, String scheme) {
+        ComponentModel model = new ComponentModel(scheme);
+
+        String data = 
loadResource("META-INF/services/org/apache/camel/component", scheme);
+        if (data != null) {
+            Map<String, String> map = parseAsMap(data);
+            model.setJavaType(map.get("class"));
+        }
+
+        data = loadResource("META-INF/services/org/apache/camel", 
"component.properties");
+        if (data != null) {
+            Map<String, String> map = parseAsMap(data);
+            // now we have a lot more data, so we need to load it as key/value
+            model.setDescription(map.get("projectDescription"));
+            model.setGroupId(map.get("groupId"));
+            model.setArtifactId(map.get("artifactId"));
+            model.setVersionId(map.get("version"));
+        }
+
+        return model;
+    }
+
     protected void findClassProperties(RoundEnvironment roundEnv, 
Set<EndpointOption> endpointOptions, TypeElement classElement, String prefix) {
         Elements elementUtils = processingEnv.getElementUtils();
         while (true) {
@@ -361,6 +399,44 @@ public class EndpointAnnotationProcessor extends 
AbstractProcessor {
         }
     }
 
+    protected String loadResource(String packageName, String fileName) {
+        Filer filer = processingEnv.getFiler();
+
+        FileObject resource;
+        try {
+            resource = filer.getResource(StandardLocation.CLASS_OUTPUT, "", 
packageName + "/" + fileName);
+        } catch (Throwable e) {
+            return "Crap" + e.getMessage();
+        }
+
+        if (resource == null) {
+            return null;
+        }
+
+        try {
+            InputStream is = resource.openInputStream();
+            return loadText(is, true);
+        } catch (Exception e) {
+            warning("Could not load file");
+        }
+
+        return null;
+    }
+
+    protected Map<String, String> parseAsMap(String data) {
+        Map<String, String> answer = new HashMap<String, String>();
+        String[] lines = data.split("\n");
+        for (String line : lines) {
+            int idx = line.indexOf('=');
+            String key = line.substring(0, idx);
+            String value = line.substring(idx + 1);
+            // remove ending line break for the values
+            value = value.trim().replaceAll("\n", "");
+            answer.put(key.trim(), value);
+        }
+        return answer;
+    }
+
     protected void log(String message) {
         processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, 
message);
     }
@@ -382,6 +458,64 @@ public class EndpointAnnotationProcessor extends 
AbstractProcessor {
         processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
buffer.toString());
     }
 
+    private static final class ComponentModel {
+
+        private String scheme;
+        private String javaType;
+        private String description;
+        private String groupId;
+        private String artifactId;
+        private String versionId;
+
+        private ComponentModel(String scheme) {
+            this.scheme = scheme;
+        }
+
+        public String getScheme() {
+            return scheme;
+        }
+
+        public String getJavaType() {
+            return javaType;
+        }
+
+        public void setJavaType(String javaType) {
+            this.javaType = javaType;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+        public void setDescription(String description) {
+            this.description = description;
+        }
+
+        public String getGroupId() {
+            return groupId;
+        }
+
+        public void setGroupId(String groupId) {
+            this.groupId = groupId;
+        }
+
+        public String getArtifactId() {
+            return artifactId;
+        }
+
+        public void setArtifactId(String artifactId) {
+            this.artifactId = artifactId;
+        }
+
+        public String getVersionId() {
+            return versionId;
+        }
+
+        public void setVersionId(String versionId) {
+            this.versionId = versionId;
+        }
+    }
+
     private static final class EndpointOption {
 
         private String name;

http://git-wip-us.apache.org/repos/asf/camel/blob/7e0d92c6/tooling/apt/src/main/java/org/apache/camel/tools/apt/IOHelper.java
----------------------------------------------------------------------
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/IOHelper.java 
b/tooling/apt/src/main/java/org/apache/camel/tools/apt/IOHelper.java
new file mode 100644
index 0000000..e6c764a
--- /dev/null
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/IOHelper.java
@@ -0,0 +1,82 @@
+/**
+ * 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.tools.apt;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+class IOHelper {
+
+    private IOHelper() {
+    }
+
+    /**
+     * Loads the entire stream into memory as a String and returns it.
+     * <p/>
+     * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
+     * terminator at the of the text.
+     * <p/>
+     * Warning, don't use for crazy big streams :)
+     */
+    public static String loadText(InputStream in, boolean 
skipCommentOrEmptyLines) throws IOException {
+        StringBuilder builder = new StringBuilder();
+        InputStreamReader isr = new InputStreamReader(in);
+        try {
+            BufferedReader reader = new BufferedReader(isr);
+            while (true) {
+                String line = reader.readLine();
+                if (line != null) {
+
+                    boolean empty = Strings.isNullOrEmpty(line);
+                    boolean comment = line.trim().startsWith("#");
+                    if (skipCommentOrEmptyLines && (empty || comment)) {
+                        continue;
+                    }
+
+                    builder.append(line);
+                    builder.append("\n");
+                } else {
+                    break;
+                }
+            }
+            return builder.toString();
+        } finally {
+            close(isr, in);
+        }
+    }
+
+    /**
+     * Closes the given resources if they are available.
+     *
+     * @param closeables the objects to close
+     */
+    public static void close(Closeable... closeables) {
+        for (Closeable closeable : closeables) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+    }
+
+
+
+}

Reply via email to