You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by dh...@apache.org on 2014/06/19 22:34:37 UTC

git commit: Added support in API components for parameterized endpoint configuration fields, e.g. parameters are now mapped to List, instead of List, and documentation also shows the generic type parameters

Repository: camel
Updated Branches:
  refs/heads/master 394dbb462 -> ad26a8ab4


Added support in API components for parameterized endpoint configuration fields, e.g. parameters are now mapped to List<String>, instead of List, and documentation also shows the generic type parameters


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

Branch: refs/heads/master
Commit: ad26a8ab4fef1b44fcf1d8ca2c81c9972272287a
Parents: 394dbb4
Author: Dhiraj Bokde <dh...@yahoo.com>
Authored: Thu Jun 19 13:34:00 2014 -0700
Committer: Dhiraj Bokde <dh...@yahoo.com>
Committed: Thu Jun 19 13:34:32 2014 -0700

----------------------------------------------------------------------
 .../camel/util/component/ApiMethodParser.java   | 47 +++++++++++--
 .../component/ArgumentSubstitutionParser.java   | 11 +++-
 .../camel-api-component-maven-plugin/pom.xml    |  7 ++
 .../maven/AbstractApiMethodGeneratorMojo.java   | 69 ++++++++++++++++++--
 .../camel/maven/AbstractGeneratorMojo.java      | 20 +++---
 .../camel/maven/DocumentGeneratorMojo.java      | 33 ++++++++++
 .../maven/JavadocApiMethodGeneratorMojo.java    | 43 +++++++-----
 .../src/main/resources/api-document.vm          |  2 +-
 8 files changed, 188 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
