CAMEL-11379: Optimise - core type converters to be invoked faster

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

Branch: refs/heads/master
Commit: aeb71af0cce0e485a639f63daad4f909fa65c74e
Parents: 5cf3ad1
Author: Claus Ibsen <davscl...@apache.org>
Authored: Sat Jun 24 19:41:50 2017 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Sat Jun 24 19:41:50 2017 +0200

----------------------------------------------------------------------
 .../ManagedTypeConverterRegistryMBean.java      |   3 +
 .../camel/converter/IOConverterOptimised.java   | 163 +++++++++++++++++++
 .../camel/converter/NIOConverterOptimised.java  |  82 ++++++++++
 .../converter/ObjectConverterOptimised.java     |  92 +++++++++++
 .../converter/BaseTypeConverterRegistry.java    |  22 ++-
 .../impl/converter/DefaultTypeConverter.java    |   6 +-
 .../converter/LazyLoadingTypeConverter.java     |   2 +-
 .../impl/converter/OptimisedTypeConverter.java  |  91 ++++-------
 .../camel/impl/converter/UriTypeConverter.java  |   1 +
 .../mbean/ManagedTypeConverterRegistry.java     |   4 +
 .../apache/camel/spi/TypeConverterRegistry.java |   5 +
 .../ManagedTypeConverterRegistryTest.java       |  15 ++
 12 files changed, 417 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
index 7d38df3..ef5de0c 100644
--- 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
+++ 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
@@ -32,6 +32,9 @@ public interface ManagedTypeConverterRegistryMBean extends 
ManagedServiceMBean {
     @ManagedAttribute(description = "Number of type conversion hits 
(successful conversions)")
     long getHitCounter();
 
+    @ManagedAttribute(description = "Number of type conversion hits by 
optimised core converters (successful conversions)")
+    long getCoreHitCounter();
+
     @ManagedAttribute(description = "Number of type conversion misses (no 
suitable type converter)")
     long getMissCounter();
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/converter/IOConverterOptimised.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..590b398
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/converter/IOConverterOptimised.java
@@ -0,0 +1,163 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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;
+
+/**
+ * Optimised {@link IOConverter}
+ */
+public class IOConverterOptimised {
+
+    private IOConverterOptimised() {
+    }
+
+    public static Object convertTo(final Class<?> type, final Exchange 
exchange, final Object value) throws Exception {
+        Class fromType = value.getClass();
+
+        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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/converter/NIOConverterOptimised.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..cd30f47
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/converter/NIOConverterOptimised.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/converter/ObjectConverterOptimised.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..d7378bd
--- /dev/null
+++ 
b/camel-core/src/main/java/org/apache/camel/converter/ObjectConverterOptimised.java
@@ -0,0 +1,92 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.util.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;
+        }
+
+        // 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());
+            }
+        }
+
+        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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
----------------------------------------------------------------------
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 21e437a..7c6f401 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
@@ -80,6 +80,7 @@ public abstract class BaseTypeConverterRegistry extends 
ServiceSupport implement
     protected final LongAdder noopCounter = new LongAdder();
     protected final LongAdder attemptCounter = new LongAdder();
     protected final LongAdder missCounter = new LongAdder();
+    protected final LongAdder coreHitCounter = new LongAdder();
     protected final LongAdder hitCounter = new LongAdder();
     protected final LongAdder failedCounter = new LongAdder();
 
@@ -244,9 +245,9 @@ public abstract class BaseTypeConverterRegistry extends 
ServiceSupport implement
         }
     }
 
