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");