You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2018/10/31 08:15:30 UTC

[camel] branch sandbox/camel-3.x updated (fdbbb8f -> 9a3de64)

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a change to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from fdbbb8f  Fix build
     new 511248a  Fix version
     new 9a3de64  Use statically generated type converter for core converters and optimize the converter registry

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../main/java/org/apache/camel/TypeConverter.java  |   2 +
 camel-core/pom.xml                                 |  12 +
 .../apache/camel/component/bean/BeanConverter.java |   4 +-
 .../camel/converter/IOConverterOptimised.java      | 172 -------
 .../camel/converter/NIOConverterOptimised.java     |  82 ----
 .../apache/camel/converter/ObjectConverter.java    | 165 +++----
 .../camel/converter/ObjectConverterOptimised.java  |  84 ----
 .../converter/TimePatternConverterOptimised.java   |  42 --
 .../impl/converter/BaseTypeConverterRegistry.java  | 529 +++++++++++----------
 .../converter/CorePackageScanClassResolver.java    | 125 -----
 .../impl/converter/CoreTypeConverterLoader.java    |  39 --
 .../camel/impl/converter/EnumTypeConverter.java    |   6 +-
 .../camel/impl/converter/FutureTypeConverter.java  |   4 +-
 .../impl/converter/OptimisedTypeConverter.java     |  77 ---
 .../impl/converter/ToStringTypeConverter.java      |   8 +-
 .../apache/camel/builder/SimpleBuilderTest.java    |   2 +-
 .../apache/camel/builder/xml/XPathFeatureTest.java |   6 +-
 .../apache/camel/converter/ConverterBenchmark.java | 160 +++++++
 .../org/apache/camel/converter/ConverterTest.java  |  20 +
 .../camel/converter/DurationConverterTest.java     |   2 +-
 .../camel/converter/ObjectConverterTest.java       |  24 +-
 .../java/org/apache/camel/util/ObjectHelper.java   |  10 +-
 .../component/cxf/converter/CxfConverter.java      |   6 +-
 .../cxf/converter/CxfPayloadConverter.java         |  12 +-
 .../camel/component/exec/ExecResultConverter.java  |   4 +-
 .../camel/component/jetty/JettyConverter.java      |   4 +-
 docs/pom.xml                                       |   2 +-
 .../pom.xml                                        |   2 +-
 .../apache/camel/tools/apt/ConverterProcessor.java | 159 +++++--
 29 files changed, 714 insertions(+), 1050 deletions(-)
 delete mode 100644 camel-core/src/main/java/org/apache/camel/converter/IOConverterOptimised.java
 delete mode 100644 camel-core/src/main/java/org/apache/camel/converter/NIOConverterOptimised.java
 delete mode 100644 camel-core/src/main/java/org/apache/camel/converter/ObjectConverterOptimised.java
 delete mode 100644 camel-core/src/main/java/org/apache/camel/converter/TimePatternConverterOptimised.java
 delete mode 100644 camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java
 delete mode 100644 camel-core/src/main/java/org/apache/camel/impl/converter/CoreTypeConverterLoader.java
 delete mode 100644 camel-core/src/main/java/org/apache/camel/impl/converter/OptimisedTypeConverter.java
 create mode 100644 camel-core/src/test/java/org/apache/camel/converter/ConverterBenchmark.java


[camel] 02/02: Use statically generated type converter for core converters and optimize the converter registry

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 9a3de64451939b021e550a6e82fdd365c8988d68
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon Oct 29 22:33:02 2018 +0100

    Use statically generated type converter for core converters and optimize the converter registry
    
    Before
    ------
    Benchmark                                           Mode  Cnt    Score    Error  Units
    ConverterBenchmark.benchmarkConversionIntToLong          avgt    5   17,861 ±  1,333  us/op
    ConverterBenchmark.benchmarkConversionListToStringArray  avgt    5   90,854 ± 21,918  us/op
    ConverterBenchmark.benchmarkConversionStringToChar       avgt    5   27,644 ±  1,563  us/op
    ConverterBenchmark.benchmarkConversionStringToURI        avgt    5  157,240 ± 11,084  us/op
    ConverterBenchmark.benchmarkConversionTimeEnum           avgt    5   73,541 ± 10,457  us/op
    ConverterBenchmark.benchmarkLoadTime                     avgt    5  586,724 ± 73,011  us/op
    
    After
    -----
    Benchmark                                           Mode  Cnt    Score    Error  Units
    ConverterBenchmark.benchmarkConversionIntToLong          avgt    5   13,242 ±  0,041  us/op
    ConverterBenchmark.benchmarkConversionListToStringArray  avgt    5   50,731 ±  2,220  us/op
    ConverterBenchmark.benchmarkConversionStringToChar       avgt    5   24,443 ±  1,268  us/op
    ConverterBenchmark.benchmarkConversionStringToURI        avgt    5   98,887 ±  6,203  us/op
    ConverterBenchmark.benchmarkConversionTimeEnum           avgt    5   35,148 ±  1,820  us/op
    ConverterBenchmark.benchmarkLoadTime                     avgt    5  551,463 ± 12,174  us/op
---
 .../main/java/org/apache/camel/TypeConverter.java  |   2 +
 camel-core/pom.xml                                 |  12 +
 .../apache/camel/component/bean/BeanConverter.java |   4 +-
 .../camel/converter/IOConverterOptimised.java      | 172 -------
 .../camel/converter/NIOConverterOptimised.java     |  82 ----
 .../apache/camel/converter/ObjectConverter.java    | 165 +++----
 .../camel/converter/ObjectConverterOptimised.java  |  84 ----
 .../converter/TimePatternConverterOptimised.java   |  42 --
 .../impl/converter/BaseTypeConverterRegistry.java  | 529 +++++++++++----------
 .../converter/CorePackageScanClassResolver.java    | 125 -----
 .../impl/converter/CoreTypeConverterLoader.java    |  39 --
 .../camel/impl/converter/EnumTypeConverter.java    |   6 +-
 .../camel/impl/converter/FutureTypeConverter.java  |   4 +-
 .../impl/converter/OptimisedTypeConverter.java     |  77 ---
 .../impl/converter/ToStringTypeConverter.java      |   8 +-
 .../apache/camel/builder/SimpleBuilderTest.java    |   2 +-
 .../apache/camel/builder/xml/XPathFeatureTest.java |   6 +-
 .../apache/camel/converter/ConverterBenchmark.java | 160 +++++++
 .../org/apache/camel/converter/ConverterTest.java  |  20 +
 .../camel/converter/DurationConverterTest.java     |   2 +-
 .../camel/converter/ObjectConverterTest.java       |  24 +-
 .../java/org/apache/camel/util/ObjectHelper.java   |  10 +-
 .../component/cxf/converter/CxfConverter.java      |   6 +-
 .../cxf/converter/CxfPayloadConverter.java         |  12 +-
 .../camel/component/exec/ExecResultConverter.java  |   4 +-
 .../camel/component/jetty/JettyConverter.java      |   4 +-
 .../apache/camel/tools/apt/ConverterProcessor.java | 159 +++++--
 27 files changed, 712 insertions(+), 1048 deletions(-)