-    protected Object doConvertTo(final Class<?> type, final Exchange exchange, 
final Object value, final boolean tryConvert) {
+    protected Object doConvertTo(final Class<?> type, final Exchange exchange, 
final Object value, final boolean tryConvert) throws Exception {
         if (log.isTraceEnabled()) {
-            log.trace("Converting {} -> {} with value: {}",
+            log.trace("Finding type converter to convert {} -> {} with value: 
{}",
                     new Object[]{value == null ? "null" : 
value.getClass().getCanonicalName(), 
                         type.getCanonicalName(), value});
         }
@@ -296,7 +297,12 @@ public abstract class BaseTypeConverterRegistry extends 
ServiceSupport implement
         // use the optimised core converter first
         Object result = optimisedTypeConverter.convertTo(type, exchange, 
value);
         if (result != null) {
-            log.trace("Using optimised converter to convert: {} -> {}", type, 
value.getClass());
+            if (statistics.isStatisticsEnabled()) {
+                coreHitCounter.increment();
+            }
+            if (log.isTraceEnabled()) {
+                log.trace("Using optimised core converter to convert: {} -> 
{}", type, value.getClass().getCanonicalName());
+            }
             return result;
         }
 
@@ -727,6 +733,11 @@ public abstract class BaseTypeConverterRegistry extends 
ServiceSupport implement
         }
 
         @Override
+        public long getCoreHitCounter() {
+            return coreHitCounter.longValue();
+        }
+
+        @Override
         public long getMissCounter() {
             return missCounter.longValue();
         }
@@ -741,6 +752,7 @@ public abstract class BaseTypeConverterRegistry extends 
ServiceSupport implement
             noopCounter.reset();
             attemptCounter.reset();
             hitCounter.reset();
+            coreHitCounter.reset();
             missCounter.reset();
             failedCounter.reset();
         }
@@ -757,8 +769,8 @@ public abstract class BaseTypeConverterRegistry extends 
ServiceSupport implement
 
         @Override
         public String toString() {
-            return String.format("TypeConverterRegistry utilization[noop=%s, 
attempts=%s, hits=%s, misses=%s, failures=%s]",
-                    getNoopCounter(), getAttemptCounter(), getHitCounter(), 
getMissCounter(), getFailedCounter());
+            return String.format("TypeConverterRegistry utilization[noop=%s, 
attempts=%s, hits=%s, coreHits=%s, misses=%s, failures=%s]",
+                    getNoopCounter(), getAttemptCounter(), getHitCounter(), 
getCoreHitCounter(), getMissCounter(), getFailedCounter());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
 
b/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
index b486f92..0adbb16 100644
--- 
a/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
@@ -62,10 +62,8 @@ public class DefaultTypeConverter extends 
BaseTypeConverterRegistry {
             loadTypeConverters();
             int additional = typeMappings.size() - core;
 
-            if (additional > 0) {
-                // report how many type converters we have loaded
-                log.info("Type converters loaded (core: {}, classpath: {})", 
core, additional);
-            }
+            // report how many type converters we have loaded
+            log.info("Type converters loaded (core: {}, classpath: {})", core, 
additional);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
 
b/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
index 1f9326f..bc477de 100644
--- 
a/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
@@ -50,7 +50,7 @@ public class LazyLoadingTypeConverter extends 
BaseTypeConverterRegistry {
     }
 
     @Override
-    protected Object doConvertTo(final Class<?> type, final Exchange exchange, 
final Object value, boolean tryConvert) {
+    protected Object doConvertTo(final Class<?> type, final Exchange exchange, 
final Object value, boolean tryConvert) throws Exception {
         Object answer = super.doConvertTo(type, exchange, value, tryConvert);
         if (answer == null && !loaded.get()) {
             // okay we could not convert, so try again, but load the 
converters up front

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/impl/converter/OptimisedTypeConverter.java
----------------------------------------------------------------------
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
index 45cc390..a05fcd9 100644
--- 
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
@@ -16,83 +16,56 @@
  */
 package org.apache.camel.impl.converter;
 
-import java.util.Iterator;
+import java.util.Map;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.converter.ObjectConverter;
-import org.apache.camel.converter.TimePatternConverter;
-import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.converter.IOConverterOptimised;
+import org.apache.camel.converter.NIOConverterOptimised;
+import org.apache.camel.converter.ObjectConverterOptimised;
 
 /**
  * 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 null
-     * @param value the value
-     * @return the converted value, or null if no core type converter exists 
to convert
+     * @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) {
-        // 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();
-            }
-        }
-
-        // 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());
-            }
-        }
+    public Object convertTo(final Class<?> type, final Exchange exchange, 
final Object value) throws Exception {
+        Object answer;
 
-        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);
+        // use the optimised type converters and use them in the most commonly 
used order
+        answer = ObjectConverterOptimised.convertTo(type, exchange, value);
+        if (answer == null) {
+            answer = IOConverterOptimised.convertTo(type, exchange, value);
         }
-
-        if (type == Iterator.class) {
-            return ObjectHelper.createIterator(value);
-        } else if (type == Iterable.class) {
-            return ObjectHelper.createIterable(value);
+        if (answer == null) {
+            answer = NIOConverterOptimised.convertTo(type, exchange, value);
         }
 
-        if (type == Class.class) {
-            return ObjectConverter.toClass(value, exchange);
+        // specially optimised for enums
+        if (answer == null && type.isEnum()) {
+            answer = enumTypeConverter.convertTo(type, exchange, value);
         }
 
-        // no optimised type converter found
-        return null;
+        return answer;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/impl/converter/UriTypeConverter.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/converter/UriTypeConverter.java
 
b/camel-core/src/main/java/org/apache/camel/impl/converter/UriTypeConverter.java
index e7584e6..bd7355a 100644
--- 
a/camel-core/src/main/java/org/apache/camel/impl/converter/UriTypeConverter.java
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/converter/UriTypeConverter.java
@@ -26,6 +26,7 @@ import org.apache.camel.TypeConverter;
 /**
  * A {@link TypeConverter} that converts to and from {@link URI}s.
  */
+@Converter
 public final class UriTypeConverter {
 
     private UriTypeConverter() {

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
index bbd07f9..76234c8 100644
--- 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
+++ 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
@@ -59,6 +59,10 @@ public class ManagedTypeConverterRegistry extends 
ManagedService implements Mana
         return registry.getStatistics().getHitCounter();
     }
 
+    public long getCoreHitCounter() {
+        return registry.getStatistics().getCoreHitCounter();
+    }
+
     public long getMissCounter() {
         return registry.getStatistics().getMissCounter();
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java 
b/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java
index 387b3ab..ca426c1 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java
@@ -55,6 +55,11 @@ public interface TypeConverterRegistry extends StaticService 
{
         long getHitCounter();
 
         /**
+         * Number of successful conversions by optimised core converters
+         */
+        long getCoreHitCounter();
+
+        /**
          * Number of attempts which cannot be converted as no suitable type 
converter exists
          */
         long getMissCounter();

http://git-wip-us.apache.org/repos/asf/camel/blob/aeb71af0/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
 
b/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
index e93d0d0..f158571 100644
--- 
a/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
+++ 
b/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
@@ -69,6 +69,21 @@ public class ManagedTypeConverterRegistryTest extends 
ManagementTestSupport {
         Long miss = (Long) mbeanServer.getAttribute(name, "MissCounter");
         assertEquals(0, miss.intValue());
 
+        template.sendBody("direct:start", "5");
+
+        // should hit
+        Long hit = (Long) mbeanServer.getAttribute(name, "HitCounter");
+        assertEquals(1, hit.intValue());
+        Long coreHit = (Long) mbeanServer.getAttribute(name, "CoreHitCounter");
+        assertEquals(1, coreHit.intValue());
+        failed = (Long) mbeanServer.getAttribute(name, "FailedCounter");
+        assertEquals(0, failed.intValue());
+        miss = (Long) mbeanServer.getAttribute(name, "MissCounter");
+        assertEquals(0, miss.intValue());
+
+        // reset
+        mbeanServer.invoke(name, "resetTypeConversionCounters", null, null);
+
         try {
             template.sendBody("direct:start", "foo");
             fail("Should have thrown exception");

Reply via email to