index 03c9124..c5331be 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
@@ -35,8 +35,10 @@ import org.slf4j.LoggerFactory;
  */
 public abstract class ApiMethodParser<T> {
 
+    private static final String METHOD_PREFIX = "^(\\s*(public|final|synchronized|native)\\s+)*(\\s*<[^\\>]>)?\\s*(\\S+)\\s+([^\\(]+\\s*)\\(";
     private static final Pattern METHOD_PATTERN = Pattern.compile("\\s*(\\S+)\\s+(\\S+)\\s*\\(\\s*([\\S\\s,]*)\\)\\s*;?\\s*");
     private static final Pattern ARGS_PATTERN = Pattern.compile("\\s*(\\S+)\\s+([^\\s,]+)\\s*,?");
+    private static final Pattern GENERIC_ARG_PATTERN = Pattern.compile("(\\S+)<([^>]+)>");
     private static final String JAVA_LANG = "java.lang.";
     private static final Map<String, Class> PRIMITIVE_TYPES;
 
@@ -53,6 +55,7 @@ public abstract class ApiMethodParser<T> {
         PRIMITIVE_TYPES.put("short", Short.TYPE);
     }
 
+
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     private final Class<T> proxyType;
@@ -92,8 +95,14 @@ public abstract class ApiMethodParser<T> {
         // parse sorted signatures and generate descriptions
         List<ApiMethodModel> result = new ArrayList<ApiMethodModel>();
         for (String signature: signatures) {
-            // remove all type parameters and modifiers
-            signature = signature.replaceAll("<[^>]*>|\\s*(public|final|synchronized|native)\\s*", "");
+
+            // remove all modifiers and type parameters for method
+            signature = signature.replaceAll(METHOD_PREFIX, "$4 $5(");
+            // remove all final modifiers for arguments
+            signature = signature.replaceAll("(\\(|,\\s*)final\\s+", "$1");
+            // remove all redundant spaces in generic parameters
+            signature = signature.replaceAll("\\s*<\\s*", "<").replaceAll("\\s*>", ">");
+
             log.debug("Processing " + signature);
 
             final Matcher methodMatcher = METHOD_PATTERN.matcher(signature);
@@ -101,7 +110,12 @@ public abstract class ApiMethodParser<T> {
                 throw new IllegalArgumentException("Invalid method signature " + signature);
             }
 
-            final Class<?> resultType = forName(methodMatcher.group(1));
+            // drop any generic type parameters in result, if any
+            final String resultTypeWithArgs = methodMatcher.group(1);
+            final Matcher resultMatcher = GENERIC_ARG_PATTERN.matcher(resultTypeWithArgs);
+            final Class<?> resultType = (resultMatcher.matches()) ?
+                forName(resultMatcher.group(1)) : forName(resultTypeWithArgs);
+
             final String name = methodMatcher.group(2);
             final String argSignature = methodMatcher.group(3);
 
@@ -110,8 +124,17 @@ public abstract class ApiMethodParser<T> {
             List<Class<?>> argTypes = new ArrayList<Class<?>>();
             final Matcher argsMatcher = ARGS_PATTERN.matcher(argSignature);
             while (argsMatcher.find()) {
-                final Class<?> type = forName(argsMatcher.group(1));
-                arguments.add(new Argument(argsMatcher.group(2), type));
+                final String argTypeWithParams = argsMatcher.group(1);
+                final Matcher genericMatcher = GENERIC_ARG_PATTERN.matcher(argTypeWithParams);
+                Class<?> type;
+                String typeArgs = null;
+                if (genericMatcher.matches()) {
+                    type = forName(genericMatcher.group(1));
+                    typeArgs = genericMatcher.group(2);
+                } else {
+                    type = forName(argTypeWithParams);
+                }
+                arguments.add(new Argument(argsMatcher.group(2), type, typeArgs));
                 argTypes.add(type);
             }
 
@@ -298,10 +321,12 @@ public abstract class ApiMethodParser<T> {
     public static final class Argument {
         private final String name;
         private final Class<?> type;
+        private final String typeArgs;
 
-        protected Argument(String name, Class<?> type) {
+        protected Argument(String name, Class<?> type, String typeArgs) {
             this.name = name;
             this.type = type;
+            this.typeArgs = typeArgs;
         }
 
         public String getName() {
@@ -312,10 +337,18 @@ public abstract class ApiMethodParser<T> {
             return type;
         }
 
+        public String getTypeArgs() {
+            return typeArgs;
+        }
+
         @Override
         public String toString() {
             StringBuilder builder = new StringBuilder();
-            builder.append(type.getCanonicalName()).append(" ").append(name);
+            builder.append(type.getCanonicalName());
+            if (typeArgs != null) {
+                builder.append("<").append(typeArgs).append(">");
+            }
+            builder.append(" ").append(name);
             return builder.toString();
         }
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/camel-core/src/main/java/org/apache/camel/util/component/ArgumentSubstitutionParser.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ArgumentSubstitutionParser.java b/camel-core/src/main/java/org/apache/camel/util/component/ArgumentSubstitutionParser.java
index d9686e9..06ff551 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ArgumentSubstitutionParser.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ArgumentSubstitutionParser.java
@@ -87,7 +87,9 @@ public class ArgumentSubstitutionParser<T> extends ApiMethodParser<T> {
                     final List<Argument> updatedArguments = new ArrayList<Argument>();
                     final Map<Pattern, List<NameReplacement>> argMap = methodEntry.getValue();
                     for (Argument argument : model.getArguments()) {
+
                         final Class<?> argType = argument.getType();
+                        final String typeArgs = argument.getTypeArgs();
                         final String argTypeName = argType.getCanonicalName();
 
                         for (Map.Entry<Pattern, List<NameReplacement>> argEntry : argMap.entrySet()) {
@@ -98,20 +100,23 @@ public class ArgumentSubstitutionParser<T> extends ApiMethodParser<T> {
                                 final List<NameReplacement> adapters = argEntry.getValue();
                                 for (NameReplacement adapter : adapters) {
                                     if (adapter.typePattern == null) {
+
                                         // no type pattern
                                         final String newName = getJavaArgName(matcher.replaceAll(adapter.replacement));
-                                        argument = new Argument(newName, argType);
+                                        argument = new Argument(newName, argType, typeArgs);
+
                                     } else {
+
                                         final Matcher typeMatcher = adapter.typePattern.matcher(argTypeName);
                                         if (typeMatcher.find()) {
                                             if (!adapter.replaceWithType) {
                                                 // replace argument name
                                                 final String newName = getJavaArgName(matcher.replaceAll(adapter.replacement));
-                                                argument = new Argument(newName, argType);
+                                                argument = new Argument(newName, argType, typeArgs);
                                             } else {
                                                 // replace name with argument type name
                                                 final String newName = getJavaArgName(typeMatcher.replaceAll(adapter.replacement));
-                                                argument = new Argument(newName, argType);
+                                                argument = new Argument(newName, argType, typeArgs);
                                             }
                                         }
                                     }

http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/tooling/maven/camel-api-component-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/pom.xml b/tooling/maven/camel-api-component-maven-plugin/pom.xml
index dcffb8e..a7e5549 100644
--- a/tooling/maven/camel-api-component-maven-plugin/pom.xml
+++ b/tooling/maven/camel-api-component-maven-plugin/pom.xml
@@ -101,6 +101,13 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <!-- Camel annotations in provided scope to avoid compile errors in IDEs -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>spi-annotations</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
     <!-- VelocityEngine javadoc for testing -->
     <dependency>
       <groupId>org.apache.velocity</groupId>

http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractApiMethodGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractApiMethodGeneratorMojo.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractApiMethodGeneratorMojo.java
index 7a38ce0..82132ed 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractApiMethodGeneratorMojo.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractApiMethodGeneratorMojo.java
@@ -74,6 +74,7 @@ public abstract class AbstractApiMethodGeneratorMojo extends AbstractSourceGener
         parser.setClassLoader(getProjectClassLoader());
 
         // parse signatures
+        @SuppressWarnings("unchecked")
         final List<ApiMethodParser.ApiMethodModel> models = parser.parse();
 
         // generate enumeration from model
@@ -90,6 +91,7 @@ public abstract class AbstractApiMethodGeneratorMojo extends AbstractSourceGener
         }
     }
 
+    @SuppressWarnings("unchecked")
     protected ApiMethodParser createAdapterParser(Class proxyType) {
         return new ArgumentSubstitutionParser(proxyType, getArgumentSubstitutions());
     }
@@ -152,7 +154,7 @@ public abstract class AbstractApiMethodGeneratorMojo extends AbstractSourceGener
         context.put("componentPackage", componentPackage);
 
         // generate parameter names and types for configuration, sorted by parameter name
-        Map<String, Class<?>> parameters = new TreeMap<String, Class<?>>();
+        Map<String,ApiMethodParser.Argument> parameters = new TreeMap<String, ApiMethodParser.Argument>();
         for (ApiMethodParser.ApiMethodModel model : models) {
             for (ApiMethodParser.Argument argument : model.getArguments()) {
                 final String name = argument.getName();
@@ -161,11 +163,7 @@ public abstract class AbstractApiMethodGeneratorMojo extends AbstractSourceGener
                 if (!parameters.containsKey(name) &&
                         (propertyNamePattern == null || !propertyNamePattern.matcher(name).matches()) &&
                         (propertyTypePattern == null || !propertyTypePattern.matcher(typeName).matches())) {
-                    if (type.isPrimitive()) {
-                        // replace primitives with wrapper classes
-                        type = ClassUtils.primitiveToWrapper(type);
-                    }
-                    parameters.put(name, type);
+                    parameters.put(name, argument);
                 }
             }
         }
@@ -275,4 +273,63 @@ public abstract class AbstractApiMethodGeneratorMojo extends AbstractSourceGener
         return builder.toString();
     }
 
+    public String getCanonicalName(ApiMethodParser.Argument argument) throws MojoExecutionException {
+
+        // replace primitives with wrapper classes
+        final Class<?> type = argument.getType();
+        if (type.isPrimitive()) {
+            return getCanonicalName(ClassUtils.primitiveToWrapper(type));
+        }
+
+        // get default name prefix
+        String canonicalName = getCanonicalName(type);
+
+        final String typeArgs = argument.getTypeArgs();
+        if (typeArgs != null) {
+
+            // add generic type arguments
+            StringBuilder parameterizedType = new StringBuilder(canonicalName);
+            parameterizedType.append('<');
+
+            String[] argTypes = typeArgs.split(",");
+            boolean ignore = false;
+            for (String argType : argTypes) {
+
+                // try loading as is first
+                try {
+                    parameterizedType.append(getCanonicalName(getProjectClassLoader().loadClass(argType)));
+                } catch (ClassNotFoundException e) {
+
+                    // try loading with default java.lang package prefix
+                    try {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Could not load " + argType + ", trying to load java.lang." + argType);
+                        }
+                        parameterizedType.append(
+                            getCanonicalName(getProjectClassLoader().loadClass("java.lang." + argType)));
+                    } catch (ClassNotFoundException e1) {
+                        log.warn("Ignoring type parameters " + typeArgs + "> for argument " + argument.getName() +
+                            ", unable to load parameteric type argument " + argType, e1);
+                        ignore = true;
+                    }
+                }
+
+                if (ignore) {
+                    // give up
+                    break;
+                } else {
+                    parameterizedType.append(",");
+                }
+            }
+
+            if (!ignore) {
+                // replace the last ',' with '>'
+                parameterizedType.deleteCharAt(parameterizedType.length() - 1);
+                parameterizedType.append('>');
+                canonicalName = parameterizedType.toString();
+            }
+        }
+
+        return canonicalName;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractGeneratorMojo.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractGeneratorMojo.java
index b37d272..26ebdaf 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractGeneratorMojo.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/AbstractGeneratorMojo.java
@@ -71,16 +71,6 @@ public abstract class AbstractGeneratorMojo extends AbstractMojo {
     private VelocityEngine engine;
     private ClassLoader projectClassLoader;
 
-    public static String getCanonicalName(Class<?> type) {
-        // remove java.lang prefix for default Java package
-        String canonicalName = type.getCanonicalName();
-        final int pkgEnd = canonicalName.lastIndexOf('.');
-        if (pkgEnd > 0 && canonicalName.substring(0, pkgEnd).equals("java.lang")) {
-            canonicalName = canonicalName.substring(pkgEnd + 1);
-        }
-        return canonicalName;
-    }
-
     public VelocityEngine getEngine() {
         if (engine == null) {
             // initialize velocity to load resources from class loader and use Log4J
@@ -151,4 +141,14 @@ public abstract class AbstractGeneratorMojo extends AbstractMojo {
             }
         }
     }
+
+    public static String getCanonicalName(Class<?> type) {
+        // remove java.lang prefix for default Java package
+        String canonicalName = type.getCanonicalName();
+        final int pkgEnd = canonicalName.lastIndexOf('.');
+        if (pkgEnd > 0 && canonicalName.substring(0, pkgEnd).equals("java.lang")) {
+            canonicalName = canonicalName.substring(pkgEnd + 1);
+        }
+        return canonicalName;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/DocumentGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/DocumentGeneratorMojo.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/DocumentGeneratorMojo.java
index 3db7343..17a87cb 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/DocumentGeneratorMojo.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/DocumentGeneratorMojo.java
@@ -20,6 +20,8 @@ import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -407,6 +409,37 @@ public class DocumentGeneratorMojo extends AbstractGeneratorMojo implements Mave
         }
     }
 
+    public static String getCanonicalName(Field field) {
+        final Type fieldType = field.getGenericType();
+        if (fieldType instanceof ParameterizedType) {
+            return getCanonicalName((ParameterizedType) fieldType);
+        } else {
+            return getCanonicalName(field.getType());
+        }
+    }
+
+    private static String getCanonicalName(ParameterizedType fieldType) {
+        final Type[] typeArguments = fieldType.getActualTypeArguments();
+
+        if (typeArguments.length > 0) {
+            final StringBuilder result = new StringBuilder(getCanonicalName((Class<?>) fieldType.getRawType()));
+            result.append("&lt;");
+            for (Type typeArg : typeArguments) {
+                if (typeArg instanceof ParameterizedType) {
+                    result.append(getCanonicalName((ParameterizedType) typeArg));
+                } else {
+                    result.append(getCanonicalName((Class<?>) typeArg));
+                }
+                result.append(',');
+            }
+            result.deleteCharAt(result.length() - 1);
+            result.append("&gt;");
+            return result.toString();
+        }
+
+        return getCanonicalName((Class<?>) fieldType.getRawType());
+    }
+
     public static class EndpointInfo {
         private String endpoint;
         private String aliases;

http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocApiMethodGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocApiMethodGeneratorMojo.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocApiMethodGeneratorMojo.java
index 902682c..8b02c3e 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocApiMethodGeneratorMojo.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocApiMethodGeneratorMojo.java
@@ -19,10 +19,8 @@ package org.apache.camel.maven;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -36,6 +34,7 @@ import javax.swing.text.html.parser.Parser;
 import javax.swing.text.html.parser.TagElement;
 
 import org.apache.camel.util.component.ApiMethodParser;
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
@@ -72,14 +71,8 @@ public class JavadocApiMethodGeneratorMojo extends AbstractApiMethodGeneratorMoj
         Map<String, String> result = new HashMap<String, String>();
 
         final Pattern packagePatterns = Pattern.compile(excludePackages);
-        Pattern classPatterns = null;
-        if (excludeClasses != null) {
-            classPatterns = Pattern.compile(excludeClasses);
-        }
-        Pattern methodPatterns = null;
-        if (excludeMethods != null) {
-            methodPatterns = Pattern.compile(excludeMethods);
-        }
+        final Pattern classPatterns = (excludeClasses != null) ? Pattern.compile(excludeClasses) : null;
+        final Pattern methodPatterns = (excludeMethods != null) ? Pattern.compile(excludeMethods) : null;
 
         // for proxy class and super classes not matching excluded packages or classes
         for (Class aClass = getProxyType();
@@ -104,6 +97,12 @@ public class JavadocApiMethodGeneratorMojo extends AbstractApiMethodGeneratorMoj
                 final JavadocParser htmlParser = new JavadocParser(dtd, javaDocPath);
                 htmlParser.parse(new InputStreamReader(inputStream, "UTF-8"));
 
+                // look for parse errors
+                final String parseError = htmlParser.getErrorMessage();
+                if (parseError != null) {
+                    throw new MojoExecutionException(parseError);
+                }
+
                 // get public method signature
                 final Map<String, String> methodMap = htmlParser.getMethodText();
                 for (String method : htmlParser.getMethods()) {
@@ -185,6 +184,7 @@ public class JavadocApiMethodGeneratorMojo extends AbstractApiMethodGeneratorMoj
 
         private List<String> methods = new ArrayList<String>();
         private Map<String, String> methodText = new HashMap<String, String>();
+        private String errorMessage;
 
         public JavadocParser(DTD dtd, String docPath) {
             super(dtd);
@@ -211,11 +211,7 @@ public class JavadocApiMethodGeneratorMojo extends AbstractApiMethodGeneratorMoj
                             if (href != null) {
                                 String hrefAttr = (String) href;
                                 if (hrefAttr.contains(hrefPattern)) {
-                                    try {
-                                        methodWithTypes = URLDecoder.decode(hrefAttr.substring(hrefAttr.indexOf('#') + 1), "UTF-8");
-                                    } catch (UnsupportedEncodingException e) {
-                                        throw new IllegalStateException(e);
-                                    }
+                                    methodWithTypes = StringEscapeUtils.unescapeHtml(hrefAttr.substring(hrefAttr.indexOf('#') + 1));
                                 }
                             }
                         }
@@ -249,11 +245,13 @@ public class JavadocApiMethodGeneratorMojo extends AbstractApiMethodGeneratorMoj
                 return "()";
             }
             final String[] types = typeString.split(",");
-            String argText = methodTextBuilder.toString().replaceAll("&nbsp;", " ").replaceAll("&nbsp", " ");
+            // use HTTP decode
+            String argText = StringEscapeUtils.unescapeHtml(methodTextBuilder.toString());
             final String[] args = argText.substring(argText.indexOf('(') + 1, argText.indexOf(')')).split(",");
             StringBuilder builder = new StringBuilder("(");
             for (int i = 0; i < types.length; i++) {
-                final String[] arg = args[i].trim().split(" ");
+                // split on space or non-breaking space
+                final String[] arg = args[i].trim().split(" |\u00A0");
                 builder.append(types[i]).append(" ").append(arg[1].trim()).append(",");
             }
             builder.deleteCharAt(builder.length() - 1);
@@ -268,6 +266,17 @@ public class JavadocApiMethodGeneratorMojo extends AbstractApiMethodGeneratorMoj
             }
         }
 
+        @Override
+        protected void handleError(int ln, String msg) {
+            if (msg.startsWith("exception ")) {
+                this.errorMessage = "Exception parsing Javadoc line " + ln + ": " + msg;
+            }
+        }
+
+        private String getErrorMessage() {
+            return errorMessage;
+        }
+
         private List<String> getMethods() {
             return methods;
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/ad26a8ab/tooling/maven/camel-api-component-maven-plugin/src/main/resources/api-document.vm
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/resources/api-document.vm b/tooling/maven/camel-api-component-maven-plugin/src/main/resources/api-document.vm
index 66d7f18..b87e19c 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/resources/api-document.vm
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/resources/api-document.vm
@@ -179,7 +179,7 @@
 #foreach( $field in $endpointConfig.DeclaredFields )
         <tr>
             <td>$field.Name</td>
-            <td>$helper.getCanonicalName($field.Type)</td>
+            <td>$helper.getCanonicalName($field)</td>
         </tr>
 #end
     </table>