diff --git a/camel-api/src/main/java/org/apache/camel/TypeConverter.java b/camel-api/src/main/java/org/apache/camel/TypeConverter.java
index 1f1fe5b..1222d0e 100644
--- a/camel-api/src/main/java/org/apache/camel/TypeConverter.java
+++ b/camel-api/src/main/java/org/apache/camel/TypeConverter.java
@@ -25,6 +25,8 @@ package org.apache.camel;
  */
 public interface TypeConverter {
 
+    Object MISS_VALUE = Void.TYPE;
+
     /**
      * Whether the type converter allows returning null as a valid response.
      * <p/>
diff --git a/camel-core/pom.xml b/camel-core/pom.xml
index 4bda334..51c6e83 100644
--- a/camel-core/pom.xml
+++ b/camel-core/pom.xml
@@ -203,6 +203,18 @@
       </exclusions>
     </dependency>
     <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-core</artifactId>
+      <version>1.21</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.openjdk.jmh</groupId>
+      <artifactId>jmh-generator-annprocess</artifactId>
+      <version>1.21</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.hamcrest</groupId>
       <artifactId>java-hamcrest</artifactId>
       <version>${hamcrest-version}</version>
diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java b/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java
index 6ca7403..fc85841 100644
--- a/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java
@@ -22,6 +22,8 @@ import org.apache.camel.FallbackConverter;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.spi.TypeConverterRegistry;
 
+import static org.apache.camel.TypeConverter.MISS_VALUE;
+
 /**
  * A set of converter methods for working with beans
  */
@@ -40,7 +42,7 @@ public final class BeanConverter {
             BeanInvocation bi = (BeanInvocation) value;
             if (bi.getArgs() == null || bi.getArgs().length != 1) {
                 // not possible to convert at this time as we try to convert the data passed in at first argument
-                return Void.TYPE;
+                return MISS_VALUE;
             }
 
             Class<?> from = bi.getArgs()[0].getClass();
diff --git a/camel-core/src/main/java/org/apache/camel/converter/IOConverterOptimised.java b/camel-core/src/main/java/org/apache/camel/converter/IOConverterOptimised.java
deleted file mode 100644
index cddbb03..0000000
--- a/camel-core/src/main/java/org/apache/camel/converter/IOConverterOptimised.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * 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.converter;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.InputStream;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.net.URL;
-import java.util.Properties;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.StreamCache;
-
-/**
- * Optimised {@link IOConverter}
- */
-public final class IOConverterOptimised {
-
-    private IOConverterOptimised() {
-    }
-
-    // CHECKSTYLE:OFF
-    public static Object convertTo(final Class<?> type, final Exchange exchange, final Object value) throws Exception {
-        Class fromType = value.getClass();
-
-        // if the value is StreamCache then ensure its readable before doing conversions
-        // by resetting it (this is also what StreamCachingAdvice does)
-        if (value instanceof StreamCache) {
-            ((StreamCache) value).reset();
-        }
-
-        if (type == InputStream.class) {
-            if (fromType == String.class) {
-                return IOConverter.toInputStream((String) value, exchange);
-            } else if (fromType == URL.class) {
-                return IOConverter.toInputStream((URL) value);
-            } else if (fromType == File.class) {
-                return IOConverter.toInputStream((File) value);
-            } else if (fromType == byte[].class) {
-                return IOConverter.toInputStream((byte[]) value);
-            } else if (fromType == ByteArrayOutputStream.class) {
-                return IOConverter.toInputStream((ByteArrayOutputStream) value);
-            } else if (fromType == BufferedReader.class) {
-                return IOConverter.toInputStream((BufferedReader) value, exchange);
-            } else if (fromType == StringBuilder.class) {
-                return IOConverter.toInputStream((StringBuilder) value, exchange);
-            }
-            return null;
-        }
-
-        if (type == Reader.class) {
-            if (fromType == File.class) {
-                return IOConverter.toReader((File) value, exchange);
-            } else if (fromType == String.class) {
-                return IOConverter.toReader((String) value);
-            } else if (InputStream.class.isAssignableFrom(fromType)) {
-                return IOConverter.toReader((InputStream) value, exchange);
-            }
-            return null;
-        }
-
-        if (type == File.class) {
-            if (fromType == String.class) {
-                return IOConverter.toFile((String) value);
-            }
-            return null;
-        }
-
-        if (type == OutputStream.class) {
-            if (fromType == File.class) {
-                return IOConverter.toOutputStream((File) value);
-            }
-            return null;
-        }
-
-        if (type == Writer.class) {
-            if (fromType == File.class) {
-                return IOConverter.toWriter((File) value, exchange);
-            } else if (OutputStream.class.isAssignableFrom(fromType)) {
-                return IOConverter.toWriter((OutputStream) value, exchange);
-            }
-            return null;
-        }
-
-        if (type == String.class) {
-            if (fromType == byte[].class) {
-                return IOConverter.toString((byte[]) value, exchange);
-            } else if (fromType == File.class) {
-                return IOConverter.toString((File) value, exchange);
-            } else if (fromType == URL.class) {
-                return IOConverter.toString((URL) value, exchange);
-            } else if (fromType == BufferedReader.class) {
-                return IOConverter.toString((BufferedReader) value);
-            } else if (Reader.class.isAssignableFrom(fromType)) {
-                return IOConverter.toString((Reader) value);
-            } else if (InputStream.class.isAssignableFrom(fromType)) {
-                return IOConverter.toString((InputStream) value, exchange);
-            } else if (fromType == ByteArrayOutputStream.class) {
-                return IOConverter.toString((ByteArrayOutputStream) value, exchange);
-            }
-            return null;
-        }
-
-        if (type == byte[].class) {
-            if (fromType == BufferedReader.class) {
-                return IOConverter.toByteArray((BufferedReader) value, exchange);
-            } else if (Reader.class.isAssignableFrom(fromType)) {
-                return IOConverter.toByteArray((Reader) value, exchange);
-            } else if (fromType == File.class) {
-                return IOConverter.toByteArray((File) value);
-            } else if (fromType == String.class) {
-                return IOConverter.toByteArray((String) value, exchange);
-            } else if (fromType == ByteArrayOutputStream.class) {
-                return IOConverter.toByteArray((ByteArrayOutputStream) value);
-            } else if (InputStream.class.isAssignableFrom(fromType)) {
-                return IOConverter.toBytes((InputStream) value);
-            }
-            return null;
-        }
-
-        if (type == ObjectInput.class) {
-            if (fromType == InputStream.class || fromType == BufferedInputStream.class) {
-                return IOConverter.toObjectInput((InputStream) value, exchange);
-            }
-            return null;
-        }
-
-        if (type == ObjectOutput.class) {
-            if (fromType == OutputStream.class) {
-                return IOConverter.toObjectOutput((OutputStream) value);
-            }
-            return null;
-        }
-
-        if (type == Properties.class) {
-            if (fromType == File.class) {
-                return IOConverter.toProperties((File) value);
-            } else if (fromType == InputStream.class) {
-                return IOConverter.toProperties((InputStream) value);
-            } else if (fromType == Reader.class) {
-                return IOConverter.toProperties((Reader) value);
-            }
-            return null;
-        }
-
-        // no optimised type converter found
-        return null;
-    }
-    // CHECKSTYLE:ON
-
-}
diff --git a/camel-core/src/main/java/org/apache/camel/converter/NIOConverterOptimised.java b/camel-core/src/main/java/org/apache/camel/converter/NIOConverterOptimised.java
deleted file mode 100644
index cbef7a9..0000000
--- a/camel-core/src/main/java/org/apache/camel/converter/NIOConverterOptimised.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * 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.converter;
-
-import java.io.File;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-import org.apache.camel.Exchange;
-
-/**
- * Optimised {@link NIOConverter}
- */
-public final class NIOConverterOptimised {
-
-    private NIOConverterOptimised() {
-    }
-
-    public static Object convertTo(final Class<?> type, final Exchange exchange, final Object value) throws Exception {
-        Class fromType = value.getClass();
-
-        if (type == String.class) {
-            if (fromType == ByteBuffer.class) {
-                return NIOConverter.toString((ByteBuffer) value, exchange);
-            }
-            return null;
-        }
-
-        if (type == byte[].class) {
-            if (fromType == ByteBuffer.class) {
-                return NIOConverter.toByteArray((ByteBuffer) value);
-            }
-            return null;
-        }
-
-        if (type == InputStream.class) {
-            if (fromType == ByteBuffer.class) {
-                return NIOConverter.toInputStream((ByteBuffer) value);
-            }
-            return null;
-        }
-
-        if (type == ByteBuffer.class) {
-            if (fromType == byte[].class) {
-                return NIOConverter.toByteBuffer((byte[]) value);
-            } else if (fromType == File.class) {
-                return NIOConverter.toByteBuffer((File) value);
-            } else if (fromType == String.class) {
-                return NIOConverter.toByteBuffer((String) value, exchange);
-            } else if (fromType == short.class || fromType == Short.class) {
-                return NIOConverter.toByteBuffer((Short) value);
-            } else if (fromType == int.class || fromType == Integer.class) {
-                return NIOConverter.toByteBuffer((Integer) value);
-            } else if (fromType == long.class || fromType == Long.class) {
-                return NIOConverter.toByteBuffer((Long) value);
-            } else if (fromType == float.class || fromType == Float.class) {
-                return NIOConverter.toByteBuffer((Float) value);
-            } else if (fromType == double.class || fromType == Double.class) {
-                return NIOConverter.toByteBuffer((Double) value);
-            }
-            return null;
-        }
-
-        // no optimised type converter found
-        return null;
-    }
-
-}
diff --git a/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java b/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java
index 75f0131..3e326d7 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/ObjectConverter.java
@@ -76,18 +76,17 @@ public final class ObjectConverter {
     /**
      * Returns the converted value, or null if the value is null
      */
-    @Converter
-    public static Byte toByte(Object value) {
-        if (value instanceof Byte) {
-            return (Byte) value;
-        } else if (value instanceof Number) {
-            Number number = (Number) value;
-            return number.byteValue();
-        } else if (value instanceof String) {
-            return Byte.valueOf((String) value);
-        } else {
+    @Converter(allowNull = true)
+    public static Byte toByte(Number value) {
+        if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
             return null;
         }
+        return value.byteValue();
+    }
+
+    @Converter
+    public static Byte toByte(String value) {
+        return Byte.valueOf(value);
     }
 
     @Converter
@@ -118,85 +117,77 @@ public final class ObjectConverter {
      * Returns the converted value, or null if the value is null
      */
     @Converter
-    public static Class<?> toClass(Object value, Exchange exchange) {
-        if (value instanceof Class) {
-            return (Class<?>) value;
-        } else if (value instanceof String) {
-            // prefer to use class resolver API
-            if (exchange != null) {
-                return exchange.getContext().getClassResolver().resolveClass((String) value);
-            } else {
-                return org.apache.camel.util.ObjectHelper.loadClass((String) value);
-            }
+    public static Class<?> toClass(String value, Exchange exchange) {
+        // prefer to use class resolver API
+        if (exchange != null) {
+            return exchange.getContext().getClassResolver().resolveClass((String) value);
         } else {
-            return null;
+            return org.apache.camel.util.ObjectHelper.loadClass((String) value);
         }
     }
 
     /**
      * Returns the converted value, or null if the value is null
      */
-    @Converter
-    public static Short toShort(Object value) {
-        if (value instanceof Short) {
-            return (Short) value;
-        } else if (value instanceof Number) {
-            Number number = (Number) value;
-            return number.shortValue();
-        } else if (value instanceof String) {
-            return Short.valueOf((String) value);
-        } else {
+    @Converter(allowNull = true)
+    public static Short toShort(Number value) {
+        if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
             return null;
         }
+        return value.shortValue();
+    }
+
+    @Converter
+    public static Short toShort(String value) {
+        return Short.valueOf(value);
     }
 
     /**
      * Returns the converted value, or null if the value is null
      */
-    @Converter
-    public static Integer toInteger(Object value) {
-        if (value instanceof Integer) {
-            return (Integer) value;
-        } else if (value instanceof Number) {
-            Number number = (Number) value;
-            return number.intValue();
-        } else if (value instanceof String) {
-            return Integer.valueOf((String) value);
-        } else {
+    @Converter(allowNull = true)
+    public static Integer toInteger(Number value) {
+        if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
             return null;
         }
+        return value.intValue();
+    }
+
+    @Converter
+    public static Integer toInteger(String value) {
+        return Integer.valueOf(value);
     }
 
     /**
      * Returns the converted value, or null if the value is null
      */
-    @Converter
-    public static Long toLong(Object value) {
-        if (value instanceof Long) {
-            return (Long) value;
-        } else if (value instanceof Number) {
-            Number number = (Number) value;
-            return number.longValue();
-        } else if (value instanceof String) {
-            return Long.valueOf((String) value);
-        } else {
+    @Converter(allowNull = true)
+    public static Long toLong(Number value) {
+        if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
             return null;
         }
+        return value.longValue();
+    }
+
+    @Converter
+    public static Long toLong(String value) {
+        return Long.valueOf(value);
     }
 
     /**
      * Returns the converted value, or null if the value is null
      */
-    @Converter
+    @Converter(allowNull = true)
     public static BigInteger toBigInteger(Object value) {
+        if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
+            return null;
+        }
         if (value instanceof String) {
             return new BigInteger((String) value);
         }
 
         Long num = null;
-        if (value instanceof Long) {
-            num = (Long) value;
-        } else if (value instanceof Number) {
+        if (value instanceof Number) {
             Number number = (Number) value;
             num = number.longValue();
         }
@@ -211,40 +202,32 @@ public final class ObjectConverter {
      * Returns the converted value, or null if the value is null
      */
     @Converter
-    public static Float toFloat(Object value) {
-        if (value instanceof Float) {
-            return (Float) value;
-        } else if (value instanceof Number) {
-            if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
-                return Float.NaN;
-            }
-            Number number = (Number) value;
-            return number.floatValue();
-        } else if (value instanceof String) {
-            return Float.valueOf((String) value);
-        } else {
-            return null;
+    public static Float toFloat(Number value) {
+        if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
+            return Float.NaN;
         }
+        return value.floatValue();
+    }
+
+    @Converter
+    public static Float toFloat(String value) {
+        return Float.valueOf(value);
     }
 
     /**
      * Returns the converted value, or null if the value is null
      */
     @Converter
-    public static Double toDouble(Object value) {
-        if (value instanceof Double) {
-            return (Double) value;
-        } else if (value instanceof Number) {
-            if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
-                return Double.NaN;
-            }
-            Number number = (Number) value;
-            return number.doubleValue();
-        } else if (value instanceof String) {
-            return Double.valueOf((String) value);
-        } else {
-            return null;
+    public static Double toDouble(Number value) {
+        if (org.apache.camel.util.ObjectHelper.isNaN(value)) {
+            return Double.NaN;
         }
+        return value.doubleValue();
+    }
+
+    @Converter
+    public static Double toDouble(String value) {
+        return Double.valueOf(value);
     }
 
     // add fast type converters from most common used
@@ -275,26 +258,6 @@ public final class ObjectConverter {
     }
 
     @Converter
-    public static Integer toInteger(String value) {
-        return Integer.valueOf(value);
-    }
-
-    @Converter
-    public static Long toLong(String value) {
-        return Long.valueOf(value);
-    }
-
-    @Converter
-    public static Float toFloat(String value) {
-        return Float.valueOf(value);
-    }
-
-    @Converter
-    public static Double toDouble(String value) {
-        return Double.valueOf(value);
-    }
-
-    @Converter
     public static Boolean toBoolean(String value) {
         return Boolean.parseBoolean(value);
     }
diff --git a/camel-core/src/main/java/org/apache/camel/converter/ObjectConverterOptimised.java b/camel-core/src/main/java/org/apache/camel/converter/ObjectConverterOptimised.java
deleted file mode 100644
index c6391ed..0000000
--- a/camel-core/src/main/java/org/apache/camel/converter/ObjectConverterOptimised.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * 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.converter;
-
-import java.util.Iterator;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.support.ObjectHelper;
-
-/**
- * Optimised {@link ObjectConverter}
- */
-public final class ObjectConverterOptimised {
-
-    private ObjectConverterOptimised() {
-    }
-
-    public static Object convertTo(final Class<?> type, final Exchange exchange, final Object value) throws Exception {
-        // converting to a String is very common
-        if (type == String.class) {
-            Class fromType = value.getClass();
-            if (fromType == boolean.class || fromType == Boolean.class) {
-                return value.toString();
-            } else if (fromType == int.class || fromType == Integer.class) {
-                return value.toString();
-            } else if (fromType == long.class || fromType == Long.class) {
-                return value.toString();
-            } else if (fromType == char[].class) {
-                return ObjectConverter.fromCharArray((char[]) value);
-            } else if (fromType == StringBuffer.class || fromType == StringBuilder.class) {
-                return value.toString();
-            }
-            return null;
-        }
-
-        if (type == boolean.class || type == Boolean.class) {
-            return ObjectConverter.toBoolean(value);
-        } else if (type == int.class || type == Integer.class) {
-            return ObjectConverter.toInteger(value);
-        } else if (type == long.class || type == Long.class) {
-            return ObjectConverter.toLong(value);
-        } else if (type == byte.class || type == Byte.class) {
-            return ObjectConverter.toByte(value);
-        } else if (type == double.class || type == Double.class) {
-            return ObjectConverter.toDouble(value);
-        } else if (type == float.class || type == Float.class) {
-            return ObjectConverter.toFloat(value);
-        } else if (type == short.class || type == Short.class) {
-            return ObjectConverter.toShort(value);
-        } else if ((type == char.class || type == Character.class) && value.getClass() == String.class) {
-            return ObjectConverter.toCharacter((String) value);
-        } else if ((type == char[].class || type == Character[].class) && value.getClass() == String.class) {
-            return ObjectConverter.toCharArray((String) value);
-        }
-
-        if (type == Iterator.class) {
-            return ObjectHelper.createIterator(value);
-        } else if (type == Iterable.class) {
-            return ObjectHelper.createIterable(value);
-        }
-
-        if (type == Class.class) {
-            return ObjectConverter.toClass(value, exchange);
-        }
-
-        // no optimised type converter found
-        return null;
-    }
-
-}
diff --git a/camel-core/src/main/java/org/apache/camel/converter/TimePatternConverterOptimised.java b/camel-core/src/main/java/org/apache/camel/converter/TimePatternConverterOptimised.java
deleted file mode 100644
index bb45a40..0000000
--- a/camel-core/src/main/java/org/apache/camel/converter/TimePatternConverterOptimised.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * 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.converter;
-
-import org.apache.camel.Exchange;
-
-/**
- * Optimised {@link TimePatternConverter}
- */
-public final class TimePatternConverterOptimised {
-
-    private TimePatternConverterOptimised() {
-    }
-
-    public static Object convertTo(final Class<?> type, final Exchange exchange, final Object value) throws Exception {
-        // special for String -> long where we support time patterns
-        if (type == long.class || type == Long.class) {
-            Class fromType = value.getClass();
-            if (fromType == String.class) {
-                return TimePatternConverter.toMilliSeconds(value.toString());
-            }
-        }
-
-        // no optimised type converter found
-        return null;
-    }
-
-}
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java b/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
index 27d90dc..a728621 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
@@ -18,16 +18,13 @@ package org.apache.camel.impl.converter;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.LongAdder;
+import java.util.concurrent.locks.StampedLock;
+import java.util.function.Predicate;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
@@ -43,31 +40,33 @@ import org.apache.camel.TypeConverterExists;
 import org.apache.camel.TypeConverterExistsException;
 import org.apache.camel.TypeConverterLoaderException;
 import org.apache.camel.TypeConverters;
+import org.apache.camel.spi.CamelLogger;
 import org.apache.camel.spi.FactoryFinder;
 import org.apache.camel.spi.Injector;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.TypeConverterAware;
 import org.apache.camel.spi.TypeConverterLoader;
 import org.apache.camel.spi.TypeConverterRegistry;
-import org.apache.camel.spi.CamelLogger;
-import org.apache.camel.support.LRUCacheFactory;
 import org.apache.camel.support.MessageHelper;
 import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.support.TypeConverterSupport;
 import org.apache.camel.util.ObjectHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.camel.util.function.TriConsumer;
 
 /**
  * Base implementation of a type converter registry used for
  * <a href="http://camel.apache.org/type-converter.html">type converters</a> in Camel.
  */
 public abstract class BaseTypeConverterRegistry extends ServiceSupport implements TypeConverter, TypeConverterRegistry, CamelContextAware {
-    protected final Logger log = LoggerFactory.getLogger(getClass());
-    protected final OptimisedTypeConverter optimisedTypeConverter = new OptimisedTypeConverter();
-    protected final ConcurrentMap<TypeMapping, TypeConverter> typeMappings = new ConcurrentHashMap<>();
-    // for misses use a soft reference cache map, as the classes may be un-deployed at runtime
-    @SuppressWarnings("unchecked")
-    protected final Map<TypeMapping, TypeMapping> misses = LRUCacheFactory.newLRUSoftCache(1000);
+
+    protected static final TypeConverter MISS_CONVERTER = new TypeConverterSupport() {
+        @Override
+        public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {
+            return (T) MISS_VALUE;
+        }
+    };
+
+    protected final DoubleMap<Class<?>, Class<?>, TypeConverter> typeMappings = new DoubleMap<>(200);
     protected final List<TypeConverterLoader> typeConverterLoaders = new ArrayList<>();
     protected final List<FallbackTypeConverter> fallbackConverters = new CopyOnWriteArrayList<>();
     protected final PackageScanClassResolver resolver;
@@ -130,44 +129,7 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     @SuppressWarnings("unchecked")
     @Override
     public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
-        if (!isRunAllowed()) {
-            throw new IllegalStateException(this + " is not started");
-        }
-
-        Object answer;
-        try {
-            answer = doConvertTo(type, exchange, value, false);
-        } catch (Exception e) {
-            if (statistics.isStatisticsEnabled()) {
-                failedCounter.increment();
-            }
-            // if its a ExecutionException then we have rethrow it as its not due to failed conversion
-            // this is special for FutureTypeConverter
-            boolean execution = ObjectHelper.getException(ExecutionException.class, e) != null
-                    || ObjectHelper.getException(CamelExecutionException.class, e) != null;
-            if (execution) {
-                throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
-            }
-
-            // error occurred during type conversion
-            if (e instanceof TypeConversionException) {
-                throw (TypeConversionException) e;
-            } else {
-                throw createTypeConversionException(exchange, type, value, e);
-            }
-        }
-        if (answer == Void.TYPE) {
-            if (statistics.isStatisticsEnabled()) {
-                missCounter.increment();
-            }
-            // Could not find suitable conversion
-            return null;
-        } else {
-            if (statistics.isStatisticsEnabled()) {
-                hitCounter.increment();
-            }
-            return (T) answer;
-        }
+        return (T) doConvertTo(type, exchange, value, false, false);
     }
 
     @Override
@@ -178,36 +140,12 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     @SuppressWarnings("unchecked")
     @Override
     public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException {
-        if (!isRunAllowed()) {
-            throw new IllegalStateException(this + " is not started");
-        }
-
-        Object answer;
-        try {
-            answer = doConvertTo(type, exchange, value, false);
-        } catch (Exception e) {
-            if (statistics.isStatisticsEnabled()) {
-                failedCounter.increment();
-            }
-            // error occurred during type conversion
-            if (e instanceof TypeConversionException) {
-                throw (TypeConversionException) e;
-            } else {
-                throw createTypeConversionException(exchange, type, value, e);
-            }
-        }
-        if (answer == Void.TYPE || value == null) {
-            if (statistics.isStatisticsEnabled()) {
-                missCounter.increment();
-            }
+        Object answer = doConvertTo(type, exchange, value, true, false);
+        if (answer == null) {
             // Could not find suitable conversion
             throw new NoTypeConversionAvailableException(value, type);
-        } else {
-            if (statistics.isStatisticsEnabled()) {
-                hitCounter.increment();
-            }
-            return (T) answer;
         }
+        return (T) answer;
     }
 
     @Override
@@ -218,20 +156,32 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     @SuppressWarnings("unchecked")
     @Override
     public <T> T tryConvertTo(Class<T> type, Exchange exchange, Object value) {
-        if (!isRunAllowed()) {
-            return null;
-        }
+        return (T) doConvertTo(type, exchange, value, false, true);
+    }
 
+    protected Object doConvertTo(final Class<?> type, final Exchange exchange, final Object value, final boolean mandatory, final boolean tryConvert) {
         Object answer;
         try {
-            answer = doConvertTo(type, exchange, value, true);
+            answer = doConvertTo(type, exchange, value, tryConvert);
         } catch (Exception e) {
             if (statistics.isStatisticsEnabled()) {
                 failedCounter.increment();
             }
-            return null;
+            if (tryConvert) {
+                return null;
+            }
+
+            // if its a ExecutionException then we have rethrow it as its not due to failed conversion
+            // this is special for FutureTypeConverter
+            boolean execution = ObjectHelper.getException(ExecutionException.class, e) != null
+                    || ObjectHelper.getException(CamelExecutionException.class, e) != null;
+            if (execution) {
+                throw CamelExecutionException.wrapCamelExecutionException(exchange, e);
+            }
+            // error occurred during type conversion
+            throw createTypeConversionException(exchange, type, value, e);
         }
-        if (answer == Void.TYPE) {
+        if (answer == MISS_VALUE) {
             // Could not find suitable conversion
             if (statistics.isStatisticsEnabled()) {
                 missCounter.increment();
@@ -241,25 +191,52 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
             if (statistics.isStatisticsEnabled()) {
                 hitCounter.increment();
             }
-            return (T) answer;
+            return answer;
         }
     }
 
     protected Object doConvertTo(final Class<?> type, final Exchange exchange, final Object value, final boolean tryConvert) throws Exception {
-        if (log.isTraceEnabled()) {
+        boolean trace = log.isTraceEnabled();
+        boolean statisticsEnabled = statistics.isStatisticsEnabled();
+
+        if (trace) {
             log.trace("Finding type converter to convert {} -> {} with value: {}",
-                    new Object[]{value == null ? "null" : value.getClass().getCanonicalName(), 
-                        type.getCanonicalName(), value});
+                    value == null ? "null" : value.getClass().getCanonicalName(),
+                    type.getCanonicalName(), value);
         }
 
+
         if (value == null) {
             // no type conversion was needed
-            if (statistics.isStatisticsEnabled()) {
+            if (statisticsEnabled) {
                 noopCounter.increment();
             }
-            // lets avoid NullPointerException when converting to boolean for null values
-            if (boolean.class == type) {
-                return Boolean.FALSE;
+            // lets avoid NullPointerException when converting to primitives for null values
+            if (type.isPrimitive()) {
+                if (boolean.class == type) {
+                    return Boolean.FALSE;
+                }
+                if (int.class == type) {
+                    return 0;
+                }
+                if (long.class == type) {
+                    return 0L;
+                }
+                if (byte.class == type) {
+                    return (byte) 0;
+                }
+                if (short.class == type) {
+                    return (short) 0;
+                }
+                if (double.class == type) {
+                    return 0.0;
+                }
+                if (float.class == type) {
+                    return 0.0f;
+                }
+                if (char.class == type) {
+                    return '\0';
+                }
             }
             return null;
         }
@@ -267,66 +244,33 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
         // same instance type
         if (type.isInstance(value)) {
             // no type conversion was needed
-            if (statistics.isStatisticsEnabled()) {
+            if (statisticsEnabled) {
                 noopCounter.increment();
             }
             return value;
         }
 
-        // special for NaN numbers, which we can only convert for floating numbers
-        if ((value instanceof Float && value.equals(Float.NaN)) || (value instanceof Double && value.equals(Double.NaN))) {
-            // no type conversion was needed
-            if (statistics.isStatisticsEnabled()) {
-                noopCounter.increment();
-            }
-            if (Float.class.isAssignableFrom(type)) {
-                return Float.NaN;
-            } else if (Double.class.isAssignableFrom(type)) {
-                return Double.NaN;
-            } else {
-                // we cannot convert the NaN
-                return Void.TYPE;
-            }
-        }
-
         // okay we need to attempt to convert
-        if (statistics.isStatisticsEnabled()) {
+        if (statisticsEnabled) {
             attemptCounter.increment();
         }
 
-        // use the optimised core converter first
-        Object result = optimisedTypeConverter.convertTo(type, exchange, value);
-        if (result != null) {
-            if (statistics.isStatisticsEnabled()) {
-                baseHitCounter.increment();
-            }
-            if (log.isTraceEnabled()) {
-                log.trace("Using optimised core converter to convert: {} -> {}", type, value.getClass().getCanonicalName());
-            }
-            return result;
-        }
-
-        // check if we have tried it before and if its a miss
-        TypeMapping key = new TypeMapping(type, value.getClass());
-        if (misses.containsKey(key)) {
-            // we have tried before but we cannot convert this one
-            return Void.TYPE;
-        }
-        
         // try to find a suitable type converter
-        TypeConverter converter = getOrFindTypeConverter(key);
+        TypeConverter converter = getOrFindTypeConverter(type, value.getClass());
         if (converter != null) {
-            log.trace("Using converter: {} to convert {}", converter, key);
+            if (trace) {
+                log.trace("Using converter: {} to convert [{}=>{}]", converter, value.getClass(), type);
+            }
             Object rc;
             if (tryConvert) {
                 rc = converter.tryConvertTo(type, exchange, value);
             } else {
                 rc = converter.convertTo(type, exchange, value);
             }
-            if (rc == null && converter.allowNull()) {
-                return null;
-            } else if (rc != null) {
+            if (rc != null) {
                 return rc;
+            } else if (converter.allowNull()) {
+                return null;
             }
         }
 
@@ -335,7 +279,7 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
             Class<?> primitiveType = ObjectHelper.convertPrimitiveTypeToWrapperType(type);
             if (primitiveType != type) {
                 Class<?> fromType = value.getClass();
-                TypeConverter tc = getOrFindTypeConverter(new TypeMapping(primitiveType, fromType));
+                TypeConverter tc = getOrFindTypeConverter(primitiveType, fromType);
                 if (tc != null) {
                     // add the type as a known type converter as we can convert from primitive to object converter
                     addTypeConverter(type, fromType, tc);
@@ -367,9 +311,9 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
                 return null;
             }
 
-            if (Void.TYPE.equals(rc)) {
+            if (rc == MISS_VALUE) {
                 // it cannot be converted so give up
-                return Void.TYPE;
+                return MISS_VALUE;
             }
 
             if (rc != null) {
@@ -378,15 +322,14 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
                     // add it as a known type converter since we found a fallback that could do it
                     if (log.isDebugEnabled()) {
                         log.debug("Promoting fallback type converter as a known type converter to convert from: {} to: {} for the fallback converter: {}",
-                                new Object[]{type.getCanonicalName(), value.getClass().getCanonicalName(), fallback.getFallbackTypeConverter()});
+                                type.getCanonicalName(), value.getClass().getCanonicalName(), fallback.getFallbackTypeConverter());
                     }
                     addTypeConverter(type, value.getClass(), fallback.getFallbackTypeConverter());
                 }
 
                 if (log.isTraceEnabled()) {
                     log.trace("Fallback type converter {} converted type from: {} to: {}",
-                            new Object[]{fallback.getFallbackTypeConverter(),
-                                type.getCanonicalName(), value.getClass().getCanonicalName()});
+                            fallback.getFallbackTypeConverter(), type.getCanonicalName(), value.getClass().getCanonicalName());
                 }
 
                 // return converted value
@@ -397,18 +340,17 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
         if (!tryConvert) {
             // Could not find suitable conversion, so remember it
             // do not register misses for try conversions
-            misses.put(key, key);
+            typeMappings.put(type, value.getClass(), MISS_CONVERTER);
         }
 
         // Could not find suitable conversion, so return Void to indicate not found
-        return Void.TYPE;
+        return MISS_VALUE;
     }
 
     @Override
     public void addTypeConverter(Class<?> toType, Class<?> fromType, TypeConverter typeConverter) {
         log.trace("Adding type converter: {}", typeConverter);
-        TypeMapping key = new TypeMapping(toType, fromType);
-        TypeConverter converter = typeMappings.get(key);
+        TypeConverter converter = typeMappings.get(toType, fromType);
         // only override it if its different
         // as race conditions can lead to many threads trying to promote the same fallback converter
 
@@ -433,9 +375,7 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
             }
 
             if (add) {
-                typeMappings.put(key, typeConverter);
-                // remove any previous misses, as we added the new type converter
-                misses.remove(key);
+                typeMappings.put(toType, fromType, typeConverter);
             }
         }
     }
@@ -455,13 +395,7 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     @Override
     public boolean removeTypeConverter(Class<?> toType, Class<?> fromType) {
         log.trace("Removing type converter from: {} to: {}", fromType, toType);
-        TypeMapping key = new TypeMapping(toType, fromType);
-        TypeConverter converter = typeMappings.remove(key);
-        if (converter != null) {
-            typeMappings.remove(key);
-            misses.remove(key);
-        }
-        return converter != null;
+        return typeMappings.remove(toType, fromType);
     }
 
     @Override
@@ -502,8 +436,7 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     }
 
     public TypeConverter getTypeConverter(Class<?> toType, Class<?> fromType) {
-        TypeMapping key = new TypeMapping(toType, fromType);
-        return typeMappings.get(key);
+        return typeMappings.get(toType, fromType);
     }
 
     @Override
@@ -516,36 +449,13 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
         this.injector = injector;
     }
 
-    public Set<Class<?>> getFromClassMappings() {
-        Set<Class<?>> answer = new HashSet<>();
-        for (TypeMapping mapping : typeMappings.keySet()) {
-            answer.add(mapping.getFromType());
-        }
-        return answer;
-    }
-
-    public Map<Class<?>, TypeConverter> getToClassMappings(Class<?> fromClass) {
-        Map<Class<?>, TypeConverter> answer = new HashMap<>();
-        for (Map.Entry<TypeMapping, TypeConverter> entry : typeMappings.entrySet()) {
-            TypeMapping mapping = entry.getKey();
-            if (mapping.isApplicable(fromClass)) {
-                answer.put(mapping.getToType(), entry.getValue());
-            }
-        }
-        return answer;
-    }
-
-    public Map<TypeMapping, TypeConverter> getTypeMappings() {
-        return typeMappings;
-    }
-
-    protected <T> TypeConverter getOrFindTypeConverter(TypeMapping key) {
-        TypeConverter converter = typeMappings.get(key);
+    protected <T> TypeConverter getOrFindTypeConverter(Class<?> toType, Class<?> fromType) {
+        TypeConverter converter = typeMappings.get(toType, fromType);
         if (converter == null) {
             // converter not found, try to lookup then
-            converter = lookup(key.getToType(), key.getFromType());
+            converter = lookup(toType, fromType);
             if (converter != null) {
-                typeMappings.putIfAbsent(key, converter);
+                typeMappings.put(toType, fromType, converter);
             }
         }
         return converter;
@@ -588,21 +498,16 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
             if (fromType != null && !fromType.equals(Object.class)) {
 
                 // lets try classes derived from this toType
-                Set<Map.Entry<TypeMapping, TypeConverter>> entries = typeMappings.entrySet();
-                for (Map.Entry<TypeMapping, TypeConverter> entry : entries) {
-                    TypeMapping key = entry.getKey();
-                    Class<?> aToType = key.getToType();
-                    if (toType.isAssignableFrom(aToType)) {
-                        Class<?> aFromType = key.getFromType();
+                TypeConverter converter = typeMappings.getFirst(
+                        to -> toType.isAssignableFrom(to),
                         // skip Object based we do them last
-                        if (!aFromType.equals(Object.class) && aFromType.isAssignableFrom(fromType)) {
-                            return entry.getValue();
-                        }
-                    }
+                        from -> !from.equals(Object.class) && from.isAssignableFrom(fromType));
+                if (converter != null) {
+                    return converter;
                 }
 
                 // lets test for Object based converters as last resort
-                TypeConverter converter = getTypeConverter(toType, Object.class);
+                converter = getTypeConverter(toType, Object.class);
                 if (converter != null) {
                     return converter;
                 }
@@ -614,10 +519,8 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     }
 
     public List<Class<?>[]> listAllTypeConvertersFromTo() {
-        List<Class<?>[]> answer = new ArrayList<>(typeMappings.size());
-        for (TypeMapping mapping : typeMappings.keySet()) {
-            answer.add(new Class<?>[]{mapping.getFromType(), mapping.getToType()});
-        }
+        List<Class<?>[]> answer = new ArrayList<>();
+        typeMappings.forEach((k1, k2, v) -> answer.add(new Class<?>[]{k2, k1}));
         return answer;
     }
 
@@ -626,7 +529,7 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
      */
     public void loadCoreTypeConverters() throws Exception {
         // load all the type converters from camel-core
-        CoreTypeConverterLoader core = new CoreTypeConverterLoader();
+        CoreStaticTypeConverterLoader core = new CoreStaticTypeConverterLoader();
         core.load(this);
     }
 
@@ -654,6 +557,11 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     }
 
     protected TypeConversionException createTypeConversionException(Exchange exchange, Class<?> type, Object value, Throwable cause) {
+        if (cause instanceof TypeConversionException) {
+            if (((TypeConversionException) cause).getToType() == type) {
+                return (TypeConversionException) cause;
+            }
+        }
         Object body;
         // extract the body for logging which allows to limit the message body in the exception/stacktrace
         // and also can be used to turn off logging sensitive message data
@@ -701,12 +609,17 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
         // log utilization statistics when stopping, including mappings
         if (statistics.isStatisticsEnabled()) {
             String info = statistics.toString();
-            info += String.format(" mappings[total=%s, misses=%s]", typeMappings.size(), misses.size());
+            AtomicInteger misses = new AtomicInteger();
+            typeMappings.forEach((k1, k2, v) -> {
+                if (v == MISS_CONVERTER) {
+                    misses.incrementAndGet();
+                }
+            });
+            info += String.format(" mappings[total=%s, misses=%s]", typeMappings.size(), misses);
             log.info(info);
         }
 
         typeMappings.clear();
-        misses.clear();
         statistics.reset();
     }
 
@@ -775,75 +688,193 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
     }
 
     /**
-     * Represents a mapping from one type (which can be null) to another
+     * Represents a fallback type converter
      */
-    protected static final class TypeMapping {
-        private final Class<?> toType;
-        private final Class<?> fromType;
-        private final int hashCode;
+    protected static class FallbackTypeConverter {
+        private final boolean canPromote;
+        private final TypeConverter fallbackTypeConverter;
 
-        TypeMapping(Class<?> toType, Class<?> fromType) {
-            this.toType = toType;
-            this.fromType = fromType;
+        FallbackTypeConverter(TypeConverter fallbackTypeConverter, boolean canPromote) {
+            this.canPromote = canPromote;
+            this.fallbackTypeConverter = fallbackTypeConverter;
+        }
 
-            // pre calculate hashcode
-            int hash = toType.hashCode();
-            if (fromType != null) {
-                hash *= 37 + fromType.hashCode();
-            }
-            hashCode = hash;
+        public boolean isCanPromote() {
+            return canPromote;
         }
 
-        public Class<?> getFromType() {
-            return fromType;
+        public TypeConverter getFallbackTypeConverter() {
+            return fallbackTypeConverter;
         }
+    }
 
-        public Class<?> getToType() {
-            return toType;
+    @SuppressWarnings("unchecked")
+    protected static class DoubleMap<K1, K2, V> {
+
+        static class Entry {
+            Object k1;
+            Object k2;
+            Object v;
+            Entry next;
         }
 
-        @Override
-        public boolean equals(Object object) {
-            if (object instanceof TypeMapping) {
-                TypeMapping that = (TypeMapping) object;
-                return this.fromType == that.fromType && this.toType == that.toType;
+        private Entry[] table;
+        private int mask;
+
+        public DoubleMap(int size) {
+            table = new Entry[closedTableSize(size)];
+            mask = table.length - 1;
+        }
+
+        public V get(K1 k1, K2 k2) {
+            Entry[] table = this.table;
+            int mask = this.mask;
+            int index = smear(k1.hashCode() * 31 + k2.hashCode()) & mask;
+            for (Entry entry = table[index]; entry != null; entry = entry.next) {
+                if (k1 == entry.k1 && k2 == entry.k2) {
+                    return (V) entry.v;
+                }
+            }
+            return null;
+        }
+
+        public void forEach(TriConsumer<K1, K2, V> consumer) {
+            Entry[] table = this.table;
+            for (Entry entry : table) {
+                while (entry != null) {
+                    consumer.accept((K1) entry.k1, (K2) entry.k2, (V) entry.v);
+                    entry = entry.next;
+                }
+            }
+        }
+
+        public boolean containsKey(K1 k1, K2 k2) {
+            Entry[] table = this.table;
+            int mask = this.mask;
+            int index = smear(k1.hashCode() * 31 + k2.hashCode()) & mask;
+            for (Entry entry = table[index]; entry != null; entry = entry.next) {
+                if (k1 == entry.k1 && k2 == entry.k2) {
+                    return true;
+                }
             }
             return false;
         }
 
-        @Override
-        public int hashCode() {
-            return hashCode;
+        public synchronized void put(K1 k1, K2 k2, V v) {
+            Entry[] table = this.table;
+            int size = size() + 1;
+            int realSize = closedTableSize(size);
+            if (realSize <= table.length) {
+                realSize = table.length;
+                int index = smear(k1.hashCode() * 31 + k2.hashCode()) & (realSize - 1);
+                for (Entry oldEntry = table[index]; oldEntry != null; oldEntry = oldEntry.next) {
+                    if (oldEntry.k1 == k1 && oldEntry.k2 == k2) {
+                        oldEntry.v = v;
+                        return;
+                    }
+                }
+                Entry entry = new Entry();
+                entry.k1 = k1;
+                entry.k2 = k2;
+                entry.v = v;
+                entry.next = table[index];
+                table[index] = entry;
+            } else {
+                Entry[] newT = new Entry[realSize];
+                int index = smear(k1.hashCode() * 31 + k2.hashCode()) & (realSize - 1);
+                Entry entry = new Entry();
+                newT[index] = entry;
+                entry.k1 = k1;
+                entry.k2 = k2;
+                entry.v = v;
+                for (Entry oldEntry : table) {
+                    while (oldEntry != null) {
+                        if (k1 != oldEntry.k1 || k2 != oldEntry.k2) {
+                            index = smear(oldEntry.k1.hashCode() * 31 + oldEntry.k2.hashCode()) & (realSize - 1);
+                            Entry newEntry = new Entry();
+                            newEntry.k1 = oldEntry.k1;
+                            newEntry.k2 = oldEntry.k2;
+                            newEntry.v = oldEntry.v;
+                            newEntry.next = newT[index];
+                            newT[index] = newEntry;
+                        }
+                        oldEntry = oldEntry.next;
+                    }
+                }
+                this.table = newT;
+                this.mask = realSize - 1;
+            }
         }
 
-        @Override
-        public String toString() {
-            return "[" + fromType + "=>" + toType + "]";
+        public synchronized boolean remove(K1 k1, K2 k2) {
+            Entry[] table = this.table;
+            int mask = this.mask;
+            int index = smear(k1.hashCode() * 31 + k2.hashCode()) & mask;
+            Entry prevEntry = null;
+            for (Entry oldEntry = table[index]; oldEntry != null; prevEntry = oldEntry, oldEntry = oldEntry.next) {
+                if (oldEntry.k1 == k1 && oldEntry.k2 == k2) {
+                    if (prevEntry == null) {
+                        table[index] = oldEntry.next;
+                    } else {
+                        prevEntry.next = oldEntry.next;
+                    }
+                    return true;
+                }
+            }
+            return false;
         }
 
-        public boolean isApplicable(Class<?> fromClass) {
-            return fromType.isAssignableFrom(fromClass);
+        public V getFirst(Predicate<K1> p1, Predicate<K2> p2) {
+            for (Entry entry : table) {
+                while (entry != null) {
+                    if (p1.test((K1) entry.k1) && p2.test((K2) entry.k2)) {
+                        return (V) entry.v;
+                    }
+                    entry = entry.next;
+                }
+            }
+            return null;
         }
-    }
 
-    /**
-     * Represents a fallback type converter
-     */
-    protected static class FallbackTypeConverter {
-        private final boolean canPromote;
-        private final TypeConverter fallbackTypeConverter;
+        public int size() {
+            Entry[] table = this.table;
+            int n = 0;
+            if (table != null) {
+                for (Entry e : table) {
+                    for (Entry c = e; c != null; c = c.next) {
+                        n++;
+                    }
+                }
+            }
+            return n;
+        }
 
-        FallbackTypeConverter(TypeConverter fallbackTypeConverter, boolean canPromote) {
-            this.canPromote = canPromote;
-            this.fallbackTypeConverter = fallbackTypeConverter;
+        public synchronized void clear() {
+            this.table = new Entry[table.length];
         }
 
-        public boolean isCanPromote() {
-            return canPromote;
+        private static final double MAX_LOAD_FACTOR = 1.2;
+        private static final int MAX_TABLE_SIZE = 32768;
+        private static final int C1 = 0xcc9e2d51;
+        private static final int C2 = 0x1b873593;
+
+        static int smear(int hashCode) {
+            return C2 * Integer.rotateLeft(hashCode * C1, 15);
         }
 
-        public TypeConverter getFallbackTypeConverter() {
-            return fallbackTypeConverter;
+        static int closedTableSize(int expectedEntries) {
+            // Get the recommended table size.
+            // Round down to the nearest power of 2.
+            expectedEntries = Math.max(expectedEntries, 2);
+            int tableSize = Integer.highestOneBit(expectedEntries);
+            // Check to make sure that we will not exceed the maximum load factor.
+            if (expectedEntries > (int) (MAX_LOAD_FACTOR * tableSize)) {
+                tableSize <<= 1;
+                return (tableSize > 0) ? tableSize : MAX_TABLE_SIZE;
+            }
+            return tableSize;
         }
+
     }
+
 }
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java b/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java
deleted file mode 100644
index 0ceb81d..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- * 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.impl.converter;
-
-import java.lang.annotation.Annotation;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import org.apache.camel.component.bean.BeanConverter;
-import org.apache.camel.component.file.GenericFileConverter;
-import org.apache.camel.converter.AttachmentConverter;
-import org.apache.camel.converter.CamelConverter;
-import org.apache.camel.converter.CollectionConverter;
-import org.apache.camel.converter.DateTimeConverter;
-import org.apache.camel.converter.DurationConverter;
-import org.apache.camel.converter.IOConverter;
-import org.apache.camel.converter.NIOConverter;
-import org.apache.camel.converter.ObjectConverter;
-import org.apache.camel.converter.SQLConverter;
-import org.apache.camel.converter.TimePatternConverter;
-import org.apache.camel.converter.jaxp.DomConverter;
-import org.apache.camel.converter.jaxp.StaxConverter;
-import org.apache.camel.converter.jaxp.StreamSourceConverter;
-import org.apache.camel.converter.jaxp.XmlConverter;
-import org.apache.camel.converter.stream.StreamCacheConverter;
-import org.apache.camel.spi.PackageScanClassResolver;
-import org.apache.camel.spi.PackageScanFilter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A {@link org.apache.camel.spi.ClassResolver} which loads type converters
- * from a hardcoded list of classes.
- * <p/>
- * <b>Important:</b> Whenever a new type converter class is added to camel-core
- * then the class should be added to the list in this class.
- *
- * @see CoreTypeConverterLoader
- */
-public class CorePackageScanClassResolver implements PackageScanClassResolver {
-
-    protected final Logger log = LoggerFactory.getLogger(getClass());
-    private final Set<ClassLoader> classLoaders = new LinkedHashSet<>();
-    private final Set<Class<?>> converters = new LinkedHashSet<>();
-
-    public CorePackageScanClassResolver() {
-        converters.add(ObjectConverter.class);
-        converters.add(CollectionConverter.class);
-        converters.add(DateTimeConverter.class);
-        converters.add(SQLConverter.class);
-        converters.add(IOConverter.class);
-        converters.add(NIOConverter.class);
-        converters.add(StaxConverter.class);
-        converters.add(DomConverter.class);
-        converters.add(StreamSourceConverter.class);
-        converters.add(XmlConverter.class);
-        converters.add(CamelConverter.class);
-        converters.add(StreamCacheConverter.class);
-        converters.add(TimePatternConverter.class);
-        converters.add(FutureTypeConverter.class);
-        converters.add(BeanConverter.class);
-        converters.add(GenericFileConverter.class);
-        converters.add(DurationConverter.class);
-        converters.add(AttachmentConverter.class);
-        converters.add(UriTypeConverter.class);
-    }
-
-    @Override
-    public Set<ClassLoader> getClassLoaders() {
-        // return a new set to avoid any concurrency issues in other runtimes such as OSGi
-        return Collections.unmodifiableSet(new LinkedHashSet<>(classLoaders));
-    }
-
-    @Override
-    public void addClassLoader(ClassLoader classLoader) {
-        classLoaders.add(classLoader);
-    }
-
-    @Override
-    public Set<Class<?>> findAnnotated(Class<? extends Annotation> annotation, String... packageNames) {
-        return converters;
-    }
-
-    @Override
-    public Set<Class<?>> findAnnotated(Set<Class<? extends Annotation>> annotations, String... packageNames) {
-        return converters;
-    }
-
-    @Override
-    public Set<Class<?>> findImplementations(Class<?> parent, String... packageNames) {
-        // noop
-        return null;
-    }
-
-    @Override
-    public Set<Class<?>> findByFilter(PackageScanFilter filter, String... packageNames) {
-        // noop
-        return null;
-    }
-
-    @Override
-    public void addFilter(PackageScanFilter filter) {
-        // noop
-    }
-
-    @Override
-    public void removeFilter(PackageScanFilter filter) {
-        // noop
-    }
-}
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/CoreTypeConverterLoader.java b/camel-core/src/main/java/org/apache/camel/impl/converter/CoreTypeConverterLoader.java
deleted file mode 100644
index 06b7353..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/CoreTypeConverterLoader.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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.impl.converter;
-
-import java.io.IOException;
-
-/**
- * Will load all type converters from camel-core without classpath scanning, which makes
- * it much faster.
- * <p/>
- * The {@link CorePackageScanClassResolver} contains a hardcoded list of the type converter classes to load.
- */
-public class CoreTypeConverterLoader extends AnnotationTypeConverterLoader {
-
-    public CoreTypeConverterLoader() {
-        super(new CorePackageScanClassResolver());
-    }
-
-    @Override
-    protected String[] findPackageNames() throws IOException {
-        // this method doesn't change the behavior of the CorePackageScanClassResolver
-        return new String[]{"org.apache.camel.converter", "org.apache.camel.component.bean", "org.apache.camel.component.file"};
-    }
-
-}
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/EnumTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/EnumTypeConverter.java
index 095bef8..bdcaaa6 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/EnumTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/EnumTypeConverter.java
@@ -28,8 +28,12 @@ import org.apache.camel.support.TypeConverterSupport;
  */
 public class EnumTypeConverter extends TypeConverterSupport {
 
-    @SuppressWarnings("unchecked")
     public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
+        return EnumTypeConverter.doConvertTo(type, exchange, value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T doConvertTo(Class<T> type, Exchange exchange, Object value) {
         if (type.isEnum()) {
             String text = value.toString();
             Class<Enum> enumClass = (Class<Enum>) type;
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/FutureTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/FutureTypeConverter.java
index 38032c9..b2f2004 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/FutureTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/FutureTypeConverter.java
@@ -64,7 +64,7 @@ public final class FutureTypeConverter extends TypeConverterSupport {
 
             if (future.isCancelled()) {
                 // return void to indicate its not possible to convert at this time
-                return (T) Void.TYPE;
+                return (T) MISS_VALUE;
             }
 
             // do some trace logging as the get is blocking until the response is ready
@@ -75,7 +75,7 @@ public final class FutureTypeConverter extends TypeConverterSupport {
 
             if (body == null) {
                 // return void to indicate its not possible to convert at this time
-                return (T) Void.TYPE;
+                return (T) MISS_VALUE;
             }
 
             // maybe from is already the type we want
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/OptimisedTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/OptimisedTypeConverter.java
deleted file mode 100644
index df774f8..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/OptimisedTypeConverter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * 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.impl.converter;
-
-import java.util.Map;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.converter.IOConverterOptimised;
-import org.apache.camel.converter.NIOConverterOptimised;
-import org.apache.camel.converter.ObjectConverterOptimised;
-import org.apache.camel.converter.TimePatternConverterOptimised;
-
-/**
- * Optimised type converter for performing the most common conversions using the type converters
- * from camel-core.
- * <p/>
- * The most commonly used type converters has been optimised to be invoked in a faster by
- * using direct method calls instead of a calling via a reflection method call via
- * {@link InstanceMethodTypeConverter} or {@link StaticMethodTypeConverter}.
- * In addition the performance is faster because the type converter is not looked up
- * via a key in the type converter {@link Map}; which requires creating a new object
- * as they key and perform the map lookup. The caveat is that for any new type converter
- * to be included it must be manually added by adding the nessasary source code to the
- * optimised classes such as {@link ObjectConverterOptimised}.
- */
-public class OptimisedTypeConverter {
-
-    private final EnumTypeConverter enumTypeConverter = new EnumTypeConverter();
-
-    /**
-     * Attempts to convert the value to the given type
-     *
-     * @param type     the type to convert to
-     * @param exchange the exchange, may be <tt>null</tt>
-     * @param value    the value
-     * @return the converted value, or <tt>null</tt> if no optimised core type converter exists to convert
-     */
-    public Object convertTo(final Class<?> type, final Exchange exchange, final Object value) throws Exception {
-        Object answer;
-
-        // use the optimised type converters and use them in the most commonly used order
-
-        // we need time pattern first as it can do a special String -> long conversion which should happen first
-        answer = TimePatternConverterOptimised.convertTo(type, exchange, value);
-        if (answer == null) {
-            answer = ObjectConverterOptimised.convertTo(type, exchange, value);
-        }
-        if (answer == null) {
-            answer = IOConverterOptimised.convertTo(type, exchange, value);
-        }
-        if (answer == null) {
-            answer = NIOConverterOptimised.convertTo(type, exchange, value);
-        }
-
-        // specially optimised for enums
-        if (answer == null && type.isEnum()) {
-            answer = enumTypeConverter.convertTo(type, exchange, value);
-        }
-
-        return answer;
-    }
-
-}
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java
index 2fa600d..c15f52f 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java
@@ -36,22 +36,22 @@ public class ToStringTypeConverter extends TypeConverterSupport {
 
         // should not try to convert Message
         if (Message.class.isAssignableFrom(value.getClass())) {
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
 
         // should not try to convert future
         if (Future.class.isAssignableFrom(value.getClass())) {
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
 
         // should not try to convert bean invocations
         if (BeanInvocation.class.isAssignableFrom(value.getClass())) {
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
 
         // should not try to convert files
         if (WrappedFile.class.isAssignableFrom(value.getClass())) {
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
 
         if (toType.equals(String.class)) {
diff --git a/camel-core/src/test/java/org/apache/camel/builder/SimpleBuilderTest.java b/camel-core/src/test/java/org/apache/camel/builder/SimpleBuilderTest.java
index 7e7d4de..7b29975 100644
--- a/camel-core/src/test/java/org/apache/camel/builder/SimpleBuilderTest.java
+++ b/camel-core/src/test/java/org/apache/camel/builder/SimpleBuilderTest.java
@@ -69,7 +69,7 @@ public class SimpleBuilderTest extends TestSupport {
             SimpleBuilder.simple("${body}", int.class).evaluate(exchange, Object.class);
             fail("Should have thrown exception");
         } catch (TypeConversionException e) {
-            assertIsInstanceOf(NumberFormatException.class, e.getCause());
+            assertIsInstanceOf(NumberFormatException.class, e.getCause().getCause());
         }
 
         assertEquals(true, SimpleBuilder.simple("${header.cool}", boolean.class).evaluate(exchange, Object.class));
diff --git a/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java b/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
index d745d8e..50ff16b 100644
--- a/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
+++ b/camel-core/src/test/java/org/apache/camel/builder/xml/XPathFeatureTest.java
@@ -58,8 +58,7 @@ public class XPathFeatureTest extends ContextTestSupport {
             xpath("/").stringResult().evaluate(createExchange(XML_DATA));
             fail("Expect an Exception here");
         } catch (TypeConversionException ex) {
-            assertTrue("Get a wrong exception cause.", ex.getCause() instanceof RuntimeCamelException);
-            assertTrue("Get a wrong exception cause.", ex.getCause().getCause() instanceof FileNotFoundException);
+            assertTrue("Get a wrong exception cause.", ex.getCause() instanceof FileNotFoundException);
         } finally {
             System.clearProperty(DOM_BUILDER_FACTORY_FEATURE + ":"
                 + "http://xml.org/sax/features/external-general-entities");
@@ -83,8 +82,7 @@ public class XPathFeatureTest extends ContextTestSupport {
             xpath("/").stringResult().evaluate(createExchange(XML_DATA_INVALID));
             fail("Expect an Exception here");
         } catch (TypeConversionException ex) {
-            assertTrue("Get a wrong exception cause.", ex.getCause() instanceof RuntimeCamelException);
-            assertTrue("Get a wrong exception cause.", ex.getCause().getCause() instanceof SAXParseException);
+            assertTrue("Get a wrong exception cause.", ex.getCause() instanceof SAXParseException);
         }
     }
 
diff --git a/camel-core/src/test/java/org/apache/camel/converter/ConverterBenchmark.java b/camel-core/src/test/java/org/apache/camel/converter/ConverterBenchmark.java
new file mode 100644
index 0000000..3967a9c
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/converter/ConverterBenchmark.java
@@ -0,0 +1,160 @@
+/**
+ * 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.converter;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.impl.DefaultClassResolver;
+import org.apache.camel.impl.DefaultFactoryFinderResolver;
+import org.apache.camel.impl.DefaultPackageScanClassResolver;
+import org.apache.camel.impl.converter.DefaultTypeConverter;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.spi.Injector;
+import org.apache.camel.util.ReflectionInjector;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.runner.options.TimeValue;
+
+public class ConverterBenchmark {
+
+    @Ignore
+    @Test
+    public void launchBenchmark() throws Exception {
+
+        Options opt = new OptionsBuilder()
+                // Specify which benchmarks to run.
+                // You can be more specific if you'd like to run only one benchmark per test.
+                .include(this.getClass().getName() + ".*")
+                // Set the following options as needed
+                .mode (Mode.AverageTime)
+                .timeUnit(TimeUnit.MICROSECONDS)
+                .warmupTime(TimeValue.seconds(2))
+                .warmupIterations(5)
+                .measurementTime(TimeValue.seconds(1))
+                .measurementIterations(5)
+                .threads(2)
+                .forks(1)
+                .shouldFailOnError(true)
+                .shouldDoGC(true)
+                //.jvmArgs("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining")
+                //.addProfiler(WinPerfAsmProfiler.class)
+                .build();
+
+        new Runner(opt).run();
+    }
+
+    // The JMH samples are the best documentation for how to use it
+    // http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/
+    @State (Scope.Thread)
+    public static class BenchmarkState
+    {
+        DefaultPackageScanClassResolver packageScanClassResolver;
+        Injector injector;
+        FactoryFinder factoryFinder;
+        DefaultTypeConverter converter;
+
+        @Setup (Level.Trial)
+        public void initialize() throws Exception {
+            packageScanClassResolver = new DefaultPackageScanClassResolver();
+            injector = new ReflectionInjector();
+            factoryFinder = new DefaultFactoryFinderResolver().resolveDefaultFactoryFinder(new DefaultClassResolver());
+            converter = new DefaultTypeConverter(packageScanClassResolver, injector, factoryFinder, true);
+            converter.start();
+        }
+    }
+
+    @Benchmark
+    public void benchmarkLoadTime(BenchmarkState state, Blackhole bh) throws Exception {
+
+        DefaultPackageScanClassResolver packageScanClassResolver = state.packageScanClassResolver;
+        Injector injector = state.injector;
+        FactoryFinder factoryFinder = state.factoryFinder;
+
+        DefaultTypeConverter converter = new DefaultTypeConverter(packageScanClassResolver, injector, factoryFinder, true);
+        converter.start();
+        bh.consume(converter);
+    }
+
+    @Benchmark
+    public void benchmarkConversionTimeEnum(BenchmarkState state, Blackhole bh) {
+        DefaultTypeConverter converter = state.converter;
+
+        for (int i = 0; i < 1000; i++)
+            bh.consume(converter.convertTo(LoggingLevel.class, "DEBUG"));
+    }
+
+    @Benchmark
+    public void benchmarkConversionIntToLong(BenchmarkState state, Blackhole bh) {
+        DefaultTypeConverter converter = state.converter;
+
+        for (int i = 0; i < 1000; i++)
+            bh.consume(converter.convertTo(Long.class, 3));
+    }
+
+    @Benchmark
+    public void benchmarkConversionStringToChar(BenchmarkState state, Blackhole bh) {
+        DefaultTypeConverter converter = state.converter;
+
+        for (int i = 0; i < 1000; i++)
+            bh.consume(converter.convertTo(char[].class, "Hello world"));
+    }
+
+    @Benchmark
+    public void benchmarkConversionStringToURI(BenchmarkState state, Blackhole bh) {
+        DefaultTypeConverter converter = state.converter;
+
+        for (int i = 0; i < 1000; i++)
+            bh.consume(converter.convertTo(URI.class, "uri:foo"));
+    }
+
+    @Benchmark
+    public void benchmarkConversionListToStringArray(BenchmarkState state, Blackhole bh) {
+        DefaultTypeConverter converter = state.converter;
+
+        for (int i = 0; i < 1000; i++)
+            bh.consume(converter.convertTo(String[].class, Arrays.asList("DEBUG")));
+    }
+
+    @Ignore
+    @Test
+    public void testConvertEnumPerfs() throws Exception {
+        Blackhole bh = new Blackhole("Today's password is swordfish. I understand instantiating Blackholes directly is dangerous.");
+        BenchmarkState state = new BenchmarkState();
+        state.initialize();
+        doTest(bh, state);
+    }
+
+    private void doTest(Blackhole bh, BenchmarkState state) {
+        DefaultTypeConverter converter = state.converter;
+        for (int i = 0; i < 1000000; i++) {
+            bh.consume(converter.convertTo(Long.class, 3));
+        }
+    }
+}
diff --git a/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java b/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java
index 18f48e8..d43b545 100644
--- a/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java
+++ b/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java
@@ -43,11 +43,14 @@ import org.apache.camel.support.ServiceHelper;
 import org.apache.camel.util.ReflectionInjector;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class ConverterTest extends Assert {
+
     private static final Logger LOG = LoggerFactory.getLogger(ConverterTest.class);
 
     protected TypeConverter converter = new DefaultTypeConverter(new DefaultPackageScanClassResolver(),
@@ -262,4 +265,21 @@ public class ConverterTest extends Assert {
         }
     }
 
+    @Test
+    public void testNullToBoolean() throws Exception {
+        boolean b = converter.convertTo(boolean.class, null);
+        assertFalse(b);
+    }
+
+    @Test
+    public void testNullToInt() throws Exception {
+        int i = converter.convertTo(int.class, null);
+        assertEquals(0, i);
+    }
+
+    @Test
+    public void testToInt() throws Exception {
+        int i = converter.convertTo(int.class, "0");
+        assertEquals(0, i);
+    }
 }
diff --git a/camel-core/src/test/java/org/apache/camel/converter/DurationConverterTest.java b/camel-core/src/test/java/org/apache/camel/converter/DurationConverterTest.java
index 86ad5f0..193a512 100644
--- a/camel-core/src/test/java/org/apache/camel/converter/DurationConverterTest.java
+++ b/camel-core/src/test/java/org/apache/camel/converter/DurationConverterTest.java
@@ -42,7 +42,7 @@ public class DurationConverterTest extends ContextTestSupport {
             context.getTypeConverter().convertTo(long.class, duration);
             fail("Should throw exception");
         } catch (TypeConversionException e) {
-            assertIsInstanceOf(ArithmeticException.class, e.getCause().getCause());
+            assertIsInstanceOf(ArithmeticException.class, e.getCause());
         }
     }
 
diff --git a/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java b/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java
index be5e00f..f7c3275 100644
--- a/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java
+++ b/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java
@@ -53,14 +53,11 @@ public class ObjectConverterTest extends Assert {
         assertEquals(Byte.valueOf("4"), ObjectConverter.toByte(Byte.valueOf("4")));
         assertEquals(Byte.valueOf("4"), ObjectConverter.toByte(Integer.valueOf("4")));
         assertEquals(Byte.valueOf("4"), ObjectConverter.toByte("4"));
-        assertEquals(null, ObjectConverter.toByte(new Date()));
     }
     
     @Test
     public void testToClass() {
-        assertEquals(String.class, ObjectConverter.toClass(String.class, null));
         assertEquals(String.class, ObjectConverter.toClass("java.lang.String", null));
-        assertEquals(null, ObjectConverter.toClass(new Integer(4), null));
         assertEquals(null, ObjectConverter.toClass("foo.Bar", null));
     }
 
@@ -69,9 +66,8 @@ public class ObjectConverterTest extends Assert {
         assertEquals(Short.valueOf("4"), ObjectConverter.toShort(Short.valueOf("4")));
         assertEquals(Short.valueOf("4"), ObjectConverter.toShort(Integer.valueOf("4")));
         assertEquals(Short.valueOf("4"), ObjectConverter.toShort("4"));
-        assertEquals(null, ObjectConverter.toShort(new Date()));
-        assertEquals(Short.valueOf("0"), ObjectConverter.toShort(Double.NaN));
-        assertEquals(Short.valueOf("0"), ObjectConverter.toShort(Float.NaN));
+        assertEquals(null, ObjectConverter.toShort(Double.NaN));
+        assertEquals(null, ObjectConverter.toShort(Float.NaN));
         assertEquals(Short.valueOf("4"), ObjectConverter.toShort(Short.valueOf("4")));
     }
 
@@ -80,9 +76,8 @@ public class ObjectConverterTest extends Assert {
         assertEquals(Integer.valueOf("4"), ObjectConverter.toInteger(Integer.valueOf("4")));
         assertEquals(Integer.valueOf("4"), ObjectConverter.toInteger(Long.valueOf("4")));
         assertEquals(Integer.valueOf("4"), ObjectConverter.toInteger("4"));
-        assertEquals(null, ObjectConverter.toInteger(new Date()));
-        assertEquals(Integer.valueOf("0"), ObjectConverter.toInteger(Double.NaN));
-        assertEquals(Integer.valueOf("0"), ObjectConverter.toInteger(Float.NaN));
+        assertEquals(null, ObjectConverter.toInteger(Double.NaN));
+        assertEquals(null, ObjectConverter.toInteger(Float.NaN));
         assertEquals(Integer.valueOf("4"), ObjectConverter.toInteger(Integer.valueOf("4")));
     }
 
@@ -91,9 +86,8 @@ public class ObjectConverterTest extends Assert {
         assertEquals(Long.valueOf("4"), ObjectConverter.toLong(Long.valueOf("4")));
         assertEquals(Long.valueOf("4"), ObjectConverter.toLong(Integer.valueOf("4")));
         assertEquals(Long.valueOf("4"), ObjectConverter.toLong("4"));
-        assertEquals(null, ObjectConverter.toLong(new Date()));
-        assertEquals(Long.valueOf("0"), ObjectConverter.toLong(Double.NaN));
-        assertEquals(Long.valueOf("0"), ObjectConverter.toLong(Float.NaN));
+        assertEquals(null, ObjectConverter.toLong(Double.NaN));
+        assertEquals(null, ObjectConverter.toLong(Float.NaN));
         assertEquals(Long.valueOf("4"), ObjectConverter.toLong(Long.valueOf("4")));
     }
 
@@ -102,7 +96,6 @@ public class ObjectConverterTest extends Assert {
         assertEquals(Float.valueOf("4"), ObjectConverter.toFloat(Float.valueOf("4")));
         assertEquals(Float.valueOf("4"), ObjectConverter.toFloat(Integer.valueOf("4")));
         assertEquals(Float.valueOf("4"), ObjectConverter.toFloat("4"));
-        assertEquals(null, ObjectConverter.toFloat(new Date()));
         assertEquals((Float) Float.NaN, ObjectConverter.toFloat(Double.NaN));
         assertEquals((Float) Float.NaN, ObjectConverter.toFloat(Float.NaN));
         assertEquals(Float.valueOf("4"), ObjectConverter.toFloat(Float.valueOf("4")));
@@ -113,7 +106,6 @@ public class ObjectConverterTest extends Assert {
         assertEquals(Double.valueOf("4"), ObjectConverter.toDouble(Double.valueOf("4")));
         assertEquals(Double.valueOf("4"), ObjectConverter.toDouble(Integer.valueOf("4")));
         assertEquals(Double.valueOf("4"), ObjectConverter.toDouble("4"));
-        assertEquals(null, ObjectConverter.toDouble(new Date()));
         assertEquals((Double) Double.NaN, ObjectConverter.toDouble(Double.NaN));
         assertEquals((Double) Double.NaN, ObjectConverter.toDouble(Float.NaN));
         assertEquals(Double.valueOf("4"), ObjectConverter.toDouble(Double.valueOf("4")));
@@ -126,8 +118,8 @@ public class ObjectConverterTest extends Assert {
         assertEquals(BigInteger.valueOf(4), ObjectConverter.toBigInteger("4"));
         assertEquals(BigInteger.valueOf(123456789L), ObjectConverter.toBigInteger("123456789"));
         assertEquals(null, ObjectConverter.toBigInteger(new Date()));
-        assertEquals(BigInteger.valueOf(0), ObjectConverter.toBigInteger(Double.NaN));
-        assertEquals(BigInteger.valueOf(0), ObjectConverter.toBigInteger(Float.NaN));
+        assertEquals(null, ObjectConverter.toBigInteger(Double.NaN));
+        assertEquals(null, ObjectConverter.toBigInteger(Float.NaN));
         assertEquals(BigInteger.valueOf(4), ObjectConverter.toBigInteger(Long.valueOf("4")));
         assertEquals(new BigInteger("14350442579497085228"), ObjectConverter.toBigInteger("14350442579497085228"));
     }
diff --git a/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java b/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java
index c4ee55b..f9acd94 100644
--- a/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java
+++ b/camel-util/src/main/java/org/apache/camel/util/ObjectHelper.java
@@ -1080,6 +1080,9 @@ public final class ObjectHelper {
         return null;
     }
 
+    private static final Float FLOAT_NAN = Float.NaN;
+    private static final Double DOUBLE_NAN = Double.NaN;
+
     /**
      * Is the given value a numeric NaN type
      * 
@@ -1087,11 +1090,8 @@ public final class ObjectHelper {
      * @return <tt>true</tt> if its a {@link Float#NaN} or {@link Double#NaN}.
      */
     public static boolean isNaN(Object value) {
-        if (value == null || !(value instanceof Number)) {
-            return false;
-        }
-        // value must be a number
-        return value.equals(Float.NaN) || value.equals(Double.NaN);
+        return (value instanceof Number)
+                && (FLOAT_NAN.equals(value) || DOUBLE_NAN.equals(value));
     }
 
 }
diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java
index 4b33df0..323e028 100644
--- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java
+++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java
@@ -36,6 +36,8 @@ import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.camel.support.ExchangeHelper;
 import org.apache.cxf.message.MessageContentsList;
 
+import static org.apache.camel.TypeConverter.MISS_VALUE;
+
 /**
  * The <a href="http://camel.apache.org/type-converter.html">Type Converters</a>
  * for CXF related types' converting .
@@ -160,7 +162,7 @@ public final class CxfConverter {
                 }
             }
             // return void to indicate its not possible to convert at this time
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
 
         // CXF-RS Response class
@@ -174,7 +176,7 @@ public final class CxfConverter {
             }
 
             // return void to indicate its not possible to convert at this time
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
         
         return null;
diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java
index 2e4da69..9bc96d7 100644
--- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java
+++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java
@@ -46,6 +46,8 @@ import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.cxf.staxutils.StaxSource;
 import org.apache.cxf.staxutils.StaxUtils;
 
+import static org.apache.camel.TypeConverter.MISS_VALUE;
+
 @Converter
 public final class CxfPayloadConverter {
     private static XmlConverter xml = new XmlConverter();
@@ -179,10 +181,10 @@ public final class CxfPayloadConverter {
                 }
             } catch (RuntimeCamelException e) {
                 // the internal conversion to XML can throw an exception if the content is not XML
-                // ignore this and return Void.TYPE to indicate that we cannot convert this
+                // ignore this and return MISS_VALUE to indicate that we cannot convert this
             }
             // no we could not do it currently
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
         // Convert a CxfPayload into something else
         if (CxfPayload.class.isAssignableFrom(value.getClass())) {
@@ -234,7 +236,7 @@ public final class CxfPayloadConverter {
                 Object result = tc.convertTo(type, exchange, cxfPayloadToNodeList((CxfPayload<?>) value, exchange));
                 if (result == null) {
                     // no we could not do it currently, and we just abort the convert here
-                    return (T) Void.TYPE;
+                    return (T) MISS_VALUE;
                 } else {
                     return (T) result;
                 }
@@ -249,12 +251,12 @@ public final class CxfPayloadConverter {
                     return tc.convertTo(type, exchange, nodeList.item(0));
                 } else {
                     // no we could not do it currently
-                    return (T) Void.TYPE;
+                    return (T) MISS_VALUE;
                 }
             } else {
                 if (size == 0) {
                     // empty size so we cannot convert
-                    return (T) Void.TYPE;
+                    return (T) MISS_VALUE;
                 }
             }
         }
diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java
index c49dceb..ca9723f 100644
--- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java
+++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java
@@ -30,6 +30,8 @@ import org.apache.commons.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.TypeConverter.MISS_VALUE;
+
 /**
  * Default converters for {@link ExecResult}. For details how to extend the
  * converters check out <a
@@ -96,7 +98,7 @@ public final class ExecResultConverter {
         } else {
             // use Void to indicate we cannot convert it
             // (prevents Camel from using a fallback converter which may convert a String from the instance name)  
-            return (T) Void.TYPE;
+            return (T) MISS_VALUE;
         }
     }
 
diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyConverter.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyConverter.java
index 112db0a..e382ab8 100644
--- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyConverter.java
+++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyConverter.java
@@ -23,6 +23,8 @@ import org.apache.camel.spi.TypeConverterRegistry;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Response;
 
+import static org.apache.camel.TypeConverter.MISS_VALUE;
+
 @Converter
 public final class JettyConverter {
 
@@ -41,7 +43,7 @@ public final class JettyConverter {
         if (value != null) {
             // should not try to convert Request as its not possible
             if (Request.class.isAssignableFrom(value.getClass())) {
-                return (T) Void.TYPE;
+                return (T) MISS_VALUE;
             }
         }
 
diff --git a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ConverterProcessor.java b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ConverterProcessor.java
index 43232a0..1757f21 100644
--- a/tooling/apt/src/main/java/org/apache/camel/tools/apt/ConverterProcessor.java
+++ b/tooling/apt/src/main/java/org/apache/camel/tools/apt/ConverterProcessor.java
@@ -21,9 +21,12 @@ import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.Writer;
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -33,6 +36,8 @@ import javax.annotation.processing.RoundEnvironment;
 import javax.annotation.processing.SupportedAnnotationTypes;
 import javax.annotation.processing.SupportedSourceVersion;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.ExecutableElement;
@@ -50,20 +55,25 @@ public class ConverterProcessor extends AbstractProcessor {
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         try {
-            if (this.processingEnv.getElementUtils().getTypeElement("org.apache.camel.impl.converter.CoreFallbackConverter") != null) {
+            if (roundEnv.processingOver()) {
                 return false;
             }
 
-            if (roundEnv.processingOver()) {
+            if (this.processingEnv.getElementUtils().getTypeElement("org.apache.camel.impl.converter.CoreStaticTypeConverterLoader") != null) {
+                return false;
+            }
+
+            // We're in tests, do not generate anything
+            if (this.processingEnv.getElementUtils().getTypeElement("org.apache.camel.converter.ObjectConverter") == null) {
                 return false;
             }
 
             Comparator<TypeMirror> comparator = (o1, o2) -> processingEnv.getTypeUtils().isAssignable(o1, o2)
                     ? -1 : processingEnv.getTypeUtils().isAssignable(o2, o1) ? +1 : o1.toString().compareTo(o2.toString());
 
-            Map<String, Map<TypeMirror, ExecutableElement>> converters = new HashMap<>();
-            TypeElement annotationType = this.processingEnv.getElementUtils().getTypeElement("org.apache.camel.Converter");
-            for (Element element : roundEnv.getElementsAnnotatedWith(annotationType)) {
+            Map<String, Map<TypeMirror, ExecutableElement>> converters = new TreeMap<>();
+            TypeElement converterAnnotationType = this.processingEnv.getElementUtils().getTypeElement("org.apache.camel.Converter");
+            for (Element element : roundEnv.getElementsAnnotatedWith(converterAnnotationType)) {
                 if (element.getKind() == ElementKind.METHOD) {
                     ExecutableElement ee = (ExecutableElement) element;
                     TypeMirror to = ee.getReturnType();
@@ -81,57 +91,127 @@ public class ConverterProcessor extends AbstractProcessor {
                     converters.computeIfAbsent(toString(to), c -> new TreeMap<>(comparator)).put(from, ee);
                 }
             }
-
-            // We're in tests, do not generate anything
-            if (this.processingEnv.getElementUtils().getTypeElement("org.apache.camel.converter.ObjectConverter") == null) {
-                return false;
+            TypeElement fallbackAnnotationType = this.processingEnv.getElementUtils().getTypeElement("org.apache.camel.FallbackConverter");
+            List<ExecutableElement> fallbackConverters = new ArrayList<>();
+            for (Element element : roundEnv.getElementsAnnotatedWith(fallbackAnnotationType)) {
+                if (element.getKind() == ElementKind.METHOD) {
+                    ExecutableElement ee = (ExecutableElement) element;
+                    fallbackConverters.add(ee);
+                }
             }
 
             String p = "org.apache.camel.impl.converter";
-            String c = "CoreFallbackConverter";
+            String c = "CoreStaticTypeConverterLoader";
             JavaFileObject jfo = processingEnv.getFiler().createSourceFile(p + "." + c);
             Set<String> converterClasses = new LinkedHashSet<>();
             try (Writer writer = jfo.openWriter()) {
 
                 writer.append("package ").append(p).append(";\n");
                 writer.append("\n");
-                writer.append("import org.apache.camel.support.TypeConverterSupport;\n");
                 writer.append("import org.apache.camel.Exchange;\n");
                 writer.append("import org.apache.camel.TypeConversionException;\n");
+                writer.append("import org.apache.camel.TypeConverterLoaderException;\n");
+                writer.append("import org.apache.camel.spi.TypeConverterLoader;\n");
+                writer.append("import org.apache.camel.spi.TypeConverterRegistry;\n");
+                writer.append("import org.apache.camel.support.TypeConverterSupport;\n");
                 writer.append("\n");
                 writer.append("@SuppressWarnings(\"unchecked\")\n");
-                writer.append("public class ").append(c).append(" extends TypeConverterSupport {\n");
+                writer.append("public class ").append(c).append(" implements TypeConverterLoader {\n");
+                writer.append("\n");
+                writer.append("    static abstract class SimpleTypeConverter extends TypeConverterSupport {\n");
+                writer.append("        private final boolean allowNull;\n");
                 writer.append("\n");
-                writer.append("    public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {\n");
-                writer.append("        try {\n");
-                writer.append("            return (T) doConvert(type, exchange, value);\n");
-                writer.append("        } catch (TypeConversionException e) {\n");
-                writer.append("            throw e;\n");
-                writer.append("        } catch (Exception e) {\n");
-                writer.append("            throw new TypeConversionException(value, type, e);\n");
+                writer.append("        public SimpleTypeConverter(boolean allowNull) {\n");
+                writer.append("            this.allowNull = allowNull;\n");
                 writer.append("        }\n");
-                writer.append("    }\n");
                 writer.append("\n");
-                writer.append("    private Object doConvert(Class<?> type, Exchange exchange, Object value) throws Exception {\n");
-                writer.append("        switch (type.getName()) {\n");
+                writer.append("        @Override\n");
+                writer.append("        public boolean allowNull() {\n");
+                writer.append("            return allowNull;\n");
+                writer.append("        }\n");
+                writer.append("\n");
+                writer.append("        @Override\n");
+                writer.append("        public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {\n");
+                writer.append("            try {\n");
+                writer.append("                return (T) doConvert(exchange, value);\n");
+                writer.append("            } catch (TypeConversionException e) {\n");
+                writer.append("                throw e;\n");
+                writer.append("            } catch (Exception e) {\n");
+                writer.append("                throw new TypeConversionException(value, type, e);\n");
+                writer.append("            }\n");
+                writer.append("        }\n");
+                writer.append("        protected abstract Object doConvert(Exchange exchange, Object value) throws Exception;\n");
+                writer.append("    };\n");
+                writer.append("\n");
+                writer.append("    @Override\n");
+                writer.append("    public void load(TypeConverterRegistry registry) throws TypeConverterLoaderException {\n");
+
                 for (Map.Entry<String, Map<TypeMirror, ExecutableElement>> to : converters.entrySet()) {
-                    writer.append("            case \"").append(to.getKey()).append("\": {\n");
                     for (Map.Entry<TypeMirror, ExecutableElement> from : to.getValue().entrySet()) {
-                        String name = toString(from.getKey());
-                        if ("java.lang.Object".equals(name)) {
-                            writer.append("                if (value != null) {\n");
-                        } else {
-                            writer.append("                if (value instanceof ").append(name).append(") {\n");
+                        boolean allowNull = false;
+                        for (AnnotationMirror ann : from.getValue().getAnnotationMirrors()) {
+                            if (ann.getAnnotationType().asElement() == converterAnnotationType) {
+                                for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : ann.getElementValues().entrySet()) {
+                                    switch (entry.getKey().getSimpleName().toString()) {
+                                        case "allowNull":
+                                            allowNull = (Boolean) entry.getValue().getValue();
+                                            break;
+                                        default:
+                                            throw new IllegalStateException();
+                                    }
+                                }
+                            }
+                        }
+                        writer.append("        registry.addTypeConverter(").append(to.getKey()).append(".class").append(", ")
+                                .append(toString(from.getKey())).append(".class, new SimpleTypeConverter(")
+                                .append(Boolean.toString(allowNull)).append(") {\n");
+                        writer.append("            @Override\n");
+                        writer.append("            public Object doConvert(Exchange exchange, Object value) throws Exception {\n");
+                        writer.append("                return ").append(toJava(from.getValue(), converterClasses)).append(";\n");
+                        writer.append("            }\n");
+                        writer.append("        });\n");
+                    }
+                }
+
+                for (ExecutableElement ee : fallbackConverters) {
+                    boolean allowNull = false;
+                    boolean canPromote = false;
+                    for (AnnotationMirror ann : ee.getAnnotationMirrors()) {
+                        if (ann.getAnnotationType().asElement() == fallbackAnnotationType) {
+                            for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : ann.getElementValues().entrySet()) {
+                                switch (entry.getKey().getSimpleName().toString()) {
+                                    case "allowNull":
+                                        allowNull = (Boolean) entry.getValue().getValue();
+                                        break;
+                                    case "canPromote":
+                                        canPromote = (Boolean) entry.getValue().getValue();
+                                        break;
+                                    default:
+                                        throw new IllegalStateException();
+                                }
+                            }
                         }
-                        writer.append("                    return ").append(toJava(from.getValue(), converterClasses)).append(";\n");
-                        writer.append("                }\n");
                     }
-                    writer.append("                break;\n");
+                    writer.append("        registry.addFallbackTypeConverter(new TypeConverterSupport() {\n");
+                    writer.append("            @Override\n");
+                    writer.append("            public boolean allowNull() {\n");
+                    writer.append("                return ").append(Boolean.toString(allowNull)).append(";\n");
                     writer.append("            }\n");
+                    writer.append("            @Override\n");
+                    writer.append("            public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {\n");
+                    writer.append("                try {\n");
+                    writer.append("                    return (T) ").append(toJavaFallback(ee, converterClasses)).append(";\n");
+                    writer.append("                } catch (TypeConversionException e) {\n");
+                    writer.append("                    throw e;\n");
+                    writer.append("                } catch (Exception e) {\n");
+                    writer.append("                    throw new TypeConversionException(value, type, e);\n");
+                    writer.append("                }\n");
+                    writer.append("            }\n");
+                    writer.append("        }, ").append(Boolean.toString(canPromote)).append(");\n");
                 }
-                writer.append("        }\n");
-                writer.append("        return null;\n");
+                writer.append("\n");
                 writer.append("    }\n");
+                writer.append("\n");
 
                 for (String f : converterClasses) {
                     String s = f.substring(f.lastIndexOf('.') + 1);
@@ -177,6 +257,19 @@ public class ConverterProcessor extends AbstractProcessor {
         return pfx + "(" + cast + "value" + (converter.getParameters().size() == 2 ? ", exchange" : "") + ")";
     }
 
+    private String toJavaFallback(ExecutableElement converter, Set<String> converterClasses) {
+        String pfx;
+        if (converter.getModifiers().contains(Modifier.STATIC)) {
+            pfx = converter.getEnclosingElement().toString() + "." + converter.getSimpleName();
+        } else {
+            converterClasses.add(converter.getEnclosingElement().toString());
+            pfx = "get" + converter.getEnclosingElement().getSimpleName() + "()." + converter.getSimpleName();
+        }
+        String type = toString(converter.getParameters().get(converter.getParameters().size() - 2).asType());
+        String cast = type.equals("java.lang.Object") ? "" : "(" + type + ") ";
+        return pfx + "(type, " + (converter.getParameters().size() == 4 ? "exchange, " : "") + cast + "value" + ", registry)";
+    }
+
     public static void dumpExceptionToErrorFile(String fileName, String message, Throwable e) {
         File file = new File(fileName);
         try {


[camel] 01/02: Fix version

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 511248a3edaed135952f5058fd828669c8a186aa
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon Oct 29 22:33:12 2018 +0100

    Fix version
---
 docs/pom.xml                                                  | 2 +-
 examples/camel-example-servlet-httpregistry-blueprint/pom.xml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/pom.xml b/docs/pom.xml
index 9032b1d..346879b 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-parent</artifactId>
-        <version>2.23.0-SNAPSHOT</version>
+        <version>3.0.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
 
diff --git a/examples/camel-example-servlet-httpregistry-blueprint/pom.xml b/examples/camel-example-servlet-httpregistry-blueprint/pom.xml
index 6b10a81..af042b1 100644
--- a/examples/camel-example-servlet-httpregistry-blueprint/pom.xml
+++ b/examples/camel-example-servlet-httpregistry-blueprint/pom.xml
@@ -25,7 +25,7 @@
   <parent>
     <groupId>org.apache.camel.example</groupId>
     <artifactId>examples</artifactId>
-    <version>2.23.0-SNAPSHOT</version>
+    <version>3.0.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>camel-example-servlet-httpregistry-blueprint</artifactId>